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