@rspack/dev-server 0.0.0-02df4322c5-20221125030212
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 +70 -0
- package/README.md +1 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +53 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +28 -0
- package/dist/logger.js.map +1 -0
- package/dist/reload.d.ts +9 -0
- package/dist/reload.d.ts.map +1 -0
- package/dist/reload.js +23 -0
- package/dist/reload.js.map +1 -0
- package/dist/server.d.ts +55 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +225 -0
- package/dist/server.js.map +1 -0
- package/dist/ws.d.ts +13 -0
- package/dist/ws.d.ts.map +1 -0
- package/dist/ws.js +12 -0
- package/dist/ws.js.map +1 -0
- package/jest.config.js +7 -0
- package/package.json +35 -0
- package/src/config.ts +68 -0
- package/src/index.ts +1 -0
- package/src/logger.ts +30 -0
- package/src/reload.ts +31 -0
- package/src/server.ts +307 -0
- package/src/ws.ts +18 -0
- package/tests/__snapshots__/normalizeOptions.test.ts.snap +80 -0
- package/tests/normalizeOptions.test.ts +73 -0
- package/tsconfig.json +15 -0
- package/tsconfig.tsbuildinfo +1 -0
package/src/config.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Dev,
|
|
3
|
+
WebSocketServerOptions,
|
|
4
|
+
RspackOptionsNormalized
|
|
5
|
+
} from "@rspack/core";
|
|
6
|
+
import type { WatchOptions } from "chokidar";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { resolveWatchOption } from "@rspack/core";
|
|
9
|
+
|
|
10
|
+
export interface ResolvedDev {
|
|
11
|
+
host: string;
|
|
12
|
+
port: number;
|
|
13
|
+
static: {
|
|
14
|
+
directory: string;
|
|
15
|
+
watch: false | WatchOptions;
|
|
16
|
+
};
|
|
17
|
+
devMiddleware: {};
|
|
18
|
+
hot: boolean;
|
|
19
|
+
open: boolean;
|
|
20
|
+
liveReload: boolean;
|
|
21
|
+
webSocketServer: false | WebSocketServerOptions;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function resolveDevOptions(
|
|
25
|
+
devConfig: Dev,
|
|
26
|
+
compilerOptions: RspackOptionsNormalized
|
|
27
|
+
): ResolvedDev {
|
|
28
|
+
const open = true;
|
|
29
|
+
const hot = devConfig.hot ?? true;
|
|
30
|
+
// --- static
|
|
31
|
+
const directory =
|
|
32
|
+
devConfig.static?.directory ??
|
|
33
|
+
path.resolve(compilerOptions.context, "dist");
|
|
34
|
+
let watch: false | WatchOptions = {};
|
|
35
|
+
if (devConfig.static?.watch === false) {
|
|
36
|
+
watch = false;
|
|
37
|
+
} else if (devConfig.static?.watch === true) {
|
|
38
|
+
watch = resolveWatchOption({});
|
|
39
|
+
} else if (devConfig.static?.watch) {
|
|
40
|
+
watch = devConfig.static?.watch;
|
|
41
|
+
}
|
|
42
|
+
// ---
|
|
43
|
+
const devMiddleware = devConfig.devMiddleware ?? {};
|
|
44
|
+
const liveReload = devConfig.liveReload ?? true;
|
|
45
|
+
|
|
46
|
+
let webSocketServer: false | WebSocketServerOptions = {};
|
|
47
|
+
if (devConfig.webSocketServer === false) {
|
|
48
|
+
webSocketServer = false;
|
|
49
|
+
} else if (devConfig.webSocketServer === true) {
|
|
50
|
+
webSocketServer = {};
|
|
51
|
+
} else if (devConfig.webSocketServer) {
|
|
52
|
+
webSocketServer = devConfig.webSocketServer;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
host: devConfig.host,
|
|
57
|
+
port: devConfig.port ? Number(devConfig.port) : undefined,
|
|
58
|
+
static: {
|
|
59
|
+
directory,
|
|
60
|
+
watch
|
|
61
|
+
},
|
|
62
|
+
devMiddleware,
|
|
63
|
+
open,
|
|
64
|
+
hot,
|
|
65
|
+
liveReload,
|
|
66
|
+
webSocketServer
|
|
67
|
+
};
|
|
68
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RspackDevServer } from "./server";
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface Logger {
|
|
2
|
+
error(...args: any[]): void;
|
|
3
|
+
warn(...args: any[]): void;
|
|
4
|
+
info(...args: any[]): void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const COLOR = {
|
|
8
|
+
RESET: "\x1b[0m",
|
|
9
|
+
//
|
|
10
|
+
RED: "\x1b[31m",
|
|
11
|
+
GREEN: "\x1b[32m",
|
|
12
|
+
YELLOW: "\x1b[33m"
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function createLogger(name: string): Logger {
|
|
16
|
+
if (!name.length) {
|
|
17
|
+
throw Error();
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
error(...msgs: any[]) {
|
|
21
|
+
console.log("[", name, "]:", COLOR.RED, msgs, COLOR.RESET);
|
|
22
|
+
},
|
|
23
|
+
warn(...msgs: any[]) {
|
|
24
|
+
console.log("[", name, "]:", COLOR.YELLOW, msgs, COLOR.RESET);
|
|
25
|
+
},
|
|
26
|
+
info(...msgs: any[]) {
|
|
27
|
+
console.log("[", name, "]:", COLOR.GREEN, msgs, COLOR.RESET);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
package/src/reload.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { RspackOptionsNormalized } from "@rspack/core";
|
|
2
|
+
|
|
3
|
+
interface Status {
|
|
4
|
+
isUnloading: boolean;
|
|
5
|
+
currentHash: string;
|
|
6
|
+
previousHash: string[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function reloadApp(
|
|
10
|
+
{ liveReload, hot }: RspackOptionsNormalized["devServer"],
|
|
11
|
+
status: Status
|
|
12
|
+
) {
|
|
13
|
+
if (status.isUnloading) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function applyReload(rootWindow: Window, intervalId: number) {
|
|
18
|
+
clearInterval(intervalId);
|
|
19
|
+
console.log("App update, Reloading...");
|
|
20
|
+
rootWindow.location.reload();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (liveReload) {
|
|
24
|
+
let rootWindow = self;
|
|
25
|
+
const intervalId = self.setInterval(() => {
|
|
26
|
+
if (rootWindow.location.protocol !== "about:") {
|
|
27
|
+
applyReload(rootWindow, intervalId);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/server.ts
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import type { Compiler, Dev, RspackOptionsNormalized } from "@rspack/core";
|
|
2
|
+
import type { Logger } from "./logger";
|
|
3
|
+
import type { Socket } from "net";
|
|
4
|
+
import type { FSWatcher, WatchOptions } from "chokidar";
|
|
5
|
+
import type { WebSocketServer, ClientConnection } from "./ws";
|
|
6
|
+
import type {
|
|
7
|
+
Application,
|
|
8
|
+
RequestHandler as ExpressRequestHandler,
|
|
9
|
+
ErrorRequestHandler as ExpressErrorRequestHandler
|
|
10
|
+
} from "express";
|
|
11
|
+
import type { DevMiddleware } from "@rspack/dev-middleware";
|
|
12
|
+
import type { Server } from "http";
|
|
13
|
+
import type { ResolvedDev } from "./config";
|
|
14
|
+
|
|
15
|
+
import chokidar from "chokidar";
|
|
16
|
+
import http from "http";
|
|
17
|
+
import { createLogger } from "./logger";
|
|
18
|
+
import WebpackDevServer from "webpack-dev-server";
|
|
19
|
+
import express from "express";
|
|
20
|
+
|
|
21
|
+
import rdm from "@rspack/dev-middleware";
|
|
22
|
+
import { createWebsocketServer } from "./ws";
|
|
23
|
+
import { resolveDevOptions } from "./config";
|
|
24
|
+
|
|
25
|
+
interface Middleware {
|
|
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;
|
|
41
|
+
staticWatchers: FSWatcher[];
|
|
42
|
+
sockets: Socket[];
|
|
43
|
+
app: Application;
|
|
44
|
+
server: Server;
|
|
45
|
+
private listeners: Listener[];
|
|
46
|
+
private currentHash: string;
|
|
47
|
+
private middleware: DevMiddleware | undefined;
|
|
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
|
+
}
|
|
61
|
+
|
|
62
|
+
normalizeOptions(dev: Dev = {}) {
|
|
63
|
+
return resolveDevOptions(dev, this.compiler.options);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
rewriteCompilerOptions() {
|
|
67
|
+
if (!this.compiler.options.builtins.react) {
|
|
68
|
+
this.compiler.options.builtins.react = {};
|
|
69
|
+
}
|
|
70
|
+
this.compiler.options.builtins.react.development =
|
|
71
|
+
this.compiler.options.builtins.react.development ?? true;
|
|
72
|
+
if (this.options.hot) {
|
|
73
|
+
this.compiler.options.builtins.react.refresh =
|
|
74
|
+
this.compiler.options.builtins.react.refresh ?? true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
addAdditionEntires() {
|
|
79
|
+
const entries: string[] = [];
|
|
80
|
+
|
|
81
|
+
if (this.options.hot) {
|
|
82
|
+
const hotUpdateEntryPath = require.resolve(
|
|
83
|
+
"@rspack/dev-client/devServer"
|
|
84
|
+
);
|
|
85
|
+
entries.push(hotUpdateEntryPath);
|
|
86
|
+
|
|
87
|
+
const cssHotEntryPath = require.resolve("@rspack/dev-client/css");
|
|
88
|
+
|
|
89
|
+
entries.push(cssHotEntryPath);
|
|
90
|
+
|
|
91
|
+
if (this.compiler.options.builtins.react?.refresh) {
|
|
92
|
+
const reactRefreshEntryPath = require.resolve(
|
|
93
|
+
"@rspack/dev-client/react-refresh"
|
|
94
|
+
);
|
|
95
|
+
entries.push(reactRefreshEntryPath);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const devClientEntryPath = require.resolve("@rspack/dev-client");
|
|
100
|
+
entries.push(devClientEntryPath);
|
|
101
|
+
for (const key in this.compiler.options.entry) {
|
|
102
|
+
this.compiler.options.entry[key].unshift(...entries);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static isAbsoluteURL(URL: string): boolean {
|
|
107
|
+
return WebpackDevServer.isAbsoluteURL(URL);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static findIp(gateway: string): string | undefined {
|
|
111
|
+
return WebpackDevServer.findIp(gateway);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static async internalIP(family: "v6" | "v4"): Promise<string | undefined> {
|
|
115
|
+
return WebpackDevServer.internalIP(family);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static async internalIPSync(
|
|
119
|
+
family: "v6" | "v4"
|
|
120
|
+
): Promise<string | undefined> {
|
|
121
|
+
return WebpackDevServer.internalIPSync(family);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
static async getHostname(hostname?: Host): Promise<string> {
|
|
125
|
+
return WebpackDevServer.getHostname(hostname);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static async getFreePort(port: Port, host: string): Promise<string | number> {
|
|
129
|
+
return WebpackDevServer.getFreePort(port, host);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
static findCacheDir(): string {
|
|
133
|
+
// TODO: we need remove the `webpack-dev-server` tag in WebpackDevServer;
|
|
134
|
+
return "";
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private getCompilerOptions(): RspackOptionsNormalized {
|
|
138
|
+
return this.compiler.options;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
sendMessage(
|
|
142
|
+
clients: ClientConnection[],
|
|
143
|
+
type: string,
|
|
144
|
+
data?: any,
|
|
145
|
+
params?: any
|
|
146
|
+
) {
|
|
147
|
+
for (const client of clients) {
|
|
148
|
+
if (client.readyState === 1) {
|
|
149
|
+
client.send(JSON.stringify({ type, data, params }));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
watchFiles(watchPath: string | string[], watchOptions?: WatchOptions): void {
|
|
155
|
+
const watcher = chokidar.watch(watchPath, watchOptions);
|
|
156
|
+
|
|
157
|
+
// disabling refreshing on changing the content
|
|
158
|
+
if (this.options.liveReload) {
|
|
159
|
+
// TODO: remove this after we had memory filesystem
|
|
160
|
+
if (this.options.hot) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
watcher.on("change", item => {
|
|
165
|
+
if (this.webSocketServer) {
|
|
166
|
+
this.sendMessage(
|
|
167
|
+
this.webSocketServer.clients,
|
|
168
|
+
"static-changed",
|
|
169
|
+
item
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
this.staticWatchers.push(watcher);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
invalidate(callback = () => {}): void {
|
|
179
|
+
if (this.middleware) {
|
|
180
|
+
this.middleware.invalidate(callback);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async start(): Promise<void> {
|
|
185
|
+
this.setupHooks();
|
|
186
|
+
this.setupApp();
|
|
187
|
+
this.createServer();
|
|
188
|
+
this.setupWatchStaticFiles();
|
|
189
|
+
this.createWebsocketServer();
|
|
190
|
+
this.setupDevMiddleware();
|
|
191
|
+
this.setupMiddlewares();
|
|
192
|
+
const host = await RspackDevServer.getHostname(this.options.host);
|
|
193
|
+
const port = await RspackDevServer.getFreePort(this.options.port, host);
|
|
194
|
+
await new Promise(resolve =>
|
|
195
|
+
this.server.listen(
|
|
196
|
+
{
|
|
197
|
+
port,
|
|
198
|
+
host
|
|
199
|
+
},
|
|
200
|
+
() => {
|
|
201
|
+
this.logger.info(`Loopback: http://localhost:${port}`);
|
|
202
|
+
let internalIPv4 = WebpackDevServer.internalIPSync("v4");
|
|
203
|
+
this.logger.info(
|
|
204
|
+
`Your Network (IPV4) http://${internalIPv4}:${port}`
|
|
205
|
+
);
|
|
206
|
+
resolve({});
|
|
207
|
+
}
|
|
208
|
+
)
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
startCallback(callback?: (err?: Error) => void): void {
|
|
213
|
+
throw new Error("Method not implemented.");
|
|
214
|
+
}
|
|
215
|
+
stopCallback(callback?: (err?: Error) => void): void {
|
|
216
|
+
throw new Error("Method not implemented.");
|
|
217
|
+
}
|
|
218
|
+
listen(port: Port, hostname: string, fn: (err?: Error) => void): void {
|
|
219
|
+
throw new Error("Method not implemented.");
|
|
220
|
+
}
|
|
221
|
+
close(callback?: (err?: Error) => void): void {
|
|
222
|
+
throw new Error("Method not implemented.");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async stop(): Promise<void> {
|
|
226
|
+
await Promise.all(this.staticWatchers.map(watcher => watcher.close()));
|
|
227
|
+
this.middleware = null;
|
|
228
|
+
this.staticWatchers = [];
|
|
229
|
+
if (this.server) {
|
|
230
|
+
this.server.close();
|
|
231
|
+
}
|
|
232
|
+
if (this.webSocketServer) {
|
|
233
|
+
await new Promise(resolve => {
|
|
234
|
+
this.webSocketServer.implementation.close(() => {
|
|
235
|
+
resolve(void 0);
|
|
236
|
+
});
|
|
237
|
+
for (const client of this.webSocketServer.clients) client.terminate();
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private setupApp() {
|
|
243
|
+
this.app = express();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private setupWatchStaticFiles() {
|
|
247
|
+
if (this.options.static.watch === false) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
this.watchFiles(this.options.static.directory, this.options.static.watch);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
private setupDevMiddleware() {
|
|
254
|
+
// @ts-ignored
|
|
255
|
+
this.middleware = rdm(this.compiler, this.options.devMiddleware);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private createWebsocketServer() {
|
|
259
|
+
if (this.options.webSocketServer !== false) {
|
|
260
|
+
this.webSocketServer = createWebsocketServer(this);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private setupMiddlewares() {
|
|
265
|
+
const middlewares: Middleware[] = [];
|
|
266
|
+
middlewares.push({
|
|
267
|
+
name: "rdm",
|
|
268
|
+
middleware: this.middleware
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Todo Add options
|
|
272
|
+
const connectHistoryApiFallback = require("connect-history-api-fallback");
|
|
273
|
+
middlewares.push({
|
|
274
|
+
name: "[connect-history-api-fallback]",
|
|
275
|
+
middleware: connectHistoryApiFallback({
|
|
276
|
+
verbose: true,
|
|
277
|
+
logger: console.log.bind(console)
|
|
278
|
+
})
|
|
279
|
+
});
|
|
280
|
+
middlewares.push({
|
|
281
|
+
name: "express-static",
|
|
282
|
+
path: this.compiler.options.output.publicPath ?? "/",
|
|
283
|
+
middleware: express.static(this.options.static.directory)
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
middlewares.forEach(m => {
|
|
287
|
+
if (m.path) {
|
|
288
|
+
this.app.use(m.path, m.middleware);
|
|
289
|
+
} else {
|
|
290
|
+
this.app.use(m.middleware);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
private createServer() {
|
|
296
|
+
this.server = http.createServer(this.app);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private setupHooks() {
|
|
300
|
+
this.compiler.hooks.done.tap("dev-server", stats => {
|
|
301
|
+
// send Message
|
|
302
|
+
if (this.webSocketServer) {
|
|
303
|
+
this.sendMessage(this.webSocketServer.clients, "ok"); // TODO: send hash
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
package/src/ws.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RspackDevServer } from "./server";
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
import WebpackWsServer from "webpack-dev-server/lib/servers/WebsocketServer";
|
|
4
|
+
|
|
5
|
+
export type ClientConnection = WebSocket & { isAlive?: boolean };
|
|
6
|
+
|
|
7
|
+
export interface WebSocketServer {
|
|
8
|
+
heartbeatInterval: number;
|
|
9
|
+
implementation: WebSocket.Server<WebSocket.WebSocket>;
|
|
10
|
+
server: RspackDevServer;
|
|
11
|
+
clients: ClientConnection[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function createWebsocketServer(
|
|
15
|
+
server: RspackDevServer
|
|
16
|
+
): WebSocketServer {
|
|
17
|
+
return new WebpackWsServer(server);
|
|
18
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`normalize options snapshot additional entires should added 1`] = `
|
|
4
|
+
{
|
|
5
|
+
"main": [
|
|
6
|
+
"<prefix>/rspack-dev-client/dist/devServer.js",
|
|
7
|
+
"<prefix>/rspack-dev-client/dist/css.js",
|
|
8
|
+
"<prefix>/rspack-dev-client/dist/reactRefresh.js",
|
|
9
|
+
"<prefix>/rspack-dev-client/dist/index.js",
|
|
10
|
+
"<prefix>/something",
|
|
11
|
+
],
|
|
12
|
+
}
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
exports[`normalize options snapshot no options 1`] = `
|
|
16
|
+
{
|
|
17
|
+
"devMiddleware": {},
|
|
18
|
+
"host": undefined,
|
|
19
|
+
"hot": true,
|
|
20
|
+
"liveReload": true,
|
|
21
|
+
"open": true,
|
|
22
|
+
"port": undefined,
|
|
23
|
+
"static": {
|
|
24
|
+
"directory": "<PROJECT_ROOT>/dist",
|
|
25
|
+
"watch": {},
|
|
26
|
+
},
|
|
27
|
+
"webSocketServer": {},
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
exports[`normalize options snapshot port string 1`] = `
|
|
32
|
+
{
|
|
33
|
+
"devMiddleware": {},
|
|
34
|
+
"host": undefined,
|
|
35
|
+
"hot": true,
|
|
36
|
+
"liveReload": true,
|
|
37
|
+
"open": true,
|
|
38
|
+
"port": 9000,
|
|
39
|
+
"static": {
|
|
40
|
+
"directory": "<PROJECT_ROOT>/dist",
|
|
41
|
+
"watch": {},
|
|
42
|
+
},
|
|
43
|
+
"webSocketServer": {},
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
exports[`normalize options snapshot react.development and react.refresh should be true in default when hot enabled 1`] = `
|
|
48
|
+
{
|
|
49
|
+
"builtins": {
|
|
50
|
+
"browserslist": [],
|
|
51
|
+
"decorator": {
|
|
52
|
+
"emitMetadata": true,
|
|
53
|
+
"legacy": true,
|
|
54
|
+
"useDefineForClassFields": true,
|
|
55
|
+
},
|
|
56
|
+
"define": {},
|
|
57
|
+
"html": [],
|
|
58
|
+
"minify": true,
|
|
59
|
+
"react": {
|
|
60
|
+
"development": true,
|
|
61
|
+
"refresh": true,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
"devServer": {
|
|
65
|
+
"hot": true,
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
exports[`normalize options snapshot react-refresh client added when react/refresh enabled 1`] = `
|
|
71
|
+
{
|
|
72
|
+
"main": [
|
|
73
|
+
"<prefix>/rspack-dev-client/dist/devServer.js",
|
|
74
|
+
"<prefix>/rspack-dev-client/dist/css.js",
|
|
75
|
+
"<prefix>/rspack-dev-client/dist/reactRefresh.js",
|
|
76
|
+
"<prefix>/rspack-dev-client/dist/index.js",
|
|
77
|
+
"<prefix>/something",
|
|
78
|
+
],
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { RspackOptions } from "@rspack/core";
|
|
2
|
+
import { RspackDevServer } from "@rspack/dev-server";
|
|
3
|
+
import { createCompiler } from "@rspack/core";
|
|
4
|
+
import serializer from "jest-serializer-path";
|
|
5
|
+
import os from "os";
|
|
6
|
+
expect.addSnapshotSerializer(serializer);
|
|
7
|
+
|
|
8
|
+
describe("normalize options snapshot", () => {
|
|
9
|
+
it("no options", () => {
|
|
10
|
+
match({});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("port string", () => {
|
|
14
|
+
match({
|
|
15
|
+
devServer: {
|
|
16
|
+
port: "9000"
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("additional entires should added", () => {
|
|
22
|
+
matchAdditionEntries({
|
|
23
|
+
entry: ["something"]
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("react-refresh client added when react/refresh enabled", () => {
|
|
28
|
+
matchAdditionEntries({
|
|
29
|
+
entry: ["something"],
|
|
30
|
+
builtins: {
|
|
31
|
+
react: {
|
|
32
|
+
refresh: true
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("react.development and react.refresh should be true in default when hot enabled", () => {
|
|
39
|
+
const compiler = createCompiler({
|
|
40
|
+
devServer: {
|
|
41
|
+
hot: true
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
new RspackDevServer(compiler);
|
|
45
|
+
expect({
|
|
46
|
+
builtins: compiler.options.builtins,
|
|
47
|
+
devServer: compiler.options.devServer
|
|
48
|
+
}).toMatchSnapshot();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
function match(config: RspackOptions) {
|
|
53
|
+
const compiler = createCompiler(config);
|
|
54
|
+
const server = new RspackDevServer(compiler);
|
|
55
|
+
expect(server.options).toMatchSnapshot();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function matchAdditionEntries(config: RspackOptions) {
|
|
59
|
+
const compiler = createCompiler(config);
|
|
60
|
+
const server = new RspackDevServer(compiler);
|
|
61
|
+
const entires = Object.entries(compiler.options.entry);
|
|
62
|
+
// some hack for snapshot
|
|
63
|
+
const value = Object.fromEntries(
|
|
64
|
+
entires.map(([key, item]) => {
|
|
65
|
+
const replaced = item.map(entry => {
|
|
66
|
+
const array = entry.replace(/\\/g, "/").split("/");
|
|
67
|
+
return "<prefix>" + "/" + array.slice(-3).join("/");
|
|
68
|
+
});
|
|
69
|
+
return [key, replaced];
|
|
70
|
+
})
|
|
71
|
+
);
|
|
72
|
+
expect(value).toMatchSnapshot();
|
|
73
|
+
}
|