@meteorjs/rspack 1.1.0-beta.2 → 1.1.0-beta.20
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/lib/meteorRspackConfigHelpers.js +121 -0
- package/package.json +1 -1
- package/rspack.config.js +149 -232
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const { cleanOmittedPaths } = require("./mergeRulesSplitOverlap.js");
|
|
4
|
+
const { mergeMeteorRspackFragments } = require("./meteorRspackConfigFactory.js");
|
|
5
|
+
|
|
6
|
+
// Helper function to load and process config files
|
|
7
|
+
async function loadAndProcessConfig(configPath, configType, Meteor, argv, disableWarnings) {
|
|
8
|
+
try {
|
|
9
|
+
// Load the config file
|
|
10
|
+
let config;
|
|
11
|
+
if (path.extname(configPath) === '.mjs') {
|
|
12
|
+
// For ESM modules, we need to use dynamic import
|
|
13
|
+
const fileUrl = `file://${configPath}`;
|
|
14
|
+
const module = await import(fileUrl);
|
|
15
|
+
config = module.default || module;
|
|
16
|
+
} else {
|
|
17
|
+
// For CommonJS modules, we can use require
|
|
18
|
+
config = require(configPath)?.default || require(configPath);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Process the config
|
|
22
|
+
const rawConfig = typeof config === 'function' ? config(Meteor, argv) : config;
|
|
23
|
+
const resolvedConfig = await Promise.resolve(rawConfig);
|
|
24
|
+
const userConfig = resolvedConfig && '0' in resolvedConfig ? resolvedConfig[0] : resolvedConfig;
|
|
25
|
+
|
|
26
|
+
// Define omitted paths and warning function
|
|
27
|
+
const omitPaths = [
|
|
28
|
+
"name",
|
|
29
|
+
"target",
|
|
30
|
+
"entry",
|
|
31
|
+
"output.path",
|
|
32
|
+
"output.filename",
|
|
33
|
+
...(Meteor.isServer ? ["optimization.splitChunks", "optimization.runtimeChunk"] : []),
|
|
34
|
+
].filter(Boolean);
|
|
35
|
+
|
|
36
|
+
const warningFn = path => {
|
|
37
|
+
if (disableWarnings) return;
|
|
38
|
+
console.warn(
|
|
39
|
+
`[${configType}] Ignored custom "${path}" — reserved for Meteor-Rspack integration.`,
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Clean omitted paths and merge Meteor Rspack fragments
|
|
44
|
+
let nextConfig = cleanOmittedPaths(userConfig, {
|
|
45
|
+
omitPaths,
|
|
46
|
+
warningFn,
|
|
47
|
+
});
|
|
48
|
+
nextConfig = mergeMeteorRspackFragments(nextConfig);
|
|
49
|
+
|
|
50
|
+
return nextConfig;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error(`Error loading ${configType} from ${configPath}:`, error);
|
|
53
|
+
if (configType === 'rspack.config.js') {
|
|
54
|
+
throw error; // Only rethrow for project config
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Loads both the user's Rspack configuration and its potential override.
|
|
62
|
+
*
|
|
63
|
+
* @param {string|undefined} projectConfigPath
|
|
64
|
+
* @param {object} Meteor
|
|
65
|
+
* @param {object} argv
|
|
66
|
+
* @returns {Promise<{ nextUserConfig: object|null, nextOverrideConfig: object|null }>}
|
|
67
|
+
*/
|
|
68
|
+
async function loadUserAndOverrideConfig(projectConfigPath, Meteor, argv) {
|
|
69
|
+
let nextUserConfig = null;
|
|
70
|
+
let nextOverrideConfig = null;
|
|
71
|
+
|
|
72
|
+
const projectDir = process.cwd();
|
|
73
|
+
const isMeteorPackageConfig = projectDir.includes("/packages/rspack");
|
|
74
|
+
|
|
75
|
+
if (projectConfigPath) {
|
|
76
|
+
const configDir = path.dirname(projectConfigPath);
|
|
77
|
+
const configFileName = path.basename(projectConfigPath);
|
|
78
|
+
const configExt = path.extname(configFileName);
|
|
79
|
+
const configNameWithoutExt = configFileName.replace(configExt, '');
|
|
80
|
+
const configNameFull = `${configNameWithoutExt}.override${configExt}`;
|
|
81
|
+
const overrideConfigPath = path.join(configDir, configNameFull);
|
|
82
|
+
|
|
83
|
+
if (fs.existsSync(overrideConfigPath)) {
|
|
84
|
+
nextOverrideConfig = await loadAndProcessConfig(
|
|
85
|
+
overrideConfigPath,
|
|
86
|
+
configNameFull,
|
|
87
|
+
Meteor,
|
|
88
|
+
argv,
|
|
89
|
+
Meteor.isAngularEnabled
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (fs.existsSync(projectConfigPath) && !isMeteorPackageConfig) {
|
|
94
|
+
// Check if there's a .mjs or .cjs version of the config file
|
|
95
|
+
const mjsConfigPath = projectConfigPath.replace(/\.js$/, '.mjs');
|
|
96
|
+
const cjsConfigPath = projectConfigPath.replace(/\.js$/, '.cjs');
|
|
97
|
+
|
|
98
|
+
let projectConfigPathToUse = projectConfigPath;
|
|
99
|
+
if (fs.existsSync(mjsConfigPath)) {
|
|
100
|
+
projectConfigPathToUse = mjsConfigPath;
|
|
101
|
+
} else if (fs.existsSync(cjsConfigPath)) {
|
|
102
|
+
projectConfigPathToUse = cjsConfigPath;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
nextUserConfig = await loadAndProcessConfig(
|
|
106
|
+
projectConfigPathToUse,
|
|
107
|
+
'rspack.config.js',
|
|
108
|
+
Meteor,
|
|
109
|
+
argv,
|
|
110
|
+
Meteor.isAngularEnabled
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return { nextUserConfig, nextOverrideConfig };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = {
|
|
119
|
+
loadAndProcessConfig,
|
|
120
|
+
loadUserAndOverrideConfig,
|
|
121
|
+
};
|
package/package.json
CHANGED
package/rspack.config.js
CHANGED
|
@@ -12,7 +12,6 @@ const { RequireExternalsPlugin } = require('./plugins/RequireExtenalsPlugin.js')
|
|
|
12
12
|
const { AssetExternalsPlugin } = require('./plugins/AssetExternalsPlugin.js');
|
|
13
13
|
const { generateEagerTestFile } = require("./lib/test.js");
|
|
14
14
|
const { getMeteorIgnoreEntries, createIgnoreGlobConfig } = require("./lib/ignore");
|
|
15
|
-
const { mergeMeteorRspackFragments } = require("./lib/meteorRspackConfigFactory.js");
|
|
16
15
|
const {
|
|
17
16
|
compileWithMeteor,
|
|
18
17
|
compileWithRspack,
|
|
@@ -22,6 +21,7 @@ const {
|
|
|
22
21
|
makeWebNodeBuiltinsAlias,
|
|
23
22
|
disablePlugins,
|
|
24
23
|
} = require('./lib/meteorRspackHelpers.js');
|
|
24
|
+
const { loadUserAndOverrideConfig } = require('./lib/meteorRspackConfigHelpers.js');
|
|
25
25
|
const { prepareMeteorRspackConfig } = require("./lib/meteorRspackConfigFactory");
|
|
26
26
|
|
|
27
27
|
// Safe require that doesn't throw if the module isn't found
|
|
@@ -204,15 +204,42 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
204
204
|
const Meteor = { ...inMeteor };
|
|
205
205
|
// Convert string boolean values to actual booleans
|
|
206
206
|
for (const key in Meteor) {
|
|
207
|
-
if (Meteor[key] ===
|
|
207
|
+
if (Meteor[key] === "true" || Meteor[key] === true) {
|
|
208
208
|
Meteor[key] = true;
|
|
209
|
-
} else if (Meteor[key] ===
|
|
209
|
+
} else if (Meteor[key] === "false" || Meteor[key] === false) {
|
|
210
210
|
Meteor[key] = false;
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
const
|
|
215
|
-
const
|
|
214
|
+
const isTestLike = !!Meteor.isTestLike;
|
|
215
|
+
const swcExternalHelpers = !!Meteor.swcExternalHelpers;
|
|
216
|
+
const isNative = !!Meteor.isNative;
|
|
217
|
+
|
|
218
|
+
const projectDir = process.cwd();
|
|
219
|
+
const projectConfigPath =
|
|
220
|
+
Meteor.projectConfigPath || path.resolve(projectDir, "rspack.config.js");
|
|
221
|
+
|
|
222
|
+
// Load and apply project-level overrides for the selected build
|
|
223
|
+
const { nextUserConfig, nextOverrideConfig } =
|
|
224
|
+
await loadUserAndOverrideConfig(projectConfigPath, Meteor, argv);
|
|
225
|
+
|
|
226
|
+
// Determine the mode
|
|
227
|
+
const getModeFromConfig = () => {
|
|
228
|
+
if (nextOverrideConfig?.mode) return nextOverrideConfig.mode;
|
|
229
|
+
if (nextUserConfig?.mode) return nextUserConfig.mode;
|
|
230
|
+
if (argv.mode) return argv.mode;
|
|
231
|
+
if (Meteor.isProduction) return "production";
|
|
232
|
+
if (Meteor.isDevelopment) return "development";
|
|
233
|
+
return null;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const currentMode = getModeFromConfig();
|
|
237
|
+
const isProd = currentMode
|
|
238
|
+
? currentMode === "production"
|
|
239
|
+
: !!Meteor.isProduction;
|
|
240
|
+
const isDev = currentMode
|
|
241
|
+
? currentMode === "development"
|
|
242
|
+
: !!Meteor.isDevelopment || !isProd;
|
|
216
243
|
const isTest = !!Meteor.isTest;
|
|
217
244
|
const isClient = !!Meteor.isClient;
|
|
218
245
|
const isServer = !!Meteor.isServer;
|
|
@@ -222,12 +249,8 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
222
249
|
const isTestModule = !!Meteor.isTestModule;
|
|
223
250
|
const isTestEager = !!Meteor.isTestEager;
|
|
224
251
|
const isTestFullApp = !!Meteor.isTestFullApp;
|
|
225
|
-
|
|
226
|
-
const
|
|
227
|
-
const isNative = !!Meteor.isNative;
|
|
228
|
-
const mode = isProd ? 'production' : 'development';
|
|
229
|
-
const projectDir = process.cwd();
|
|
230
|
-
const projectConfigPath = Meteor.projectConfigPath || path.resolve(projectDir, 'rspack.config.js');
|
|
252
|
+
|
|
253
|
+
const mode = isProd ? "production" : "development";
|
|
231
254
|
const configPath = Meteor.configPath;
|
|
232
255
|
const testEntry = Meteor.testEntry;
|
|
233
256
|
|
|
@@ -240,28 +263,18 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
240
263
|
const isAngularEnabled = Meteor.isAngularEnabled || false;
|
|
241
264
|
|
|
242
265
|
// Determine entry points
|
|
243
|
-
const entryPath = Meteor.entryPath;
|
|
266
|
+
const entryPath = Meteor.entryPath || "";
|
|
244
267
|
|
|
245
268
|
// Determine output points
|
|
246
269
|
const outputPath = Meteor.outputPath;
|
|
247
|
-
const outputDir = path.dirname(Meteor.outputPath ||
|
|
270
|
+
const outputDir = path.dirname(Meteor.outputPath || "");
|
|
248
271
|
|
|
249
272
|
const outputFilename = Meteor.outputFilename;
|
|
250
273
|
|
|
251
|
-
// Determine run point
|
|
252
|
-
const runPath = Meteor.runPath;
|
|
253
|
-
|
|
254
|
-
// Determine banner
|
|
255
|
-
const bannerOutput = JSON.parse(Meteor.bannerOutput || process.env.RSPACK_BANNER || '""');
|
|
256
|
-
|
|
257
|
-
// Determine output directories
|
|
258
|
-
const clientOutputDir = path.resolve(projectDir, 'public');
|
|
259
|
-
const serverOutputDir = path.resolve(projectDir, 'private');
|
|
260
|
-
|
|
261
274
|
// Determine context for bundles and assets
|
|
262
|
-
const buildContext = Meteor.buildContext ||
|
|
263
|
-
const assetsContext = Meteor.assetsContext ||
|
|
264
|
-
const chunksContext = Meteor.chunksContext ||
|
|
275
|
+
const buildContext = Meteor.buildContext || "_build";
|
|
276
|
+
const assetsContext = Meteor.assetsContext || "build-assets";
|
|
277
|
+
const chunksContext = Meteor.chunksContext || "build-chunks";
|
|
265
278
|
|
|
266
279
|
// Determine build output and pass to Meteor
|
|
267
280
|
const buildOutputDir = path.resolve(projectDir, buildContext, outputDir);
|
|
@@ -269,27 +282,38 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
269
282
|
|
|
270
283
|
const cacheStrategy = createCacheStrategy(
|
|
271
284
|
mode,
|
|
272
|
-
(Meteor.isClient &&
|
|
285
|
+
(Meteor.isClient && "client") || "server",
|
|
273
286
|
{ projectConfigPath, configPath }
|
|
274
287
|
);
|
|
275
288
|
|
|
289
|
+
// Determine run point
|
|
290
|
+
const runPath = Meteor.runPath || "";
|
|
291
|
+
|
|
292
|
+
// Determine banner
|
|
293
|
+
const bannerOutput = JSON.parse(
|
|
294
|
+
Meteor.bannerOutput || process.env.RSPACK_BANNER || '""'
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
// Determine output directories
|
|
298
|
+
const clientOutputDir = path.resolve(projectDir, "public");
|
|
299
|
+
const serverOutputDir = path.resolve(projectDir, "private");
|
|
300
|
+
|
|
276
301
|
// Expose Meteor's helpers to expand Rspack configs
|
|
277
|
-
Meteor.compileWithMeteor = deps => compileWithMeteor(deps);
|
|
302
|
+
Meteor.compileWithMeteor = (deps) => compileWithMeteor(deps);
|
|
278
303
|
Meteor.compileWithRspack = (deps, options = {}) =>
|
|
279
304
|
compileWithRspack(deps, {
|
|
280
305
|
options: mergeSplitOverlap(Meteor.swcConfigOptions, options),
|
|
281
306
|
});
|
|
282
|
-
Meteor.setCache = enabled =>
|
|
283
|
-
setCache(
|
|
284
|
-
!!enabled,
|
|
285
|
-
enabled === 'memory' ? undefined : cacheStrategy
|
|
286
|
-
);
|
|
307
|
+
Meteor.setCache = (enabled) =>
|
|
308
|
+
setCache(!!enabled, enabled === "memory" ? undefined : cacheStrategy);
|
|
287
309
|
Meteor.splitVendorChunk = () => splitVendorChunk();
|
|
288
|
-
Meteor.extendSwcConfig = (customSwcConfig) =>
|
|
310
|
+
Meteor.extendSwcConfig = (customSwcConfig) =>
|
|
311
|
+
extendSwcConfig(customSwcConfig);
|
|
289
312
|
Meteor.extendConfig = (...configs) => mergeSplitOverlap(...configs);
|
|
290
|
-
Meteor.disablePlugins = matchers =>
|
|
291
|
-
|
|
292
|
-
|
|
313
|
+
Meteor.disablePlugins = (matchers) =>
|
|
314
|
+
prepareMeteorRspackConfig({
|
|
315
|
+
disablePlugins: matchers,
|
|
316
|
+
});
|
|
293
317
|
|
|
294
318
|
// Add HtmlRspackPlugin function to Meteor
|
|
295
319
|
Meteor.HtmlRspackPlugin = (options = {}) => {
|
|
@@ -328,16 +352,13 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
328
352
|
// Set default watch options
|
|
329
353
|
const watchOptions = {
|
|
330
354
|
ignored: [
|
|
331
|
-
...createIgnoreGlobConfig([
|
|
332
|
-
...meteorIgnoreEntries,
|
|
333
|
-
...additionalEntries,
|
|
334
|
-
]),
|
|
355
|
+
...createIgnoreGlobConfig([...meteorIgnoreEntries, ...additionalEntries]),
|
|
335
356
|
],
|
|
336
357
|
};
|
|
337
358
|
|
|
338
359
|
if (Meteor.isDebug || Meteor.isVerbose) {
|
|
339
|
-
console.log(
|
|
340
|
-
console.log(
|
|
360
|
+
console.log("[i] Rspack mode:", mode);
|
|
361
|
+
console.log("[i] Meteor flags:", Meteor);
|
|
341
362
|
}
|
|
342
363
|
|
|
343
364
|
const enableSwcExternalHelpers = !isServer && swcExternalHelpers;
|
|
@@ -361,34 +382,34 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
361
382
|
...(isServer ? [/^bcrypt$/] : []),
|
|
362
383
|
];
|
|
363
384
|
const alias = {
|
|
364
|
-
|
|
385
|
+
"/": path.resolve(process.cwd()),
|
|
365
386
|
};
|
|
366
387
|
const fallback = {
|
|
367
388
|
...(isClient && makeWebNodeBuiltinsAlias()),
|
|
368
389
|
};
|
|
369
390
|
const extensions = [
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
391
|
+
".ts",
|
|
392
|
+
".tsx",
|
|
393
|
+
".mts",
|
|
394
|
+
".cts",
|
|
395
|
+
".js",
|
|
396
|
+
".jsx",
|
|
397
|
+
".mjs",
|
|
398
|
+
".cjs",
|
|
399
|
+
".json",
|
|
400
|
+
".wasm",
|
|
380
401
|
];
|
|
381
402
|
const extraRules = [];
|
|
382
403
|
|
|
383
404
|
const reactRefreshModule = isReactEnabled
|
|
384
|
-
? safeRequire(
|
|
405
|
+
? safeRequire("@rspack/plugin-react-refresh")
|
|
385
406
|
: null;
|
|
386
407
|
|
|
387
408
|
const requireExternalsPlugin = new RequireExternalsPlugin({
|
|
388
409
|
filePath: path.join(buildContext, runPath),
|
|
389
410
|
...(Meteor.isBlazeEnabled && {
|
|
390
411
|
externals: /\.html$/,
|
|
391
|
-
isEagerImport: module => module.endsWith(
|
|
412
|
+
isEagerImport: (module) => module.endsWith(".html"),
|
|
392
413
|
...(isProd && {
|
|
393
414
|
lastImports: [`./${outputFilename}`],
|
|
394
415
|
}),
|
|
@@ -398,25 +419,26 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
398
419
|
|
|
399
420
|
// Handle assets
|
|
400
421
|
const assetExternalsPlugin = new AssetExternalsPlugin();
|
|
401
|
-
const assetModuleFilename = _fileInfo => {
|
|
422
|
+
const assetModuleFilename = (_fileInfo) => {
|
|
402
423
|
const filename = _fileInfo.filename;
|
|
403
|
-
const isPublic = filename.startsWith(
|
|
424
|
+
const isPublic = filename.startsWith("/") || filename.startsWith("public");
|
|
404
425
|
if (isPublic) return `[name][ext][query]`;
|
|
405
426
|
return `${assetsContext}/[hash][ext][query]`;
|
|
406
427
|
};
|
|
407
428
|
|
|
408
429
|
const rsdoctorModule = isBundleVisualizerEnabled
|
|
409
|
-
? safeRequire(
|
|
430
|
+
? safeRequire("@rsdoctor/rspack-plugin")
|
|
410
431
|
: null;
|
|
411
|
-
const doctorPluginConfig =
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
432
|
+
const doctorPluginConfig =
|
|
433
|
+
isRun && isBundleVisualizerEnabled && rsdoctorModule?.RsdoctorRspackPlugin
|
|
434
|
+
? [
|
|
435
|
+
new rsdoctorModule.RsdoctorRspackPlugin({
|
|
436
|
+
port: isClient
|
|
437
|
+
? parseInt(Meteor.rsdoctorClientPort || "8888", 10)
|
|
438
|
+
: parseInt(Meteor.rsdoctorServerPort || "8889", 10),
|
|
439
|
+
}),
|
|
440
|
+
]
|
|
441
|
+
: [];
|
|
420
442
|
const bannerPluginConfig = !isBuild
|
|
421
443
|
? [
|
|
422
444
|
new BannerPlugin({
|
|
@@ -452,16 +474,11 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
452
474
|
: isClient && isTest && testEntry
|
|
453
475
|
? path.resolve(process.cwd(), testEntry)
|
|
454
476
|
: path.resolve(process.cwd(), buildContext, entryPath);
|
|
455
|
-
|
|
456
|
-
"--> (rspack.config.js-Line: 431)\n clientEntry: ",
|
|
457
|
-
clientEntry,
|
|
458
|
-
entryPath
|
|
459
|
-
);
|
|
460
|
-
const clientNameConfig = `[${(isTest && 'test-') || ''}client-rspack]`;
|
|
477
|
+
const clientNameConfig = `[${(isTest && "test-") || ""}client-rspack]`;
|
|
461
478
|
// Base client config
|
|
462
479
|
let clientConfig = {
|
|
463
480
|
name: clientNameConfig,
|
|
464
|
-
target:
|
|
481
|
+
target: "web",
|
|
465
482
|
mode,
|
|
466
483
|
entry: clientEntry,
|
|
467
484
|
output: {
|
|
@@ -470,7 +487,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
470
487
|
const chunkName = _module.chunk?.name;
|
|
471
488
|
const isMainChunk = !chunkName || chunkName === "main";
|
|
472
489
|
const chunkSuffix = `${chunksContext}/[id]${
|
|
473
|
-
isProd ?
|
|
490
|
+
isProd ? ".[chunkhash]" : ""
|
|
474
491
|
}.js`;
|
|
475
492
|
if (isDevEnvironment) {
|
|
476
493
|
if (isMainChunk) return outputFilename;
|
|
@@ -479,21 +496,21 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
479
496
|
if (isMainChunk) return `../${buildContext}/${outputPath}`;
|
|
480
497
|
return chunkSuffix;
|
|
481
498
|
},
|
|
482
|
-
libraryTarget:
|
|
483
|
-
publicPath:
|
|
484
|
-
chunkFilename: `${chunksContext}/[id]${isProd ?
|
|
499
|
+
libraryTarget: "commonjs2",
|
|
500
|
+
publicPath: "/",
|
|
501
|
+
chunkFilename: `${chunksContext}/[id]${isProd ? ".[chunkhash]" : ""}.js`,
|
|
485
502
|
assetModuleFilename,
|
|
486
503
|
cssFilename: `${chunksContext}/[name]${
|
|
487
|
-
isProd ?
|
|
504
|
+
isProd ? ".[contenthash]" : ""
|
|
488
505
|
}.css`,
|
|
489
506
|
cssChunkFilename: `${chunksContext}/[id]${
|
|
490
|
-
isProd ?
|
|
507
|
+
isProd ? ".[contenthash]" : ""
|
|
491
508
|
}.css`,
|
|
492
509
|
...(isProd && { clean: { keep: keepOutsideBuild() } }),
|
|
493
510
|
},
|
|
494
511
|
optimization: {
|
|
495
512
|
usedExports: true,
|
|
496
|
-
splitChunks: { chunks:
|
|
513
|
+
splitChunks: { chunks: "async" },
|
|
497
514
|
},
|
|
498
515
|
module: {
|
|
499
516
|
rules: [
|
|
@@ -502,7 +519,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
502
519
|
? [
|
|
503
520
|
{
|
|
504
521
|
test: /\.html$/i,
|
|
505
|
-
loader:
|
|
522
|
+
loader: "ignore-loader",
|
|
506
523
|
},
|
|
507
524
|
]
|
|
508
525
|
: []),
|
|
@@ -520,33 +537,36 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
520
537
|
assetExternalsPlugin,
|
|
521
538
|
].filter(Boolean),
|
|
522
539
|
new DefinePlugin({
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
540
|
+
"Meteor.isClient": JSON.stringify(true),
|
|
541
|
+
"Meteor.isServer": JSON.stringify(false),
|
|
542
|
+
"Meteor.isTest": JSON.stringify(isTestLike && !isTestFullApp),
|
|
543
|
+
"Meteor.isAppTest": JSON.stringify(isTestLike && isTestFullApp),
|
|
544
|
+
"Meteor.isDevelopment": JSON.stringify(isDev),
|
|
545
|
+
"Meteor.isProduction": JSON.stringify(isProd),
|
|
529
546
|
}),
|
|
530
547
|
...bannerPluginConfig,
|
|
531
548
|
Meteor.HtmlRspackPlugin(),
|
|
532
549
|
...doctorPluginConfig,
|
|
533
550
|
new NormalModuleReplacementPlugin(/^node:(.*)$/, (res) => {
|
|
534
|
-
res.request = res.request.replace(/^node:/,
|
|
551
|
+
res.request = res.request.replace(/^node:/, "");
|
|
535
552
|
}),
|
|
536
553
|
],
|
|
537
554
|
watchOptions,
|
|
538
|
-
devtool:
|
|
555
|
+
devtool:
|
|
556
|
+
isDevEnvironment || isNative || isTest
|
|
557
|
+
? "source-map"
|
|
558
|
+
: "hidden-source-map",
|
|
539
559
|
...(isDevEnvironment && {
|
|
540
560
|
devServer: {
|
|
541
561
|
...createRemoteDevServerConfig(),
|
|
542
|
-
static: { directory: clientOutputDir, publicPath:
|
|
562
|
+
static: { directory: clientOutputDir, publicPath: "/__rspack__/" },
|
|
543
563
|
hot: true,
|
|
544
564
|
liveReload: true,
|
|
545
565
|
...(Meteor.isBlazeEnabled && { hot: false }),
|
|
546
566
|
port: Meteor.devServerPort || 8080,
|
|
547
567
|
devMiddleware: {
|
|
548
|
-
writeToDisk: filePath =>
|
|
549
|
-
/\.(html)$/.test(filePath) && !filePath.includes(
|
|
568
|
+
writeToDisk: (filePath) =>
|
|
569
|
+
/\.(html)$/.test(filePath) && !filePath.includes(".hot-update."),
|
|
550
570
|
},
|
|
551
571
|
},
|
|
552
572
|
}),
|
|
@@ -576,23 +596,18 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
576
596
|
: isServer && isTest && testEntry
|
|
577
597
|
? path.resolve(process.cwd(), testEntry)
|
|
578
598
|
: path.resolve(projectDir, buildContext, entryPath);
|
|
579
|
-
const serverNameConfig = `[${(isTest &&
|
|
580
|
-
console.log(
|
|
581
|
-
"--> (rspack.config.js-Line: 576)\n serverEntry: ",
|
|
582
|
-
serverEntry,
|
|
583
|
-
entryPath
|
|
584
|
-
);
|
|
599
|
+
const serverNameConfig = `[${(isTest && "test-") || ""}server-rspack]`;
|
|
585
600
|
// Base server config
|
|
586
601
|
let serverConfig = {
|
|
587
602
|
name: serverNameConfig,
|
|
588
|
-
target:
|
|
603
|
+
target: "node",
|
|
589
604
|
mode,
|
|
590
605
|
entry: serverEntry,
|
|
591
606
|
output: {
|
|
592
607
|
path: serverOutputDir,
|
|
593
608
|
filename: () => `../${buildContext}/${outputPath}`,
|
|
594
|
-
libraryTarget:
|
|
595
|
-
chunkFilename: `${chunksContext}/[id]${isProd ?
|
|
609
|
+
libraryTarget: "commonjs2",
|
|
610
|
+
chunkFilename: `${chunksContext}/[id]${isProd ? ".[chunkhash]" : ""}.js`,
|
|
596
611
|
assetModuleFilename,
|
|
597
612
|
...(isProd && { clean: { keep: keepOutsideBuild() } }),
|
|
598
613
|
},
|
|
@@ -606,15 +621,15 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
606
621
|
parser: {
|
|
607
622
|
javascript: {
|
|
608
623
|
// Dynamic imports on the server are treated as bundled in the same chunk
|
|
609
|
-
dynamicImportMode:
|
|
624
|
+
dynamicImportMode: "eager",
|
|
610
625
|
},
|
|
611
626
|
},
|
|
612
627
|
},
|
|
613
628
|
resolve: {
|
|
614
629
|
extensions,
|
|
615
630
|
alias,
|
|
616
|
-
modules: [
|
|
617
|
-
conditionNames: [
|
|
631
|
+
modules: ["node_modules", path.resolve(projectDir)],
|
|
632
|
+
conditionNames: ["import", "require", "node", "default"],
|
|
618
633
|
},
|
|
619
634
|
externals,
|
|
620
635
|
externalsPresets: { node: true },
|
|
@@ -622,18 +637,18 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
622
637
|
new DefinePlugin(
|
|
623
638
|
isTest && (isTestModule || isTestEager)
|
|
624
639
|
? {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
640
|
+
"Meteor.isTest": JSON.stringify(isTest && !isTestFullApp),
|
|
641
|
+
"Meteor.isAppTest": JSON.stringify(isTest && isTestFullApp),
|
|
642
|
+
"Meteor.isDevelopment": JSON.stringify(isDev),
|
|
628
643
|
}
|
|
629
644
|
: {
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
}
|
|
645
|
+
"Meteor.isClient": JSON.stringify(false),
|
|
646
|
+
"Meteor.isServer": JSON.stringify(true),
|
|
647
|
+
"Meteor.isTest": JSON.stringify(isTestLike && !isTestFullApp),
|
|
648
|
+
"Meteor.isAppTest": JSON.stringify(isTestLike && isTestFullApp),
|
|
649
|
+
"Meteor.isDevelopment": JSON.stringify(isDev),
|
|
650
|
+
"Meteor.isProduction": JSON.stringify(isProd),
|
|
651
|
+
}
|
|
637
652
|
),
|
|
638
653
|
...bannerPluginConfig,
|
|
639
654
|
requireExternalsPlugin,
|
|
@@ -641,99 +656,15 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
641
656
|
...doctorPluginConfig,
|
|
642
657
|
],
|
|
643
658
|
watchOptions,
|
|
644
|
-
devtool:
|
|
659
|
+
devtool:
|
|
660
|
+
isDevEnvironment || isNative || isTest
|
|
661
|
+
? "source-map"
|
|
662
|
+
: "hidden-source-map",
|
|
645
663
|
...((isDevEnvironment || (isTest && !isTestEager) || isNative) &&
|
|
646
664
|
cacheStrategy),
|
|
647
665
|
...lazyCompilationConfig,
|
|
648
666
|
};
|
|
649
667
|
|
|
650
|
-
// Helper function to load and process config files
|
|
651
|
-
async function loadAndProcessConfig(configPath, configType, Meteor, argv, isAngularEnabled) {
|
|
652
|
-
try {
|
|
653
|
-
// Load the config file
|
|
654
|
-
let config;
|
|
655
|
-
if (path.extname(configPath) === '.mjs') {
|
|
656
|
-
// For ESM modules, we need to use dynamic import
|
|
657
|
-
const fileUrl = `file://${configPath}`;
|
|
658
|
-
const module = await import(fileUrl);
|
|
659
|
-
config = module.default || module;
|
|
660
|
-
} else {
|
|
661
|
-
// For CommonJS modules, we can use require
|
|
662
|
-
config = require(configPath)?.default || require(configPath);
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
// Process the config
|
|
666
|
-
const rawConfig = typeof config === 'function' ? config(Meteor, argv) : config;
|
|
667
|
-
const resolvedConfig = await Promise.resolve(rawConfig);
|
|
668
|
-
const userConfig = resolvedConfig && '0' in resolvedConfig ? resolvedConfig[0] : resolvedConfig;
|
|
669
|
-
|
|
670
|
-
// Define omitted paths and warning function
|
|
671
|
-
const omitPaths = [
|
|
672
|
-
"name",
|
|
673
|
-
"target",
|
|
674
|
-
"entry",
|
|
675
|
-
"output.path",
|
|
676
|
-
"output.filename",
|
|
677
|
-
...(Meteor.isServer ? ["optimization.splitChunks", "optimization.runtimeChunk"] : []),
|
|
678
|
-
].filter(Boolean);
|
|
679
|
-
|
|
680
|
-
const warningFn = path => {
|
|
681
|
-
if (isAngularEnabled) return;
|
|
682
|
-
console.warn(
|
|
683
|
-
`[${configType}] Ignored custom "${path}" — reserved for Meteor-Rspack integration.`,
|
|
684
|
-
);
|
|
685
|
-
};
|
|
686
|
-
|
|
687
|
-
// Clean omitted paths and merge Meteor Rspack fragments
|
|
688
|
-
let nextConfig = cleanOmittedPaths(userConfig, {
|
|
689
|
-
omitPaths,
|
|
690
|
-
warningFn,
|
|
691
|
-
});
|
|
692
|
-
nextConfig = mergeMeteorRspackFragments(nextConfig);
|
|
693
|
-
|
|
694
|
-
return nextConfig;
|
|
695
|
-
} catch (error) {
|
|
696
|
-
console.error(`Error loading ${configType} from ${configPath}:`, error);
|
|
697
|
-
if (configType === 'rspack.config.js') {
|
|
698
|
-
throw error; // Only rethrow for project config
|
|
699
|
-
}
|
|
700
|
-
return null;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// Load and apply project-level overrides for the selected build
|
|
705
|
-
// Check if we're in a Meteor package directory by looking at the path
|
|
706
|
-
const isMeteorPackageConfig = projectDir.includes('/packages/rspack');
|
|
707
|
-
if (fs.existsSync(projectConfigPath) && !isMeteorPackageConfig) {
|
|
708
|
-
// Check if there's a .mjs or .cjs version of the config file
|
|
709
|
-
const mjsConfigPath = projectConfigPath.replace(/\.js$/, '.mjs');
|
|
710
|
-
const cjsConfigPath = projectConfigPath.replace(/\.js$/, '.cjs');
|
|
711
|
-
|
|
712
|
-
let projectConfigPathToUse = projectConfigPath;
|
|
713
|
-
if (fs.existsSync(mjsConfigPath)) {
|
|
714
|
-
projectConfigPathToUse = mjsConfigPath;
|
|
715
|
-
} else if (fs.existsSync(cjsConfigPath)) {
|
|
716
|
-
projectConfigPathToUse = cjsConfigPath;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
const nextUserConfig = await loadAndProcessConfig(
|
|
720
|
-
projectConfigPathToUse,
|
|
721
|
-
'rspack.config.js',
|
|
722
|
-
Meteor,
|
|
723
|
-
argv,
|
|
724
|
-
isAngularEnabled
|
|
725
|
-
);
|
|
726
|
-
|
|
727
|
-
if (nextUserConfig) {
|
|
728
|
-
if (Meteor.isClient) {
|
|
729
|
-
clientConfig = mergeSplitOverlap(clientConfig, nextUserConfig);
|
|
730
|
-
}
|
|
731
|
-
if (Meteor.isServer) {
|
|
732
|
-
serverConfig = mergeSplitOverlap(serverConfig, nextUserConfig);
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
|
|
737
668
|
// Establish Angular overrides to ensure proper integration
|
|
738
669
|
const angularExpandConfig = isAngularEnabled
|
|
739
670
|
? {
|
|
@@ -771,29 +702,12 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
771
702
|
);
|
|
772
703
|
config = mergeSplitOverlap(config, testClientExpandConfig);
|
|
773
704
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
const configNameFull = `${configNameWithoutExt}.override${configExt}`;
|
|
781
|
-
const overrideConfigPath = path.join(configDir, configNameFull);
|
|
782
|
-
|
|
783
|
-
if (fs.existsSync(overrideConfigPath)) {
|
|
784
|
-
const nextOverrideConfig = await loadAndProcessConfig(
|
|
785
|
-
overrideConfigPath,
|
|
786
|
-
configNameFull,
|
|
787
|
-
Meteor,
|
|
788
|
-
argv,
|
|
789
|
-
isAngularEnabled
|
|
790
|
-
);
|
|
791
|
-
|
|
792
|
-
if (nextOverrideConfig) {
|
|
793
|
-
// Apply override config as the last step
|
|
794
|
-
config = mergeSplitOverlap(config, nextOverrideConfig);
|
|
795
|
-
}
|
|
796
|
-
}
|
|
705
|
+
if (nextUserConfig) {
|
|
706
|
+
config = mergeSplitOverlap(config, nextUserConfig);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
if (nextOverrideConfig) {
|
|
710
|
+
config = mergeSplitOverlap(config, nextOverrideConfig);
|
|
797
711
|
}
|
|
798
712
|
|
|
799
713
|
const shouldDisablePlugins = config?.disablePlugins != null;
|
|
@@ -803,15 +717,18 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
803
717
|
}
|
|
804
718
|
|
|
805
719
|
if (Meteor.isDebug || Meteor.isVerbose) {
|
|
806
|
-
console.log(
|
|
720
|
+
console.log("Config:", inspect(config, { depth: null, colors: true }));
|
|
807
721
|
}
|
|
808
722
|
|
|
809
723
|
// Check if lazyCompilation is enabled and warn the user
|
|
810
|
-
if (
|
|
724
|
+
if (
|
|
725
|
+
config.lazyCompilation === true ||
|
|
726
|
+
typeof config.lazyCompilation === "object"
|
|
727
|
+
) {
|
|
811
728
|
console.warn(
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
729
|
+
"\n⚠️ Warning: lazyCompilation may not work correctly in the current Meteor-Rspack integration.\n" +
|
|
730
|
+
" This feature will be evaluated for support in future Meteor versions.\n" +
|
|
731
|
+
" If you encounter any issues, please disable it in your rspack config.\n"
|
|
815
732
|
);
|
|
816
733
|
}
|
|
817
734
|
|