@rspack/dev-server 1.2.1 → 2.0.0-beta.1
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 +16 -17
- package/client/index.js +6 -6
- package/client/overlay.js +4 -4
- package/client/utils/ansiHTML.js +9 -9
- package/client/utils/log.js +1 -1
- package/dist/config.d.ts +1 -3
- package/dist/getPort.js +18 -8
- package/dist/server.d.ts +5 -16
- package/dist/server.js +137 -388
- package/dist/types.d.ts +10 -27
- package/package.json +39 -65
- package/client/clients/SockJSClient.js +0 -34
- package/client/modules/sockjs-client/index.js +0 -4506
- package/dist/options.json +0 -1034
- package/dist/servers/SockJSServer.d.ts +0 -10
- package/dist/servers/SockJSServer.js +0 -110
package/dist/server.js
CHANGED
|
@@ -24,26 +24,32 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
24
24
|
}) : function(o, v) {
|
|
25
25
|
o["default"] = v;
|
|
26
26
|
});
|
|
27
|
-
var __importStar = (this && this.__importStar) || function (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
37
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
45
|
exports.Server = void 0;
|
|
46
|
+
const fs = __importStar(require("node:fs"));
|
|
39
47
|
const os = __importStar(require("node:os"));
|
|
40
48
|
const path = __importStar(require("node:path"));
|
|
41
49
|
const url = __importStar(require("node:url"));
|
|
42
50
|
const util = __importStar(require("node:util"));
|
|
43
|
-
const fs = __importStar(require("graceful-fs"));
|
|
44
51
|
const ipaddr = __importStar(require("ipaddr.js"));
|
|
45
|
-
const
|
|
46
|
-
const options_json_1 = __importDefault(require("./options.json"));
|
|
52
|
+
const { styleText } = util;
|
|
47
53
|
// Define BasicApplication and Server as ambient, or import them
|
|
48
54
|
if (!process.env.WEBPACK_SERVE) {
|
|
49
55
|
process.env.WEBPACK_SERVE = 'true';
|
|
@@ -70,18 +76,33 @@ const encodeOverlaySettings = (setting) => {
|
|
|
70
76
|
: setting;
|
|
71
77
|
};
|
|
72
78
|
const DEFAULT_ALLOWED_PROTOCOLS = /^(file|.+-extension):/i;
|
|
79
|
+
/**
|
|
80
|
+
* Extracts and normalizes the hostname from a header, removing brackets for IPv6.
|
|
81
|
+
*/
|
|
82
|
+
function parseHostnameFromHeader(header) {
|
|
83
|
+
try {
|
|
84
|
+
const parsedUrl = new URL(
|
|
85
|
+
// if header doesn't have scheme, add // for parsing.
|
|
86
|
+
/^(.+:)?\/\//.test(header) ? header : `//${header}`, 'http://localhost/');
|
|
87
|
+
let { hostname } = parsedUrl;
|
|
88
|
+
// `URL#hostname` keeps IPv6 brackets, but our validation expects bare IPv6.
|
|
89
|
+
if (hostname.startsWith('[') && hostname.endsWith(']')) {
|
|
90
|
+
hostname = hostname.slice(1, -1);
|
|
91
|
+
}
|
|
92
|
+
return hostname;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
73
98
|
function isMultiCompiler(compiler) {
|
|
74
99
|
return Array.isArray(compiler.compilers);
|
|
75
100
|
}
|
|
76
101
|
class Server {
|
|
77
102
|
constructor(options, compiler) {
|
|
78
103
|
this.isTlsServer = false;
|
|
79
|
-
(0, schema_utils_1.validate)(options_json_1.default, options, {
|
|
80
|
-
name: 'Dev Server',
|
|
81
|
-
baseDataPath: 'options',
|
|
82
|
-
});
|
|
83
104
|
this.compiler = compiler;
|
|
84
|
-
this.logger = this.compiler.getInfrastructureLogger('
|
|
105
|
+
this.logger = this.compiler.getInfrastructureLogger('rspack-dev-server');
|
|
85
106
|
this.options = options;
|
|
86
107
|
this.staticWatchers = [];
|
|
87
108
|
this.listeners = [];
|
|
@@ -89,9 +110,6 @@ class Server {
|
|
|
89
110
|
this.sockets = [];
|
|
90
111
|
this.currentHash = undefined;
|
|
91
112
|
}
|
|
92
|
-
static get schema() {
|
|
93
|
-
return options_json_1.default;
|
|
94
|
-
}
|
|
95
113
|
static get DEFAULT_STATS() {
|
|
96
114
|
return {
|
|
97
115
|
all: false,
|
|
@@ -158,14 +176,6 @@ class Server {
|
|
|
158
176
|
}
|
|
159
177
|
}
|
|
160
178
|
}
|
|
161
|
-
// TODO remove me in the next major release, we have `findIp`
|
|
162
|
-
static async internalIP(family) {
|
|
163
|
-
return Server.findIp(family, false);
|
|
164
|
-
}
|
|
165
|
-
// TODO remove me in the next major release, we have `findIp`
|
|
166
|
-
static internalIPSync(family) {
|
|
167
|
-
return Server.findIp(family, false);
|
|
168
|
-
}
|
|
169
179
|
static async getHostname(hostname) {
|
|
170
180
|
if (hostname === 'local-ip') {
|
|
171
181
|
return (Server.findIp('v4', false) || Server.findIp('v6', false) || '0.0.0.0');
|
|
@@ -184,13 +194,13 @@ class Server {
|
|
|
184
194
|
}
|
|
185
195
|
const { default: pRetry } = await import('p-retry');
|
|
186
196
|
const getPort = require('./getPort');
|
|
187
|
-
const basePort = typeof process.env.
|
|
188
|
-
? Number.parseInt(process.env.
|
|
197
|
+
const basePort = typeof process.env.RSPACK_DEV_SERVER_BASE_PORT !== 'undefined'
|
|
198
|
+
? Number.parseInt(process.env.RSPACK_DEV_SERVER_BASE_PORT, 10)
|
|
189
199
|
: 8080;
|
|
190
200
|
// Try to find unused port and listen on it for 3 times,
|
|
191
201
|
// if port is not specified in options.
|
|
192
|
-
const defaultPortRetry = typeof process.env.
|
|
193
|
-
? Number.parseInt(process.env.
|
|
202
|
+
const defaultPortRetry = typeof process.env.RSPACK_DEV_SERVER_PORT_RETRY !== 'undefined'
|
|
203
|
+
? Number.parseInt(process.env.RSPACK_DEV_SERVER_PORT_RETRY, 10)
|
|
194
204
|
: 3;
|
|
195
205
|
return pRetry(() => getPort(basePort, host), {
|
|
196
206
|
retries: defaultPortRetry,
|
|
@@ -214,45 +224,19 @@ class Server {
|
|
|
214
224
|
dir = parent;
|
|
215
225
|
}
|
|
216
226
|
if (!dir) {
|
|
217
|
-
return path.resolve(cwd, '.cache/
|
|
227
|
+
return path.resolve(cwd, '.cache/rspack-dev-server');
|
|
218
228
|
}
|
|
219
229
|
if (process.versions.pnp === '1') {
|
|
220
|
-
return path.resolve(dir, '.pnp/.cache/
|
|
230
|
+
return path.resolve(dir, '.pnp/.cache/rspack-dev-server');
|
|
221
231
|
}
|
|
222
232
|
if (process.versions.pnp === '3') {
|
|
223
|
-
return path.resolve(dir, '.yarn/.cache/
|
|
233
|
+
return path.resolve(dir, '.yarn/.cache/rspack-dev-server');
|
|
224
234
|
}
|
|
225
|
-
return path.resolve(dir, 'node_modules/.cache/
|
|
226
|
-
}
|
|
227
|
-
static isWebTarget(compiler) {
|
|
228
|
-
if (compiler.platform?.web) {
|
|
229
|
-
return compiler.platform.web;
|
|
230
|
-
}
|
|
231
|
-
// TODO improve for the next major version and keep only `webTargets` to fallback for old versions
|
|
232
|
-
if (compiler.options.externalsPresets?.web) {
|
|
233
|
-
return true;
|
|
234
|
-
}
|
|
235
|
-
if (compiler.options.resolve?.conditionNames?.includes('browser')) {
|
|
236
|
-
return true;
|
|
237
|
-
}
|
|
238
|
-
const webTargets = [
|
|
239
|
-
'web',
|
|
240
|
-
'webworker',
|
|
241
|
-
'electron-preload',
|
|
242
|
-
'electron-renderer',
|
|
243
|
-
'nwjs',
|
|
244
|
-
'node-webkit',
|
|
245
|
-
undefined,
|
|
246
|
-
null,
|
|
247
|
-
];
|
|
248
|
-
if (Array.isArray(compiler.options.target)) {
|
|
249
|
-
return compiler.options.target.some((r) => webTargets.includes(r));
|
|
250
|
-
}
|
|
251
|
-
return webTargets.includes(compiler.options.target);
|
|
235
|
+
return path.resolve(dir, 'node_modules/.cache/rspack-dev-server');
|
|
252
236
|
}
|
|
253
237
|
addAdditionalEntries(compiler) {
|
|
254
238
|
const additionalEntries = [];
|
|
255
|
-
const isWebTarget =
|
|
239
|
+
const isWebTarget = Boolean(compiler.platform.web);
|
|
256
240
|
// TODO maybe empty client
|
|
257
241
|
if (this.options.client && isWebTarget) {
|
|
258
242
|
let webSocketURLStr = '';
|
|
@@ -277,20 +261,14 @@ class Server {
|
|
|
277
261
|
searchParams.set('password', webSocketURL.password);
|
|
278
262
|
}
|
|
279
263
|
let hostname;
|
|
280
|
-
// SockJS is not supported server mode, so `hostname` and `port` can't specified, let's ignore them
|
|
281
|
-
const isSockJSType = webSocketServer.type === 'sockjs';
|
|
282
264
|
const isWebSocketServerHostDefined = typeof webSocketServer.options.host !== 'undefined';
|
|
283
265
|
const isWebSocketServerPortDefined = typeof webSocketServer.options.port !== 'undefined';
|
|
284
|
-
if (isSockJSType &&
|
|
285
|
-
(isWebSocketServerHostDefined || isWebSocketServerPortDefined)) {
|
|
286
|
-
this.logger.warn("SockJS only supports client mode and does not support custom hostname and port options. Please consider using 'ws' if you need to customize these options.");
|
|
287
|
-
}
|
|
288
266
|
// We are proxying dev server and need to specify custom `hostname`
|
|
289
267
|
if (typeof webSocketURL.hostname !== 'undefined') {
|
|
290
268
|
hostname = webSocketURL.hostname;
|
|
291
269
|
}
|
|
292
|
-
// Web socket server works on custom `hostname
|
|
293
|
-
else if (isWebSocketServerHostDefined
|
|
270
|
+
// Web socket server works on custom `hostname`
|
|
271
|
+
else if (isWebSocketServerHostDefined) {
|
|
294
272
|
hostname = webSocketServer.options.host;
|
|
295
273
|
}
|
|
296
274
|
// The `host` option is specified
|
|
@@ -307,8 +285,8 @@ class Server {
|
|
|
307
285
|
if (typeof webSocketURL.port !== 'undefined') {
|
|
308
286
|
port = webSocketURL.port;
|
|
309
287
|
}
|
|
310
|
-
// Web socket server works on custom `port
|
|
311
|
-
else if (isWebSocketServerPortDefined
|
|
288
|
+
// Web socket server works on custom `port`
|
|
289
|
+
else if (isWebSocketServerPortDefined) {
|
|
312
290
|
port = webSocketServer.options.port;
|
|
313
291
|
}
|
|
314
292
|
// The `port` option is specified
|
|
@@ -331,10 +309,8 @@ class Server {
|
|
|
331
309
|
pathname = webSocketURL.pathname;
|
|
332
310
|
}
|
|
333
311
|
// Web socket server works on custom `path`
|
|
334
|
-
else if (typeof webSocketServer.options.
|
|
335
|
-
|
|
336
|
-
pathname =
|
|
337
|
-
webSocketServer.options.prefix || webSocketServer.options.path;
|
|
312
|
+
else if (typeof webSocketServer.options.path !== 'undefined') {
|
|
313
|
+
pathname = webSocketServer.options.path;
|
|
338
314
|
}
|
|
339
315
|
searchParams.set('pathname', pathname);
|
|
340
316
|
const client = this.options.client;
|
|
@@ -374,10 +350,9 @@ class Server {
|
|
|
374
350
|
if (clientHotEntry) {
|
|
375
351
|
additionalEntries.push(clientHotEntry);
|
|
376
352
|
}
|
|
377
|
-
const webpack = compiler.webpack || require('webpack');
|
|
378
353
|
// use a hook to add entries if available
|
|
379
354
|
for (const additionalEntry of additionalEntries) {
|
|
380
|
-
new
|
|
355
|
+
new compiler.rspack.EntryPlugin(compiler.context, additionalEntry, {
|
|
381
356
|
name: undefined,
|
|
382
357
|
}).apply(compiler);
|
|
383
358
|
}
|
|
@@ -396,25 +371,21 @@ class Server {
|
|
|
396
371
|
if (compilerWithDevServer) {
|
|
397
372
|
return compilerWithDevServer.options;
|
|
398
373
|
}
|
|
399
|
-
//
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
'webworker',
|
|
404
|
-
'electron-preload',
|
|
405
|
-
'electron-renderer',
|
|
406
|
-
'node-webkit',
|
|
407
|
-
undefined,
|
|
408
|
-
null,
|
|
409
|
-
].includes(config.options.target));
|
|
410
|
-
if (compilerWithWebPreset) {
|
|
411
|
-
return compilerWithWebPreset.options;
|
|
374
|
+
// Compiler for `web` target
|
|
375
|
+
const compilerWithWebTarget = this.compiler.compilers.find((compiler) => Boolean(compiler.platform.web));
|
|
376
|
+
if (compilerWithWebTarget) {
|
|
377
|
+
return compilerWithWebTarget.options;
|
|
412
378
|
}
|
|
413
379
|
// Fallback
|
|
414
380
|
return this.compiler.compilers[0].options;
|
|
415
381
|
}
|
|
416
382
|
return this.compiler.options;
|
|
417
383
|
}
|
|
384
|
+
shouldLogInfrastructureInfo() {
|
|
385
|
+
const compilerOptions = this.getCompilerOptions();
|
|
386
|
+
const { level = 'info' } = compilerOptions.infrastructureLogging || {};
|
|
387
|
+
return level === 'info' || level === 'log' || level === 'verbose';
|
|
388
|
+
}
|
|
418
389
|
async normalizeOptions() {
|
|
419
390
|
const { options } = this;
|
|
420
391
|
const compilerOptions = this.getCompilerOptions();
|
|
@@ -545,12 +516,6 @@ class Server {
|
|
|
545
516
|
options.allowedHosts.includes('all')) {
|
|
546
517
|
options.allowedHosts = 'all';
|
|
547
518
|
}
|
|
548
|
-
if (typeof options.bonjour === 'undefined') {
|
|
549
|
-
options.bonjour = false;
|
|
550
|
-
}
|
|
551
|
-
else if (typeof options.bonjour === 'boolean') {
|
|
552
|
-
options.bonjour = options.bonjour ? {} : false;
|
|
553
|
-
}
|
|
554
519
|
if (typeof options.client === 'undefined' ||
|
|
555
520
|
(typeof options.client === 'object' && options.client !== null)) {
|
|
556
521
|
if (!options.client) {
|
|
@@ -634,13 +599,7 @@ class Server {
|
|
|
634
599
|
};
|
|
635
600
|
}
|
|
636
601
|
const serverOptions = options.server.options;
|
|
637
|
-
if (options.server.type === '
|
|
638
|
-
typeof serverOptions.spdy === 'undefined') {
|
|
639
|
-
serverOptions.spdy = { protocols: ['h2', 'http/1.1'] };
|
|
640
|
-
}
|
|
641
|
-
if (options.server.type === 'https' ||
|
|
642
|
-
options.server.type === 'http2' ||
|
|
643
|
-
options.server.type === 'spdy') {
|
|
602
|
+
if (options.server.type === 'https' || options.server.type === 'http2') {
|
|
644
603
|
if (typeof serverOptions.requestCert === 'undefined') {
|
|
645
604
|
serverOptions.requestCert = false;
|
|
646
605
|
}
|
|
@@ -674,7 +633,6 @@ class Server {
|
|
|
674
633
|
return stats ? fs.readFileSync(item) : item;
|
|
675
634
|
}
|
|
676
635
|
};
|
|
677
|
-
// @ts-expect-error too complex
|
|
678
636
|
serverOptions[property] = (Array.isArray(value)
|
|
679
637
|
? value.map((item) => readFile(item))
|
|
680
638
|
: readFile(value));
|
|
@@ -706,10 +664,14 @@ class Server {
|
|
|
706
664
|
this.logger.info('Generating SSL certificate...');
|
|
707
665
|
const selfsigned = require('selfsigned');
|
|
708
666
|
const attributes = [{ name: 'commonName', value: 'localhost' }];
|
|
709
|
-
const
|
|
667
|
+
const notBeforeDate = new Date();
|
|
668
|
+
const notAfterDate = new Date(notBeforeDate);
|
|
669
|
+
notAfterDate.setDate(notAfterDate.getDate() + 30);
|
|
670
|
+
const pems = await selfsigned.generate(attributes, {
|
|
710
671
|
algorithm: 'sha256',
|
|
711
|
-
days: 30,
|
|
712
672
|
keySize: 2048,
|
|
673
|
+
notBeforeDate,
|
|
674
|
+
notAfterDate,
|
|
713
675
|
extensions: [
|
|
714
676
|
{
|
|
715
677
|
name: 'basicConstraints',
|
|
@@ -844,44 +806,6 @@ class Server {
|
|
|
844
806
|
if (typeof options.port === 'string' && options.port !== 'auto') {
|
|
845
807
|
options.port = Number(options.port);
|
|
846
808
|
}
|
|
847
|
-
/**
|
|
848
|
-
* Assume a proxy configuration specified as:
|
|
849
|
-
* proxy: {
|
|
850
|
-
* 'context': { options }
|
|
851
|
-
* }
|
|
852
|
-
* OR
|
|
853
|
-
* proxy: {
|
|
854
|
-
* 'context': 'target'
|
|
855
|
-
* }
|
|
856
|
-
*/
|
|
857
|
-
if (typeof options.proxy !== 'undefined') {
|
|
858
|
-
options.proxy = options.proxy.map((item) => {
|
|
859
|
-
if (typeof item === 'function') {
|
|
860
|
-
return item;
|
|
861
|
-
}
|
|
862
|
-
const getLogLevelForProxy = (level) => {
|
|
863
|
-
if (level === 'none') {
|
|
864
|
-
return 'silent';
|
|
865
|
-
}
|
|
866
|
-
if (level === 'log') {
|
|
867
|
-
return 'info';
|
|
868
|
-
}
|
|
869
|
-
if (level === 'verbose') {
|
|
870
|
-
return 'debug';
|
|
871
|
-
}
|
|
872
|
-
return level;
|
|
873
|
-
};
|
|
874
|
-
if (typeof item.logLevel === 'undefined') {
|
|
875
|
-
item.logLevel = getLogLevelForProxy(compilerOptions.infrastructureLogging
|
|
876
|
-
? compilerOptions.infrastructureLogging.level
|
|
877
|
-
: 'info');
|
|
878
|
-
}
|
|
879
|
-
if (typeof item.logProvider === 'undefined') {
|
|
880
|
-
item.logProvider = () => this.logger;
|
|
881
|
-
}
|
|
882
|
-
return item;
|
|
883
|
-
});
|
|
884
|
-
}
|
|
885
809
|
if (typeof options.setupExitSignals === 'undefined') {
|
|
886
810
|
options.setupExitSignals = true;
|
|
887
811
|
}
|
|
@@ -974,9 +898,7 @@ class Server {
|
|
|
974
898
|
typeof this.options.webSocketServer
|
|
975
899
|
.type === 'string' &&
|
|
976
900
|
// @ts-expect-error
|
|
977
|
-
|
|
978
|
-
this.options.webSocketServer.type ===
|
|
979
|
-
'sockjs');
|
|
901
|
+
this.options.webSocketServer.type === 'ws';
|
|
980
902
|
let clientTransport;
|
|
981
903
|
if (this.options.client) {
|
|
982
904
|
if (typeof this.options.client
|
|
@@ -996,12 +918,13 @@ class Server {
|
|
|
996
918
|
}
|
|
997
919
|
switch (typeof clientTransport) {
|
|
998
920
|
case 'string':
|
|
999
|
-
// could be '
|
|
921
|
+
// could be 'ws' or a path that should be required
|
|
1000
922
|
if (clientTransport === 'sockjs') {
|
|
1001
|
-
|
|
923
|
+
throw new Error("SockJS support has been removed. Please set client.webSocketTransport to 'ws' or provide a custom transport implementation path.");
|
|
1002
924
|
}
|
|
1003
|
-
|
|
1004
|
-
clientImplementation =
|
|
925
|
+
if (clientTransport === 'ws') {
|
|
926
|
+
clientImplementation =
|
|
927
|
+
require.resolve('../client/clients/WebSocketClient');
|
|
1005
928
|
}
|
|
1006
929
|
else {
|
|
1007
930
|
try {
|
|
@@ -1018,7 +941,7 @@ class Server {
|
|
|
1018
941
|
if (!clientImplementationFound) {
|
|
1019
942
|
throw new Error(`${!isKnownWebSocketServerImplementation
|
|
1020
943
|
? 'When you use custom web socket implementation you must explicitly specify client.webSocketTransport. '
|
|
1021
|
-
: ''}client.webSocketTransport must be a string denoting a default implementation (e.g. '
|
|
944
|
+
: ''}client.webSocketTransport must be a string denoting a default implementation (e.g. 'ws') or a full path to a JS file via require.resolve(...) which exports a class `);
|
|
1022
945
|
}
|
|
1023
946
|
return clientImplementation;
|
|
1024
947
|
}
|
|
@@ -1027,12 +950,12 @@ class Server {
|
|
|
1027
950
|
let implementationFound = true;
|
|
1028
951
|
switch (typeof this.options.webSocketServer.type) {
|
|
1029
952
|
case 'string':
|
|
1030
|
-
// Could be '
|
|
953
|
+
// Could be 'ws' or a path that should be required
|
|
1031
954
|
if (this.options.webSocketServer
|
|
1032
955
|
.type === 'sockjs') {
|
|
1033
|
-
|
|
956
|
+
throw new Error("SockJS support has been removed. Please set webSocketServer to 'ws' or provide a custom WebSocket server implementation.");
|
|
1034
957
|
}
|
|
1035
|
-
|
|
958
|
+
if (this.options.webSocketServer
|
|
1036
959
|
.type === 'ws') {
|
|
1037
960
|
implementation = require('./servers/WebsocketServer');
|
|
1038
961
|
}
|
|
@@ -1053,7 +976,7 @@ class Server {
|
|
|
1053
976
|
implementationFound = false;
|
|
1054
977
|
}
|
|
1055
978
|
if (!implementationFound) {
|
|
1056
|
-
throw new Error("webSocketServer (webSocketServer.type) must be a string denoting a default implementation (e.g. 'ws'
|
|
979
|
+
throw new Error("webSocketServer (webSocketServer.type) must be a string denoting a default implementation (e.g. 'ws'), a full path to " +
|
|
1057
980
|
'a JS file which exports a class extending BaseServer (webpack-dev-server/lib/servers/BaseServer.js) ' +
|
|
1058
981
|
'via require.resolve(...), or the class itself which extends BaseServer');
|
|
1059
982
|
}
|
|
@@ -1074,24 +997,21 @@ class Server {
|
|
|
1074
997
|
const { ProgressPlugin } = this.compiler.compilers
|
|
1075
998
|
? this.compiler.compilers[0].webpack
|
|
1076
999
|
: this.compiler.webpack;
|
|
1077
|
-
new ProgressPlugin((percent, msg
|
|
1000
|
+
new ProgressPlugin((percent, msg) => {
|
|
1078
1001
|
const percentValue = Math.floor(percent * 100);
|
|
1079
1002
|
let msgValue = msg;
|
|
1080
1003
|
if (percentValue === 100) {
|
|
1081
1004
|
msgValue = 'Compilation completed';
|
|
1082
1005
|
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1006
|
+
const payload = {
|
|
1007
|
+
percent: percentValue,
|
|
1008
|
+
msg: msgValue,
|
|
1009
|
+
};
|
|
1086
1010
|
if (this.webSocketServer) {
|
|
1087
|
-
this.sendMessage(this.webSocketServer.clients, 'progress-update',
|
|
1088
|
-
percent: percentValue,
|
|
1089
|
-
msg: msgValue,
|
|
1090
|
-
pluginName,
|
|
1091
|
-
});
|
|
1011
|
+
this.sendMessage(this.webSocketServer.clients, 'progress-update', payload);
|
|
1092
1012
|
}
|
|
1093
1013
|
if (this.server) {
|
|
1094
|
-
this.server.emit('progress-update',
|
|
1014
|
+
this.server.emit('progress-update', payload);
|
|
1095
1015
|
}
|
|
1096
1016
|
}).apply(this.compiler);
|
|
1097
1017
|
}
|
|
@@ -1127,19 +1047,18 @@ class Server {
|
|
|
1127
1047
|
continue;
|
|
1128
1048
|
}
|
|
1129
1049
|
this.addAdditionalEntries(compiler);
|
|
1130
|
-
const
|
|
1131
|
-
new
|
|
1050
|
+
const { ProvidePlugin, HotModuleReplacementPlugin } = compiler.rspack;
|
|
1051
|
+
new ProvidePlugin({
|
|
1132
1052
|
__webpack_dev_server_client__: this.getClientTransport(),
|
|
1133
1053
|
}).apply(compiler);
|
|
1134
1054
|
if (this.options.hot) {
|
|
1135
|
-
const HMRPluginExists = compiler.options.plugins.find((plugin) => plugin &&
|
|
1136
|
-
plugin.constructor === webpack.HotModuleReplacementPlugin);
|
|
1055
|
+
const HMRPluginExists = compiler.options.plugins.find((plugin) => plugin && plugin.constructor === HotModuleReplacementPlugin);
|
|
1137
1056
|
if (HMRPluginExists) {
|
|
1138
1057
|
this.logger.warn('"hot: true" automatically applies HMR plugin, you don\'t have to add it manually to your webpack configuration.');
|
|
1139
1058
|
}
|
|
1140
1059
|
else {
|
|
1141
1060
|
// Apply the HMR plugin
|
|
1142
|
-
const plugin = new
|
|
1061
|
+
const plugin = new HotModuleReplacementPlugin();
|
|
1143
1062
|
plugin.apply(compiler);
|
|
1144
1063
|
}
|
|
1145
1064
|
}
|
|
@@ -1162,7 +1081,7 @@ class Server {
|
|
|
1162
1081
|
// eslint-disable-next-line n/no-process-exit
|
|
1163
1082
|
process.exit();
|
|
1164
1083
|
}
|
|
1165
|
-
this.logger.info('Gracefully shutting down.
|
|
1084
|
+
this.logger.info('Gracefully shutting down. Press ^C again to force exit...');
|
|
1166
1085
|
needForceShutdown = true;
|
|
1167
1086
|
this.stopCallback(() => {
|
|
1168
1087
|
if (typeof this.compiler.close === 'function') {
|
|
@@ -1204,12 +1123,12 @@ class Server {
|
|
|
1204
1123
|
return statsObj.toJson(stats);
|
|
1205
1124
|
}
|
|
1206
1125
|
setupHooks() {
|
|
1207
|
-
this.compiler.hooks.invalid.tap('
|
|
1126
|
+
this.compiler.hooks.invalid.tap('rspack-dev-server', () => {
|
|
1208
1127
|
if (this.webSocketServer) {
|
|
1209
1128
|
this.sendMessage(this.webSocketServer.clients, 'invalid');
|
|
1210
1129
|
}
|
|
1211
1130
|
});
|
|
1212
|
-
this.compiler.hooks.done.tap('
|
|
1131
|
+
this.compiler.hooks.done.tap('rspack-dev-server', (stats) => {
|
|
1213
1132
|
if (this.webSocketServer) {
|
|
1214
1133
|
this.sendStats(this.webSocketServer.clients, this.getStats(stats));
|
|
1215
1134
|
}
|
|
@@ -1286,7 +1205,7 @@ class Server {
|
|
|
1286
1205
|
});
|
|
1287
1206
|
}
|
|
1288
1207
|
// compress is placed last and uses unshift so that it will be the first middleware used
|
|
1289
|
-
if (this.options.compress
|
|
1208
|
+
if (this.options.compress) {
|
|
1290
1209
|
const compression = require('compression');
|
|
1291
1210
|
middlewares.push({ name: 'compression', middleware: compression() });
|
|
1292
1211
|
}
|
|
@@ -1300,42 +1219,9 @@ class Server {
|
|
|
1300
1219
|
name: 'webpack-dev-middleware',
|
|
1301
1220
|
middleware: this.middleware,
|
|
1302
1221
|
});
|
|
1303
|
-
// Should be after `webpack-dev-middleware`, otherwise other middlewares might rewrite response
|
|
1304
1222
|
middlewares.push({
|
|
1305
|
-
name: '
|
|
1306
|
-
path: '/
|
|
1307
|
-
middleware: (req, res, next) => {
|
|
1308
|
-
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
1309
|
-
next();
|
|
1310
|
-
return;
|
|
1311
|
-
}
|
|
1312
|
-
const clientPath = path.join(__dirname, '../', 'client/modules/sockjs-client/index.js');
|
|
1313
|
-
// Express send Etag and other headers by default, so let's keep them for compatibility reasons
|
|
1314
|
-
if (typeof res.sendFile === 'function') {
|
|
1315
|
-
res.sendFile(clientPath);
|
|
1316
|
-
return;
|
|
1317
|
-
}
|
|
1318
|
-
let stats;
|
|
1319
|
-
try {
|
|
1320
|
-
// TODO implement `inputFileSystem.createReadStream` in webpack
|
|
1321
|
-
stats = fs.statSync(clientPath);
|
|
1322
|
-
}
|
|
1323
|
-
catch {
|
|
1324
|
-
next();
|
|
1325
|
-
return;
|
|
1326
|
-
}
|
|
1327
|
-
res.setHeader('Content-Type', 'application/javascript; charset=UTF-8');
|
|
1328
|
-
res.setHeader('Content-Length', stats.size);
|
|
1329
|
-
if (req.method === 'HEAD') {
|
|
1330
|
-
res.end();
|
|
1331
|
-
return;
|
|
1332
|
-
}
|
|
1333
|
-
fs.createReadStream(clientPath).pipe(res);
|
|
1334
|
-
},
|
|
1335
|
-
});
|
|
1336
|
-
middlewares.push({
|
|
1337
|
-
name: 'webpack-dev-server-invalidate',
|
|
1338
|
-
path: '/webpack-dev-server/invalidate',
|
|
1223
|
+
name: 'rspack-dev-server-invalidate',
|
|
1224
|
+
path: '/rspack-dev-server/invalidate',
|
|
1339
1225
|
middleware: (req, res, next) => {
|
|
1340
1226
|
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
1341
1227
|
next();
|
|
@@ -1346,8 +1232,8 @@ class Server {
|
|
|
1346
1232
|
},
|
|
1347
1233
|
});
|
|
1348
1234
|
middlewares.push({
|
|
1349
|
-
name: '
|
|
1350
|
-
path: '/
|
|
1235
|
+
name: 'rspack-dev-server-open-editor',
|
|
1236
|
+
path: '/rspack-dev-server/open-editor',
|
|
1351
1237
|
middleware: (req, res, next) => {
|
|
1352
1238
|
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
1353
1239
|
next();
|
|
@@ -1368,8 +1254,8 @@ class Server {
|
|
|
1368
1254
|
},
|
|
1369
1255
|
});
|
|
1370
1256
|
middlewares.push({
|
|
1371
|
-
name: '
|
|
1372
|
-
path: '/
|
|
1257
|
+
name: 'rspack-dev-server-assets',
|
|
1258
|
+
path: '/rspack-dev-server',
|
|
1373
1259
|
middleware: (req, res, next) => {
|
|
1374
1260
|
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
1375
1261
|
next();
|
|
@@ -1388,9 +1274,11 @@ class Server {
|
|
|
1388
1274
|
}
|
|
1389
1275
|
res.write('<!DOCTYPE html><html><head><meta charset="utf-8"/></head><body>');
|
|
1390
1276
|
const statsForPrint = typeof stats.stats !== 'undefined'
|
|
1391
|
-
? stats.toJson({})
|
|
1277
|
+
? stats.toJson({ assets: true })
|
|
1392
1278
|
.children
|
|
1393
|
-
: [
|
|
1279
|
+
: [
|
|
1280
|
+
stats.toJson({ assets: true }),
|
|
1281
|
+
];
|
|
1394
1282
|
res.write('<h1>Assets Report:</h1>');
|
|
1395
1283
|
for (const [index, item] of statsForPrint?.entries() ?? []) {
|
|
1396
1284
|
res.write('<div>');
|
|
@@ -1420,19 +1308,18 @@ class Server {
|
|
|
1420
1308
|
if (this.options.proxy) {
|
|
1421
1309
|
const { createProxyMiddleware } = require('http-proxy-middleware');
|
|
1422
1310
|
const getProxyMiddleware = (proxyConfig) => {
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
if (
|
|
1426
|
-
|
|
1427
|
-
return createProxyMiddleware(context, proxyConfig);
|
|
1311
|
+
const { context, ...proxyOptions } = proxyConfig;
|
|
1312
|
+
const pathFilter = proxyOptions.pathFilter ?? context;
|
|
1313
|
+
if (typeof pathFilter !== 'undefined') {
|
|
1314
|
+
proxyOptions.pathFilter = pathFilter;
|
|
1428
1315
|
}
|
|
1429
|
-
if (
|
|
1430
|
-
|
|
1316
|
+
if (typeof proxyOptions.logger === 'undefined') {
|
|
1317
|
+
proxyOptions.logger = this.logger;
|
|
1431
1318
|
}
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
util.deprecate(() => { }, `Invalid proxy configuration:\n\n${JSON.stringify(proxyConfig, null, 2)}\n\nThe use of proxy object notation as proxy routes has been removed.\nPlease use the 'router' or 'context' options. Read more at https://github.com/chimurai/http-proxy-middleware/tree/v2.0.6#http-proxy-middleware-options`, 'DEP_WEBPACK_DEV_SERVER_PROXY_ROUTES_ARGUMENT')();
|
|
1319
|
+
if (proxyOptions.target || proxyOptions.router) {
|
|
1320
|
+
return createProxyMiddleware(proxyOptions);
|
|
1435
1321
|
}
|
|
1322
|
+
util.deprecate(() => { }, `Invalid proxy configuration:\n\n${JSON.stringify(proxyConfig, null, 2)}\n\nThe use of proxy object notation as proxy routes has been removed.\nPlease use the 'router' or 'context' options. Read more at https://github.com/chimurai/http-proxy-middleware`, 'DEP_WEBPACK_DEV_SERVER_PROXY_ROUTES_ARGUMENT')();
|
|
1436
1323
|
};
|
|
1437
1324
|
/**
|
|
1438
1325
|
* @example
|
|
@@ -1473,34 +1360,10 @@ class Server {
|
|
|
1473
1360
|
proxyMiddleware = getProxyMiddleware(proxyConfig);
|
|
1474
1361
|
}
|
|
1475
1362
|
}
|
|
1476
|
-
|
|
1477
|
-
// - In case the bypass function is defined we'll retrieve the
|
|
1478
|
-
// bypassUrl from it otherwise bypassUrl would be null
|
|
1479
|
-
// TODO remove in the next major in favor `context` and `router` options
|
|
1480
|
-
const isByPassFuncDefined = typeof proxyConfig.bypass === 'function';
|
|
1481
|
-
if (isByPassFuncDefined) {
|
|
1482
|
-
util.deprecate(() => { }, "Using the 'bypass' option is deprecated. Please use the 'router' or 'context' options. Read more at https://github.com/chimurai/http-proxy-middleware/tree/v2.0.6#http-proxy-middleware-options", 'DEP_WEBPACK_DEV_SERVER_PROXY_BYPASS_ARGUMENT')();
|
|
1483
|
-
}
|
|
1484
|
-
const bypassUrl = isByPassFuncDefined
|
|
1485
|
-
? await proxyConfig.bypass(req, res, proxyConfig)
|
|
1486
|
-
: null;
|
|
1487
|
-
if (typeof bypassUrl === 'boolean') {
|
|
1488
|
-
// skip the proxy
|
|
1489
|
-
res.statusCode = 404;
|
|
1490
|
-
req.url = '';
|
|
1491
|
-
next();
|
|
1492
|
-
}
|
|
1493
|
-
else if (typeof bypassUrl === 'string') {
|
|
1494
|
-
// byPass to that url
|
|
1495
|
-
req.url = bypassUrl;
|
|
1496
|
-
next();
|
|
1497
|
-
}
|
|
1498
|
-
else if (proxyMiddleware) {
|
|
1363
|
+
if (proxyMiddleware) {
|
|
1499
1364
|
return proxyMiddleware(req, res, next);
|
|
1500
1365
|
}
|
|
1501
|
-
|
|
1502
|
-
next();
|
|
1503
|
-
}
|
|
1366
|
+
next();
|
|
1504
1367
|
};
|
|
1505
1368
|
middlewares.push({
|
|
1506
1369
|
name: 'http-proxy-middleware',
|
|
@@ -1659,15 +1522,11 @@ class Server {
|
|
|
1659
1522
|
});
|
|
1660
1523
|
}
|
|
1661
1524
|
createWebSocketServer() {
|
|
1662
|
-
// @ts-expect-error constructor
|
|
1663
1525
|
this.webSocketServer = new (this.getServerTransport())(this);
|
|
1664
1526
|
(this.webSocketServer?.implementation).on('connection', (client, request) => {
|
|
1665
1527
|
const headers = typeof request !== 'undefined'
|
|
1666
1528
|
? request.headers
|
|
1667
|
-
:
|
|
1668
|
-
.headers !== 'undefined'
|
|
1669
|
-
? client.headers
|
|
1670
|
-
: undefined;
|
|
1529
|
+
: undefined;
|
|
1671
1530
|
if (!headers) {
|
|
1672
1531
|
this.logger.warn('webSocketServer implementation must pass headers for the "connection" event');
|
|
1673
1532
|
}
|
|
@@ -1741,56 +1600,7 @@ class Server {
|
|
|
1741
1600
|
});
|
|
1742
1601
|
}));
|
|
1743
1602
|
}
|
|
1744
|
-
runBonjour() {
|
|
1745
|
-
const { Bonjour } = require('bonjour-service');
|
|
1746
|
-
const type = this.isTlsServer ? 'https' : 'http';
|
|
1747
|
-
this.bonjour = new Bonjour();
|
|
1748
|
-
this.bonjour?.publish({
|
|
1749
|
-
name: `Webpack Dev Server ${os.hostname()}:${this.options.port}`,
|
|
1750
|
-
port: this.options.port,
|
|
1751
|
-
type,
|
|
1752
|
-
subtypes: ['webpack'],
|
|
1753
|
-
...this.options.bonjour,
|
|
1754
|
-
});
|
|
1755
|
-
}
|
|
1756
|
-
stopBonjour(callback = () => { }) {
|
|
1757
|
-
this.bonjour?.unpublishAll(() => {
|
|
1758
|
-
this.bonjour?.destroy();
|
|
1759
|
-
if (callback) {
|
|
1760
|
-
callback();
|
|
1761
|
-
}
|
|
1762
|
-
});
|
|
1763
|
-
}
|
|
1764
1603
|
async logStatus() {
|
|
1765
|
-
const { cyan, isColorSupported, red } = require('colorette');
|
|
1766
|
-
const getColorsOption = (compilerOptions) => {
|
|
1767
|
-
let colorsEnabled;
|
|
1768
|
-
if (compilerOptions.stats &&
|
|
1769
|
-
typeof compilerOptions.stats.colors !==
|
|
1770
|
-
'undefined') {
|
|
1771
|
-
colorsEnabled = compilerOptions.stats
|
|
1772
|
-
.colors;
|
|
1773
|
-
}
|
|
1774
|
-
else {
|
|
1775
|
-
colorsEnabled = isColorSupported;
|
|
1776
|
-
}
|
|
1777
|
-
return colorsEnabled;
|
|
1778
|
-
};
|
|
1779
|
-
const colors = {
|
|
1780
|
-
info(useColor, msg) {
|
|
1781
|
-
if (useColor) {
|
|
1782
|
-
return cyan(msg);
|
|
1783
|
-
}
|
|
1784
|
-
return msg;
|
|
1785
|
-
},
|
|
1786
|
-
error(useColor, msg) {
|
|
1787
|
-
if (useColor) {
|
|
1788
|
-
return red(msg);
|
|
1789
|
-
}
|
|
1790
|
-
return msg;
|
|
1791
|
-
},
|
|
1792
|
-
};
|
|
1793
|
-
const useColor = getColorsOption(this.getCompilerOptions());
|
|
1794
1604
|
const server = this.server;
|
|
1795
1605
|
if (this.options.ipc) {
|
|
1796
1606
|
this.logger.info(`Project is running at: "${server?.address()}"`);
|
|
@@ -1803,28 +1613,13 @@ class Server {
|
|
|
1803
1613
|
}
|
|
1804
1614
|
const { address, port } = addressInfo;
|
|
1805
1615
|
const prettyPrintURL = (newHostname) => url.format({ protocol, hostname: newHostname, port, pathname: '/' });
|
|
1806
|
-
let host;
|
|
1807
1616
|
let localhost;
|
|
1808
1617
|
let loopbackIPv4;
|
|
1809
1618
|
let loopbackIPv6;
|
|
1810
1619
|
let networkUrlIPv4;
|
|
1811
1620
|
let networkUrlIPv6;
|
|
1812
|
-
if (this.options.host) {
|
|
1813
|
-
|
|
1814
|
-
localhost = prettyPrintURL('localhost');
|
|
1815
|
-
}
|
|
1816
|
-
else {
|
|
1817
|
-
let isIP;
|
|
1818
|
-
try {
|
|
1819
|
-
isIP = ipaddr.parse(this.options.host);
|
|
1820
|
-
}
|
|
1821
|
-
catch {
|
|
1822
|
-
// Ignore
|
|
1823
|
-
}
|
|
1824
|
-
if (!isIP) {
|
|
1825
|
-
host = prettyPrintURL(this.options.host);
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1621
|
+
if (this.options.host === 'localhost') {
|
|
1622
|
+
localhost = prettyPrintURL('localhost');
|
|
1828
1623
|
}
|
|
1829
1624
|
const parsedIP = ipaddr.parse(address);
|
|
1830
1625
|
if (parsedIP.range() === 'unspecified') {
|
|
@@ -1856,28 +1651,19 @@ class Server {
|
|
|
1856
1651
|
networkUrlIPv6 = prettyPrintURL(address);
|
|
1857
1652
|
}
|
|
1858
1653
|
}
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
if (localhost || loopbackIPv4 || loopbackIPv6) {
|
|
1864
|
-
const loopbacks = [];
|
|
1865
|
-
if (localhost) {
|
|
1866
|
-
loopbacks.push([colors.info(useColor, localhost)]);
|
|
1867
|
-
}
|
|
1868
|
-
if (loopbackIPv4) {
|
|
1869
|
-
loopbacks.push([colors.info(useColor, loopbackIPv4)]);
|
|
1870
|
-
}
|
|
1871
|
-
if (loopbackIPv6) {
|
|
1872
|
-
loopbacks.push([colors.info(useColor, loopbackIPv6)]);
|
|
1873
|
-
}
|
|
1874
|
-
this.logger.info(`Loopback: ${loopbacks.join(', ')}`);
|
|
1654
|
+
const urlLogs = [];
|
|
1655
|
+
const local = localhost || loopbackIPv4 || loopbackIPv6;
|
|
1656
|
+
if (local) {
|
|
1657
|
+
urlLogs.push(` ${styleText('white', '➜')} ${styleText(['white', 'dim'], 'Local:')} ${styleText('cyan', local)}`);
|
|
1875
1658
|
}
|
|
1876
1659
|
if (networkUrlIPv4) {
|
|
1877
|
-
|
|
1660
|
+
urlLogs.push(` ${styleText('white', '➜')} ${styleText(['white', 'dim'], 'Network:')} ${styleText('cyan', networkUrlIPv4)}`);
|
|
1661
|
+
}
|
|
1662
|
+
else if (networkUrlIPv6) {
|
|
1663
|
+
urlLogs.push(` ${styleText('white', '➜')} ${styleText(['white', 'dim'], 'Network:')} ${styleText('cyan', networkUrlIPv6)}`);
|
|
1878
1664
|
}
|
|
1879
|
-
if (
|
|
1880
|
-
|
|
1665
|
+
if (urlLogs.length && this.shouldLogInfrastructureInfo()) {
|
|
1666
|
+
console.log(`${urlLogs.join('\n')}\n`);
|
|
1881
1667
|
}
|
|
1882
1668
|
if (this.options.open?.length > 0) {
|
|
1883
1669
|
const openTarget = prettyPrintURL(!this.options.host ||
|
|
@@ -1888,22 +1674,6 @@ class Server {
|
|
|
1888
1674
|
await this.openBrowser(openTarget);
|
|
1889
1675
|
}
|
|
1890
1676
|
}
|
|
1891
|
-
if (this.options.static?.length > 0) {
|
|
1892
|
-
this.logger.info(`Content not from webpack is served from '${colors.info(useColor, this.options.static
|
|
1893
|
-
.map((staticOption) => staticOption.directory)
|
|
1894
|
-
.join(', '))}' directory`);
|
|
1895
|
-
}
|
|
1896
|
-
if (this.options.historyApiFallback) {
|
|
1897
|
-
this.logger.info(`404s will fallback to '${colors.info(useColor, this.options.historyApiFallback
|
|
1898
|
-
.index || '/index.html')}'`);
|
|
1899
|
-
}
|
|
1900
|
-
if (this.options.bonjour) {
|
|
1901
|
-
const bonjourProtocol = this.options.bonjour?.type ||
|
|
1902
|
-
this.isTlsServer
|
|
1903
|
-
? 'https'
|
|
1904
|
-
: 'http';
|
|
1905
|
-
this.logger.info(`Broadcasting "${bonjourProtocol}" with subtype of "webpack" via ZeroConf DNS (Bonjour)`);
|
|
1906
|
-
}
|
|
1907
1677
|
}
|
|
1908
1678
|
setHeaders(req, res, next) {
|
|
1909
1679
|
let { headers } = this.options;
|
|
@@ -1971,12 +1741,7 @@ class Server {
|
|
|
1971
1741
|
if (DEFAULT_ALLOWED_PROTOCOLS.test(header)) {
|
|
1972
1742
|
return true;
|
|
1973
1743
|
}
|
|
1974
|
-
|
|
1975
|
-
// TODO resolve me in the next major release
|
|
1976
|
-
// eslint-disable-next-line n/no-deprecated-api
|
|
1977
|
-
const { hostname } = url.parse(
|
|
1978
|
-
// if header doesn't have scheme, add // for parsing.
|
|
1979
|
-
/^(.+:)?\/\//.test(header) ? header : `//${header}`, false, true);
|
|
1744
|
+
const hostname = parseHostnameFromHeader(header);
|
|
1980
1745
|
if (hostname === null) {
|
|
1981
1746
|
return false;
|
|
1982
1747
|
}
|
|
@@ -1987,8 +1752,8 @@ class Server {
|
|
|
1987
1752
|
// A note on IPv6 addresses:
|
|
1988
1753
|
// header will always contain the brackets denoting
|
|
1989
1754
|
// an IPv6-address in URLs,
|
|
1990
|
-
// these are removed from
|
|
1991
|
-
// so we
|
|
1755
|
+
// these are not removed from `URL#hostname`,
|
|
1756
|
+
// so we normalize to a pure IPv6-address when parsing.
|
|
1992
1757
|
// For convenience, always allow localhost (hostname === 'localhost')
|
|
1993
1758
|
// and its subdomains (hostname.endsWith(".localhost")).
|
|
1994
1759
|
// allow hostname of listening address (hostname === this.options.host)
|
|
@@ -2012,9 +1777,7 @@ class Server {
|
|
|
2012
1777
|
if (DEFAULT_ALLOWED_PROTOCOLS.test(originHeader)) {
|
|
2013
1778
|
return true;
|
|
2014
1779
|
}
|
|
2015
|
-
|
|
2016
|
-
// eslint-disable-next-line n/no-deprecated-api
|
|
2017
|
-
const origin = url.parse(originHeader, false, true).hostname;
|
|
1780
|
+
const origin = parseHostnameFromHeader(originHeader);
|
|
2018
1781
|
if (origin === null) {
|
|
2019
1782
|
return false;
|
|
2020
1783
|
}
|
|
@@ -2028,10 +1791,7 @@ class Server {
|
|
|
2028
1791
|
if (DEFAULT_ALLOWED_PROTOCOLS.test(hostHeader)) {
|
|
2029
1792
|
return true;
|
|
2030
1793
|
}
|
|
2031
|
-
|
|
2032
|
-
const host = url.parse(
|
|
2033
|
-
// if hostHeader doesn't have scheme, add // for parsing.
|
|
2034
|
-
/^(.+:)?\/\//.test(hostHeader) ? hostHeader : `//${hostHeader}`, false, true).hostname;
|
|
1794
|
+
const host = parseHostnameFromHeader(hostHeader);
|
|
2035
1795
|
if (host === null) {
|
|
2036
1796
|
return false;
|
|
2037
1797
|
}
|
|
@@ -2042,8 +1802,7 @@ class Server {
|
|
|
2042
1802
|
}
|
|
2043
1803
|
sendMessage(clients, type, data, params) {
|
|
2044
1804
|
for (const client of clients) {
|
|
2045
|
-
// `
|
|
2046
|
-
// `ws` uses `WebSocket.OPEN`, but it is mean `1` too
|
|
1805
|
+
// `ws` uses `WebSocket.OPEN` to indicate client is ready to accept data
|
|
2047
1806
|
if (client.readyState === 1) {
|
|
2048
1807
|
client.send(JSON.stringify({ type, data, params }));
|
|
2049
1808
|
}
|
|
@@ -2147,9 +1906,6 @@ class Server {
|
|
|
2147
1906
|
if (this.options.webSocketServer) {
|
|
2148
1907
|
this.createWebSocketServer();
|
|
2149
1908
|
}
|
|
2150
|
-
if (this.options.bonjour) {
|
|
2151
|
-
this.runBonjour();
|
|
2152
|
-
}
|
|
2153
1909
|
await this.logStatus();
|
|
2154
1910
|
if (typeof this.options.onListening === 'function') {
|
|
2155
1911
|
this.options.onListening(this);
|
|
@@ -2161,13 +1917,6 @@ class Server {
|
|
|
2161
1917
|
.catch(callback);
|
|
2162
1918
|
}
|
|
2163
1919
|
async stop() {
|
|
2164
|
-
if (this.bonjour) {
|
|
2165
|
-
await new Promise((resolve) => {
|
|
2166
|
-
this.stopBonjour(() => {
|
|
2167
|
-
resolve();
|
|
2168
|
-
});
|
|
2169
|
-
});
|
|
2170
|
-
}
|
|
2171
1920
|
this.webSocketProxies = [];
|
|
2172
1921
|
await Promise.all(this.staticWatchers.map((watcher) => watcher.close()));
|
|
2173
1922
|
this.staticWatchers = [];
|