3
3
const ipaddr = require ( 'ipaddr.js' ) ;
4
4
const getSocketClientPath = require ( './getSocketClientPath' ) ;
5
5
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
+
6
11
class DevServerPlugin {
7
12
/**
8
- * @param {? Object } options - Dev-Server options
13
+ * @param {Object } options - Dev-Server options
9
14
*/
10
15
constructor ( options ) {
11
16
this . options = options ;
12
17
}
13
18
14
19
/**
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 }
23
21
*/
24
- apply ( compiler ) {
22
+ getWebSocketURL ( ) {
25
23
const { options } = this ;
26
24
27
25
/** @type {"ws:" | "wss:" | "http:" | "https:" | "auto:" } */
@@ -112,7 +110,7 @@ class DevServerPlugin {
112
110
searchParams . logging = options . client . logging ;
113
111
}
114
112
115
- const webSocketURL = encodeURIComponent (
113
+ return encodeURIComponent (
116
114
new URL (
117
115
`${ protocol } //${ ipaddr . IPv6 . isIPv6 ( host ) ? `[${ host } ]` : host } ${
118
116
port ? `:${ port } ` : ''
@@ -128,11 +126,20 @@ class DevServerPlugin {
128
126
/ [ ! ' ( ) * ] / g,
129
127
( character ) => `%${ character . charCodeAt ( 0 ) . toString ( 16 ) } `
130
128
) ;
129
+ }
131
130
131
+ /**
132
+ * @returns {string }
133
+ */
134
+ getClientEntry ( ) {
135
+ const webSocketURL = this . getWebSocketURL ( ) ;
132
136
/** @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 ;
136
143
137
144
/** @type {(string[] | string) } */
138
145
let hotEntry ;
@@ -142,47 +149,35 @@ class DevServerPlugin {
142
149
} else if ( options . hot ) {
143
150
hotEntry = require . resolve ( 'webpack/hot/dev-server' ) ;
144
151
}
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 = { } ;
162
152
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
+ }
182
155
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
+ }
185
174
175
+ /**
176
+ * Apply the plugin
177
+ * @param {Object } compiler the compiler instance
178
+ * @returns {void }
179
+ */
180
+ apply ( compiler ) {
186
181
/**
187
182
*
188
183
* Description of the option for checkInject method
@@ -211,38 +206,28 @@ class DevServerPlugin {
211
206
return defaultValue ;
212
207
} ;
213
208
214
- const compilerOptions = compiler . options ;
209
+ const additionalEntries = [ ] ;
215
210
216
- compilerOptions . plugins = compilerOptions . plugins || [ ] ;
211
+ const clientEntry = this . getClientEntry ( ) ;
217
212
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
+ }
230
222
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 ( ) ;
239
224
240
225
if (
241
226
hotEntry &&
242
227
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 )
246
231
)
247
232
) {
248
233
additionalEntries . push ( hotEntry ) ;
@@ -259,25 +244,72 @@ class DevServerPlugin {
259
244
} ) . apply ( compiler ) ;
260
245
}
261
246
} 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' ,
264
294
additionalEntries
265
295
) ;
266
296
compiler . hooks . entryOption . call (
267
- compilerOptions . context ,
268
- compilerOptions . entry
297
+ compiler . options . context ,
298
+ compiler . options . entry
269
299
) ;
270
300
}
271
301
272
302
const providePlugin = new webpack . ProvidePlugin ( {
273
- __webpack_dev_server_client__ : getSocketClientPath ( options ) ,
303
+ __webpack_dev_server_client__ : getSocketClientPath ( this . options ) ,
274
304
} ) ;
275
305
276
306
providePlugin . apply ( compiler ) ;
277
307
308
+ compiler . options . plugins = compiler . options . plugins || [ ] ;
309
+
278
310
if (
279
311
hotEntry &&
280
- ! compilerOptions . plugins . find (
312
+ ! compiler . options . plugins . find (
281
313
( p ) => p . constructor === webpack . HotModuleReplacementPlugin
282
314
)
283
315
) {
0 commit comments