react-cosmos-plugin-rspack 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/cosmos.plugin.json +5 -0
- package/dist/client/errorOverlay/reactErrorOverlay.js +1476 -0
- package/dist/client/index.js +3839 -0
- package/dist/client/reactDevtoolsHook.js +8 -0
- package/dist/client/userImports.js +13 -0
- package/dist/server/rspackServerPlugin.js +691 -0
- package/dist/server/userImportsLoader.cjs +32 -0
- package/dist/ui/build.js +55 -0
- package/package.json +57 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// src/client/reactDevtoolsHook.ts
|
|
2
|
+
if (process.env.NODE_ENV === "development") {
|
|
3
|
+
try {
|
|
4
|
+
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
5
|
+
} catch (err) {
|
|
6
|
+
console.warn("Could not access parent React devtools hook");
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,691 @@
|
|
|
1
|
+
// src/server/rspackConfigPlugin.ts
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
// src/server/rspackConfig/constants.ts
|
|
5
|
+
var RENDERER_FILENAME = "renderer.html";
|
|
6
|
+
|
|
7
|
+
// src/server/rspackConfigPlugin.ts
|
|
8
|
+
async function rspackConfigPlugin({
|
|
9
|
+
cosmosConfig
|
|
10
|
+
}) {
|
|
11
|
+
if (cosmosConfig.rendererUrl) {
|
|
12
|
+
return cosmosConfig;
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
...cosmosConfig,
|
|
16
|
+
rendererUrl: path.join(cosmosConfig.publicUrl, RENDERER_FILENAME)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/server/rspackDevServerPlugin.ts
|
|
21
|
+
import * as path8 from "node:path";
|
|
22
|
+
import { serveStaticDir } from "react-cosmos";
|
|
23
|
+
import webpackHotMiddleware from "webpack-hot-middleware";
|
|
24
|
+
|
|
25
|
+
// src/server/cosmosConfig/createRspackCosmosConfig.ts
|
|
26
|
+
import * as path3 from "node:path";
|
|
27
|
+
import { fileExists } from "react-cosmos";
|
|
28
|
+
|
|
29
|
+
// src/server/utils/resolveLoose.ts
|
|
30
|
+
import * as path2 from "node:path";
|
|
31
|
+
|
|
32
|
+
// src/server/utils/isNodeError.ts
|
|
33
|
+
function isNodeError(err) {
|
|
34
|
+
return err && err.stack && err.message;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/server/utils/resolve.ts
|
|
38
|
+
import { createRequire } from "node:module";
|
|
39
|
+
function resolve(moduleId) {
|
|
40
|
+
const require2 = createRequire(import.meta.url);
|
|
41
|
+
return require2.resolve(moduleId);
|
|
42
|
+
}
|
|
43
|
+
function resolveFrom(fromDirectory, moduleId) {
|
|
44
|
+
const require2 = createRequire(import.meta.url);
|
|
45
|
+
return require2.resolve(moduleId, { paths: [fromDirectory] });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/server/utils/resolveSilent.ts
|
|
49
|
+
function resolveFromSilent(fromDirectory, moduleId) {
|
|
50
|
+
try {
|
|
51
|
+
return resolveFrom(fromDirectory, moduleId);
|
|
52
|
+
} catch (err) {
|
|
53
|
+
if (!isNodeError(err) || err.code !== "MODULE_NOT_FOUND") console.log(err);
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/server/utils/resolveLoose.ts
|
|
59
|
+
function resolveLoose(fromDirectory, moduleId) {
|
|
60
|
+
return path2.isAbsolute(moduleId) ? moduleId : resolveFromSilent(fromDirectory, moduleId) || // Final attempt: Resolve relative paths that don't either
|
|
61
|
+
// 1. Don't start with ./
|
|
62
|
+
// 2. Don't point to an existing file
|
|
63
|
+
path2.join(fromDirectory, moduleId);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/server/cosmosConfig/createRspackCosmosConfig.ts
|
|
67
|
+
function createRspackCosmosConfig(cosmosConfig) {
|
|
68
|
+
const { rootDir } = cosmosConfig;
|
|
69
|
+
const configInput = cosmosConfig.rspack || {};
|
|
70
|
+
return {
|
|
71
|
+
configPath: getRspackConfigPath(configInput, rootDir),
|
|
72
|
+
overridePath: getRspackOverridePath(configInput, rootDir),
|
|
73
|
+
includeHashInOutputFilename: getIncludeHashInOutputFilename(configInput),
|
|
74
|
+
hotReload: getHotReload(configInput),
|
|
75
|
+
reloadOnFail: getReloadOnFail(configInput)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function getRspackConfigPath({ configPath }, rootDir) {
|
|
79
|
+
if (typeof configPath === "undefined") {
|
|
80
|
+
return resolveLoose(rootDir, "rspack.config.js");
|
|
81
|
+
}
|
|
82
|
+
if (!configPath) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
const absPath = resolveLoose(rootDir, configPath);
|
|
86
|
+
if (!fileExists(absPath)) {
|
|
87
|
+
const relPath = path3.relative(process.cwd(), absPath);
|
|
88
|
+
throw new Error(`rspack config not found at path: ${relPath}`);
|
|
89
|
+
}
|
|
90
|
+
return absPath;
|
|
91
|
+
}
|
|
92
|
+
function getRspackOverridePath({ overridePath }, rootDir) {
|
|
93
|
+
if (typeof overridePath === "undefined") {
|
|
94
|
+
return resolveLoose(rootDir, "rspack.override.js");
|
|
95
|
+
}
|
|
96
|
+
if (!overridePath) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const absPath = resolveLoose(rootDir, overridePath);
|
|
100
|
+
if (!fileExists(absPath)) {
|
|
101
|
+
const relPath = path3.relative(process.cwd(), absPath);
|
|
102
|
+
throw new Error(`rspack override module not found at path: ${relPath}`);
|
|
103
|
+
}
|
|
104
|
+
return absPath;
|
|
105
|
+
}
|
|
106
|
+
function getIncludeHashInOutputFilename({
|
|
107
|
+
includeHashInOutputFilename = false
|
|
108
|
+
}) {
|
|
109
|
+
return includeHashInOutputFilename;
|
|
110
|
+
}
|
|
111
|
+
function getHotReload({ hotReload = true }) {
|
|
112
|
+
return hotReload;
|
|
113
|
+
}
|
|
114
|
+
function getReloadOnFail({ reloadOnFail = false }) {
|
|
115
|
+
return reloadOnFail;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/server/utils/requireModule.ts
|
|
119
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
120
|
+
import * as path4 from "node:path";
|
|
121
|
+
function requireFrom(fromDirectory, moduleId) {
|
|
122
|
+
const require2 = createRequire2(path4.resolve(fromDirectory, "noop.js"));
|
|
123
|
+
return require2(moduleId);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/server/utils/requireSilent.ts
|
|
127
|
+
function requireFromSilent(fromDirectory, moduleId) {
|
|
128
|
+
try {
|
|
129
|
+
return requireFrom(fromDirectory, moduleId);
|
|
130
|
+
} catch (err) {
|
|
131
|
+
if (!isNodeError(err) || err.code !== "MODULE_NOT_FOUND") {
|
|
132
|
+
console.log(err);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/server/getRspack.ts
|
|
138
|
+
function getRspack(rootDir) {
|
|
139
|
+
const userRspack = requireFromSilent(
|
|
140
|
+
rootDir,
|
|
141
|
+
"@rspack/core"
|
|
142
|
+
);
|
|
143
|
+
if (!userRspack) {
|
|
144
|
+
console.warn("[Cosmos] rspack dependency missing!");
|
|
145
|
+
console.log(
|
|
146
|
+
'Install using "yarn add --dev @rspack/core" or "npm install --save-dev @rspack/core"'
|
|
147
|
+
);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
return userRspack.rspack;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/server/rspackConfig/getDevRspackConfig.ts
|
|
154
|
+
import * as path7 from "node:path";
|
|
155
|
+
|
|
156
|
+
// src/server/rspackConfig/getUserRspackConfig.ts
|
|
157
|
+
import * as path5 from "node:path";
|
|
158
|
+
import {
|
|
159
|
+
getCliArgs,
|
|
160
|
+
importModule,
|
|
161
|
+
moduleExists
|
|
162
|
+
} from "react-cosmos";
|
|
163
|
+
|
|
164
|
+
// src/server/rspackConfig/getRspackNodeEnv.ts
|
|
165
|
+
function getRspackNodeEnv() {
|
|
166
|
+
return process.env.NODE_ENV === "production" ? "production" : "development";
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// src/server/utils/omit.ts
|
|
170
|
+
function omit(o, fields) {
|
|
171
|
+
const result = { ...o };
|
|
172
|
+
for (const field of fields) {
|
|
173
|
+
delete result[field];
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/server/rspackConfig/plugins.ts
|
|
179
|
+
function getGlobalsPlugin({ publicUrl }, userRspack, devServerOn) {
|
|
180
|
+
const cleanPublicUrl = removeTrailingSlash(publicUrl);
|
|
181
|
+
return new userRspack.DefinePlugin({
|
|
182
|
+
// "if (__DEV__)" blocks get stripped when compiling a static export build
|
|
183
|
+
__DEV__: JSON.stringify(devServerOn),
|
|
184
|
+
"process.env.NODE_ENV": JSON.stringify(getRspackNodeEnv()),
|
|
185
|
+
"process.env.PUBLIC_URL": JSON.stringify(cleanPublicUrl)
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
function hasPlugin(plugins, pluginName) {
|
|
189
|
+
return plugins && plugins.filter((p) => isInstanceOfRspackPlugin(p, pluginName)).length > 0;
|
|
190
|
+
}
|
|
191
|
+
function isInstanceOfRspackPlugin(plugin, constructorName) {
|
|
192
|
+
return plugin.constructor && plugin.constructor.name === constructorName;
|
|
193
|
+
}
|
|
194
|
+
function ignoreEmptyRspackPlugins(plugins = []) {
|
|
195
|
+
return plugins.filter(Boolean);
|
|
196
|
+
}
|
|
197
|
+
function removeTrailingSlash(url) {
|
|
198
|
+
return url.replace(/\/$/, "");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/server/rspackConfig/htmlPlugin.ts
|
|
202
|
+
function ensureHtmlWebpackPlugin({ rootDir }, plugins) {
|
|
203
|
+
if (hasPlugin(plugins, "HtmlWebpackPlugin")) {
|
|
204
|
+
return plugins.map(
|
|
205
|
+
(plugin) => isHtmlWebpackPlugin(plugin) ? changeHtmlPluginFilename(plugin) : plugin
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
const htmlWebpackPlugin = getHtmlWebpackPlugin(rootDir);
|
|
209
|
+
if (!htmlWebpackPlugin) {
|
|
210
|
+
return plugins;
|
|
211
|
+
}
|
|
212
|
+
return [
|
|
213
|
+
...plugins,
|
|
214
|
+
new htmlWebpackPlugin({
|
|
215
|
+
title: "React Cosmos",
|
|
216
|
+
filename: RENDERER_FILENAME
|
|
217
|
+
})
|
|
218
|
+
];
|
|
219
|
+
}
|
|
220
|
+
function getHtmlWebpackPlugin(rootDir) {
|
|
221
|
+
return requireFromSilent(
|
|
222
|
+
rootDir,
|
|
223
|
+
"html-webpack-plugin"
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
function isHtmlWebpackPlugin(plugin) {
|
|
227
|
+
return isInstanceOfRspackPlugin(plugin, "HtmlWebpackPlugin");
|
|
228
|
+
}
|
|
229
|
+
function changeHtmlPluginFilename(htmlPlugin) {
|
|
230
|
+
if (!isIndexHtmlWebpackPlugin(htmlPlugin)) {
|
|
231
|
+
return htmlPlugin;
|
|
232
|
+
}
|
|
233
|
+
const options = htmlPlugin.userOptions || htmlPlugin.options;
|
|
234
|
+
const safeOptions = omit(options, ["chunks"]);
|
|
235
|
+
return new htmlPlugin.constructor({
|
|
236
|
+
...safeOptions,
|
|
237
|
+
filename: RENDERER_FILENAME
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function isIndexHtmlWebpackPlugin(htmlPlugin) {
|
|
241
|
+
const { filename } = htmlPlugin.userOptions || htmlPlugin.options;
|
|
242
|
+
return filename === "index.html" || typeof filename !== "string" || filename.endsWith("/index.html");
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/server/rspackConfig/getDefaultRspackConfig.ts
|
|
246
|
+
function getDefaultRspackConfig(rootDir) {
|
|
247
|
+
const postcssLoaderPath = resolveFromSilent(rootDir, "postcss-loader");
|
|
248
|
+
const mdxLoaderPath = resolveFromSilent(rootDir, "@mdx-js/loader");
|
|
249
|
+
const rules = [];
|
|
250
|
+
const plugins = [];
|
|
251
|
+
rules.push({
|
|
252
|
+
test: /\.(j|t)s$/,
|
|
253
|
+
exclude: [/[\\/]node_modules[\\/]/],
|
|
254
|
+
loader: "builtin:swc-loader",
|
|
255
|
+
options: {
|
|
256
|
+
sourceMap: true,
|
|
257
|
+
jsc: { parser: { syntax: "typescript" } }
|
|
258
|
+
},
|
|
259
|
+
type: "javascript/auto"
|
|
260
|
+
});
|
|
261
|
+
rules.push({
|
|
262
|
+
test: /\.(j|t)sx$/,
|
|
263
|
+
loader: "builtin:swc-loader",
|
|
264
|
+
exclude: [/[\\/]node_modules[\\/]/],
|
|
265
|
+
options: {
|
|
266
|
+
sourceMap: true,
|
|
267
|
+
jsc: {
|
|
268
|
+
parser: {
|
|
269
|
+
syntax: "typescript",
|
|
270
|
+
tsx: true
|
|
271
|
+
},
|
|
272
|
+
transform: { react: { runtime: "automatic" } }
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
type: "javascript/auto"
|
|
276
|
+
});
|
|
277
|
+
rules.push({
|
|
278
|
+
test: /\.css?$/,
|
|
279
|
+
exclude: [/[\\/]node_modules[\\/]/],
|
|
280
|
+
use: postcssLoaderPath ? [{ loader: postcssLoaderPath }] : void 0,
|
|
281
|
+
type: "css"
|
|
282
|
+
});
|
|
283
|
+
if (mdxLoaderPath) {
|
|
284
|
+
rules.push({
|
|
285
|
+
test: /\.mdx$/,
|
|
286
|
+
loader: mdxLoaderPath,
|
|
287
|
+
exclude: [/[\\/]node_modules[\\/]/]
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
const htmlWebpackPlugin = getHtmlWebpackPlugin(rootDir);
|
|
291
|
+
if (htmlWebpackPlugin) {
|
|
292
|
+
plugins.push(
|
|
293
|
+
new htmlWebpackPlugin({
|
|
294
|
+
title: "React Cosmos",
|
|
295
|
+
filename: RENDERER_FILENAME
|
|
296
|
+
})
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
const config = {
|
|
300
|
+
// Besides other advantages, cheap-module-source-map is compatible with
|
|
301
|
+
// React.componentDidCatch https://github.com/facebook/react/issues/10441
|
|
302
|
+
devtool: "cheap-module-source-map",
|
|
303
|
+
resolve: {
|
|
304
|
+
extensionAlias: {
|
|
305
|
+
".js": [".ts", ".tsx", ".js"]
|
|
306
|
+
},
|
|
307
|
+
extensions: [".js", ".jsx", ".ts", ".tsx"]
|
|
308
|
+
},
|
|
309
|
+
module: {
|
|
310
|
+
rules
|
|
311
|
+
},
|
|
312
|
+
plugins,
|
|
313
|
+
stats: {
|
|
314
|
+
preset: "errors-only",
|
|
315
|
+
builtAt: true
|
|
316
|
+
},
|
|
317
|
+
infrastructureLogging: { level: "warn" },
|
|
318
|
+
experiments: {
|
|
319
|
+
topLevelAwait: true
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
return {
|
|
323
|
+
...config,
|
|
324
|
+
mode: getRspackNodeEnv(),
|
|
325
|
+
optimization: {
|
|
326
|
+
// Cosmos reads component names at run-time, so it is crucial to not
|
|
327
|
+
// minify even when building with production env (ie. when exporting)
|
|
328
|
+
// https://github.com/react-cosmos/react-cosmos/issues/701
|
|
329
|
+
minimize: false
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// src/server/rspackConfig/getUserRspackConfig.ts
|
|
335
|
+
async function getUserRspackConfig(cosmosConfig) {
|
|
336
|
+
const baseRspackConfig = await getBaseRspackConfig(cosmosConfig);
|
|
337
|
+
const { overridePath } = createRspackCosmosConfig(cosmosConfig);
|
|
338
|
+
if (!overridePath || !moduleExists(overridePath)) {
|
|
339
|
+
console.log(
|
|
340
|
+
`[Cosmos] Learn how to override rspack config for cosmos: https://github.com/react-cosmos/react-cosmos/tree/main/docs#webpack-config-override`
|
|
341
|
+
);
|
|
342
|
+
return baseRspackConfig;
|
|
343
|
+
}
|
|
344
|
+
const relPath = path5.relative(process.cwd(), overridePath);
|
|
345
|
+
console.log(`[Cosmos] Overriding rspack config at ${relPath}`);
|
|
346
|
+
const module = await importModule(overridePath);
|
|
347
|
+
const rspackOverride = module.default;
|
|
348
|
+
return rspackOverride(baseRspackConfig, getRspackNodeEnv());
|
|
349
|
+
}
|
|
350
|
+
async function getBaseRspackConfig(cosmosConfig) {
|
|
351
|
+
const { rootDir } = cosmosConfig;
|
|
352
|
+
const { configPath } = createRspackCosmosConfig(cosmosConfig);
|
|
353
|
+
if (!configPath || !moduleExists(configPath)) {
|
|
354
|
+
console.log("[Cosmos] Using default rspack config");
|
|
355
|
+
return getDefaultRspackConfig(rootDir);
|
|
356
|
+
}
|
|
357
|
+
const relPath = path5.relative(process.cwd(), configPath);
|
|
358
|
+
console.log(`[Cosmos] Using rspack config found at ${relPath}`);
|
|
359
|
+
const module = await importModule(configPath);
|
|
360
|
+
const rspackConfig = module.default;
|
|
361
|
+
const cliArgs = getCliArgs();
|
|
362
|
+
return typeof rspackConfig === "function" ? (
|
|
363
|
+
// When cliargs.env is falsey, react-cosmos-plugin-webpack passes the result
|
|
364
|
+
// of getRspackNodeEnv() which is the string "production" or "development"
|
|
365
|
+
// but that doesn't seem to be what webpack does:
|
|
366
|
+
//
|
|
367
|
+
// https://github.com/webpack/webpack-cli/blob/79a969fb02c870667d8a3b7035405566d2b4d088/packages/webpack-cli/src/webpack-cli.ts#L1903C35-L1903C43
|
|
368
|
+
await rspackConfig(cliArgs.env || {}, cliArgs)
|
|
369
|
+
) : rspackConfig;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// src/server/rspackConfig/resolveRspackClientPath.ts
|
|
373
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
374
|
+
function resolveRspackClientPath(relPath) {
|
|
375
|
+
const require2 = createRequire3(import.meta.url);
|
|
376
|
+
return require2.resolve(`../client/${relPath}`);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// src/server/rspackConfig/resolveRspackLoaderPath.ts
|
|
380
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
381
|
+
function resolveRspackLoaderPath() {
|
|
382
|
+
const require2 = createRequire4(import.meta.url);
|
|
383
|
+
return require2.resolve("./userImportsLoader.cjs");
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// src/server/rspackConfig/getRspackConfigModule.ts
|
|
387
|
+
function getRspackConfigModule(cosmosConfig, rspackConfig) {
|
|
388
|
+
return {
|
|
389
|
+
...rspackConfig.module,
|
|
390
|
+
rules: getRules(cosmosConfig, rspackConfig)
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
function getRules(cosmosConfig, { module }) {
|
|
394
|
+
const existingRules = module && module.rules || [];
|
|
395
|
+
return [...existingRules, getUserImportsLoaderRule(cosmosConfig)];
|
|
396
|
+
}
|
|
397
|
+
function getUserImportsLoaderRule(cosmosConfig) {
|
|
398
|
+
return {
|
|
399
|
+
include: resolveRspackClientPath("userImports"),
|
|
400
|
+
use: {
|
|
401
|
+
loader: resolveRspackLoaderPath(),
|
|
402
|
+
options: { cosmosConfig }
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// src/server/rspackConfig/getRspackConfigResolve.ts
|
|
408
|
+
import * as path6 from "node:path";
|
|
409
|
+
function getRspackConfigResolve(cosmosConfig, rspackConfig) {
|
|
410
|
+
return resolveLocalReactDeps(cosmosConfig, rspackConfig.resolve);
|
|
411
|
+
}
|
|
412
|
+
function resolveLocalReactDeps(cosmosConfig, resolve6 = {}) {
|
|
413
|
+
const { rootDir } = cosmosConfig;
|
|
414
|
+
let alias = resolve6.alias || {};
|
|
415
|
+
let reactAlias = hasAlias(alias, "react");
|
|
416
|
+
let reactDomAlias = hasAlias(alias, "react-dom");
|
|
417
|
+
if (reactAlias && reactDomAlias) {
|
|
418
|
+
console.log("[Cosmos] React and React DOM aliases found in rspack config");
|
|
419
|
+
return resolve6;
|
|
420
|
+
}
|
|
421
|
+
if (reactAlias) {
|
|
422
|
+
console.log("[Cosmos] React alias found in rspack config");
|
|
423
|
+
} else {
|
|
424
|
+
const reactPath = resolveFromSilent(rootDir, "react");
|
|
425
|
+
if (!reactPath)
|
|
426
|
+
throw new Error(`[Cosmos] Local dependency not found: react`);
|
|
427
|
+
alias = addAlias(alias, "react", path6.dirname(reactPath));
|
|
428
|
+
}
|
|
429
|
+
if (reactDomAlias) {
|
|
430
|
+
console.log("[Cosmos] React DOM alias found in rspack config");
|
|
431
|
+
} else {
|
|
432
|
+
const reactDomPath = resolveFromSilent(rootDir, "react-dom");
|
|
433
|
+
if (!reactDomPath)
|
|
434
|
+
throw new Error(`[Cosmos] Local dependency not found: react-dom`);
|
|
435
|
+
alias = addAlias(alias, "react-dom", path6.dirname(reactDomPath));
|
|
436
|
+
}
|
|
437
|
+
return { ...resolve6, alias };
|
|
438
|
+
}
|
|
439
|
+
function hasAlias(alias, name) {
|
|
440
|
+
if (!alias) return false;
|
|
441
|
+
const exactName = `${name}$`;
|
|
442
|
+
const keys = Object.keys(alias);
|
|
443
|
+
return keys.includes(name) || keys.includes(exactName);
|
|
444
|
+
}
|
|
445
|
+
function addAlias(alias, name, value) {
|
|
446
|
+
return { ...alias, [name]: value };
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// src/server/rspackConfig/rspackConfigTopLevelAwait.ts
|
|
450
|
+
function ensureRspackConfigTopLevelAwait(baseWebpackConfig) {
|
|
451
|
+
const experiments = baseWebpackConfig.experiments || {};
|
|
452
|
+
if (!experiments.topLevelAwait) {
|
|
453
|
+
experiments.topLevelAwait = true;
|
|
454
|
+
}
|
|
455
|
+
return experiments;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/server/rspackConfig/getDevRspackConfig.ts
|
|
459
|
+
async function getDevRspackConfig(cosmosConfig, userRspack) {
|
|
460
|
+
const baseRspackConfig = await getUserRspackConfig(cosmosConfig);
|
|
461
|
+
const rspackConfig = {
|
|
462
|
+
...baseRspackConfig,
|
|
463
|
+
entry: getEntry(cosmosConfig),
|
|
464
|
+
output: getOutput(cosmosConfig),
|
|
465
|
+
module: getRspackConfigModule(cosmosConfig, baseRspackConfig),
|
|
466
|
+
resolve: getRspackConfigResolve(cosmosConfig, baseRspackConfig),
|
|
467
|
+
plugins: getPlugins(cosmosConfig, baseRspackConfig, userRspack),
|
|
468
|
+
experiments: getExperiments(baseRspackConfig)
|
|
469
|
+
};
|
|
470
|
+
if (rspackConfig.optimization?.splitChunks) {
|
|
471
|
+
const { name } = rspackConfig.optimization.splitChunks;
|
|
472
|
+
if (name === false) delete rspackConfig.optimization.splitChunks.name;
|
|
473
|
+
}
|
|
474
|
+
return rspackConfig;
|
|
475
|
+
}
|
|
476
|
+
function getEntry(cosmosConfig) {
|
|
477
|
+
const { hotReload, reloadOnFail } = createRspackCosmosConfig(cosmosConfig);
|
|
478
|
+
const devtoolsHook = resolveRspackClientPath("reactDevtoolsHook");
|
|
479
|
+
const clientIndex = resolveRspackClientPath("index");
|
|
480
|
+
return hotReload ? [devtoolsHook, getHotMiddlewareEntry(reloadOnFail), clientIndex] : [devtoolsHook, clientIndex];
|
|
481
|
+
}
|
|
482
|
+
function getOutput({ publicUrl }) {
|
|
483
|
+
const filename = "[name].js";
|
|
484
|
+
return {
|
|
485
|
+
filename,
|
|
486
|
+
publicPath: publicUrl,
|
|
487
|
+
// Enable click-to-open source in react-error-overlay
|
|
488
|
+
devtoolModuleFilenameTemplate: (info) => path7.resolve(info.absoluteResourcePath).replace(/\\/g, "/")
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
function getPlugins(cosmosConfig, baseRspackConfig, userRspack) {
|
|
492
|
+
const existingPlugins = ignoreEmptyRspackPlugins(baseRspackConfig.plugins);
|
|
493
|
+
const globalsPlugin = getGlobalsPlugin(cosmosConfig, userRspack, true);
|
|
494
|
+
let plugins = [...existingPlugins, globalsPlugin];
|
|
495
|
+
const { hotReload } = createRspackCosmosConfig(cosmosConfig);
|
|
496
|
+
if (hotReload && !hasPlugin(plugins, "HotModuleReplacementPlugin")) {
|
|
497
|
+
const hmrPlugin = new userRspack.HotModuleReplacementPlugin();
|
|
498
|
+
plugins = [...plugins, hmrPlugin];
|
|
499
|
+
}
|
|
500
|
+
return ensureHtmlWebpackPlugin(cosmosConfig, plugins);
|
|
501
|
+
}
|
|
502
|
+
function getHotMiddlewareEntry(reloadOnFail) {
|
|
503
|
+
const clientPath = resolve("webpack-hot-middleware/client");
|
|
504
|
+
return `${clientPath}?reload=${reloadOnFail}&overlay=false`;
|
|
505
|
+
}
|
|
506
|
+
function getExperiments(baseWebpackConfig) {
|
|
507
|
+
return ensureRspackConfigTopLevelAwait(baseWebpackConfig);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// src/server/rspackDevServerPlugin.ts
|
|
511
|
+
async function rspackDevServerPlugin({
|
|
512
|
+
cosmosConfig,
|
|
513
|
+
platform,
|
|
514
|
+
expressApp,
|
|
515
|
+
sendMessage
|
|
516
|
+
}) {
|
|
517
|
+
if (platform !== "web") {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
const userRspack = getRspack(cosmosConfig.rootDir);
|
|
521
|
+
if (!userRspack) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
const rspackConfig = await getDevRspackConfig(
|
|
525
|
+
cosmosConfig,
|
|
526
|
+
userRspack
|
|
527
|
+
);
|
|
528
|
+
if (cosmosConfig.staticPath === null) {
|
|
529
|
+
const rspackDerivedStaticPath = getRspackStaticPath(rspackConfig);
|
|
530
|
+
if (rspackDerivedStaticPath !== null) {
|
|
531
|
+
serveStaticDir(
|
|
532
|
+
expressApp,
|
|
533
|
+
path8.resolve(cosmosConfig.rootDir, rspackDerivedStaticPath),
|
|
534
|
+
cosmosConfig.publicUrl
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
function sendBuildMessage(msg) {
|
|
539
|
+
sendMessage(msg);
|
|
540
|
+
}
|
|
541
|
+
const rspackCompiler = userRspack(rspackConfig);
|
|
542
|
+
rspackCompiler.hooks.invalid.tap("Cosmos", (filePath) => {
|
|
543
|
+
if (typeof filePath === "string") {
|
|
544
|
+
const relFilePath = path8.relative(process.cwd(), filePath);
|
|
545
|
+
console.log("[Cosmos] rspack build invalidated by", relFilePath);
|
|
546
|
+
} else {
|
|
547
|
+
console.log("[Cosmos] rspack build invalidated by unknown file");
|
|
548
|
+
}
|
|
549
|
+
sendBuildMessage({ type: "buildStart" });
|
|
550
|
+
});
|
|
551
|
+
rspackCompiler.hooks.failed.tap("Cosmos", () => {
|
|
552
|
+
sendBuildMessage({ type: "buildError" });
|
|
553
|
+
});
|
|
554
|
+
const onCompilationDone = new Promise((resolve6) => {
|
|
555
|
+
rspackCompiler.hooks.done.tap("Cosmos", (stats) => {
|
|
556
|
+
resolve6();
|
|
557
|
+
if (stats.hasErrors()) {
|
|
558
|
+
sendBuildMessage({ type: "buildError" });
|
|
559
|
+
} else {
|
|
560
|
+
sendBuildMessage({ type: "buildDone" });
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
console.log("[Cosmos] Building rspack...");
|
|
565
|
+
const wdmModule = await import("webpack-dev-middleware");
|
|
566
|
+
const wdmInst = wdmModule.default(
|
|
567
|
+
// Rspack's Compiler type is pretty close to webpack's Compiler type, but
|
|
568
|
+
// is missing a few members. Hopefully WDM doesn't need them, however.
|
|
569
|
+
// @rspack/dev-server itself uses webpack-dev-middleware so it should be
|
|
570
|
+
// fine.
|
|
571
|
+
rspackCompiler,
|
|
572
|
+
{
|
|
573
|
+
// publicPath is the base path for the rspack assets and has to match
|
|
574
|
+
// rspack.output.publicPath
|
|
575
|
+
publicPath: cosmosConfig.publicUrl
|
|
576
|
+
}
|
|
577
|
+
);
|
|
578
|
+
expressApp.use(wdmInst);
|
|
579
|
+
const { hotReload } = createRspackCosmosConfig(cosmosConfig);
|
|
580
|
+
if (hotReload) {
|
|
581
|
+
expressApp.use(
|
|
582
|
+
webpackHotMiddleware(
|
|
583
|
+
// As above, rspack's Compiler type is pretty close to webpack's
|
|
584
|
+
// Compiler type so this should be fine.
|
|
585
|
+
rspackCompiler
|
|
586
|
+
)
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
await onCompilationDone;
|
|
590
|
+
return async () => {
|
|
591
|
+
await new Promise((res) => wdmInst.close(res));
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
function getRspackStaticPath({ devServer }) {
|
|
595
|
+
return devServer && typeof devServer.contentBase === "string" ? devServer.contentBase : null;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// src/server/rspackConfig/getExportRspackConfig.ts
|
|
599
|
+
import * as path9 from "node:path";
|
|
600
|
+
async function getExportRspackConfig(cosmosConfig, userRspack) {
|
|
601
|
+
const baseRspackConfig = await getUserRspackConfig(cosmosConfig);
|
|
602
|
+
return {
|
|
603
|
+
...baseRspackConfig,
|
|
604
|
+
entry: getEntry2(),
|
|
605
|
+
output: getOutput2(cosmosConfig),
|
|
606
|
+
module: getRspackConfigModule(cosmosConfig, baseRspackConfig),
|
|
607
|
+
resolve: getRspackConfigResolve(cosmosConfig, baseRspackConfig),
|
|
608
|
+
plugins: getPlugins2(cosmosConfig, baseRspackConfig, userRspack),
|
|
609
|
+
experiments: getExperiments2(baseRspackConfig)
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
function getEntry2() {
|
|
613
|
+
const devtoolsHook = resolveRspackClientPath("reactDevtoolsHook");
|
|
614
|
+
const clientIndex = resolveRspackClientPath("index");
|
|
615
|
+
return [devtoolsHook, clientIndex];
|
|
616
|
+
}
|
|
617
|
+
function getOutput2(cosmosConfig) {
|
|
618
|
+
const { exportPath, publicUrl } = cosmosConfig;
|
|
619
|
+
const { includeHashInOutputFilename } = createRspackCosmosConfig(cosmosConfig);
|
|
620
|
+
return {
|
|
621
|
+
path: path9.join(exportPath, publicUrl),
|
|
622
|
+
filename: includeHashInOutputFilename ? "[name].[contenthash].js" : "[name].js",
|
|
623
|
+
publicPath: publicUrl
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
function getPlugins2(cosmosConfig, baseRspackConfig, userRspack) {
|
|
627
|
+
const existingPlugins = ignoreEmptyRspackPlugins(baseRspackConfig.plugins);
|
|
628
|
+
const globalsPlugin = getGlobalsPlugin(cosmosConfig, userRspack, false);
|
|
629
|
+
return ensureHtmlWebpackPlugin(cosmosConfig, [
|
|
630
|
+
...existingPlugins,
|
|
631
|
+
globalsPlugin
|
|
632
|
+
]);
|
|
633
|
+
}
|
|
634
|
+
function getExperiments2(baseWebpackConfig) {
|
|
635
|
+
return ensureRspackConfigTopLevelAwait(baseWebpackConfig);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// src/server/rspackExportPlugin.ts
|
|
639
|
+
async function rspackExportPlugin({ cosmosConfig }) {
|
|
640
|
+
const userRspack = getRspack(cosmosConfig.rootDir);
|
|
641
|
+
if (!userRspack) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
const rspackConfig = await getExportRspackConfig(cosmosConfig, userRspack);
|
|
645
|
+
try {
|
|
646
|
+
await runRspackCompiler(userRspack, rspackConfig);
|
|
647
|
+
} catch (err) {
|
|
648
|
+
const rspackError = err;
|
|
649
|
+
if (rspackError.rspackErrors) {
|
|
650
|
+
rspackError.rspackErrors.forEach((error) => {
|
|
651
|
+
console.error(`${error}
|
|
652
|
+
`);
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
throw rspackError;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
function runRspackCompiler(userRspack, rspackConfig) {
|
|
659
|
+
return new Promise((resolve6, reject) => {
|
|
660
|
+
const compiler = userRspack(rspackConfig);
|
|
661
|
+
compiler.run((err, stats) => {
|
|
662
|
+
if (err) {
|
|
663
|
+
reject(err);
|
|
664
|
+
} else if (stats?.hasErrors()) {
|
|
665
|
+
const error = new RspackCompilationError();
|
|
666
|
+
error.rspackErrors = stats.toJson().errors;
|
|
667
|
+
reject(error);
|
|
668
|
+
} else {
|
|
669
|
+
resolve6(stats);
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
var RspackCompilationError = class extends Error {
|
|
675
|
+
rspackErrors;
|
|
676
|
+
constructor() {
|
|
677
|
+
super("Rspack errors occurred");
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
// src/server/rspackServerPlugin.ts
|
|
682
|
+
var rspackServerPlugin = {
|
|
683
|
+
name: "rspack",
|
|
684
|
+
config: rspackConfigPlugin,
|
|
685
|
+
devServer: rspackDevServerPlugin,
|
|
686
|
+
export: rspackExportPlugin
|
|
687
|
+
};
|
|
688
|
+
var rspackServerPlugin_default = rspackServerPlugin;
|
|
689
|
+
export {
|
|
690
|
+
rspackServerPlugin_default as default
|
|
691
|
+
};
|