Skip to content

Commit eaed4a8

Browse files
refactor: code (#3429)
1 parent 9ccf7ea commit eaed4a8

File tree

1 file changed

+115
-83
lines changed

1 file changed

+115
-83
lines changed

lib/utils/DevServerPlugin.js

Lines changed: 115 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,23 @@
33
const ipaddr = require('ipaddr.js');
44
const getSocketClientPath = require('./getSocketClientPath');
55

6+
/**
7+
* An Entry, it can be of type string or string[] or Object<string | string[],string>
8+
* @typedef {(string[] | string | Object<string | string[],string>)} Entry
9+
*/
10+
611
class DevServerPlugin {
712
/**
8-
* @param {?Object} options - Dev-Server options
13+
* @param {Object} options - Dev-Server options
914
*/
1015
constructor(options) {
1116
this.options = options;
1217
}
1318

1419
/**
15-
* An Entry, it can be of type string or string[] or Object<string | string[],string>
16-
* @typedef {(string[] | string | Object<string | string[],string>)} Entry
17-
*/
18-
19-
/**
20-
* Apply the plugin
21-
* @param {Object} compiler the compiler instance
22-
* @returns {void}
20+
* @returns {string}
2321
*/
24-
apply(compiler) {
22+
getWebSocketURL() {
2523
const { options } = this;
2624

2725
/** @type {"ws:" | "wss:" | "http:" | "https:" | "auto:"} */
@@ -112,7 +110,7 @@ class DevServerPlugin {
112110
searchParams.logging = options.client.logging;
113111
}
114112

115-
const webSocketURL = encodeURIComponent(
113+
return encodeURIComponent(
116114
new URL(
117115
`${protocol}//${ipaddr.IPv6.isIPv6(host) ? `[${host}]` : host}${
118116
port ? `:${port}` : ''
@@ -128,11 +126,20 @@ class DevServerPlugin {
128126
/[!'()*]/g,
129127
(character) => `%${character.charCodeAt(0).toString(16)}`
130128
);
129+
}
131130

131+
/**
132+
* @returns {string}
133+
*/
134+
getClientEntry() {
135+
const webSocketURL = this.getWebSocketURL();
132136
/** @type {string} */
133-
const clientEntry = `${require.resolve(
134-
'../../client/index.js'
135-
)}?${webSocketURL}`;
137+
138+
return `${require.resolve('../../client/index.js')}?${webSocketURL}`;
139+
}
140+
141+
getHotEntry() {
142+
const { options } = this;
136143

137144
/** @type {(string[] | string)} */
138145
let hotEntry;
@@ -142,47 +149,35 @@ class DevServerPlugin {
142149
} else if (options.hot) {
143150
hotEntry = require.resolve('webpack/hot/dev-server');
144151
}
145-
/**
146-
* prependEntry Method for webpack 4
147-
* @param {Entry} originalEntry
148-
* @param {Entry} additionalEntries
149-
* @returns {Entry}
150-
*/
151-
const prependEntry = (originalEntry, additionalEntries) => {
152-
if (typeof originalEntry === 'function') {
153-
return () =>
154-
Promise.resolve(originalEntry()).then((entry) =>
155-
prependEntry(entry, additionalEntries)
156-
);
157-
}
158-
159-
if (typeof originalEntry === 'object' && !Array.isArray(originalEntry)) {
160-
/** @type {Object<string,string>} */
161-
const clone = {};
162152

163-
Object.keys(originalEntry).forEach((key) => {
164-
// entry[key] should be a string here
165-
const entryDescription = originalEntry[key];
166-
clone[key] = prependEntry(entryDescription, additionalEntries);
167-
});
168-
169-
return clone;
170-
}
171-
172-
// in this case, entry is a string or an array.
173-
// make sure that we do not add duplicates.
174-
/** @type {Entry} */
175-
const entriesClone = additionalEntries.slice(0);
176-
177-
[].concat(originalEntry).forEach((newEntry) => {
178-
if (!entriesClone.includes(newEntry)) {
179-
entriesClone.push(newEntry);
180-
}
181-
});
153+
return hotEntry;
154+
}
182155

183-
return entriesClone;
184-
};
156+
/**
157+
* @param {Object} compilerOptions
158+
* @returns {boolean}
159+
*/
160+
// eslint-disable-next-line class-methods-use-this
161+
isWebTarget(compilerOptions) {
162+
return compilerOptions.externalsPresets
163+
? compilerOptions.externalsPresets.web
164+
: [
165+
'web',
166+
'webworker',
167+
'electron-renderer',
168+
'node-webkit',
169+
// eslint-disable-next-line no-undefined
170+
undefined,
171+
null,
172+
].includes(compilerOptions.target);
173+
}
185174

175+
/**
176+
* Apply the plugin
177+
* @param {Object} compiler the compiler instance
178+
* @returns {void}
179+
*/
180+
apply(compiler) {
186181
/**
187182
*
188183
* Description of the option for checkInject method
@@ -211,38 +206,28 @@ class DevServerPlugin {
211206
return defaultValue;
212207
};
213208

214-
const compilerOptions = compiler.options;
209+
const additionalEntries = [];
215210

216-
compilerOptions.plugins = compilerOptions.plugins || [];
211+
const clientEntry = this.getClientEntry();
217212

218-
/** @type {boolean} */
219-
const isWebTarget = compilerOptions.externalsPresets
220-
? compilerOptions.externalsPresets.web
221-
: [
222-
'web',
223-
'webworker',
224-
'electron-renderer',
225-
'node-webkit',
226-
// eslint-disable-next-line no-undefined
227-
undefined,
228-
null,
229-
].includes(compilerOptions.target);
213+
if (
214+
checkInject(
215+
this.options.client ? this.options.client.needClientEntry : null,
216+
compiler.options,
217+
this.isWebTarget(compiler.options)
218+
)
219+
) {
220+
additionalEntries.push(clientEntry);
221+
}
230222

231-
/** @type {Entry} */
232-
const additionalEntries = checkInject(
233-
options.client ? options.client.needClientEntry : null,
234-
compilerOptions,
235-
isWebTarget
236-
)
237-
? [clientEntry]
238-
: [];
223+
const hotEntry = this.getHotEntry();
239224

240225
if (
241226
hotEntry &&
242227
checkInject(
243-
options.client ? options.client.hotEntry : null,
244-
compilerOptions,
245-
true
228+
this.options.client ? this.options.client.hotEntry : null,
229+
compiler.options,
230+
Boolean(this.options.hot)
246231
)
247232
) {
248233
additionalEntries.push(hotEntry);
@@ -259,25 +244,72 @@ class DevServerPlugin {
259244
}).apply(compiler);
260245
}
261246
} else {
262-
compilerOptions.entry = prependEntry(
263-
compilerOptions.entry || './src',
247+
/**
248+
* prependEntry Method for webpack 4
249+
* @param {Entry} originalEntry
250+
* @param {Entry} newAdditionalEntries
251+
* @returns {Entry}
252+
*/
253+
const prependEntry = (originalEntry, newAdditionalEntries) => {
254+
if (typeof originalEntry === 'function') {
255+
return () =>
256+
Promise.resolve(originalEntry()).then((entry) =>
257+
prependEntry(entry, newAdditionalEntries)
258+
);
259+
}
260+
261+
if (
262+
typeof originalEntry === 'object' &&
263+
!Array.isArray(originalEntry)
264+
) {
265+
/** @type {Object<string,string>} */
266+
const clone = {};
267+
268+
Object.keys(originalEntry).forEach((key) => {
269+
// entry[key] should be a string here
270+
const entryDescription = originalEntry[key];
271+
272+
clone[key] = prependEntry(entryDescription, newAdditionalEntries);
273+
});
274+
275+
return clone;
276+
}
277+
278+
// in this case, entry is a string or an array.
279+
// make sure that we do not add duplicates.
280+
/** @type {Entry} */
281+
const entriesClone = additionalEntries.slice(0);
282+
283+
[].concat(originalEntry).forEach((newEntry) => {
284+
if (!entriesClone.includes(newEntry)) {
285+
entriesClone.push(newEntry);
286+
}
287+
});
288+
289+
return entriesClone;
290+
};
291+
292+
compiler.options.entry = prependEntry(
293+
compiler.options.entry || './src',
264294
additionalEntries
265295
);
266296
compiler.hooks.entryOption.call(
267-
compilerOptions.context,
268-
compilerOptions.entry
297+
compiler.options.context,
298+
compiler.options.entry
269299
);
270300
}
271301

272302
const providePlugin = new webpack.ProvidePlugin({
273-
__webpack_dev_server_client__: getSocketClientPath(options),
303+
__webpack_dev_server_client__: getSocketClientPath(this.options),
274304
});
275305

276306
providePlugin.apply(compiler);
277307

308+
compiler.options.plugins = compiler.options.plugins || [];
309+
278310
if (
279311
hotEntry &&
280-
!compilerOptions.plugins.find(
312+
!compiler.options.plugins.find(
281313
(p) => p.constructor === webpack.HotModuleReplacementPlugin
282314
)
283315
) {

0 commit comments

Comments
 (0)