@rspack/dev-server 0.0.0-0074001a71-20230224065505

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.
Files changed (108) hide show
  1. package/CHANGELOG.md +234 -0
  2. package/LICENSE +22 -0
  3. package/README.md +16 -0
  4. package/dist/config.d.ts +25 -0
  5. package/dist/config.d.ts.map +1 -0
  6. package/dist/config.js +3 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +6 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/reload.d.ts +9 -0
  13. package/dist/reload.d.ts.map +1 -0
  14. package/dist/reload.js +23 -0
  15. package/dist/reload.js.map +1 -0
  16. package/dist/server.d.ts +28 -0
  17. package/dist/server.d.ts.map +1 -0
  18. package/dist/server.js +401 -0
  19. package/dist/server.js.map +1 -0
  20. package/jest.config.js +10 -0
  21. package/package.json +40 -0
  22. package/src/config.ts +27 -0
  23. package/src/index.ts +1 -0
  24. package/src/reload.ts +31 -0
  25. package/src/server.ts +474 -0
  26. package/tests/__snapshots__/normalizeOptions.test.ts.snap +232 -0
  27. package/tests/e2e/hot-reaload.test.ts +115 -0
  28. package/tests/e2e-fixtures/react/app.jsx +14 -0
  29. package/tests/e2e-fixtures/react/index.css +3 -0
  30. package/tests/e2e-fixtures/react/index.html +12 -0
  31. package/tests/e2e-fixtures/react/index.jsx +6 -0
  32. package/tests/e2e-fixtures/react/node_modules/react/LICENSE +21 -0
  33. package/tests/e2e-fixtures/react/node_modules/react/README.md +37 -0
  34. package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-dev-runtime.development.js +1296 -0
  35. package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-dev-runtime.production.min.js +10 -0
  36. package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-dev-runtime.profiling.min.js +10 -0
  37. package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-runtime.development.js +1314 -0
  38. package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-runtime.production.min.js +11 -0
  39. package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-runtime.profiling.min.js +11 -0
  40. package/tests/e2e-fixtures/react/node_modules/react/cjs/react.development.js +2739 -0
  41. package/tests/e2e-fixtures/react/node_modules/react/cjs/react.production.min.js +26 -0
  42. package/tests/e2e-fixtures/react/node_modules/react/cjs/react.shared-subset.development.js +20 -0
  43. package/tests/e2e-fixtures/react/node_modules/react/cjs/react.shared-subset.production.min.js +10 -0
  44. package/tests/e2e-fixtures/react/node_modules/react/index.js +7 -0
  45. package/tests/e2e-fixtures/react/node_modules/react/jsx-dev-runtime.js +7 -0
  46. package/tests/e2e-fixtures/react/node_modules/react/jsx-runtime.js +7 -0
  47. package/tests/e2e-fixtures/react/node_modules/react/package.json +47 -0
  48. package/tests/e2e-fixtures/react/node_modules/react/react.shared-subset.js +7 -0
  49. package/tests/e2e-fixtures/react/node_modules/react/umd/react.development.js +3342 -0
  50. package/tests/e2e-fixtures/react/node_modules/react/umd/react.production.min.js +31 -0
  51. package/tests/e2e-fixtures/react/node_modules/react/umd/react.profiling.min.js +31 -0
  52. package/tests/e2e-fixtures/react/node_modules/react-dom/LICENSE +21 -0
  53. package/tests/e2e-fixtures/react/node_modules/react-dom/README.md +60 -0
  54. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server-legacy.browser.development.js +7018 -0
  55. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +93 -0
  56. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js +7078 -0
  57. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.min.js +101 -0
  58. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server.browser.development.js +7003 -0
  59. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js +96 -0
  60. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server.node.development.js +7059 -0
  61. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server.node.production.min.js +102 -0
  62. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-test-utils.development.js +1741 -0
  63. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-test-utils.production.min.js +40 -0
  64. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom.development.js +29868 -0
  65. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom.production.min.js +323 -0
  66. package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom.profiling.min.js +367 -0
  67. package/tests/e2e-fixtures/react/node_modules/react-dom/client.js +25 -0
  68. package/tests/e2e-fixtures/react/node_modules/react-dom/index.js +38 -0
  69. package/tests/e2e-fixtures/react/node_modules/react-dom/package.json +62 -0
  70. package/tests/e2e-fixtures/react/node_modules/react-dom/profiling.js +38 -0
  71. package/tests/e2e-fixtures/react/node_modules/react-dom/server.browser.js +17 -0
  72. package/tests/e2e-fixtures/react/node_modules/react-dom/server.js +3 -0
  73. package/tests/e2e-fixtures/react/node_modules/react-dom/server.node.js +17 -0
  74. package/tests/e2e-fixtures/react/node_modules/react-dom/test-utils.js +7 -0
  75. package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-server-legacy.browser.development.js +7015 -0
  76. package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-server-legacy.browser.production.min.js +75 -0
  77. package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-server.browser.development.js +7000 -0
  78. package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-server.browser.production.min.js +76 -0
  79. package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-test-utils.development.js +1737 -0
  80. package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-test-utils.production.min.js +33 -0
  81. package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom.development.js +29869 -0
  82. package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom.production.min.js +267 -0
  83. package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom.profiling.min.js +285 -0
  84. package/tests/e2e-fixtures/react/node_modules/scheduler/LICENSE +21 -0
  85. package/tests/e2e-fixtures/react/node_modules/scheduler/README.md +9 -0
  86. package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler-unstable_mock.development.js +700 -0
  87. package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler-unstable_mock.production.min.js +20 -0
  88. package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler-unstable_post_task.development.js +207 -0
  89. package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler-unstable_post_task.production.min.js +14 -0
  90. package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler.development.js +634 -0
  91. package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler.production.min.js +19 -0
  92. package/tests/e2e-fixtures/react/node_modules/scheduler/index.js +7 -0
  93. package/tests/e2e-fixtures/react/node_modules/scheduler/package.json +36 -0
  94. package/tests/e2e-fixtures/react/node_modules/scheduler/umd/scheduler-unstable_mock.development.js +699 -0
  95. package/tests/e2e-fixtures/react/node_modules/scheduler/umd/scheduler-unstable_mock.production.min.js +19 -0
  96. package/tests/e2e-fixtures/react/node_modules/scheduler/umd/scheduler.development.js +152 -0
  97. package/tests/e2e-fixtures/react/node_modules/scheduler/umd/scheduler.production.min.js +146 -0
  98. package/tests/e2e-fixtures/react/node_modules/scheduler/umd/scheduler.profiling.min.js +146 -0
  99. package/tests/e2e-fixtures/react/node_modules/scheduler/unstable_mock.js +7 -0
  100. package/tests/e2e-fixtures/react/node_modules/scheduler/unstable_post_task.js +7 -0
  101. package/tests/e2e-fixtures/react/package.json +8 -0
  102. package/tests/e2e-fixtures/react/webpack.config.js +26 -0
  103. package/tests/helpers/emitFile.ts +69 -0
  104. package/tests/helpers/runBrowser.ts +85 -0
  105. package/tests/helpers/tempDir.ts +58 -0
  106. package/tests/normalizeOptions.test.ts +107 -0
  107. package/tsconfig.json +15 -0
  108. package/tsconfig.tsbuildinfo +1 -0
package/src/server.ts ADDED
@@ -0,0 +1,474 @@
1
+ import { Compiler, MultiCompiler } from "@rspack/core";
2
+ import type { Socket } from "net";
3
+ import type { FSWatcher, WatchOptions } from "chokidar";
4
+ import rdm, { getRspackMemoryAssets } from "@rspack/dev-middleware";
5
+ import type { Server } from "http";
6
+ import fs from "fs";
7
+ import WebpackDevServer from "webpack-dev-server";
8
+ import type { ResolvedDevServer, DevServer } from "./config";
9
+
10
+ export class RspackDevServer extends WebpackDevServer {
11
+ /**
12
+ * resolved after `normalizedOptions`
13
+ */
14
+ options: ResolvedDevServer;
15
+ staticWatchers: FSWatcher[];
16
+ sockets: Socket[];
17
+ server: Server;
18
+ // @ts-expect-error
19
+ public compiler: Compiler | MultiCompiler;
20
+ webSocketServer: WebpackDevServer.WebSocketServerImplementation | undefined;
21
+
22
+ constructor(options: DevServer, compiler: Compiler | MultiCompiler) {
23
+ // @ts-expect-error
24
+ super(options, compiler);
25
+ }
26
+
27
+ addAdditionEntires(compiler: Compiler) {
28
+ const additionalEntries: string[] = [];
29
+ const isWebTarget = isWebTarget2(compiler);
30
+ if (this.options.client && isWebTarget) {
31
+ let webSocketURLStr = "";
32
+
33
+ if (this.options.webSocketServer) {
34
+ const webSocketURL = this.options.client
35
+ .webSocketURL as WebpackDevServer.WebSocketURL;
36
+ const webSocketServer = this.options.webSocketServer;
37
+ const searchParams = new URLSearchParams();
38
+
39
+ let protocol: string;
40
+
41
+ // We are proxying dev server and need to specify custom `hostname`
42
+ if (typeof webSocketURL.protocol !== "undefined") {
43
+ protocol = webSocketURL.protocol;
44
+ } else {
45
+ protocol = this.options.server.type === "http" ? "ws:" : "wss:";
46
+ }
47
+
48
+ searchParams.set("protocol", protocol);
49
+
50
+ if (typeof webSocketURL.username !== "undefined") {
51
+ searchParams.set("username", webSocketURL.username);
52
+ }
53
+
54
+ if (typeof webSocketURL.password !== "undefined") {
55
+ searchParams.set("password", webSocketURL.password);
56
+ }
57
+
58
+ let hostname: string;
59
+
60
+ // SockJS is not supported server mode, so `hostname` and `port` can't specified, let's ignore them
61
+ // TODO show warning about this
62
+ const isSockJSType = webSocketServer.type === "sockjs";
63
+
64
+ // We are proxying dev server and need to specify custom `hostname`
65
+ if (typeof webSocketURL.hostname !== "undefined") {
66
+ hostname = webSocketURL.hostname;
67
+ }
68
+ // Web socket server works on custom `hostname`, only for `ws` because `sock-js` is not support custom `hostname`
69
+ else if (
70
+ typeof webSocketServer.options.host !== "undefined" &&
71
+ !isSockJSType
72
+ ) {
73
+ hostname = webSocketServer.options.host;
74
+ }
75
+ // The `host` option is specified
76
+ else if (typeof this.options.host !== "undefined") {
77
+ hostname = this.options.host;
78
+ }
79
+ // The `port` option is not specified
80
+ else {
81
+ hostname = "0.0.0.0";
82
+ }
83
+
84
+ searchParams.set("hostname", hostname);
85
+
86
+ let port: number | string;
87
+
88
+ // We are proxying dev server and need to specify custom `port`
89
+ if (typeof webSocketURL.port !== "undefined") {
90
+ port = webSocketURL.port;
91
+ }
92
+ // Web socket server works on custom `port`, only for `ws` because `sock-js` is not support custom `port`
93
+ else if (
94
+ typeof webSocketServer.options.port !== "undefined" &&
95
+ !isSockJSType
96
+ ) {
97
+ port = webSocketServer.options.port;
98
+ }
99
+ // The `port` option is specified
100
+ else if (typeof this.options.port === "number") {
101
+ port = this.options.port;
102
+ }
103
+ // The `port` option is specified using `string`
104
+ else if (
105
+ typeof this.options.port === "string" &&
106
+ this.options.port !== "auto"
107
+ ) {
108
+ port = Number(this.options.port);
109
+ }
110
+ // The `port` option is not specified or set to `auto`
111
+ else {
112
+ port = "0";
113
+ }
114
+
115
+ searchParams.set("port", String(port));
116
+
117
+ let pathname = "";
118
+
119
+ // We are proxying dev server and need to specify custom `pathname`
120
+ if (typeof webSocketURL.pathname !== "undefined") {
121
+ pathname = webSocketURL.pathname;
122
+ }
123
+ // Web socket server works on custom `path`
124
+ else if (
125
+ typeof webSocketServer.options.prefix !== "undefined" ||
126
+ typeof webSocketServer.options.path !== "undefined"
127
+ ) {
128
+ pathname =
129
+ webSocketServer.options.prefix || webSocketServer.options.path;
130
+ }
131
+
132
+ searchParams.set("pathname", pathname);
133
+
134
+ const client = /** @type {ClientConfiguration} */ this.options.client;
135
+
136
+ if (typeof client.logging !== "undefined") {
137
+ searchParams.set("logging", client.logging);
138
+ }
139
+
140
+ if (typeof client.progress !== "undefined") {
141
+ searchParams.set("progress", String(client.progress));
142
+ }
143
+
144
+ if (typeof client.overlay !== "undefined") {
145
+ searchParams.set(
146
+ "overlay",
147
+ typeof client.overlay === "boolean"
148
+ ? String(client.overlay)
149
+ : JSON.stringify(client.overlay)
150
+ );
151
+ }
152
+
153
+ if (typeof client.reconnect !== "undefined") {
154
+ searchParams.set(
155
+ "reconnect",
156
+ typeof client.reconnect === "number"
157
+ ? String(client.reconnect)
158
+ : "10"
159
+ );
160
+ }
161
+
162
+ if (typeof this.options.hot !== "undefined") {
163
+ searchParams.set("hot", String(this.options.hot));
164
+ }
165
+
166
+ if (typeof this.options.liveReload !== "undefined") {
167
+ searchParams.set("live-reload", String(this.options.liveReload));
168
+ }
169
+
170
+ webSocketURLStr = searchParams.toString();
171
+ }
172
+
173
+ // TODO: should use providerPlugin
174
+ additionalEntries.push(this.getClientTransport());
175
+
176
+ additionalEntries.push(
177
+ `${require.resolve("@rspack/dev-client")}?${webSocketURLStr}`
178
+ );
179
+ }
180
+
181
+ if (this.options.hot) {
182
+ const hotUpdateEntryPath = require.resolve(
183
+ "@rspack/dev-client/devServer"
184
+ );
185
+ additionalEntries.push(hotUpdateEntryPath);
186
+
187
+ if (compiler.options.builtins.react?.refresh) {
188
+ const reactRefreshEntryPath = require.resolve(
189
+ "@rspack/dev-client/react-refresh"
190
+ );
191
+ additionalEntries.push(reactRefreshEntryPath);
192
+ }
193
+ }
194
+
195
+ for (const key in compiler.options.entry) {
196
+ compiler.options.entry[key].import.unshift(...additionalEntries);
197
+ }
198
+ }
199
+
200
+ watchFiles(watchPath: string | string[], watchOptions?: WatchOptions): void {
201
+ const chokidar = require("chokidar");
202
+ const watcher = chokidar.watch(watchPath, watchOptions);
203
+
204
+ // disabling refreshing on changing the content
205
+ if (this.options.liveReload) {
206
+ // TODO: remove this after we had memory filesystem
207
+ if (this.options.hot) {
208
+ return;
209
+ }
210
+
211
+ watcher.on("change", item => {
212
+ if (this.webSocketServer) {
213
+ this.sendMessage(
214
+ this.webSocketServer.clients,
215
+ "static-changed",
216
+ item
217
+ );
218
+ }
219
+ });
220
+ }
221
+
222
+ this.staticWatchers.push(watcher);
223
+ }
224
+
225
+ getClientTransport(): string {
226
+ // WARNING: we can't use `super.getClientTransport`,
227
+ // because we doesn't had same directory structure.
228
+ // and TODO: we need impelement `webpack.providerPlugin`
229
+ let clientImplementation: string | undefined;
230
+ let clientImplementationFound = true;
231
+ const isKnownWebSocketServerImplementation =
232
+ this.options.webSocketServer &&
233
+ typeof this.options.webSocketServer.type === "string" &&
234
+ (this.options.webSocketServer.type === "ws" ||
235
+ this.options.webSocketServer.type === "sockjs");
236
+
237
+ let clientTransport: string | undefined;
238
+
239
+ if (this.options.client) {
240
+ if (
241
+ // @ts-ignore
242
+ typeof this.options.client.webSocketTransport !== "undefined"
243
+ ) {
244
+ // @ts-ignore
245
+ clientTransport = this.options.client.webSocketTransport;
246
+ } else if (isKnownWebSocketServerImplementation) {
247
+ // @ts-ignore
248
+ clientTransport = this.options.webSocketServer.type;
249
+ } else {
250
+ clientTransport = "ws";
251
+ }
252
+ } else {
253
+ clientTransport = "ws";
254
+ }
255
+
256
+ switch (typeof clientTransport) {
257
+ case "string":
258
+ // could be 'sockjs', 'ws', or a path that should be required
259
+ if (clientTransport === "sockjs") {
260
+ clientImplementation = require.resolve(
261
+ "@rspack/dev-client/clients/SockJSClient"
262
+ );
263
+ } else if (clientTransport === "ws") {
264
+ clientImplementation = require.resolve(
265
+ "@rspack/dev-client/clients/WebSocketClient"
266
+ );
267
+ } else {
268
+ try {
269
+ clientImplementation = require.resolve(clientTransport);
270
+ throw Error("Do not support custom ws client now");
271
+ } catch (e) {
272
+ clientImplementationFound = false;
273
+ }
274
+ }
275
+ break;
276
+ default:
277
+ clientImplementationFound = false;
278
+ }
279
+ if (!clientImplementationFound) {
280
+ throw new Error(
281
+ `${
282
+ !isKnownWebSocketServerImplementation
283
+ ? "When you use custom web socket implementation you must explicitly specify client.webSocketTransport. "
284
+ : ""
285
+ }client.webSocketTransport must be a string denoting a default implementation (e.g. 'sockjs', 'ws') or a full path to a JS file via require.resolve(...) which exports a class `
286
+ );
287
+ }
288
+
289
+ return clientImplementation;
290
+ }
291
+
292
+ async initialize() {
293
+ const compilers =
294
+ this.compiler instanceof MultiCompiler
295
+ ? this.compiler.compilers
296
+ : [this.compiler];
297
+
298
+ compilers.forEach(compiler => {
299
+ compiler.options.builtins.react ??= {};
300
+ if (this.options.hot) {
301
+ compiler.options.builtins.react.refresh ??= true;
302
+ compiler.options.builtins.react.development ??= true;
303
+ } else if (compiler.options.builtins.react.refresh) {
304
+ this.logger.warn(
305
+ "builtins.react.refresh needs builtins.react.development and devServer.hot enabled"
306
+ );
307
+ }
308
+ });
309
+
310
+ if (this.options.webSocketServer) {
311
+ compilers.forEach(compiler => {
312
+ this.addAdditionEntires(compiler);
313
+ });
314
+ }
315
+
316
+ this.setupHooks();
317
+ // @ts-expect-error: `setupApp` is private function in base class.
318
+ this.setupApp();
319
+ // @ts-expect-error: `setupHostHeaderCheck` is private function in base class.
320
+ this.setupHostHeaderCheck();
321
+ this.setupDevMiddleware();
322
+ // @ts-expect-error: `setupBuiltInRoutes` is private function in base class.
323
+ this.setupBuiltInRoutes();
324
+ // @ts-expect-error: `setupWatchFiles` is private function in base class.
325
+ this.setupWatchFiles();
326
+ // @ts-expect-error: `setupWatchStaticFiles` is private function in base class.
327
+ this.setupWatchStaticFiles();
328
+ this.setupMiddlewares();
329
+ // @ts-expect-error: `createServer` is private function in base class.
330
+ this.createServer();
331
+
332
+ if (this.options.setupExitSignals) {
333
+ const signals = ["SIGINT", "SIGTERM"];
334
+
335
+ let needForceShutdown = false;
336
+
337
+ signals.forEach(signal => {
338
+ const listener = () => {
339
+ if (needForceShutdown) {
340
+ process.exit();
341
+ }
342
+
343
+ this.logger.info(
344
+ "Gracefully shutting down. To force exit, press ^C again. Please wait..."
345
+ );
346
+
347
+ needForceShutdown = true;
348
+
349
+ this.stopCallback(() => {
350
+ if (typeof this.compiler.close === "function") {
351
+ this.compiler.close(() => {
352
+ process.exit();
353
+ });
354
+ } else {
355
+ process.exit();
356
+ }
357
+ });
358
+ };
359
+
360
+ // @ts-expect-error: `listeners` is private function in base class.
361
+ this.listeners.push({ name: signal, listener });
362
+
363
+ process.on(signal, listener);
364
+ });
365
+ }
366
+
367
+ // Proxy WebSocket without the initial http request
368
+ // https://github.com/chimurai/http-proxy-middleware#external-websocket-upgrade
369
+ // @ts-expect-error: `webSocketProxies` is private function in base class.
370
+ this.webSocketProxies.forEach(webSocketProxy => {
371
+ this.server.on("upgrade", webSocketProxy.upgrade);
372
+ }, this);
373
+ }
374
+
375
+ private setupDevMiddleware() {
376
+ // @ts-ignored
377
+ this.middleware = rdm(this.compiler, this.options.devMiddleware);
378
+ }
379
+
380
+ private setupMiddlewares() {
381
+ const middlewares: WebpackDevServer.Middleware[] = [];
382
+ const compilers =
383
+ this.compiler instanceof MultiCompiler
384
+ ? this.compiler.compilers
385
+ : [this.compiler];
386
+
387
+ if (Array.isArray(this.options.static)) {
388
+ this.options.static.forEach(staticOptions => {
389
+ staticOptions.publicPath.forEach(publicPath => {
390
+ compilers.forEach(compiler => {
391
+ if (compiler.options.builtins.noEmitAssets) {
392
+ middlewares.push({
393
+ name: "rspack-memory-assets",
394
+ path: publicPath,
395
+ middleware: getRspackMemoryAssets(compiler, this.middleware)
396
+ });
397
+ }
398
+ });
399
+ });
400
+ });
401
+ }
402
+
403
+ compilers.forEach(compiler => {
404
+ if (compiler.options.experiments.lazyCompilation) {
405
+ middlewares.push({
406
+ middleware: (req, res, next) => {
407
+ if (req.url.indexOf("/lazy-compilation-web/") > -1) {
408
+ const path = req.url.replace("/lazy-compilation-web/", "");
409
+ if (fs.existsSync(path)) {
410
+ compiler.rebuild(new Set([path]), new Set(), error => {
411
+ if (error) {
412
+ throw error;
413
+ }
414
+ res.write("");
415
+ res.end();
416
+ console.log("lazy compiler success");
417
+ });
418
+ }
419
+ }
420
+ }
421
+ });
422
+ }
423
+ });
424
+
425
+ middlewares.forEach(middleware => {
426
+ if (typeof middleware === "function") {
427
+ this.app.use(middleware);
428
+ } else if (typeof middleware.path !== "undefined") {
429
+ this.app.use(middleware.path, middleware.middleware);
430
+ } else {
431
+ this.app.use(middleware.middleware);
432
+ }
433
+ });
434
+
435
+ // @ts-expect-error
436
+ super.setupMiddlewares();
437
+ }
438
+
439
+ private setupHooks() {
440
+ this.compiler.hooks.done.tap("dev-server", stats => {
441
+ // send Message
442
+ if (this.webSocketServer) {
443
+ this.sendMessage(this.webSocketServer.clients, "ok"); // TODO: send hash
444
+ }
445
+ });
446
+ }
447
+ }
448
+
449
+ // TODO: use WebpackDevServer.isWebTarget instead of this once we have a new webpack-dev-server version
450
+ function isWebTarget2(compiler: Compiler): boolean {
451
+ if (
452
+ compiler.options.resolve.conditionNames &&
453
+ compiler.options.resolve.conditionNames.includes("browser")
454
+ ) {
455
+ return true;
456
+ }
457
+ const target = compiler.options.target;
458
+ const webTargets = [
459
+ "web",
460
+ "webworker",
461
+ "electron-preload",
462
+ "electron-renderer",
463
+ "node-webkit",
464
+ undefined,
465
+ null
466
+ ];
467
+ if (Array.isArray(target)) {
468
+ return target.some(r => webTargets.includes(r));
469
+ }
470
+ if (typeof target === "string") {
471
+ return webTargets.includes(target);
472
+ }
473
+ return false;
474
+ }
@@ -0,0 +1,232 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`normalize options snapshot additional entires should added 1`] = `
4
+ {
5
+ "main": [
6
+ "<prefix>/dist/clients/WebSocketClient.js",
7
+ "<prefix>/rspack-dev-client/dist/index.js?protocol=ws%3A&hostname=0.0.0.0&port=8080&pathname=%2Fws&logging=info&overlay=true&reconnect=10&hot=true&live-reload=true",
8
+ "<prefix>/rspack-dev-client/dist/devServer.js",
9
+ "<prefix>/rspack-dev-client/dist/reactRefresh.js",
10
+ "<prefix>/something",
11
+ ],
12
+ }
13
+ `;
14
+
15
+ exports[`normalize options snapshot no options 1`] = `
16
+ {
17
+ "allowedHosts": "auto",
18
+ "bonjour": false,
19
+ "client": {
20
+ "logging": "info",
21
+ "overlay": true,
22
+ "reconnect": 10,
23
+ "webSocketURL": {},
24
+ },
25
+ "compress": true,
26
+ "devMiddleware": {},
27
+ "historyApiFallback": false,
28
+ "host": undefined,
29
+ "hot": true,
30
+ "liveReload": true,
31
+ "magicHtml": true,
32
+ "open": [],
33
+ "port": 8080,
34
+ "server": {
35
+ "options": {},
36
+ "type": "http",
37
+ },
38
+ "setupExitSignals": true,
39
+ "static": [
40
+ {
41
+ "directory": "<PROJECT_ROOT>/public",
42
+ "publicPath": [
43
+ "/",
44
+ ],
45
+ "serveIndex": {
46
+ "icons": true,
47
+ },
48
+ "staticOptions": {},
49
+ "watch": {
50
+ "alwaysStat": true,
51
+ "atomic": false,
52
+ "followSymlinks": false,
53
+ "ignoreInitial": true,
54
+ "ignorePermissionErrors": true,
55
+ "ignored": undefined,
56
+ "interval": undefined,
57
+ "persistent": true,
58
+ "usePolling": false,
59
+ },
60
+ },
61
+ ],
62
+ "watchFiles": [],
63
+ "webSocketServer": {
64
+ "options": {
65
+ "path": "/ws",
66
+ },
67
+ "type": "ws",
68
+ },
69
+ }
70
+ `;
71
+
72
+ exports[`normalize options snapshot port string 1`] = `
73
+ {
74
+ "allowedHosts": "auto",
75
+ "bonjour": false,
76
+ "client": {
77
+ "logging": "info",
78
+ "overlay": true,
79
+ "reconnect": 10,
80
+ "webSocketURL": {},
81
+ },
82
+ "compress": true,
83
+ "devMiddleware": {},
84
+ "historyApiFallback": false,
85
+ "host": undefined,
86
+ "hot": true,
87
+ "liveReload": true,
88
+ "magicHtml": true,
89
+ "open": [],
90
+ "port": 9000,
91
+ "server": {
92
+ "options": {},
93
+ "type": "http",
94
+ },
95
+ "setupExitSignals": true,
96
+ "static": [
97
+ {
98
+ "directory": "<PROJECT_ROOT>/public",
99
+ "publicPath": [
100
+ "/",
101
+ ],
102
+ "serveIndex": {
103
+ "icons": true,
104
+ },
105
+ "staticOptions": {},
106
+ "watch": {
107
+ "alwaysStat": true,
108
+ "atomic": false,
109
+ "followSymlinks": false,
110
+ "ignoreInitial": true,
111
+ "ignorePermissionErrors": true,
112
+ "ignored": undefined,
113
+ "interval": undefined,
114
+ "persistent": true,
115
+ "usePolling": false,
116
+ },
117
+ },
118
+ ],
119
+ "watchFiles": [],
120
+ "webSocketServer": {
121
+ "options": {
122
+ "path": "/ws",
123
+ },
124
+ "type": "ws",
125
+ },
126
+ }
127
+ `;
128
+
129
+ exports[`normalize options snapshot react.development and react.refresh should be true in default when hot enabled 1`] = `
130
+ {
131
+ "builtins": {
132
+ "copy": undefined,
133
+ "css": {
134
+ "modules": {
135
+ "exportsOnly": false,
136
+ "localIdentName": "[hash]",
137
+ "localsConvention": "asIs",
138
+ },
139
+ },
140
+ "decorator": {
141
+ "emitMetadata": true,
142
+ "legacy": true,
143
+ },
144
+ "define": {},
145
+ "devFriendlySplitChunks": false,
146
+ "emotion": undefined,
147
+ "html": [],
148
+ "minifyOptions": {
149
+ "dropConsole": false,
150
+ "passes": 1,
151
+ "pureFuncs": [],
152
+ },
153
+ "noEmitAssets": false,
154
+ "postcss": {
155
+ "pxtorem": undefined,
156
+ },
157
+ "presetEnv": undefined,
158
+ "progress": undefined,
159
+ "react": {
160
+ "development": true,
161
+ "refresh": true,
162
+ },
163
+ "treeShaking": true,
164
+ },
165
+ "devServer": {
166
+ "allowedHosts": "auto",
167
+ "bonjour": false,
168
+ "client": {
169
+ "logging": "info",
170
+ "overlay": true,
171
+ "reconnect": 10,
172
+ "webSocketURL": {},
173
+ },
174
+ "compress": true,
175
+ "devMiddleware": {},
176
+ "historyApiFallback": false,
177
+ "host": undefined,
178
+ "hot": true,
179
+ "liveReload": true,
180
+ "magicHtml": true,
181
+ "open": [],
182
+ "port": 8080,
183
+ "server": {
184
+ "options": {},
185
+ "type": "http",
186
+ },
187
+ "setupExitSignals": true,
188
+ "static": [
189
+ {
190
+ "directory": "<PROJECT_ROOT>/public",
191
+ "publicPath": [
192
+ "/",
193
+ ],
194
+ "serveIndex": {
195
+ "icons": true,
196
+ },
197
+ "staticOptions": {},
198
+ "watch": {
199
+ "alwaysStat": true,
200
+ "atomic": false,
201
+ "followSymlinks": false,
202
+ "ignoreInitial": true,
203
+ "ignorePermissionErrors": true,
204
+ "ignored": undefined,
205
+ "interval": undefined,
206
+ "persistent": true,
207
+ "usePolling": false,
208
+ },
209
+ },
210
+ ],
211
+ "watchFiles": [],
212
+ "webSocketServer": {
213
+ "options": {
214
+ "path": "/ws",
215
+ },
216
+ "type": "ws",
217
+ },
218
+ },
219
+ }
220
+ `;
221
+
222
+ exports[`normalize options snapshot react-refresh client added when react/refresh enabled 1`] = `
223
+ {
224
+ "main": [
225
+ "<prefix>/dist/clients/WebSocketClient.js",
226
+ "<prefix>/rspack-dev-client/dist/index.js?protocol=ws%3A&hostname=0.0.0.0&port=8080&pathname=%2Fws&logging=info&overlay=true&reconnect=10&hot=true&live-reload=true",
227
+ "<prefix>/rspack-dev-client/dist/devServer.js",
228
+ "<prefix>/rspack-dev-client/dist/reactRefresh.js",
229
+ "<prefix>/something",
230
+ ],
231
+ }
232
+ `;