@rspack/dev-server 0.0.20 → 0.0.22
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 +30 -0
- package/LICENSE +1 -1
- package/dist/config.d.ts +20 -15
- 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 +308 -255
- package/dist/server.js.map +1 -1
- package/jest.config.js +6 -3
- package/package.json +13 -10
- package/src/config.ts +22 -68
- package/src/server.ts +350 -309
- package/tests/__snapshots__/normalizeOptions.test.ts.snap +226 -16
- package/tests/e2e/hot-reaload.test.ts +115 -0
- package/tests/e2e-fixtures/react/app.jsx +14 -0
- package/tests/e2e-fixtures/react/index.css +3 -0
- package/tests/e2e-fixtures/react/index.html +12 -0
- package/tests/e2e-fixtures/react/index.jsx +6 -0
- package/tests/e2e-fixtures/react/node_modules/react/LICENSE +21 -0
- package/tests/e2e-fixtures/react/node_modules/react/README.md +37 -0
- package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-dev-runtime.development.js +1296 -0
- package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-dev-runtime.production.min.js +10 -0
- package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-dev-runtime.profiling.min.js +10 -0
- package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-runtime.development.js +1314 -0
- package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-runtime.production.min.js +11 -0
- package/tests/e2e-fixtures/react/node_modules/react/cjs/react-jsx-runtime.profiling.min.js +11 -0
- package/tests/e2e-fixtures/react/node_modules/react/cjs/react.development.js +2739 -0
- package/tests/e2e-fixtures/react/node_modules/react/cjs/react.production.min.js +26 -0
- package/tests/e2e-fixtures/react/node_modules/react/cjs/react.shared-subset.development.js +20 -0
- package/tests/e2e-fixtures/react/node_modules/react/cjs/react.shared-subset.production.min.js +10 -0
- package/tests/e2e-fixtures/react/node_modules/react/index.js +7 -0
- package/tests/e2e-fixtures/react/node_modules/react/jsx-dev-runtime.js +7 -0
- package/tests/e2e-fixtures/react/node_modules/react/jsx-runtime.js +7 -0
- package/tests/e2e-fixtures/react/node_modules/react/package.json +47 -0
- package/tests/e2e-fixtures/react/node_modules/react/react.shared-subset.js +7 -0
- package/tests/e2e-fixtures/react/node_modules/react/umd/react.development.js +3342 -0
- package/tests/e2e-fixtures/react/node_modules/react/umd/react.production.min.js +31 -0
- package/tests/e2e-fixtures/react/node_modules/react/umd/react.profiling.min.js +31 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/LICENSE +21 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/README.md +60 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server-legacy.browser.development.js +7018 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.min.js +93 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server-legacy.node.development.js +7078 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.min.js +101 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server.browser.development.js +7003 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js +96 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server.node.development.js +7059 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-server.node.production.min.js +102 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-test-utils.development.js +1741 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom-test-utils.production.min.js +40 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom.development.js +29868 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom.production.min.js +323 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/cjs/react-dom.profiling.min.js +367 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/client.js +25 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/index.js +38 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/package.json +62 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/profiling.js +38 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/server.browser.js +17 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/server.js +3 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/server.node.js +17 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/test-utils.js +7 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-server-legacy.browser.development.js +7015 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-server-legacy.browser.production.min.js +75 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-server.browser.development.js +7000 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-server.browser.production.min.js +76 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-test-utils.development.js +1737 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom-test-utils.production.min.js +33 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom.development.js +29869 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom.production.min.js +267 -0
- package/tests/e2e-fixtures/react/node_modules/react-dom/umd/react-dom.profiling.min.js +285 -0
- 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 +8 -0
- package/tests/e2e-fixtures/react/webpack.config.js +26 -0
- package/tests/helpers/emitFile.ts +69 -0
- package/tests/helpers/runBrowser.ts +85 -0
- package/tests/helpers/tempDir.ts +58 -0
- package/tests/normalizeOptions.test.ts +59 -17
- 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,153 +1,207 @@
|
|
|
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
|
-
|
|
72
|
-
if (this.options.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
27
|
+
addAdditionEntires(compiler: Compiler) {
|
|
28
|
+
const additionalEntries: string[] = [];
|
|
29
|
+
// TODO: align with webpack-dev-server after options.target is aligned
|
|
30
|
+
const isWebTarget =
|
|
31
|
+
compiler.options.target.includes("web") ||
|
|
32
|
+
compiler.options.target.includes("webworker");
|
|
33
|
+
if (this.options.client && isWebTarget) {
|
|
34
|
+
let webSocketURLStr = "";
|
|
35
|
+
|
|
36
|
+
if (this.options.webSocketServer) {
|
|
37
|
+
const webSocketURL = this.options.client
|
|
38
|
+
.webSocketURL as WebpackDevServer.WebSocketURL;
|
|
39
|
+
const webSocketServer = this.options.webSocketServer;
|
|
40
|
+
const searchParams = new URLSearchParams();
|
|
41
|
+
|
|
42
|
+
let protocol: string;
|
|
43
|
+
|
|
44
|
+
// We are proxying dev server and need to specify custom `hostname`
|
|
45
|
+
if (typeof webSocketURL.protocol !== "undefined") {
|
|
46
|
+
protocol = webSocketURL.protocol;
|
|
47
|
+
} else {
|
|
48
|
+
protocol = this.options.server.type === "http" ? "ws:" : "wss:";
|
|
49
|
+
}
|
|
77
50
|
|
|
78
|
-
|
|
79
|
-
const entries: string[] = [];
|
|
51
|
+
searchParams.set("protocol", protocol);
|
|
80
52
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
);
|
|
85
|
-
entries.push(hotUpdateEntryPath);
|
|
53
|
+
if (typeof webSocketURL.username !== "undefined") {
|
|
54
|
+
searchParams.set("username", webSocketURL.username);
|
|
55
|
+
}
|
|
86
56
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
);
|
|
91
|
-
entries.push(reactRefreshEntryPath);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
57
|
+
if (typeof webSocketURL.password !== "undefined") {
|
|
58
|
+
searchParams.set("password", webSocketURL.password);
|
|
59
|
+
}
|
|
94
60
|
|
|
95
|
-
|
|
96
|
-
entries.push(devClientEntryPath);
|
|
97
|
-
for (const key in this.compiler.options.entry) {
|
|
98
|
-
this.compiler.options.entry[key].import.unshift(...entries);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
61
|
+
let hostname: string;
|
|
101
62
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
63
|
+
// SockJS is not supported server mode, so `hostname` and `port` can't specified, let's ignore them
|
|
64
|
+
// TODO show warning about this
|
|
65
|
+
const isSockJSType = webSocketServer.type === "sockjs";
|
|
105
66
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
67
|
+
// We are proxying dev server and need to specify custom `hostname`
|
|
68
|
+
if (typeof webSocketURL.hostname !== "undefined") {
|
|
69
|
+
hostname = webSocketURL.hostname;
|
|
70
|
+
}
|
|
71
|
+
// Web socket server works on custom `hostname`, only for `ws` because `sock-js` is not support custom `hostname`
|
|
72
|
+
else if (
|
|
73
|
+
typeof webSocketServer.options.host !== "undefined" &&
|
|
74
|
+
!isSockJSType
|
|
75
|
+
) {
|
|
76
|
+
hostname = webSocketServer.options.host;
|
|
77
|
+
}
|
|
78
|
+
// The `host` option is specified
|
|
79
|
+
else if (typeof this.options.host !== "undefined") {
|
|
80
|
+
hostname = this.options.host;
|
|
81
|
+
}
|
|
82
|
+
// The `port` option is not specified
|
|
83
|
+
else {
|
|
84
|
+
hostname = "0.0.0.0";
|
|
85
|
+
}
|
|
109
86
|
|
|
110
|
-
|
|
111
|
-
return WebpackDevServer.internalIP(family);
|
|
112
|
-
}
|
|
87
|
+
searchParams.set("hostname", hostname);
|
|
113
88
|
|
|
114
|
-
|
|
115
|
-
family: "v6" | "v4"
|
|
116
|
-
): Promise<string | undefined> {
|
|
117
|
-
return WebpackDevServer.internalIPSync(family);
|
|
118
|
-
}
|
|
89
|
+
let port: number | string;
|
|
119
90
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
91
|
+
// We are proxying dev server and need to specify custom `port`
|
|
92
|
+
if (typeof webSocketURL.port !== "undefined") {
|
|
93
|
+
port = webSocketURL.port;
|
|
94
|
+
}
|
|
95
|
+
// Web socket server works on custom `port`, only for `ws` because `sock-js` is not support custom `port`
|
|
96
|
+
else if (
|
|
97
|
+
typeof webSocketServer.options.port !== "undefined" &&
|
|
98
|
+
!isSockJSType
|
|
99
|
+
) {
|
|
100
|
+
port = webSocketServer.options.port;
|
|
101
|
+
}
|
|
102
|
+
// The `port` option is specified
|
|
103
|
+
else if (typeof this.options.port === "number") {
|
|
104
|
+
port = this.options.port;
|
|
105
|
+
}
|
|
106
|
+
// The `port` option is specified using `string`
|
|
107
|
+
else if (
|
|
108
|
+
typeof this.options.port === "string" &&
|
|
109
|
+
this.options.port !== "auto"
|
|
110
|
+
) {
|
|
111
|
+
port = Number(this.options.port);
|
|
112
|
+
}
|
|
113
|
+
// The `port` option is not specified or set to `auto`
|
|
114
|
+
else {
|
|
115
|
+
port = "0";
|
|
116
|
+
}
|
|
123
117
|
|
|
124
|
-
|
|
125
|
-
return WebpackDevServer.getFreePort(port, host);
|
|
126
|
-
}
|
|
118
|
+
searchParams.set("port", String(port));
|
|
127
119
|
|
|
128
|
-
|
|
129
|
-
// TODO: we need remove the `webpack-dev-server` tag in WebpackDevServer;
|
|
130
|
-
return "";
|
|
131
|
-
}
|
|
120
|
+
let pathname = "";
|
|
132
121
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
122
|
+
// We are proxying dev server and need to specify custom `pathname`
|
|
123
|
+
if (typeof webSocketURL.pathname !== "undefined") {
|
|
124
|
+
pathname = webSocketURL.pathname;
|
|
125
|
+
}
|
|
126
|
+
// Web socket server works on custom `path`
|
|
127
|
+
else if (
|
|
128
|
+
typeof webSocketServer.options.prefix !== "undefined" ||
|
|
129
|
+
typeof webSocketServer.options.path !== "undefined"
|
|
130
|
+
) {
|
|
131
|
+
pathname =
|
|
132
|
+
webSocketServer.options.prefix || webSocketServer.options.path;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
searchParams.set("pathname", pathname);
|
|
136
|
+
|
|
137
|
+
const client = /** @type {ClientConfiguration} */ this.options.client;
|
|
138
|
+
|
|
139
|
+
if (typeof client.logging !== "undefined") {
|
|
140
|
+
searchParams.set("logging", client.logging);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (typeof client.progress !== "undefined") {
|
|
144
|
+
searchParams.set("progress", String(client.progress));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (typeof client.overlay !== "undefined") {
|
|
148
|
+
searchParams.set(
|
|
149
|
+
"overlay",
|
|
150
|
+
typeof client.overlay === "boolean"
|
|
151
|
+
? String(client.overlay)
|
|
152
|
+
: JSON.stringify(client.overlay)
|
|
153
|
+
);
|
|
154
|
+
}
|
|
136
155
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
156
|
+
if (typeof client.reconnect !== "undefined") {
|
|
157
|
+
searchParams.set(
|
|
158
|
+
"reconnect",
|
|
159
|
+
typeof client.reconnect === "number"
|
|
160
|
+
? String(client.reconnect)
|
|
161
|
+
: "10"
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (typeof this.options.hot !== "undefined") {
|
|
166
|
+
searchParams.set("hot", String(this.options.hot));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (typeof this.options.liveReload !== "undefined") {
|
|
170
|
+
searchParams.set("live-reload", String(this.options.liveReload));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
webSocketURLStr = searchParams.toString();
|
|
146
174
|
}
|
|
175
|
+
|
|
176
|
+
// TODO: should use providerPlugin
|
|
177
|
+
additionalEntries.push(this.getClientTransport());
|
|
178
|
+
|
|
179
|
+
additionalEntries.push(
|
|
180
|
+
`${require.resolve("@rspack/dev-client")}?${webSocketURLStr}`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (this.options.hot) {
|
|
185
|
+
const hotUpdateEntryPath = require.resolve(
|
|
186
|
+
"@rspack/dev-client/devServer"
|
|
187
|
+
);
|
|
188
|
+
additionalEntries.push(hotUpdateEntryPath);
|
|
189
|
+
|
|
190
|
+
if (compiler.options.builtins.react?.refresh) {
|
|
191
|
+
const reactRefreshEntryPath = require.resolve(
|
|
192
|
+
"@rspack/dev-client/react-refresh"
|
|
193
|
+
);
|
|
194
|
+
additionalEntries.push(reactRefreshEntryPath);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
for (const key in compiler.options.entry) {
|
|
199
|
+
compiler.options.entry[key].import.unshift(...additionalEntries);
|
|
147
200
|
}
|
|
148
201
|
}
|
|
149
202
|
|
|
150
203
|
watchFiles(watchPath: string | string[], watchOptions?: WatchOptions): void {
|
|
204
|
+
const chokidar = require("chokidar");
|
|
151
205
|
const watcher = chokidar.watch(watchPath, watchOptions);
|
|
152
206
|
|
|
153
207
|
// disabling refreshing on changing the content
|
|
@@ -171,79 +225,154 @@ export class RspackDevServer {
|
|
|
171
225
|
this.staticWatchers.push(watcher);
|
|
172
226
|
}
|
|
173
227
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
228
|
+
getClientTransport(): string {
|
|
229
|
+
// WARNING: we can't use `super.getClientTransport`,
|
|
230
|
+
// because we doesn't had same directory structure.
|
|
231
|
+
// and TODO: we need impelement `webpack.providerPlugin`
|
|
232
|
+
let clientImplementation: string | undefined;
|
|
233
|
+
let clientImplementationFound = true;
|
|
234
|
+
const isKnownWebSocketServerImplementation =
|
|
235
|
+
this.options.webSocketServer &&
|
|
236
|
+
typeof this.options.webSocketServer.type === "string" &&
|
|
237
|
+
(this.options.webSocketServer.type === "ws" ||
|
|
238
|
+
this.options.webSocketServer.type === "sockjs");
|
|
239
|
+
|
|
240
|
+
let clientTransport: string | undefined;
|
|
241
|
+
|
|
242
|
+
if (this.options.client) {
|
|
243
|
+
if (
|
|
244
|
+
// @ts-ignore
|
|
245
|
+
typeof this.options.client.webSocketTransport !== "undefined"
|
|
246
|
+
) {
|
|
247
|
+
// @ts-ignore
|
|
248
|
+
clientTransport = this.options.client.webSocketTransport;
|
|
249
|
+
} else if (isKnownWebSocketServerImplementation) {
|
|
250
|
+
// @ts-ignore
|
|
251
|
+
clientTransport = this.options.webSocketServer.type;
|
|
252
|
+
} else {
|
|
253
|
+
clientTransport = "ws";
|
|
254
|
+
}
|
|
255
|
+
} else {
|
|
256
|
+
clientTransport = "ws";
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
switch (typeof clientTransport) {
|
|
260
|
+
case "string":
|
|
261
|
+
// could be 'sockjs', 'ws', or a path that should be required
|
|
262
|
+
if (clientTransport === "sockjs") {
|
|
263
|
+
clientImplementation = require.resolve(
|
|
264
|
+
"@rspack/dev-client/clients/SockJSClient"
|
|
265
|
+
);
|
|
266
|
+
} else if (clientTransport === "ws") {
|
|
267
|
+
clientImplementation = require.resolve(
|
|
268
|
+
"@rspack/dev-client/clients/WebSocketClient"
|
|
269
|
+
);
|
|
270
|
+
} else {
|
|
271
|
+
try {
|
|
272
|
+
clientImplementation = require.resolve(clientTransport);
|
|
273
|
+
throw Error("Do not support custom ws client now");
|
|
274
|
+
} catch (e) {
|
|
275
|
+
clientImplementationFound = false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
break;
|
|
279
|
+
default:
|
|
280
|
+
clientImplementationFound = false;
|
|
281
|
+
}
|
|
282
|
+
if (!clientImplementationFound) {
|
|
283
|
+
throw new Error(
|
|
284
|
+
`${
|
|
285
|
+
!isKnownWebSocketServerImplementation
|
|
286
|
+
? "When you use custom web socket implementation you must explicitly specify client.webSocketTransport. "
|
|
287
|
+
: ""
|
|
288
|
+
}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 `
|
|
289
|
+
);
|
|
177
290
|
}
|
|
291
|
+
|
|
292
|
+
return clientImplementation;
|
|
178
293
|
}
|
|
179
294
|
|
|
180
|
-
async
|
|
295
|
+
async initialize() {
|
|
296
|
+
const compilers =
|
|
297
|
+
this.compiler instanceof MultiCompiler
|
|
298
|
+
? this.compiler.compilers
|
|
299
|
+
: [this.compiler];
|
|
300
|
+
|
|
301
|
+
compilers.forEach(compiler => {
|
|
302
|
+
compiler.options.builtins.react ??= {};
|
|
303
|
+
if (this.options.hot) {
|
|
304
|
+
compiler.options.builtins.react.refresh ??= true;
|
|
305
|
+
compiler.options.builtins.react.development ??= true;
|
|
306
|
+
} else if (compiler.options.builtins.react.refresh) {
|
|
307
|
+
this.logger.warn(
|
|
308
|
+
"builtins.react.refresh needs builtins.react.development and devServer.hot enabled"
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
if (this.options.webSocketServer) {
|
|
314
|
+
compilers.forEach(compiler => {
|
|
315
|
+
this.addAdditionEntires(compiler);
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
181
319
|
this.setupHooks();
|
|
320
|
+
// @ts-expect-error: `setupApp` is private function in base class.
|
|
182
321
|
this.setupApp();
|
|
183
|
-
|
|
184
|
-
this.
|
|
185
|
-
this.createWebsocketServer();
|
|
322
|
+
// @ts-expect-error: `setupHostHeaderCheck` is private function in base class.
|
|
323
|
+
this.setupHostHeaderCheck();
|
|
186
324
|
this.setupDevMiddleware();
|
|
325
|
+
// @ts-expect-error: `setupBuiltInRoutes` is private function in base class.
|
|
326
|
+
this.setupBuiltInRoutes();
|
|
327
|
+
// @ts-expect-error: `setupWatchFiles` is private function in base class.
|
|
328
|
+
this.setupWatchFiles();
|
|
329
|
+
// @ts-expect-error: `setupWatchStaticFiles` is private function in base class.
|
|
330
|
+
this.setupWatchStaticFiles();
|
|
187
331
|
this.setupMiddlewares();
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
332
|
+
// @ts-expect-error: `createServer` is private function in base class.
|
|
333
|
+
this.createServer();
|
|
334
|
+
|
|
335
|
+
if (this.options.setupExitSignals) {
|
|
336
|
+
const signals = ["SIGINT", "SIGTERM"];
|
|
337
|
+
|
|
338
|
+
let needForceShutdown = false;
|
|
339
|
+
|
|
340
|
+
signals.forEach(signal => {
|
|
341
|
+
const listener = () => {
|
|
342
|
+
if (needForceShutdown) {
|
|
343
|
+
process.exit();
|
|
344
|
+
}
|
|
345
|
+
|
|
199
346
|
this.logger.info(
|
|
200
|
-
|
|
347
|
+
"Gracefully shutting down. To force exit, press ^C again. Please wait..."
|
|
201
348
|
);
|
|
202
|
-
resolve({});
|
|
203
|
-
}
|
|
204
|
-
)
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
349
|
|
|
208
|
-
|
|
209
|
-
throw new Error("Method not implemented.");
|
|
210
|
-
}
|
|
211
|
-
stopCallback(callback?: (err?: Error) => void): void {
|
|
212
|
-
throw new Error("Method not implemented.");
|
|
213
|
-
}
|
|
214
|
-
listen(port: Port, hostname: string, fn: (err?: Error) => void): void {
|
|
215
|
-
throw new Error("Method not implemented.");
|
|
216
|
-
}
|
|
217
|
-
close(callback?: (err?: Error) => void): void {
|
|
218
|
-
throw new Error("Method not implemented.");
|
|
219
|
-
}
|
|
350
|
+
needForceShutdown = true;
|
|
220
351
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
resolve(void 0);
|
|
232
|
-
});
|
|
233
|
-
for (const client of this.webSocketServer.clients) client.terminate();
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
}
|
|
352
|
+
this.stopCallback(() => {
|
|
353
|
+
if (typeof this.compiler.close === "function") {
|
|
354
|
+
this.compiler.close(() => {
|
|
355
|
+
process.exit();
|
|
356
|
+
});
|
|
357
|
+
} else {
|
|
358
|
+
process.exit();
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
};
|
|
237
362
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
363
|
+
// @ts-expect-error: `listeners` is private function in base class.
|
|
364
|
+
this.listeners.push({ name: signal, listener });
|
|
241
365
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return;
|
|
366
|
+
process.on(signal, listener);
|
|
367
|
+
});
|
|
245
368
|
}
|
|
246
|
-
|
|
369
|
+
|
|
370
|
+
// Proxy WebSocket without the initial http request
|
|
371
|
+
// https://github.com/chimurai/http-proxy-middleware#external-websocket-upgrade
|
|
372
|
+
// @ts-expect-error: `webSocketProxies` is private function in base class.
|
|
373
|
+
this.webSocketProxies.forEach(webSocketProxy => {
|
|
374
|
+
this.server.on("upgrade", webSocketProxy.upgrade);
|
|
375
|
+
}, this);
|
|
247
376
|
}
|
|
248
377
|
|
|
249
378
|
private setupDevMiddleware() {
|
|
@@ -251,151 +380,63 @@ export class RspackDevServer {
|
|
|
251
380
|
this.middleware = rdm(this.compiler, this.options.devMiddleware);
|
|
252
381
|
}
|
|
253
382
|
|
|
254
|
-
private createWebsocketServer() {
|
|
255
|
-
if (this.options.webSocketServer !== false) {
|
|
256
|
-
this.webSocketServer = createWebsocketServer(this);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
383
|
private setupMiddlewares() {
|
|
261
|
-
const
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
throw error;
|
|
277
|
-
}
|
|
278
|
-
res.write("");
|
|
279
|
-
res.end();
|
|
280
|
-
console.log("lazy compiler success");
|
|
384
|
+
const middlewares: WebpackDevServer.Middleware[] = [];
|
|
385
|
+
const compilers =
|
|
386
|
+
this.compiler instanceof MultiCompiler
|
|
387
|
+
? this.compiler.compilers
|
|
388
|
+
: [this.compiler];
|
|
389
|
+
|
|
390
|
+
if (Array.isArray(this.options.static)) {
|
|
391
|
+
this.options.static.forEach(staticOptions => {
|
|
392
|
+
staticOptions.publicPath.forEach(publicPath => {
|
|
393
|
+
compilers.forEach(compiler => {
|
|
394
|
+
if (compiler.options.builtins.noEmitAssets) {
|
|
395
|
+
middlewares.push({
|
|
396
|
+
name: "rspack-memory-assets",
|
|
397
|
+
path: publicPath,
|
|
398
|
+
middleware: getRspackMemoryAssets(compiler, this.middleware)
|
|
281
399
|
});
|
|
282
400
|
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
401
|
+
});
|
|
402
|
+
});
|
|
285
403
|
});
|
|
286
404
|
}
|
|
287
405
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
const { createProxyMiddleware } = require("http-proxy-middleware");
|
|
305
|
-
function getProxyMiddleware(proxyConfig) {
|
|
306
|
-
if (proxyConfig.target) {
|
|
307
|
-
const context = proxyConfig.context || proxyConfig.path;
|
|
308
|
-
return createProxyMiddleware(context, proxyConfig);
|
|
309
|
-
}
|
|
310
|
-
if (proxyConfig.router) {
|
|
311
|
-
return createProxyMiddleware(proxyConfig);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
if (!Array.isArray(options.proxy)) {
|
|
315
|
-
if (
|
|
316
|
-
Object.prototype.hasOwnProperty.call(options.proxy, "target") ||
|
|
317
|
-
Object.prototype.hasOwnProperty.call(options.proxy, "router")
|
|
318
|
-
) {
|
|
319
|
-
options.proxy = [options.proxy];
|
|
320
|
-
} else {
|
|
321
|
-
options.proxy = Object.keys(options.proxy).map(context => {
|
|
322
|
-
let proxyOptions;
|
|
323
|
-
// For backwards compatibility reasons.
|
|
324
|
-
const correctedContext = context
|
|
325
|
-
.replace(/^\*$/, "**")
|
|
326
|
-
.replace(/\/\*$/, "");
|
|
327
|
-
|
|
328
|
-
if (
|
|
329
|
-
typeof (/** @type {ProxyConfigMap} */ options.proxy[context]) ===
|
|
330
|
-
"string"
|
|
331
|
-
) {
|
|
332
|
-
proxyOptions = {
|
|
333
|
-
context: correctedContext,
|
|
334
|
-
target:
|
|
335
|
-
/** @type {ProxyConfigMap} */
|
|
336
|
-
options.proxy[context]
|
|
337
|
-
};
|
|
338
|
-
} else {
|
|
339
|
-
proxyOptions = {
|
|
340
|
-
// @ts-ignore
|
|
341
|
-
.../** @type {ProxyConfigMap} */ options.proxy[context]
|
|
342
|
-
};
|
|
343
|
-
proxyOptions.context = correctedContext;
|
|
406
|
+
compilers.forEach(compiler => {
|
|
407
|
+
if (compiler.options.experiments.lazyCompilation) {
|
|
408
|
+
middlewares.push({
|
|
409
|
+
middleware: (req, res, next) => {
|
|
410
|
+
if (req.url.indexOf("/lazy-compilation-web/") > -1) {
|
|
411
|
+
const path = req.url.replace("/lazy-compilation-web/", "");
|
|
412
|
+
if (fs.existsSync(path)) {
|
|
413
|
+
compiler.rebuild(new Set([path]), new Set(), error => {
|
|
414
|
+
if (error) {
|
|
415
|
+
throw error;
|
|
416
|
+
}
|
|
417
|
+
res.write("");
|
|
418
|
+
res.end();
|
|
419
|
+
console.log("lazy compiler success");
|
|
420
|
+
});
|
|
421
|
+
}
|
|
344
422
|
}
|
|
345
|
-
|
|
346
|
-
return proxyOptions;
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
options.proxy.forEach(proxyConfig => {
|
|
351
|
-
const handler = async (req, res, next) => {
|
|
352
|
-
let proxyMiddleware = getProxyMiddleware(proxyConfig);
|
|
353
|
-
const isByPassFuncDefined = typeof proxyConfig.bypass === "function";
|
|
354
|
-
const bypassUrl = isByPassFuncDefined
|
|
355
|
-
? await proxyConfig.bypass(req, res, proxyConfig)
|
|
356
|
-
: null;
|
|
357
|
-
if (typeof bypassUrl === "boolean") {
|
|
358
|
-
req.url = null;
|
|
359
|
-
next();
|
|
360
|
-
} else if (typeof bypassUrl === "string") {
|
|
361
|
-
req.url = bypassUrl;
|
|
362
|
-
} else if (proxyMiddleware) {
|
|
363
|
-
return proxyMiddleware(req, res, next);
|
|
364
|
-
} else {
|
|
365
|
-
next();
|
|
366
423
|
}
|
|
367
|
-
};
|
|
368
|
-
middlewares.push({
|
|
369
|
-
name: "http-proxy-middleware",
|
|
370
|
-
middleware: handler
|
|
371
|
-
});
|
|
372
|
-
middlewares.push({
|
|
373
|
-
name: "http-proxy-middleware-error-handler",
|
|
374
|
-
middleware: (error, req, res, next) => handler(req, res, next)
|
|
375
424
|
});
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
const publicPath =
|
|
379
|
-
this.compiler.options.output.publicPath === "auto"
|
|
380
|
-
? ""
|
|
381
|
-
: this.compiler.options.output.publicPath;
|
|
382
|
-
middlewares.push({
|
|
383
|
-
name: "express-static",
|
|
384
|
-
path: publicPath,
|
|
385
|
-
middleware: express.static(this.options.static.directory)
|
|
425
|
+
}
|
|
386
426
|
});
|
|
387
427
|
|
|
388
|
-
middlewares.forEach(
|
|
389
|
-
if (
|
|
390
|
-
this.app.use(
|
|
428
|
+
middlewares.forEach(middleware => {
|
|
429
|
+
if (typeof middleware === "function") {
|
|
430
|
+
this.app.use(middleware);
|
|
431
|
+
} else if (typeof middleware.path !== "undefined") {
|
|
432
|
+
this.app.use(middleware.path, middleware.middleware);
|
|
391
433
|
} else {
|
|
392
|
-
this.app.use(
|
|
434
|
+
this.app.use(middleware.middleware);
|
|
393
435
|
}
|
|
394
436
|
});
|
|
395
|
-
}
|
|
396
437
|
|
|
397
|
-
|
|
398
|
-
|
|
438
|
+
// @ts-expect-error
|
|
439
|
+
super.setupMiddlewares();
|
|
399
440
|
}
|
|
400
441
|
|
|
401
442
|
private setupHooks() {
|