webpack-dev-server 5.0.3 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/client/clients/SockJSClient.js +5 -6
- package/client/clients/WebSocketClient.js +5 -6
- package/client/index.js +15 -2
- package/client/modules/logger/index.js +200 -113
- package/client/modules/sockjs-client/index.js +1 -1
- package/client/overlay/fsm.js +2 -2
- package/client/overlay.js +6 -6
- package/client/progress.js +124 -0
- package/client/utils/reloadApp.js +1 -1
- package/lib/Server.js +600 -369
- package/lib/options.json +23 -5
- package/package.json +30 -29
- package/types/bin/cli-flags.d.ts +15 -0
- package/types/lib/Server.d.ts +187 -282
- package/types/lib/servers/WebsocketServer.d.ts +0 -1
package/lib/Server.js
CHANGED
|
@@ -18,9 +18,6 @@ const schema = require("./options.json");
|
|
|
18
18
|
/** @typedef {import("webpack").Stats} Stats */
|
|
19
19
|
/** @typedef {import("webpack").MultiStats} MultiStats */
|
|
20
20
|
/** @typedef {import("os").NetworkInterfaceInfo} NetworkInterfaceInfo */
|
|
21
|
-
/** @typedef {import("express").NextFunction} NextFunction */
|
|
22
|
-
/** @typedef {import("express").RequestHandler} ExpressRequestHandler */
|
|
23
|
-
/** @typedef {import("express").ErrorRequestHandler} ExpressErrorRequestHandler */
|
|
24
21
|
/** @typedef {import("chokidar").WatchOptions} WatchOptions */
|
|
25
22
|
/** @typedef {import("chokidar").FSWatcher} FSWatcher */
|
|
26
23
|
/** @typedef {import("connect-history-api-fallback").Options} ConnectHistoryApiFallbackOptions */
|
|
@@ -34,14 +31,32 @@ const schema = require("./options.json");
|
|
|
34
31
|
/** @typedef {import("ipaddr.js").IPv4} IPv4 */
|
|
35
32
|
/** @typedef {import("ipaddr.js").IPv6} IPv6 */
|
|
36
33
|
/** @typedef {import("net").Socket} Socket */
|
|
34
|
+
/** @typedef {import("http").Server} HTTPServer*/
|
|
37
35
|
/** @typedef {import("http").IncomingMessage} IncomingMessage */
|
|
38
36
|
/** @typedef {import("http").ServerResponse} ServerResponse */
|
|
39
37
|
/** @typedef {import("open").Options} OpenOptions */
|
|
38
|
+
/** @typedef {import("express").Application} ExpressApplication */
|
|
39
|
+
/** @typedef {import("express").RequestHandler} ExpressRequestHandler */
|
|
40
|
+
/** @typedef {import("express").ErrorRequestHandler} ExpressErrorRequestHandler */
|
|
41
|
+
/** @typedef {import("express").Request} ExpressRequest */
|
|
42
|
+
/** @typedef {import("express").Response} ExpressResponse */
|
|
43
|
+
|
|
44
|
+
/** @typedef {(err?: any) => void} NextFunction */
|
|
45
|
+
/** @typedef {(req: IncomingMessage, res: ServerResponse) => void} SimpleHandleFunction */
|
|
46
|
+
/** @typedef {(req: IncomingMessage, res: ServerResponse, next: NextFunction) => void} NextHandleFunction */
|
|
47
|
+
/** @typedef {(err: any, req: IncomingMessage, res: ServerResponse, next: NextFunction) => void} ErrorHandleFunction */
|
|
48
|
+
/** @typedef {SimpleHandleFunction | NextHandleFunction | ErrorHandleFunction} HandleFunction */
|
|
40
49
|
|
|
41
50
|
/** @typedef {import("https").ServerOptions & { spdy?: { plain?: boolean | undefined, ssl?: boolean | undefined, 'x-forwarded-for'?: string | undefined, protocol?: string | undefined, protocols?: string[] | undefined }}} ServerOptions */
|
|
42
51
|
|
|
43
|
-
/**
|
|
44
|
-
|
|
52
|
+
/**
|
|
53
|
+
* @template {BasicApplication} [T=ExpressApplication]
|
|
54
|
+
* @typedef {T extends ExpressApplication ? ExpressRequest : IncomingMessage} Request
|
|
55
|
+
*/
|
|
56
|
+
/**
|
|
57
|
+
* @template {BasicApplication} [T=ExpressApplication]
|
|
58
|
+
* @typedef {T extends ExpressApplication ? ExpressResponse : ServerResponse} Response
|
|
59
|
+
*/
|
|
45
60
|
|
|
46
61
|
/**
|
|
47
62
|
* @template {Request} T
|
|
@@ -88,8 +103,16 @@ const schema = require("./options.json");
|
|
|
88
103
|
*/
|
|
89
104
|
|
|
90
105
|
/**
|
|
106
|
+
* @template {BasicApplication} [A=ExpressApplication]
|
|
107
|
+
* @template {BasicServer} [S=import("http").Server]
|
|
108
|
+
* @typedef {"http" | "https" | "spdy" | "http2" | string | function(ServerOptions, A): S} ServerType
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @template {BasicApplication} [A=ExpressApplication]
|
|
113
|
+
* @template {BasicServer} [S=import("http").Server]
|
|
91
114
|
* @typedef {Object} ServerConfiguration
|
|
92
|
-
* @property {
|
|
115
|
+
* @property {ServerType<A, S>} [type]
|
|
93
116
|
* @property {ServerOptions} [options]
|
|
94
117
|
*/
|
|
95
118
|
|
|
@@ -173,10 +196,23 @@ const schema = require("./options.json");
|
|
|
173
196
|
*/
|
|
174
197
|
|
|
175
198
|
/**
|
|
176
|
-
* @
|
|
199
|
+
* @template {BasicApplication} [T=ExpressApplication]
|
|
200
|
+
* @typedef {T extends ExpressApplication ? ExpressRequestHandler | ExpressErrorRequestHandler : HandleFunction} MiddlewareHandler
|
|
177
201
|
*/
|
|
178
202
|
|
|
179
203
|
/**
|
|
204
|
+
* @typedef {{ name?: string, path?: string, middleware: MiddlewareHandler }} MiddlewareObject
|
|
205
|
+
*/
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @typedef {MiddlewareObject | MiddlewareHandler } Middleware
|
|
209
|
+
*/
|
|
210
|
+
|
|
211
|
+
/** @typedef {import("net").Server | import("tls").Server} BasicServer */
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @template {BasicApplication} [A=ExpressApplication]
|
|
215
|
+
* @template {BasicServer} [S=import("http").Server]
|
|
180
216
|
* @typedef {Object} Configuration
|
|
181
217
|
* @property {boolean | string} [ipc]
|
|
182
218
|
* @property {Host} [host]
|
|
@@ -190,17 +226,16 @@ const schema = require("./options.json");
|
|
|
190
226
|
* @property {boolean | Record<string, never> | BonjourOptions} [bonjour]
|
|
191
227
|
* @property {string | string[] | WatchFiles | Array<string | WatchFiles>} [watchFiles]
|
|
192
228
|
* @property {boolean | string | Static | Array<string | Static>} [static]
|
|
193
|
-
* @property {
|
|
194
|
-
* @property {
|
|
195
|
-
* @property {"http" | "https" | "spdy" | string | ServerConfiguration} [server]
|
|
229
|
+
* @property {ServerType<A, S> | ServerConfiguration<A, S>} [server]
|
|
230
|
+
* @property {() => Promise<A>} [app]
|
|
196
231
|
* @property {boolean | "sockjs" | "ws" | string | WebSocketServerConfiguration} [webSocketServer]
|
|
197
232
|
* @property {ProxyConfigArray} [proxy]
|
|
198
233
|
* @property {boolean | string | Open | Array<string | Open>} [open]
|
|
199
234
|
* @property {boolean} [setupExitSignals]
|
|
200
235
|
* @property {boolean | ClientConfiguration} [client]
|
|
201
|
-
* @property {Headers | ((req: Request, res: Response, context: DevMiddlewareContext<Request, Response>) => Headers)} [headers]
|
|
202
|
-
* @property {(devServer: Server) => void} [onListening]
|
|
203
|
-
* @property {(middlewares: Middleware[], devServer: Server) => Middleware[]} [setupMiddlewares]
|
|
236
|
+
* @property {Headers | ((req: Request, res: Response, context: DevMiddlewareContext<Request, Response> | undefined) => Headers)} [headers]
|
|
237
|
+
* @property {(devServer: Server<A, S>) => void} [onListening]
|
|
238
|
+
* @property {(middlewares: Middleware[], devServer: Server<A, S>) => Middleware[]} [setupMiddlewares]
|
|
204
239
|
*/
|
|
205
240
|
|
|
206
241
|
if (!process.env.WEBPACK_SERVE) {
|
|
@@ -245,10 +280,46 @@ const encodeOverlaySettings = (setting) =>
|
|
|
245
280
|
? encodeURIComponent(setting.toString())
|
|
246
281
|
: setting;
|
|
247
282
|
|
|
283
|
+
// Working for overload, because typescript doesn't support this yes
|
|
284
|
+
/**
|
|
285
|
+
* @overload
|
|
286
|
+
* @param {NextHandleFunction} fn
|
|
287
|
+
* @returns {BasicApplication}
|
|
288
|
+
*/
|
|
289
|
+
/**
|
|
290
|
+
* @overload
|
|
291
|
+
* @param {HandleFunction} fn
|
|
292
|
+
* @returns {BasicApplication}
|
|
293
|
+
*/
|
|
294
|
+
/**
|
|
295
|
+
* @overload
|
|
296
|
+
* @param {string} route
|
|
297
|
+
* @param {NextHandleFunction} fn
|
|
298
|
+
* @returns {BasicApplication}
|
|
299
|
+
*/
|
|
300
|
+
/**
|
|
301
|
+
* @param {string} route
|
|
302
|
+
* @param {HandleFunction} fn
|
|
303
|
+
* @returns {BasicApplication}
|
|
304
|
+
*/
|
|
305
|
+
// eslint-disable-next-line no-unused-vars
|
|
306
|
+
function useFn(route, fn) {
|
|
307
|
+
return /** @type {BasicApplication} */ ({});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* @typedef {Object} BasicApplication
|
|
312
|
+
* @property {typeof useFn} use
|
|
313
|
+
*/
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* @template {BasicApplication} [A=ExpressApplication]
|
|
317
|
+
* @template {BasicServer} [S=HTTPServer]
|
|
318
|
+
*/
|
|
248
319
|
class Server {
|
|
249
320
|
/**
|
|
250
|
-
* @param {Configuration
|
|
251
|
-
* @param {Compiler | MultiCompiler
|
|
321
|
+
* @param {Configuration<A, S>} options
|
|
322
|
+
* @param {Compiler | MultiCompiler} compiler
|
|
252
323
|
*/
|
|
253
324
|
constructor(options = {}, compiler) {
|
|
254
325
|
validate(/** @type {Schema} */ (schema), options, {
|
|
@@ -256,12 +327,12 @@ class Server {
|
|
|
256
327
|
baseDataPath: "options",
|
|
257
328
|
});
|
|
258
329
|
|
|
259
|
-
this.compiler =
|
|
330
|
+
this.compiler = compiler;
|
|
260
331
|
/**
|
|
261
332
|
* @type {ReturnType<Compiler["getInfrastructureLogger"]>}
|
|
262
333
|
* */
|
|
263
334
|
this.logger = this.compiler.getInfrastructureLogger("webpack-dev-server");
|
|
264
|
-
this.options =
|
|
335
|
+
this.options = options;
|
|
265
336
|
/**
|
|
266
337
|
* @type {FSWatcher[]}
|
|
267
338
|
*/
|
|
@@ -324,11 +395,59 @@ class Server {
|
|
|
324
395
|
}
|
|
325
396
|
|
|
326
397
|
/**
|
|
327
|
-
* @param {string}
|
|
398
|
+
* @param {string} gatewayOrFamily or family
|
|
399
|
+
* @param {boolean} [isInternal] ip should be internal
|
|
328
400
|
* @returns {string | undefined}
|
|
329
401
|
*/
|
|
330
|
-
static findIp(
|
|
331
|
-
|
|
402
|
+
static findIp(gatewayOrFamily, isInternal) {
|
|
403
|
+
if (gatewayOrFamily === "v4" || gatewayOrFamily === "v6") {
|
|
404
|
+
let host;
|
|
405
|
+
|
|
406
|
+
const networks = Object.values(os.networkInterfaces())
|
|
407
|
+
.flatMap((networks) => networks ?? [])
|
|
408
|
+
.filter((network) => {
|
|
409
|
+
if (!network || !network.address) {
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (network.family !== `IP${gatewayOrFamily}`) {
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (
|
|
418
|
+
typeof isInternal !== "undefined" &&
|
|
419
|
+
network.internal !== isInternal
|
|
420
|
+
) {
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (gatewayOrFamily === "v6") {
|
|
425
|
+
const range = ipaddr.parse(network.address).range();
|
|
426
|
+
|
|
427
|
+
if (
|
|
428
|
+
range !== "ipv4Mapped" &&
|
|
429
|
+
range !== "uniqueLocal" &&
|
|
430
|
+
range !== "loopback"
|
|
431
|
+
) {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return network.address;
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
for (const network of networks) {
|
|
440
|
+
host = network.address;
|
|
441
|
+
|
|
442
|
+
if (host.includes(":")) {
|
|
443
|
+
host = `[${host}]`;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return host;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const gatewayIp = ipaddr.parse(gatewayOrFamily);
|
|
332
451
|
|
|
333
452
|
// Look for the matching interface in all local interfaces.
|
|
334
453
|
for (const addresses of Object.values(os.networkInterfaces())) {
|
|
@@ -348,32 +467,22 @@ class Server {
|
|
|
348
467
|
}
|
|
349
468
|
}
|
|
350
469
|
|
|
470
|
+
// TODO remove me in the next major release, we have `findIp`
|
|
351
471
|
/**
|
|
352
472
|
* @param {"v4" | "v6"} family
|
|
353
473
|
* @returns {Promise<string | undefined>}
|
|
354
474
|
*/
|
|
355
475
|
static async internalIP(family) {
|
|
356
|
-
|
|
357
|
-
const { gateway } = await require("default-gateway")[family]();
|
|
358
|
-
|
|
359
|
-
return Server.findIp(gateway);
|
|
360
|
-
} catch {
|
|
361
|
-
// ignore
|
|
362
|
-
}
|
|
476
|
+
return Server.findIp(family, false);
|
|
363
477
|
}
|
|
364
478
|
|
|
479
|
+
// TODO remove me in the next major release, we have `findIp`
|
|
365
480
|
/**
|
|
366
481
|
* @param {"v4" | "v6"} family
|
|
367
482
|
* @returns {string | undefined}
|
|
368
483
|
*/
|
|
369
484
|
static internalIPSync(family) {
|
|
370
|
-
|
|
371
|
-
const { gateway } = require("default-gateway")[family].sync();
|
|
372
|
-
|
|
373
|
-
return Server.findIp(gateway);
|
|
374
|
-
} catch {
|
|
375
|
-
// ignore
|
|
376
|
-
}
|
|
485
|
+
return Server.findIp(family, false);
|
|
377
486
|
}
|
|
378
487
|
|
|
379
488
|
/**
|
|
@@ -383,14 +492,12 @@ class Server {
|
|
|
383
492
|
static async getHostname(hostname) {
|
|
384
493
|
if (hostname === "local-ip") {
|
|
385
494
|
return (
|
|
386
|
-
(
|
|
387
|
-
(await Server.internalIP("v6")) ||
|
|
388
|
-
"0.0.0.0"
|
|
495
|
+
Server.findIp("v4", false) || Server.findIp("v6", false) || "0.0.0.0"
|
|
389
496
|
);
|
|
390
497
|
} else if (hostname === "local-ipv4") {
|
|
391
|
-
return
|
|
498
|
+
return Server.findIp("v4", false) || "0.0.0.0";
|
|
392
499
|
} else if (hostname === "local-ipv6") {
|
|
393
|
-
return
|
|
500
|
+
return Server.findIp("v6", false) || "::";
|
|
394
501
|
}
|
|
395
502
|
|
|
396
503
|
return hostname;
|
|
@@ -470,7 +577,11 @@ class Server {
|
|
|
470
577
|
* @returns bool
|
|
471
578
|
*/
|
|
472
579
|
static isWebTarget(compiler) {
|
|
473
|
-
|
|
580
|
+
if (compiler.platform && compiler.platform.web) {
|
|
581
|
+
return compiler.platform.web;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// TODO improve for the next major version and keep only `webTargets` to fallback for old versions
|
|
474
585
|
if (
|
|
475
586
|
compiler.options.externalsPresets &&
|
|
476
587
|
compiler.options.externalsPresets.web
|
|
@@ -490,6 +601,7 @@ class Server {
|
|
|
490
601
|
"webworker",
|
|
491
602
|
"electron-preload",
|
|
492
603
|
"electron-renderer",
|
|
604
|
+
"nwjs",
|
|
493
605
|
"node-webkit",
|
|
494
606
|
// eslint-disable-next-line no-undefined
|
|
495
607
|
undefined,
|
|
@@ -537,9 +649,7 @@ class Server {
|
|
|
537
649
|
if (typeof webSocketURL.protocol !== "undefined") {
|
|
538
650
|
protocol = webSocketURL.protocol;
|
|
539
651
|
} else {
|
|
540
|
-
protocol =
|
|
541
|
-
/** @type {ServerConfiguration} */
|
|
542
|
-
(this.options.server).type === "http" ? "ws:" : "wss:";
|
|
652
|
+
protocol = this.isTlsServer ? "wss:" : "ws:";
|
|
543
653
|
}
|
|
544
654
|
|
|
545
655
|
searchParams.set("protocol", protocol);
|
|
@@ -1007,39 +1117,41 @@ class Server {
|
|
|
1007
1117
|
? options.hot
|
|
1008
1118
|
: true;
|
|
1009
1119
|
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1120
|
+
if (
|
|
1121
|
+
typeof options.server === "function" ||
|
|
1122
|
+
typeof options.server === "string"
|
|
1123
|
+
) {
|
|
1124
|
+
options.server = {
|
|
1125
|
+
type: options.server,
|
|
1126
|
+
options: {},
|
|
1127
|
+
};
|
|
1128
|
+
} else {
|
|
1129
|
+
const serverOptions =
|
|
1130
|
+
/** @type {ServerConfiguration<A, S>} */
|
|
1131
|
+
(options.server || {});
|
|
1132
|
+
|
|
1133
|
+
options.server = {
|
|
1134
|
+
type: serverOptions.type || "http",
|
|
1135
|
+
options: { ...serverOptions.options },
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
const serverOptions = /** @type {ServerOptions} */ (options.server.options);
|
|
1023
1140
|
|
|
1024
1141
|
if (
|
|
1025
1142
|
options.server.type === "spdy" &&
|
|
1026
|
-
typeof
|
|
1027
|
-
"undefined"
|
|
1143
|
+
typeof serverOptions.spdy === "undefined"
|
|
1028
1144
|
) {
|
|
1029
|
-
|
|
1030
|
-
(options.server.options).spdy = {
|
|
1031
|
-
protocols: ["h2", "http/1.1"],
|
|
1032
|
-
};
|
|
1145
|
+
serverOptions.spdy = { protocols: ["h2", "http/1.1"] };
|
|
1033
1146
|
}
|
|
1034
1147
|
|
|
1035
|
-
if (
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
) {
|
|
1041
|
-
|
|
1042
|
-
(options.server.options).requestCert = false;
|
|
1148
|
+
if (
|
|
1149
|
+
options.server.type === "https" ||
|
|
1150
|
+
options.server.type === "http2" ||
|
|
1151
|
+
options.server.type === "spdy"
|
|
1152
|
+
) {
|
|
1153
|
+
if (typeof serverOptions.requestCert === "undefined") {
|
|
1154
|
+
serverOptions.requestCert = false;
|
|
1043
1155
|
}
|
|
1044
1156
|
|
|
1045
1157
|
const httpsProperties =
|
|
@@ -1047,19 +1159,13 @@ class Server {
|
|
|
1047
1159
|
(["ca", "cert", "crl", "key", "pfx"]);
|
|
1048
1160
|
|
|
1049
1161
|
for (const property of httpsProperties) {
|
|
1050
|
-
if (
|
|
1051
|
-
typeof (
|
|
1052
|
-
/** @type {ServerOptions} */ (options.server.options)[property]
|
|
1053
|
-
) === "undefined"
|
|
1054
|
-
) {
|
|
1162
|
+
if (typeof serverOptions[property] === "undefined") {
|
|
1055
1163
|
// eslint-disable-next-line no-continue
|
|
1056
1164
|
continue;
|
|
1057
1165
|
}
|
|
1058
1166
|
|
|
1059
1167
|
/** @type {any} */
|
|
1060
|
-
const value =
|
|
1061
|
-
/** @type {ServerOptions} */
|
|
1062
|
-
(options.server.options)[property];
|
|
1168
|
+
const value = serverOptions[property];
|
|
1063
1169
|
/**
|
|
1064
1170
|
* @param {string | Buffer | undefined} item
|
|
1065
1171
|
* @returns {string | Buffer | undefined}
|
|
@@ -1087,17 +1193,14 @@ class Server {
|
|
|
1087
1193
|
};
|
|
1088
1194
|
|
|
1089
1195
|
/** @type {any} */
|
|
1090
|
-
(
|
|
1196
|
+
(serverOptions)[property] = Array.isArray(value)
|
|
1091
1197
|
? value.map((item) => readFile(item))
|
|
1092
1198
|
: readFile(value);
|
|
1093
1199
|
}
|
|
1094
1200
|
|
|
1095
1201
|
let fakeCert;
|
|
1096
1202
|
|
|
1097
|
-
if (
|
|
1098
|
-
!(/** @type {ServerOptions} */ (options.server.options).key) ||
|
|
1099
|
-
!(/** @type {ServerOptions} */ (options.server.options).cert)
|
|
1100
|
-
) {
|
|
1203
|
+
if (!serverOptions.key || !serverOptions.cert) {
|
|
1101
1204
|
const certificateDir = Server.findCacheDir();
|
|
1102
1205
|
const certificatePath = path.join(certificateDir, "server.pem");
|
|
1103
1206
|
let certificateExists;
|
|
@@ -1116,13 +1219,11 @@ class Server {
|
|
|
1116
1219
|
|
|
1117
1220
|
// cert is more than 30 days old, kill it with fire
|
|
1118
1221
|
if ((now - Number(certificateStat.ctime)) / certificateTtl > 30) {
|
|
1119
|
-
const { rimraf } = require("rimraf");
|
|
1120
|
-
|
|
1121
1222
|
this.logger.info(
|
|
1122
1223
|
"SSL certificate is more than 30 days old. Removing...",
|
|
1123
1224
|
);
|
|
1124
1225
|
|
|
1125
|
-
await
|
|
1226
|
+
await fs.promises.rm(certificatePath, { recursive: true });
|
|
1126
1227
|
|
|
1127
1228
|
certificateExists = false;
|
|
1128
1229
|
}
|
|
@@ -1131,7 +1232,6 @@ class Server {
|
|
|
1131
1232
|
if (!certificateExists) {
|
|
1132
1233
|
this.logger.info("Generating SSL certificate...");
|
|
1133
1234
|
|
|
1134
|
-
// @ts-ignore
|
|
1135
1235
|
const selfsigned = require("selfsigned");
|
|
1136
1236
|
const attributes = [{ name: "commonName", value: "localhost" }];
|
|
1137
1237
|
const pems = selfsigned.generate(attributes, {
|
|
@@ -1212,14 +1312,8 @@ class Server {
|
|
|
1212
1312
|
this.logger.info(`SSL certificate: ${certificatePath}`);
|
|
1213
1313
|
}
|
|
1214
1314
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
/** @type {ServerOptions} */
|
|
1218
|
-
(options.server.options).key || fakeCert;
|
|
1219
|
-
/** @type {ServerOptions} */
|
|
1220
|
-
(options.server.options).cert =
|
|
1221
|
-
/** @type {ServerOptions} */
|
|
1222
|
-
(options.server.options).cert || fakeCert;
|
|
1315
|
+
serverOptions.key = serverOptions.key || fakeCert;
|
|
1316
|
+
serverOptions.cert = serverOptions.cert || fakeCert;
|
|
1223
1317
|
}
|
|
1224
1318
|
|
|
1225
1319
|
if (typeof options.ipc === "boolean") {
|
|
@@ -1281,15 +1375,15 @@ class Server {
|
|
|
1281
1375
|
*/
|
|
1282
1376
|
const result = [];
|
|
1283
1377
|
|
|
1284
|
-
options.open
|
|
1378
|
+
for (const item of options.open) {
|
|
1285
1379
|
if (typeof item === "string") {
|
|
1286
1380
|
result.push({ target: item, options: defaultOpenOptions });
|
|
1287
|
-
|
|
1288
|
-
|
|
1381
|
+
// eslint-disable-next-line no-continue
|
|
1382
|
+
continue;
|
|
1289
1383
|
}
|
|
1290
1384
|
|
|
1291
1385
|
result.push(...getOpenItemsFromObject(item));
|
|
1292
|
-
}
|
|
1386
|
+
}
|
|
1293
1387
|
|
|
1294
1388
|
/** @type {NormalizedOpen[]} */
|
|
1295
1389
|
(options.open) = result;
|
|
@@ -1522,8 +1616,9 @@ class Server {
|
|
|
1522
1616
|
}
|
|
1523
1617
|
|
|
1524
1618
|
/**
|
|
1619
|
+
* @template T
|
|
1525
1620
|
* @private
|
|
1526
|
-
* @returns {
|
|
1621
|
+
* @returns {T}
|
|
1527
1622
|
*/
|
|
1528
1623
|
getServerTransport() {
|
|
1529
1624
|
let implementation;
|
|
@@ -1553,9 +1648,8 @@ class Server {
|
|
|
1553
1648
|
try {
|
|
1554
1649
|
// eslint-disable-next-line import/no-dynamic-require
|
|
1555
1650
|
implementation = require(
|
|
1556
|
-
/** @type {WebSocketServerConfiguration} */
|
|
1557
|
-
|
|
1558
|
-
).type,
|
|
1651
|
+
/** @type {WebSocketServerConfiguration} */
|
|
1652
|
+
(this.options.webSocketServer).type,
|
|
1559
1653
|
);
|
|
1560
1654
|
} catch (error) {
|
|
1561
1655
|
implementationFound = false;
|
|
@@ -1563,9 +1657,9 @@ class Server {
|
|
|
1563
1657
|
}
|
|
1564
1658
|
break;
|
|
1565
1659
|
case "function":
|
|
1566
|
-
implementation =
|
|
1567
|
-
|
|
1568
|
-
|
|
1660
|
+
implementation =
|
|
1661
|
+
/** @type {WebSocketServerConfiguration} */
|
|
1662
|
+
(this.options.webSocketServer).type;
|
|
1569
1663
|
break;
|
|
1570
1664
|
default:
|
|
1571
1665
|
implementationFound = false;
|
|
@@ -1631,12 +1725,22 @@ class Server {
|
|
|
1631
1725
|
* @returns {Promise<void>}
|
|
1632
1726
|
*/
|
|
1633
1727
|
async initialize() {
|
|
1728
|
+
this.setupHooks();
|
|
1729
|
+
|
|
1730
|
+
await this.setupApp();
|
|
1731
|
+
await this.createServer();
|
|
1732
|
+
|
|
1634
1733
|
if (this.options.webSocketServer) {
|
|
1635
1734
|
const compilers =
|
|
1636
1735
|
/** @type {MultiCompiler} */
|
|
1637
1736
|
(this.compiler).compilers || [this.compiler];
|
|
1638
1737
|
|
|
1639
|
-
|
|
1738
|
+
for (const compiler of compilers) {
|
|
1739
|
+
if (compiler.options.devServer === false) {
|
|
1740
|
+
// eslint-disable-next-line no-continue
|
|
1741
|
+
continue;
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1640
1744
|
this.addAdditionalEntries(compiler);
|
|
1641
1745
|
|
|
1642
1746
|
const webpack = compiler.webpack || require("webpack");
|
|
@@ -1661,7 +1765,7 @@ class Server {
|
|
|
1661
1765
|
plugin.apply(compiler);
|
|
1662
1766
|
}
|
|
1663
1767
|
}
|
|
1664
|
-
}
|
|
1768
|
+
}
|
|
1665
1769
|
|
|
1666
1770
|
if (
|
|
1667
1771
|
this.options.client &&
|
|
@@ -1671,16 +1775,9 @@ class Server {
|
|
|
1671
1775
|
}
|
|
1672
1776
|
}
|
|
1673
1777
|
|
|
1674
|
-
this.setupHooks();
|
|
1675
|
-
this.setupApp();
|
|
1676
|
-
this.setupHostHeaderCheck();
|
|
1677
|
-
this.setupDevMiddleware();
|
|
1678
|
-
// Should be after `webpack-dev-middleware`, otherwise other middlewares might rewrite response
|
|
1679
|
-
this.setupBuiltInRoutes();
|
|
1680
1778
|
this.setupWatchFiles();
|
|
1681
1779
|
this.setupWatchStaticFiles();
|
|
1682
1780
|
this.setupMiddlewares();
|
|
1683
|
-
this.createServer();
|
|
1684
1781
|
|
|
1685
1782
|
if (this.options.setupExitSignals) {
|
|
1686
1783
|
const signals = ["SIGINT", "SIGTERM"];
|
|
@@ -1718,24 +1815,30 @@ class Server {
|
|
|
1718
1815
|
|
|
1719
1816
|
// Proxy WebSocket without the initial http request
|
|
1720
1817
|
// https://github.com/chimurai/http-proxy-middleware#external-websocket-upgrade
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1818
|
+
const webSocketProxies =
|
|
1819
|
+
/** @type {RequestHandler[]} */
|
|
1820
|
+
(this.webSocketProxies);
|
|
1821
|
+
|
|
1822
|
+
for (const webSocketProxy of webSocketProxies) {
|
|
1823
|
+
/** @type {S} */
|
|
1724
1824
|
(this.server).on(
|
|
1725
1825
|
"upgrade",
|
|
1726
1826
|
/** @type {RequestHandler & { upgrade: NonNullable<RequestHandler["upgrade"]> }} */
|
|
1727
1827
|
(webSocketProxy).upgrade,
|
|
1728
1828
|
);
|
|
1729
|
-
}
|
|
1829
|
+
}
|
|
1730
1830
|
}
|
|
1731
1831
|
|
|
1732
1832
|
/**
|
|
1733
1833
|
* @private
|
|
1734
|
-
* @returns {void}
|
|
1834
|
+
* @returns {Promise<void>}
|
|
1735
1835
|
*/
|
|
1736
|
-
setupApp() {
|
|
1737
|
-
/** @type {
|
|
1738
|
-
this.app =
|
|
1836
|
+
async setupApp() {
|
|
1837
|
+
/** @type {A | undefined}*/
|
|
1838
|
+
this.app =
|
|
1839
|
+
typeof this.options.app === "function"
|
|
1840
|
+
? await this.options.app()
|
|
1841
|
+
: getExpress()();
|
|
1739
1842
|
}
|
|
1740
1843
|
|
|
1741
1844
|
/**
|
|
@@ -1789,204 +1892,297 @@ class Server {
|
|
|
1789
1892
|
* @private
|
|
1790
1893
|
* @returns {void}
|
|
1791
1894
|
*/
|
|
1792
|
-
|
|
1793
|
-
/** @type {
|
|
1794
|
-
(this.app).all(
|
|
1795
|
-
"*",
|
|
1796
|
-
/**
|
|
1797
|
-
* @param {Request} req
|
|
1798
|
-
* @param {Response} res
|
|
1799
|
-
* @param {NextFunction} next
|
|
1800
|
-
* @returns {void}
|
|
1801
|
-
*/
|
|
1802
|
-
(req, res, next) => {
|
|
1803
|
-
if (
|
|
1804
|
-
this.checkHeader(
|
|
1805
|
-
/** @type {{ [key: string]: string | undefined }} */
|
|
1806
|
-
(req.headers),
|
|
1807
|
-
"host",
|
|
1808
|
-
)
|
|
1809
|
-
) {
|
|
1810
|
-
return next();
|
|
1811
|
-
}
|
|
1895
|
+
setupWatchStaticFiles() {
|
|
1896
|
+
const watchFiles = /** @type {NormalizedStatic[]} */ (this.options.static);
|
|
1812
1897
|
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1898
|
+
if (watchFiles.length > 0) {
|
|
1899
|
+
for (const item of watchFiles) {
|
|
1900
|
+
if (item.watch) {
|
|
1901
|
+
this.watchFiles(item.directory, item.watch);
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1816
1905
|
}
|
|
1817
1906
|
|
|
1818
1907
|
/**
|
|
1819
1908
|
* @private
|
|
1820
1909
|
* @returns {void}
|
|
1821
1910
|
*/
|
|
1822
|
-
|
|
1823
|
-
const
|
|
1911
|
+
setupWatchFiles() {
|
|
1912
|
+
const watchFiles = /** @type {WatchFiles[]} */ (this.options.watchFiles);
|
|
1824
1913
|
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1914
|
+
if (watchFiles.length > 0) {
|
|
1915
|
+
for (const item of watchFiles) {
|
|
1916
|
+
this.watchFiles(item.paths, item.options);
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1830
1919
|
}
|
|
1831
1920
|
|
|
1832
1921
|
/**
|
|
1833
1922
|
* @private
|
|
1834
1923
|
* @returns {void}
|
|
1835
1924
|
*/
|
|
1836
|
-
|
|
1837
|
-
|
|
1925
|
+
setupMiddlewares() {
|
|
1926
|
+
/**
|
|
1927
|
+
* @type {Array<Middleware>}
|
|
1928
|
+
*/
|
|
1929
|
+
let middlewares = [];
|
|
1838
1930
|
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1931
|
+
// Register setup host header check for security
|
|
1932
|
+
middlewares.push({
|
|
1933
|
+
name: "host-header-check",
|
|
1934
|
+
/**
|
|
1935
|
+
* @param {Request} req
|
|
1936
|
+
* @param {Response} res
|
|
1937
|
+
* @param {NextFunction} next
|
|
1938
|
+
* @returns {void}
|
|
1939
|
+
*/
|
|
1940
|
+
middleware: (req, res, next) => {
|
|
1941
|
+
const headers =
|
|
1942
|
+
/** @type {{ [key: string]: string | undefined }} */
|
|
1943
|
+
(req.headers);
|
|
1944
|
+
const headerName = headers[":authority"] ? ":authority" : "host";
|
|
1842
1945
|
|
|
1843
|
-
|
|
1946
|
+
if (this.checkHeader(headers, headerName)) {
|
|
1947
|
+
next();
|
|
1948
|
+
return;
|
|
1949
|
+
}
|
|
1844
1950
|
|
|
1845
|
-
|
|
1951
|
+
res.statusCode = 403;
|
|
1952
|
+
res.end("Invalid Host header");
|
|
1953
|
+
},
|
|
1846
1954
|
});
|
|
1847
1955
|
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1956
|
+
const isHTTP2 =
|
|
1957
|
+
/** @type {ServerConfiguration<A, S>} */ (this.options.server).type ===
|
|
1958
|
+
"http2";
|
|
1851
1959
|
|
|
1852
|
-
|
|
1853
|
-
|
|
1960
|
+
if (isHTTP2) {
|
|
1961
|
+
// TODO patch for https://github.com/pillarjs/finalhandler/pull/45, need remove then will be resolved
|
|
1962
|
+
middlewares.push({
|
|
1963
|
+
name: "http2-status-message-patch",
|
|
1964
|
+
middleware:
|
|
1965
|
+
/** @type {NextHandleFunction} */
|
|
1966
|
+
(_req, res, next) => {
|
|
1967
|
+
Object.defineProperty(res, "statusMessage", {
|
|
1968
|
+
get() {
|
|
1969
|
+
return "";
|
|
1970
|
+
},
|
|
1971
|
+
set() {},
|
|
1972
|
+
});
|
|
1854
1973
|
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1974
|
+
next();
|
|
1975
|
+
},
|
|
1976
|
+
});
|
|
1977
|
+
}
|
|
1858
1978
|
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
}
|
|
1979
|
+
// compress is placed last and uses unshift so that it will be the first middleware used
|
|
1980
|
+
if (this.options.compress && !isHTTP2) {
|
|
1981
|
+
const compression = require("compression");
|
|
1982
|
+
|
|
1983
|
+
middlewares.push({ name: "compression", middleware: compression() });
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
if (typeof this.options.headers !== "undefined") {
|
|
1987
|
+
middlewares.push({
|
|
1988
|
+
name: "set-headers",
|
|
1989
|
+
middleware: this.setHeaders.bind(this),
|
|
1990
|
+
});
|
|
1991
|
+
}
|
|
1864
1992
|
|
|
1865
|
-
|
|
1993
|
+
middlewares.push({
|
|
1994
|
+
name: "webpack-dev-middleware",
|
|
1995
|
+
middleware: /** @type {MiddlewareHandler} */ (this.middleware),
|
|
1866
1996
|
});
|
|
1867
1997
|
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1998
|
+
// Should be after `webpack-dev-middleware`, otherwise other middlewares might rewrite response
|
|
1999
|
+
middlewares.push({
|
|
2000
|
+
name: "webpack-dev-server-sockjs-bundle",
|
|
2001
|
+
path: "/__webpack_dev_server__/sockjs.bundle.js",
|
|
2002
|
+
/**
|
|
2003
|
+
* @param {Request} req
|
|
2004
|
+
* @param {Response} res
|
|
2005
|
+
* @param {NextFunction} next
|
|
2006
|
+
* @returns {void}
|
|
2007
|
+
*/
|
|
2008
|
+
middleware: (req, res, next) => {
|
|
2009
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
2010
|
+
next();
|
|
2011
|
+
return;
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
const clientPath = path.join(
|
|
2015
|
+
__dirname,
|
|
2016
|
+
"..",
|
|
2017
|
+
"client/modules/sockjs-client/index.js",
|
|
2018
|
+
);
|
|
2019
|
+
|
|
2020
|
+
// Express send Etag and other headers by default, so let's keep them for compatibility reasons
|
|
2021
|
+
if (typeof res.sendFile === "function") {
|
|
2022
|
+
res.sendFile(clientPath);
|
|
2023
|
+
return;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
let stats;
|
|
2027
|
+
|
|
2028
|
+
try {
|
|
2029
|
+
// TODO implement `inputFileSystem.createReadStream` in webpack
|
|
2030
|
+
stats = fs.statSync(clientPath);
|
|
2031
|
+
} catch (err) {
|
|
2032
|
+
next();
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
res.setHeader("Content-Type", "application/javascript; charset=UTF-8");
|
|
2037
|
+
res.setHeader("Content-Length", stats.size);
|
|
2038
|
+
|
|
1874
2039
|
if (req.method === "HEAD") {
|
|
1875
2040
|
res.end();
|
|
1876
2041
|
return;
|
|
1877
2042
|
}
|
|
1878
|
-
res.write(
|
|
1879
|
-
'<!DOCTYPE html><html><head><meta charset="utf-8"/></head><body>',
|
|
1880
|
-
);
|
|
1881
2043
|
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
: [/** @type {Stats} */ (stats).toJson()];
|
|
2044
|
+
fs.createReadStream(clientPath).pipe(res);
|
|
2045
|
+
},
|
|
2046
|
+
});
|
|
1886
2047
|
|
|
1887
|
-
|
|
2048
|
+
middlewares.push({
|
|
2049
|
+
name: "webpack-dev-server-invalidate",
|
|
2050
|
+
path: "/webpack-dev-server/invalidate",
|
|
2051
|
+
/**
|
|
2052
|
+
* @param {Request} req
|
|
2053
|
+
* @param {Response} res
|
|
2054
|
+
* @param {NextFunction} next
|
|
2055
|
+
* @returns {void}
|
|
2056
|
+
*/
|
|
2057
|
+
middleware: (req, res, next) => {
|
|
2058
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
2059
|
+
next();
|
|
2060
|
+
return;
|
|
2061
|
+
}
|
|
1888
2062
|
|
|
1889
|
-
|
|
1890
|
-
* @type {StatsCompilation[]}
|
|
1891
|
-
*/
|
|
1892
|
-
(statsForPrint).forEach((item, index) => {
|
|
1893
|
-
res.write("<div>");
|
|
2063
|
+
this.invalidate();
|
|
1894
2064
|
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
? item.name
|
|
1899
|
-
: /** @type {MultiStats} */ (stats).stats
|
|
1900
|
-
? `unnamed[${index}]`
|
|
1901
|
-
: "unnamed";
|
|
2065
|
+
res.end();
|
|
2066
|
+
},
|
|
2067
|
+
});
|
|
1902
2068
|
|
|
1903
|
-
|
|
1904
|
-
|
|
2069
|
+
middlewares.push({
|
|
2070
|
+
name: "webpack-dev-server-open-editor",
|
|
2071
|
+
path: "/webpack-dev-server/open-editor",
|
|
2072
|
+
/**
|
|
2073
|
+
* @param {Request} req
|
|
2074
|
+
* @param {Response} res
|
|
2075
|
+
* @param {NextFunction} next
|
|
2076
|
+
* @returns {void}
|
|
2077
|
+
*/
|
|
2078
|
+
middleware: (req, res, next) => {
|
|
2079
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
2080
|
+
next();
|
|
2081
|
+
return;
|
|
2082
|
+
}
|
|
1905
2083
|
|
|
1906
|
-
|
|
2084
|
+
if (!req.url) {
|
|
2085
|
+
next();
|
|
2086
|
+
return;
|
|
2087
|
+
}
|
|
1907
2088
|
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
const assetName = asset.name;
|
|
1912
|
-
const assetURL = `${publicPath}${assetName}`;
|
|
2089
|
+
const resolveUrl = new URL(req.url, `http://${req.headers.host}`);
|
|
2090
|
+
const params = new URLSearchParams(resolveUrl.search);
|
|
2091
|
+
const fileName = params.get("fileName");
|
|
1913
2092
|
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
</li>`,
|
|
1918
|
-
);
|
|
1919
|
-
}
|
|
2093
|
+
if (typeof fileName === "string") {
|
|
2094
|
+
// @ts-ignore
|
|
2095
|
+
const launchEditor = require("launch-editor");
|
|
1920
2096
|
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
});
|
|
2097
|
+
launchEditor(fileName);
|
|
2098
|
+
}
|
|
1924
2099
|
|
|
1925
|
-
res.end(
|
|
1926
|
-
}
|
|
2100
|
+
res.end();
|
|
2101
|
+
},
|
|
1927
2102
|
});
|
|
1928
|
-
}
|
|
1929
2103
|
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
2104
|
+
middlewares.push({
|
|
2105
|
+
name: "webpack-dev-server-assets",
|
|
2106
|
+
path: "/webpack-dev-server",
|
|
2107
|
+
/**
|
|
2108
|
+
* @param {Request} req
|
|
2109
|
+
* @param {Response} res
|
|
2110
|
+
* @param {NextFunction} next
|
|
2111
|
+
* @returns {void}
|
|
2112
|
+
*/
|
|
2113
|
+
middleware: (req, res, next) => {
|
|
2114
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
2115
|
+
next();
|
|
2116
|
+
return;
|
|
1940
2117
|
}
|
|
1941
|
-
});
|
|
1942
|
-
}
|
|
1943
|
-
}
|
|
1944
2118
|
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
setupWatchFiles() {
|
|
1950
|
-
const { watchFiles } = this.options;
|
|
2119
|
+
if (!this.middleware) {
|
|
2120
|
+
next();
|
|
2121
|
+
return;
|
|
2122
|
+
}
|
|
1951
2123
|
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
(watchFiles).forEach((item) => {
|
|
1955
|
-
this.watchFiles(item.paths, item.options);
|
|
1956
|
-
});
|
|
1957
|
-
}
|
|
1958
|
-
}
|
|
2124
|
+
this.middleware.waitUntilValid((stats) => {
|
|
2125
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
1959
2126
|
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
/**
|
|
1966
|
-
* @type {Array<Middleware>}
|
|
1967
|
-
*/
|
|
1968
|
-
let middlewares = [];
|
|
2127
|
+
// HEAD requests should not return body content
|
|
2128
|
+
if (req.method === "HEAD") {
|
|
2129
|
+
res.end();
|
|
2130
|
+
return;
|
|
2131
|
+
}
|
|
1969
2132
|
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
2133
|
+
res.write(
|
|
2134
|
+
'<!DOCTYPE html><html><head><meta charset="utf-8"/></head><body>',
|
|
2135
|
+
);
|
|
1973
2136
|
|
|
1974
|
-
|
|
1975
|
-
|
|
2137
|
+
/**
|
|
2138
|
+
* @type {StatsCompilation[]}
|
|
2139
|
+
*/
|
|
2140
|
+
const statsForPrint =
|
|
2141
|
+
typeof (/** @type {MultiStats} */ (stats).stats) !== "undefined"
|
|
2142
|
+
? /** @type {NonNullable<StatsCompilation["children"]>} */
|
|
2143
|
+
(/** @type {MultiStats} */ (stats).toJson().children)
|
|
2144
|
+
: [/** @type {Stats} */ (stats).toJson()];
|
|
2145
|
+
|
|
2146
|
+
res.write(`<h1>Assets Report:</h1>`);
|
|
2147
|
+
|
|
2148
|
+
for (const [index, item] of statsForPrint.entries()) {
|
|
2149
|
+
res.write("<div>");
|
|
2150
|
+
|
|
2151
|
+
const name =
|
|
2152
|
+
// eslint-disable-next-line no-nested-ternary
|
|
2153
|
+
typeof item.name !== "undefined"
|
|
2154
|
+
? item.name
|
|
2155
|
+
: /** @type {MultiStats} */ (stats).stats
|
|
2156
|
+
? `unnamed[${index}]`
|
|
2157
|
+
: "unnamed";
|
|
2158
|
+
|
|
2159
|
+
res.write(`<h2>Compilation: ${name}</h2>`);
|
|
2160
|
+
res.write("<ul>");
|
|
2161
|
+
|
|
2162
|
+
const publicPath =
|
|
2163
|
+
item.publicPath === "auto" ? "" : item.publicPath;
|
|
2164
|
+
const assets =
|
|
2165
|
+
/** @type {NonNullable<StatsCompilation["assets"]>} */
|
|
2166
|
+
(item.assets);
|
|
2167
|
+
|
|
2168
|
+
for (const asset of assets) {
|
|
2169
|
+
const assetName = asset.name;
|
|
2170
|
+
const assetURL = `${publicPath}${assetName}`;
|
|
2171
|
+
|
|
2172
|
+
res.write(
|
|
2173
|
+
`<li>
|
|
2174
|
+
<strong><a href="${assetURL}" target="_blank">${assetName}</a></strong>
|
|
2175
|
+
</li>`,
|
|
2176
|
+
);
|
|
2177
|
+
}
|
|
1976
2178
|
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
path: "*",
|
|
1981
|
-
middleware: this.setHeaders.bind(this),
|
|
1982
|
-
});
|
|
1983
|
-
}
|
|
2179
|
+
res.write("</ul>");
|
|
2180
|
+
res.write("</div>");
|
|
2181
|
+
}
|
|
1984
2182
|
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
/** @type {import("webpack-dev-middleware").Middleware<Request, Response>}*/
|
|
1989
|
-
(this.middleware),
|
|
2183
|
+
res.end("</body></html>");
|
|
2184
|
+
});
|
|
2185
|
+
},
|
|
1990
2186
|
});
|
|
1991
2187
|
|
|
1992
2188
|
if (this.options.proxy) {
|
|
@@ -2106,8 +2302,8 @@ class Server {
|
|
|
2106
2302
|
|
|
2107
2303
|
if (typeof bypassUrl === "boolean") {
|
|
2108
2304
|
// skip the proxy
|
|
2109
|
-
|
|
2110
|
-
req.url =
|
|
2305
|
+
res.statusCode = 404;
|
|
2306
|
+
req.url = "";
|
|
2111
2307
|
next();
|
|
2112
2308
|
} else if (typeof bypassUrl === "string") {
|
|
2113
2309
|
// byPass to that url
|
|
@@ -2124,6 +2320,7 @@ class Server {
|
|
|
2124
2320
|
name: "http-proxy-middleware",
|
|
2125
2321
|
middleware: handler,
|
|
2126
2322
|
});
|
|
2323
|
+
|
|
2127
2324
|
// Also forward error requests to the proxy so it can handle them.
|
|
2128
2325
|
middlewares.push({
|
|
2129
2326
|
name: "http-proxy-middleware-error-handler",
|
|
@@ -2141,16 +2338,17 @@ class Server {
|
|
|
2141
2338
|
|
|
2142
2339
|
middlewares.push({
|
|
2143
2340
|
name: "webpack-dev-middleware",
|
|
2144
|
-
middleware:
|
|
2145
|
-
/** @type {import("webpack-dev-middleware").Middleware<Request, Response>}*/
|
|
2146
|
-
(this.middleware),
|
|
2341
|
+
middleware: /** @type {MiddlewareHandler} */ (this.middleware),
|
|
2147
2342
|
});
|
|
2148
2343
|
}
|
|
2149
2344
|
|
|
2150
|
-
|
|
2345
|
+
const staticOptions =
|
|
2151
2346
|
/** @type {NormalizedStatic[]} */
|
|
2152
|
-
(this.options.static)
|
|
2153
|
-
|
|
2347
|
+
(this.options.static);
|
|
2348
|
+
|
|
2349
|
+
if (staticOptions.length > 0) {
|
|
2350
|
+
for (const staticOption of staticOptions) {
|
|
2351
|
+
for (const publicPath of staticOption.publicPath) {
|
|
2154
2352
|
middlewares.push({
|
|
2155
2353
|
name: "express-static",
|
|
2156
2354
|
path: publicPath,
|
|
@@ -2159,8 +2357,8 @@ class Server {
|
|
|
2159
2357
|
staticOption.staticOptions,
|
|
2160
2358
|
),
|
|
2161
2359
|
});
|
|
2162
|
-
}
|
|
2163
|
-
}
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2164
2362
|
}
|
|
2165
2363
|
|
|
2166
2364
|
if (this.options.historyApiFallback) {
|
|
@@ -2197,15 +2395,12 @@ class Server {
|
|
|
2197
2395
|
// it is able to handle '/index.html' request after redirect
|
|
2198
2396
|
middlewares.push({
|
|
2199
2397
|
name: "webpack-dev-middleware",
|
|
2200
|
-
middleware:
|
|
2201
|
-
/** @type {import("webpack-dev-middleware").Middleware<Request, Response>}*/
|
|
2202
|
-
(this.middleware),
|
|
2398
|
+
middleware: /** @type {MiddlewareHandler} */ (this.middleware),
|
|
2203
2399
|
});
|
|
2204
2400
|
|
|
2205
|
-
if (
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
staticOption.publicPath.forEach((publicPath) => {
|
|
2401
|
+
if (staticOptions.length > 0) {
|
|
2402
|
+
for (const staticOption of staticOptions) {
|
|
2403
|
+
for (const publicPath of staticOption.publicPath) {
|
|
2209
2404
|
middlewares.push({
|
|
2210
2405
|
name: "express-static",
|
|
2211
2406
|
path: publicPath,
|
|
@@ -2214,17 +2409,16 @@ class Server {
|
|
|
2214
2409
|
staticOption.staticOptions,
|
|
2215
2410
|
),
|
|
2216
2411
|
});
|
|
2217
|
-
}
|
|
2218
|
-
}
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2219
2414
|
}
|
|
2220
2415
|
}
|
|
2221
2416
|
|
|
2222
|
-
if (
|
|
2417
|
+
if (staticOptions.length > 0) {
|
|
2223
2418
|
const serveIndex = require("serve-index");
|
|
2224
2419
|
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
staticOption.publicPath.forEach((publicPath) => {
|
|
2420
|
+
for (const staticOption of staticOptions) {
|
|
2421
|
+
for (const publicPath of staticOption.publicPath) {
|
|
2228
2422
|
if (staticOption.serveIndex) {
|
|
2229
2423
|
middlewares.push({
|
|
2230
2424
|
name: "serve-index",
|
|
@@ -2249,15 +2443,14 @@ class Server {
|
|
|
2249
2443
|
},
|
|
2250
2444
|
});
|
|
2251
2445
|
}
|
|
2252
|
-
}
|
|
2253
|
-
}
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2254
2448
|
}
|
|
2255
2449
|
|
|
2256
2450
|
// Register this middleware always as the last one so that it's only used as a
|
|
2257
2451
|
// fallback when no other middleware responses.
|
|
2258
2452
|
middlewares.push({
|
|
2259
2453
|
name: "options-middleware",
|
|
2260
|
-
path: "*",
|
|
2261
2454
|
/**
|
|
2262
2455
|
* @param {Request} req
|
|
2263
2456
|
* @param {Response} res
|
|
@@ -2279,37 +2472,93 @@ class Server {
|
|
|
2279
2472
|
middlewares = this.options.setupMiddlewares(middlewares, this);
|
|
2280
2473
|
}
|
|
2281
2474
|
|
|
2282
|
-
|
|
2475
|
+
// Lazy init webpack dev middleware
|
|
2476
|
+
const lazyInitDevMiddleware = () => {
|
|
2477
|
+
if (!this.middleware) {
|
|
2478
|
+
const webpackDevMiddleware = require("webpack-dev-middleware");
|
|
2479
|
+
|
|
2480
|
+
// middleware for serving webpack bundle
|
|
2481
|
+
/** @type {import("webpack-dev-middleware").API<Request, Response>} */
|
|
2482
|
+
this.middleware = webpackDevMiddleware(
|
|
2483
|
+
this.compiler,
|
|
2484
|
+
this.options.devMiddleware,
|
|
2485
|
+
);
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
return this.middleware;
|
|
2489
|
+
};
|
|
2490
|
+
|
|
2491
|
+
for (const i of middlewares) {
|
|
2492
|
+
if (i.name === "webpack-dev-middleware") {
|
|
2493
|
+
const item = /** @type {MiddlewareObject} */ (i);
|
|
2494
|
+
|
|
2495
|
+
if (typeof item.middleware === "undefined") {
|
|
2496
|
+
item.middleware = lazyInitDevMiddleware();
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
for (const middleware of middlewares) {
|
|
2283
2502
|
if (typeof middleware === "function") {
|
|
2284
|
-
/** @type {
|
|
2285
|
-
(this.app).use(
|
|
2503
|
+
/** @type {A} */
|
|
2504
|
+
(this.app).use(
|
|
2505
|
+
/** @type {NextHandleFunction | HandleFunction} */
|
|
2506
|
+
(middleware),
|
|
2507
|
+
);
|
|
2286
2508
|
} else if (typeof middleware.path !== "undefined") {
|
|
2287
|
-
/** @type {
|
|
2288
|
-
(this.app).use(
|
|
2509
|
+
/** @type {A} */
|
|
2510
|
+
(this.app).use(
|
|
2511
|
+
middleware.path,
|
|
2512
|
+
/** @type {SimpleHandleFunction | NextHandleFunction} */
|
|
2513
|
+
(middleware.middleware),
|
|
2514
|
+
);
|
|
2289
2515
|
} else {
|
|
2290
|
-
/** @type {
|
|
2291
|
-
(this.app).use(
|
|
2516
|
+
/** @type {A} */
|
|
2517
|
+
(this.app).use(
|
|
2518
|
+
/** @type {NextHandleFunction | HandleFunction} */
|
|
2519
|
+
(middleware.middleware),
|
|
2520
|
+
);
|
|
2292
2521
|
}
|
|
2293
|
-
}
|
|
2522
|
+
}
|
|
2294
2523
|
}
|
|
2295
2524
|
|
|
2296
2525
|
/**
|
|
2297
2526
|
* @private
|
|
2298
|
-
* @returns {void}
|
|
2527
|
+
* @returns {Promise<void>}
|
|
2299
2528
|
*/
|
|
2300
|
-
createServer() {
|
|
2301
|
-
const { type, options } =
|
|
2302
|
-
|
|
2303
|
-
|
|
2529
|
+
async createServer() {
|
|
2530
|
+
const { type, options } =
|
|
2531
|
+
/** @type {ServerConfiguration<A, S>} */
|
|
2532
|
+
(this.options.server);
|
|
2533
|
+
|
|
2534
|
+
if (typeof type === "function") {
|
|
2535
|
+
/** @type {S | undefined}*/
|
|
2536
|
+
this.server = await type(
|
|
2537
|
+
/** @type {ServerOptions} */
|
|
2538
|
+
(options),
|
|
2539
|
+
/** @type {A} */
|
|
2540
|
+
(this.app),
|
|
2541
|
+
);
|
|
2542
|
+
} else {
|
|
2543
|
+
// eslint-disable-next-line import/no-dynamic-require
|
|
2544
|
+
const serverType = require(/** @type {string} */ (type));
|
|
2304
2545
|
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2546
|
+
/** @type {S | undefined}*/
|
|
2547
|
+
this.server =
|
|
2548
|
+
type === "http2"
|
|
2549
|
+
? serverType.createSecureServer(
|
|
2550
|
+
{ ...options, allowHTTP1: true },
|
|
2551
|
+
this.app,
|
|
2552
|
+
)
|
|
2553
|
+
: serverType.createServer(options, this.app);
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
this.isTlsServer =
|
|
2557
|
+
typeof (
|
|
2558
|
+
/** @type {import("tls").Server} */ (this.server).setSecureContext
|
|
2559
|
+
) !== "undefined";
|
|
2311
2560
|
|
|
2312
|
-
/** @type {
|
|
2561
|
+
/** @type {S} */
|
|
2313
2562
|
(this.server).on(
|
|
2314
2563
|
"connection",
|
|
2315
2564
|
/**
|
|
@@ -2326,7 +2575,7 @@ class Server {
|
|
|
2326
2575
|
},
|
|
2327
2576
|
);
|
|
2328
2577
|
|
|
2329
|
-
/** @type {
|
|
2578
|
+
/** @type {S} */
|
|
2330
2579
|
(this.server).on(
|
|
2331
2580
|
"error",
|
|
2332
2581
|
/**
|
|
@@ -2344,9 +2593,8 @@ class Server {
|
|
|
2344
2593
|
*/
|
|
2345
2594
|
createWebSocketServer() {
|
|
2346
2595
|
/** @type {WebSocketServerImplementation | undefined | null} */
|
|
2347
|
-
this.webSocketServer = new
|
|
2348
|
-
|
|
2349
|
-
);
|
|
2596
|
+
this.webSocketServer = new (this.getServerTransport())(this);
|
|
2597
|
+
|
|
2350
2598
|
/** @type {WebSocketServerImplementation} */
|
|
2351
2599
|
(this.webSocketServer).implementation.on(
|
|
2352
2600
|
"connection",
|
|
@@ -2513,22 +2761,19 @@ class Server {
|
|
|
2513
2761
|
*/
|
|
2514
2762
|
runBonjour() {
|
|
2515
2763
|
const { Bonjour } = require("bonjour-service");
|
|
2764
|
+
const type = this.isTlsServer ? "https" : "http";
|
|
2765
|
+
|
|
2516
2766
|
/**
|
|
2517
2767
|
* @private
|
|
2518
2768
|
* @type {Bonjour | undefined}
|
|
2519
2769
|
*/
|
|
2520
2770
|
this.bonjour = new Bonjour();
|
|
2521
2771
|
this.bonjour.publish({
|
|
2522
|
-
// @ts-expect-error
|
|
2523
2772
|
name: `Webpack Dev Server ${os.hostname()}:${this.options.port}`,
|
|
2524
|
-
// @ts-expect-error
|
|
2525
2773
|
port: /** @type {number} */ (this.options.port),
|
|
2526
|
-
|
|
2527
|
-
type:
|
|
2528
|
-
/** @type {ServerConfiguration} */
|
|
2529
|
-
(this.options.server).type === "http" ? "http" : "https",
|
|
2774
|
+
type,
|
|
2530
2775
|
subtypes: ["webpack"],
|
|
2531
|
-
.../** @type {BonjourOptions} */ (this.options.bonjour),
|
|
2776
|
+
.../** @type {Partial<BonjourOptions>} */ (this.options.bonjour),
|
|
2532
2777
|
});
|
|
2533
2778
|
}
|
|
2534
2779
|
|
|
@@ -2608,23 +2853,15 @@ class Server {
|
|
|
2608
2853
|
};
|
|
2609
2854
|
const useColor = getColorsOption(this.getCompilerOptions());
|
|
2610
2855
|
|
|
2856
|
+
const server = /** @type {S} */ (this.server);
|
|
2857
|
+
|
|
2611
2858
|
if (this.options.ipc) {
|
|
2612
|
-
this.logger.info(
|
|
2613
|
-
`Project is running at: "${
|
|
2614
|
-
/** @type {import("http").Server} */
|
|
2615
|
-
(this.server).address()
|
|
2616
|
-
}"`,
|
|
2617
|
-
);
|
|
2859
|
+
this.logger.info(`Project is running at: "${server.address()}"`);
|
|
2618
2860
|
} else {
|
|
2619
|
-
const protocol =
|
|
2620
|
-
/** @type {ServerConfiguration} */
|
|
2621
|
-
(this.options.server).type === "http" ? "http" : "https";
|
|
2861
|
+
const protocol = this.isTlsServer ? "https" : "http";
|
|
2622
2862
|
const { address, port } =
|
|
2623
2863
|
/** @type {import("net").AddressInfo} */
|
|
2624
|
-
(
|
|
2625
|
-
/** @type {import("http").Server} */
|
|
2626
|
-
(this.server).address()
|
|
2627
|
-
);
|
|
2864
|
+
(server.address());
|
|
2628
2865
|
/**
|
|
2629
2866
|
* @param {string} newHostname
|
|
2630
2867
|
* @returns {string}
|
|
@@ -2632,7 +2869,7 @@ class Server {
|
|
|
2632
2869
|
const prettyPrintURL = (newHostname) =>
|
|
2633
2870
|
url.format({ protocol, hostname: newHostname, port, pathname: "/" });
|
|
2634
2871
|
|
|
2635
|
-
let
|
|
2872
|
+
let host;
|
|
2636
2873
|
let localhost;
|
|
2637
2874
|
let loopbackIPv4;
|
|
2638
2875
|
let loopbackIPv6;
|
|
@@ -2652,7 +2889,7 @@ class Server {
|
|
|
2652
2889
|
}
|
|
2653
2890
|
|
|
2654
2891
|
if (!isIP) {
|
|
2655
|
-
|
|
2892
|
+
host = prettyPrintURL(this.options.host);
|
|
2656
2893
|
}
|
|
2657
2894
|
}
|
|
2658
2895
|
}
|
|
@@ -2661,14 +2898,15 @@ class Server {
|
|
|
2661
2898
|
|
|
2662
2899
|
if (parsedIP.range() === "unspecified") {
|
|
2663
2900
|
localhost = prettyPrintURL("localhost");
|
|
2901
|
+
loopbackIPv6 = prettyPrintURL("::1");
|
|
2664
2902
|
|
|
2665
|
-
const networkIPv4 =
|
|
2903
|
+
const networkIPv4 = Server.findIp("v4", false);
|
|
2666
2904
|
|
|
2667
2905
|
if (networkIPv4) {
|
|
2668
2906
|
networkUrlIPv4 = prettyPrintURL(networkIPv4);
|
|
2669
2907
|
}
|
|
2670
2908
|
|
|
2671
|
-
const networkIPv6 =
|
|
2909
|
+
const networkIPv6 = Server.findIp("v6", false);
|
|
2672
2910
|
|
|
2673
2911
|
if (networkIPv6) {
|
|
2674
2912
|
networkUrlIPv6 = prettyPrintURL(networkIPv6);
|
|
@@ -2697,8 +2935,8 @@ class Server {
|
|
|
2697
2935
|
|
|
2698
2936
|
this.logger.info("Project is running at:");
|
|
2699
2937
|
|
|
2700
|
-
if (
|
|
2701
|
-
this.logger.info(`Server: ${colors.info(useColor,
|
|
2938
|
+
if (host) {
|
|
2939
|
+
this.logger.info(`Server: ${colors.info(useColor, host)}`);
|
|
2702
2940
|
}
|
|
2703
2941
|
|
|
2704
2942
|
if (localhost || loopbackIPv4 || loopbackIPv6) {
|
|
@@ -2770,11 +3008,7 @@ class Server {
|
|
|
2770
3008
|
if (this.options.bonjour) {
|
|
2771
3009
|
const bonjourProtocol =
|
|
2772
3010
|
/** @type {BonjourOptions} */
|
|
2773
|
-
(this.options.bonjour).type ||
|
|
2774
|
-
/** @type {ServerConfiguration} */
|
|
2775
|
-
(this.options.server).type === "http"
|
|
2776
|
-
? "http"
|
|
2777
|
-
: "https";
|
|
3011
|
+
(this.options.bonjour).type || this.isTlsServer ? "https" : "http";
|
|
2778
3012
|
|
|
2779
3013
|
this.logger.info(
|
|
2780
3014
|
`Broadcasting "${bonjourProtocol}" with subtype of "webpack" via ZeroConf DNS (Bonjour)`,
|
|
@@ -2796,8 +3030,8 @@ class Server {
|
|
|
2796
3030
|
headers = headers(
|
|
2797
3031
|
req,
|
|
2798
3032
|
res,
|
|
2799
|
-
|
|
2800
|
-
|
|
3033
|
+
// eslint-disable-next-line no-undefined
|
|
3034
|
+
this.middleware ? this.middleware.context : undefined,
|
|
2801
3035
|
);
|
|
2802
3036
|
}
|
|
2803
3037
|
|
|
@@ -2806,6 +3040,8 @@ class Server {
|
|
|
2806
3040
|
*/
|
|
2807
3041
|
const allHeaders = [];
|
|
2808
3042
|
|
|
3043
|
+
allHeaders.push({ key: "X_TEST", value: "TEST" });
|
|
3044
|
+
|
|
2809
3045
|
if (!Array.isArray(headers)) {
|
|
2810
3046
|
// eslint-disable-next-line guard-for-in
|
|
2811
3047
|
for (const name in headers) {
|
|
@@ -2816,14 +3052,9 @@ class Server {
|
|
|
2816
3052
|
headers = allHeaders;
|
|
2817
3053
|
}
|
|
2818
3054
|
|
|
2819
|
-
headers
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
*/
|
|
2823
|
-
(header) => {
|
|
2824
|
-
res.setHeader(header.key, header.value);
|
|
2825
|
-
},
|
|
2826
|
-
);
|
|
3055
|
+
for (const { key, value } of headers) {
|
|
3056
|
+
res.setHeader(key, value);
|
|
3057
|
+
}
|
|
2827
3058
|
}
|
|
2828
3059
|
|
|
2829
3060
|
next();
|
|
@@ -3097,7 +3328,7 @@ class Server {
|
|
|
3097
3328
|
|
|
3098
3329
|
await /** @type {Promise<void>} */ (
|
|
3099
3330
|
new Promise((resolve) => {
|
|
3100
|
-
/** @type {
|
|
3331
|
+
/** @type {S} */
|
|
3101
3332
|
(this.server).listen(listenOptions, () => {
|
|
3102
3333
|
resolve();
|
|
3103
3334
|
});
|
|
@@ -3183,10 +3414,10 @@ class Server {
|
|
|
3183
3414
|
if (this.server) {
|
|
3184
3415
|
await /** @type {Promise<void>} */ (
|
|
3185
3416
|
new Promise((resolve) => {
|
|
3186
|
-
/** @type {
|
|
3417
|
+
/** @type {S} */
|
|
3187
3418
|
(this.server).close(() => {
|
|
3188
|
-
|
|
3189
|
-
|
|
3419
|
+
// eslint-disable-next-line no-undefined
|
|
3420
|
+
this.server = undefined;
|
|
3190
3421
|
resolve();
|
|
3191
3422
|
});
|
|
3192
3423
|
|
|
@@ -3205,7 +3436,6 @@ class Server {
|
|
|
3205
3436
|
(this.middleware).close((error) => {
|
|
3206
3437
|
if (error) {
|
|
3207
3438
|
reject(error);
|
|
3208
|
-
|
|
3209
3439
|
return;
|
|
3210
3440
|
}
|
|
3211
3441
|
|
|
@@ -3214,7 +3444,8 @@ class Server {
|
|
|
3214
3444
|
})
|
|
3215
3445
|
);
|
|
3216
3446
|
|
|
3217
|
-
|
|
3447
|
+
// eslint-disable-next-line no-undefined
|
|
3448
|
+
this.middleware = undefined;
|
|
3218
3449
|
}
|
|
3219
3450
|
}
|
|
3220
3451
|
|