@rspack/dev-server 0.0.21 → 0.0.23
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/CHANGELOG.md +42 -0
- package/LICENSE +2 -1
- package/dist/config.d.ts +20 -14
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -52
- package/dist/config.js.map +1 -1
- package/dist/server.d.ts +14 -41
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +330 -257
- package/dist/server.js.map +1 -1
- package/jest.config.js +3 -1
- package/package.json +14 -12
- package/src/config.ts +22 -67
- package/src/server.ts +374 -311
- package/tests/__snapshots__/normalizeOptions.test.ts.snap +164 -26
- package/tests/e2e/hot-reaload.test.ts +35 -39
- package/tests/e2e-fixtures/react/node_modules/scheduler/LICENSE +21 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/README.md +9 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler-unstable_mock.development.js +700 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler-unstable_mock.production.min.js +20 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler-unstable_post_task.development.js +207 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler-unstable_post_task.production.min.js +14 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler.development.js +634 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/cjs/scheduler.production.min.js +19 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/index.js +7 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/package.json +36 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/umd/scheduler-unstable_mock.development.js +699 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/umd/scheduler-unstable_mock.production.min.js +19 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/umd/scheduler.development.js +152 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/umd/scheduler.production.min.js +146 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/umd/scheduler.profiling.min.js +146 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/unstable_mock.js +7 -0
- package/tests/e2e-fixtures/react/node_modules/scheduler/unstable_post_task.js +7 -0
- package/tests/e2e-fixtures/react/package.json +2 -0
- package/tests/e2e-fixtures/react/webpack.config.js +6 -2
- package/tests/helpers/emitFile.ts +58 -4
- package/tests/normalizeOptions.test.ts +50 -16
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/logger.d.ts +0 -7
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -28
- package/dist/logger.js.map +0 -1
- package/dist/ws.d.ts +0 -13
- package/dist/ws.d.ts.map +0 -1
- package/dist/ws.js +0 -12
- package/dist/ws.js.map +0 -1
- package/src/logger.ts +0 -30
- package/src/ws.ts +0 -18
package/src/server.ts
CHANGED
|
@@ -1,154 +1,204 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { Logger } from "./logger";
|
|
1
|
+
import { Compiler, MultiCompiler } from "@rspack/core";
|
|
3
2
|
import type { Socket } from "net";
|
|
4
3
|
import type { FSWatcher, WatchOptions } from "chokidar";
|
|
5
|
-
import
|
|
6
|
-
import type {
|
|
7
|
-
Application,
|
|
8
|
-
RequestHandler as ExpressRequestHandler,
|
|
9
|
-
ErrorRequestHandler as ExpressErrorRequestHandler
|
|
10
|
-
} from "express";
|
|
11
|
-
import type { DevMiddleware } from "@rspack/dev-middleware";
|
|
4
|
+
import rdm, { getRspackMemoryAssets } from "@rspack/dev-middleware";
|
|
12
5
|
import type { Server } from "http";
|
|
13
|
-
import type { ResolvedDev } from "./config";
|
|
14
6
|
import fs from "fs";
|
|
15
|
-
import chokidar from "chokidar";
|
|
16
|
-
import http from "http";
|
|
17
|
-
import { createLogger } from "./logger";
|
|
18
7
|
import WebpackDevServer from "webpack-dev-server";
|
|
19
|
-
import
|
|
8
|
+
import type { ResolvedDevServer, DevServer } from "./config";
|
|
20
9
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
name?: string;
|
|
27
|
-
path?: string;
|
|
28
|
-
middleware: ExpressErrorRequestHandler | ExpressRequestHandler;
|
|
29
|
-
}
|
|
30
|
-
interface Listener {
|
|
31
|
-
name: string | Symbol;
|
|
32
|
-
listener: (...args: any) => void;
|
|
33
|
-
}
|
|
34
|
-
type Host = "local-ip" | "local-ipv4" | "local-ipv6" | string;
|
|
35
|
-
type Port = number | string | "auto";
|
|
36
|
-
|
|
37
|
-
// copy from webpack-dev-server
|
|
38
|
-
export class RspackDevServer {
|
|
39
|
-
options: ResolvedDev;
|
|
40
|
-
logger: Logger;
|
|
10
|
+
export class RspackDevServer extends WebpackDevServer {
|
|
11
|
+
/**
|
|
12
|
+
* resolved after `normalizedOptions`
|
|
13
|
+
*/
|
|
14
|
+
options: ResolvedDevServer;
|
|
41
15
|
staticWatchers: FSWatcher[];
|
|
42
16
|
sockets: Socket[];
|
|
43
|
-
app: Application;
|
|
44
17
|
server: Server;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// TODO: now only support 'ws'
|
|
49
|
-
webSocketServer: WebSocketServer | undefined;
|
|
50
|
-
|
|
51
|
-
constructor(public compiler: Compiler) {
|
|
52
|
-
this.logger = createLogger("rspack-dev-server");
|
|
53
|
-
this.staticWatchers = [];
|
|
54
|
-
this.listeners = [];
|
|
55
|
-
this.sockets = [];
|
|
56
|
-
this.currentHash = "";
|
|
57
|
-
this.options = this.normalizeOptions(compiler.options.devServer);
|
|
58
|
-
this.rewriteCompilerOptions();
|
|
59
|
-
this.addAdditionEntires();
|
|
60
|
-
}
|
|
18
|
+
// @ts-expect-error
|
|
19
|
+
public compiler: Compiler | MultiCompiler;
|
|
20
|
+
webSocketServer: WebpackDevServer.WebSocketServerImplementation | undefined;
|
|
61
21
|
|
|
62
|
-
|
|
63
|
-
|
|
22
|
+
constructor(options: DevServer, compiler: Compiler | MultiCompiler) {
|
|
23
|
+
// @ts-expect-error
|
|
24
|
+
super(options, compiler);
|
|
64
25
|
}
|
|
65
26
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
this.compiler.options.builtins.react.development =
|
|
72
|
-
this.compiler.options.builtins.react.development ?? true;
|
|
73
|
-
if (this.options.hot) {
|
|
74
|
-
this.compiler.options.builtins.react.refresh =
|
|
75
|
-
this.compiler.options.builtins.react.refresh ?? true;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
27
|
+
addAdditionEntires(compiler: Compiler) {
|
|
28
|
+
const additionalEntries: string[] = [];
|
|
29
|
+
const isWebTarget = isWebTarget2(compiler);
|
|
30
|
+
if (this.options.client && isWebTarget) {
|
|
31
|
+
let webSocketURLStr = "";
|
|
78
32
|
|
|
79
|
-
|
|
80
|
-
|
|
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();
|
|
81
38
|
|
|
82
|
-
|
|
83
|
-
const hotUpdateEntryPath = require.resolve(
|
|
84
|
-
"@rspack/dev-client/devServer"
|
|
85
|
-
);
|
|
86
|
-
entries.push(hotUpdateEntryPath);
|
|
39
|
+
let protocol: string;
|
|
87
40
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
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
|
+
}
|
|
95
47
|
|
|
96
|
-
|
|
97
|
-
entries.push(devClientEntryPath);
|
|
98
|
-
for (const key in this.compiler.options.entry) {
|
|
99
|
-
this.compiler.options.entry[key].import.unshift(...entries);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
48
|
+
searchParams.set("protocol", protocol);
|
|
102
49
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
50
|
+
if (typeof webSocketURL.username !== "undefined") {
|
|
51
|
+
searchParams.set("username", webSocketURL.username);
|
|
52
|
+
}
|
|
106
53
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
54
|
+
if (typeof webSocketURL.password !== "undefined") {
|
|
55
|
+
searchParams.set("password", webSocketURL.password);
|
|
56
|
+
}
|
|
110
57
|
|
|
111
|
-
|
|
112
|
-
return WebpackDevServer.internalIP(family);
|
|
113
|
-
}
|
|
58
|
+
let hostname: string;
|
|
114
59
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return WebpackDevServer.internalIPSync(family);
|
|
119
|
-
}
|
|
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";
|
|
120
63
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
+
}
|
|
124
83
|
|
|
125
|
-
|
|
126
|
-
return WebpackDevServer.getFreePort(port, host);
|
|
127
|
-
}
|
|
84
|
+
searchParams.set("hostname", hostname);
|
|
128
85
|
|
|
129
|
-
|
|
130
|
-
// TODO: we need remove the `webpack-dev-server` tag in WebpackDevServer;
|
|
131
|
-
return "";
|
|
132
|
-
}
|
|
86
|
+
let port: number | string;
|
|
133
87
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
+
}
|
|
137
114
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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();
|
|
147
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);
|
|
148
197
|
}
|
|
149
198
|
}
|
|
150
199
|
|
|
151
200
|
watchFiles(watchPath: string | string[], watchOptions?: WatchOptions): void {
|
|
201
|
+
const chokidar = require("chokidar");
|
|
152
202
|
const watcher = chokidar.watch(watchPath, watchOptions);
|
|
153
203
|
|
|
154
204
|
// disabling refreshing on changing the content
|
|
@@ -172,80 +222,154 @@ export class RspackDevServer {
|
|
|
172
222
|
this.staticWatchers.push(watcher);
|
|
173
223
|
}
|
|
174
224
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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";
|
|
178
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;
|
|
179
290
|
}
|
|
180
291
|
|
|
181
|
-
async
|
|
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
|
+
|
|
182
316
|
this.setupHooks();
|
|
317
|
+
// @ts-expect-error: `setupApp` is private function in base class.
|
|
183
318
|
this.setupApp();
|
|
184
|
-
|
|
185
|
-
this.
|
|
186
|
-
this.createWebsocketServer();
|
|
319
|
+
// @ts-expect-error: `setupHostHeaderCheck` is private function in base class.
|
|
320
|
+
this.setupHostHeaderCheck();
|
|
187
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();
|
|
188
328
|
this.setupMiddlewares();
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
() => {
|
|
199
|
-
|
|
200
|
-
|
|
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
|
+
|
|
201
343
|
this.logger.info(
|
|
202
|
-
|
|
344
|
+
"Gracefully shutting down. To force exit, press ^C again. Please wait..."
|
|
203
345
|
);
|
|
204
|
-
resolve({});
|
|
205
|
-
}
|
|
206
|
-
)
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
346
|
|
|
210
|
-
|
|
211
|
-
throw new Error("Method not implemented.");
|
|
212
|
-
}
|
|
213
|
-
stopCallback(callback?: (err?: Error) => void): void {
|
|
214
|
-
throw new Error("Method not implemented.");
|
|
215
|
-
}
|
|
216
|
-
listen(port: Port, hostname: string, fn: (err?: Error) => void): void {
|
|
217
|
-
throw new Error("Method not implemented.");
|
|
218
|
-
}
|
|
219
|
-
close(callback?: (err?: Error) => void): void {
|
|
220
|
-
throw new Error("Method not implemented.");
|
|
221
|
-
}
|
|
347
|
+
needForceShutdown = true;
|
|
222
348
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
resolve(void 0);
|
|
234
|
-
});
|
|
235
|
-
for (const client of this.webSocketServer.clients) client.terminate();
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
}
|
|
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
|
+
};
|
|
239
359
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
360
|
+
// @ts-expect-error: `listeners` is private function in base class.
|
|
361
|
+
this.listeners.push({ name: signal, listener });
|
|
243
362
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
return;
|
|
363
|
+
process.on(signal, listener);
|
|
364
|
+
});
|
|
247
365
|
}
|
|
248
|
-
|
|
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);
|
|
249
373
|
}
|
|
250
374
|
|
|
251
375
|
private setupDevMiddleware() {
|
|
@@ -253,151 +377,63 @@ export class RspackDevServer {
|
|
|
253
377
|
this.middleware = rdm(this.compiler, this.options.devMiddleware);
|
|
254
378
|
}
|
|
255
379
|
|
|
256
|
-
private createWebsocketServer() {
|
|
257
|
-
if (this.options.webSocketServer !== false) {
|
|
258
|
-
this.webSocketServer = createWebsocketServer(this);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
380
|
private setupMiddlewares() {
|
|
263
|
-
const
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
throw error;
|
|
279
|
-
}
|
|
280
|
-
res.write("");
|
|
281
|
-
res.end();
|
|
282
|
-
console.log("lazy compiler success");
|
|
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)
|
|
283
396
|
});
|
|
284
397
|
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
398
|
+
});
|
|
399
|
+
});
|
|
287
400
|
});
|
|
288
401
|
}
|
|
289
402
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const { createProxyMiddleware } = require("http-proxy-middleware");
|
|
307
|
-
function getProxyMiddleware(proxyConfig) {
|
|
308
|
-
if (proxyConfig.target) {
|
|
309
|
-
const context = proxyConfig.context || proxyConfig.path;
|
|
310
|
-
return createProxyMiddleware(context, proxyConfig);
|
|
311
|
-
}
|
|
312
|
-
if (proxyConfig.router) {
|
|
313
|
-
return createProxyMiddleware(proxyConfig);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
if (!Array.isArray(options.proxy)) {
|
|
317
|
-
if (
|
|
318
|
-
Object.prototype.hasOwnProperty.call(options.proxy, "target") ||
|
|
319
|
-
Object.prototype.hasOwnProperty.call(options.proxy, "router")
|
|
320
|
-
) {
|
|
321
|
-
options.proxy = [options.proxy];
|
|
322
|
-
} else {
|
|
323
|
-
options.proxy = Object.keys(options.proxy).map(context => {
|
|
324
|
-
let proxyOptions;
|
|
325
|
-
// For backwards compatibility reasons.
|
|
326
|
-
const correctedContext = context
|
|
327
|
-
.replace(/^\*$/, "**")
|
|
328
|
-
.replace(/\/\*$/, "");
|
|
329
|
-
|
|
330
|
-
if (
|
|
331
|
-
typeof (/** @type {ProxyConfigMap} */ options.proxy[context]) ===
|
|
332
|
-
"string"
|
|
333
|
-
) {
|
|
334
|
-
proxyOptions = {
|
|
335
|
-
context: correctedContext,
|
|
336
|
-
target:
|
|
337
|
-
/** @type {ProxyConfigMap} */
|
|
338
|
-
options.proxy[context]
|
|
339
|
-
};
|
|
340
|
-
} else {
|
|
341
|
-
proxyOptions = {
|
|
342
|
-
// @ts-ignore
|
|
343
|
-
.../** @type {ProxyConfigMap} */ options.proxy[context]
|
|
344
|
-
};
|
|
345
|
-
proxyOptions.context = correctedContext;
|
|
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
|
+
}
|
|
346
419
|
}
|
|
347
|
-
|
|
348
|
-
return proxyOptions;
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
options.proxy.forEach(proxyConfig => {
|
|
353
|
-
const handler = async (req, res, next) => {
|
|
354
|
-
let proxyMiddleware = getProxyMiddleware(proxyConfig);
|
|
355
|
-
const isByPassFuncDefined = typeof proxyConfig.bypass === "function";
|
|
356
|
-
const bypassUrl = isByPassFuncDefined
|
|
357
|
-
? await proxyConfig.bypass(req, res, proxyConfig)
|
|
358
|
-
: null;
|
|
359
|
-
if (typeof bypassUrl === "boolean") {
|
|
360
|
-
req.url = null;
|
|
361
|
-
next();
|
|
362
|
-
} else if (typeof bypassUrl === "string") {
|
|
363
|
-
req.url = bypassUrl;
|
|
364
|
-
} else if (proxyMiddleware) {
|
|
365
|
-
return proxyMiddleware(req, res, next);
|
|
366
|
-
} else {
|
|
367
|
-
next();
|
|
368
420
|
}
|
|
369
|
-
};
|
|
370
|
-
middlewares.push({
|
|
371
|
-
name: "http-proxy-middleware",
|
|
372
|
-
middleware: handler
|
|
373
|
-
});
|
|
374
|
-
middlewares.push({
|
|
375
|
-
name: "http-proxy-middleware-error-handler",
|
|
376
|
-
middleware: (error, req, res, next) => handler(req, res, next)
|
|
377
421
|
});
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
const publicPath =
|
|
381
|
-
this.compiler.options.output.publicPath === "auto"
|
|
382
|
-
? ""
|
|
383
|
-
: this.compiler.options.output.publicPath;
|
|
384
|
-
middlewares.push({
|
|
385
|
-
name: "express-static",
|
|
386
|
-
path: publicPath,
|
|
387
|
-
middleware: express.static(this.options.static.directory)
|
|
422
|
+
}
|
|
388
423
|
});
|
|
389
424
|
|
|
390
|
-
middlewares.forEach(
|
|
391
|
-
if (
|
|
392
|
-
this.app.use(
|
|
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);
|
|
393
430
|
} else {
|
|
394
|
-
this.app.use(
|
|
431
|
+
this.app.use(middleware.middleware);
|
|
395
432
|
}
|
|
396
433
|
});
|
|
397
|
-
}
|
|
398
434
|
|
|
399
|
-
|
|
400
|
-
|
|
435
|
+
// @ts-expect-error
|
|
436
|
+
super.setupMiddlewares();
|
|
401
437
|
}
|
|
402
438
|
|
|
403
439
|
private setupHooks() {
|
|
@@ -409,3 +445,30 @@ export class RspackDevServer {
|
|
|
409
445
|
});
|
|
410
446
|
}
|
|
411
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
|
+
}
|