@meteorjs/rspack 1.1.0-beta.9 → 2.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/.claude/settings.local.json +10 -0
- package/README.md +142 -0
- package/index.d.ts +51 -1
- package/lib/localDependenciesHelpers.js +184 -0
- package/lib/meteorRspackConfigHelpers.js +121 -0
- package/lib/meteorRspackHelpers.js +135 -3
- package/lib/swc.js +36 -6
- package/lib/test.js +8 -5
- package/package.json +10 -2
- package/plugins/MeteorRspackOutputPlugin.js +92 -1
- package/plugins/RequireExtenalsPlugin.js +10 -4
- package/rspack.config.js +352 -265
- package/scripts/bump-version.js +89 -0
- package/scripts/publish-beta.sh +4 -0
package/rspack.config.js
CHANGED
|
@@ -10,21 +10,27 @@ const { getMeteorAppSwcConfig } = require('./lib/swc.js');
|
|
|
10
10
|
const HtmlRspackPlugin = require('./plugins/HtmlRspackPlugin.js');
|
|
11
11
|
const { RequireExternalsPlugin } = require('./plugins/RequireExtenalsPlugin.js');
|
|
12
12
|
const { AssetExternalsPlugin } = require('./plugins/AssetExternalsPlugin.js');
|
|
13
|
-
const { MeteorRspackOutputPlugin } = require('./plugins/MeteorRspackOutputPlugin.js');
|
|
13
|
+
const { MeteorRspackOutputPlugin, extractDelegatedExtensions } = require('./plugins/MeteorRspackOutputPlugin.js');
|
|
14
14
|
const { generateEagerTestFile } = require("./lib/test.js");
|
|
15
15
|
const { getMeteorIgnoreEntries, createIgnoreGlobConfig } = require("./lib/ignore");
|
|
16
|
-
const { mergeMeteorRspackFragments } = require("./lib/meteorRspackConfigFactory.js");
|
|
17
16
|
const {
|
|
18
17
|
compileWithMeteor,
|
|
19
18
|
compileWithRspack,
|
|
20
19
|
setCache,
|
|
21
20
|
splitVendorChunk,
|
|
22
21
|
extendSwcConfig,
|
|
22
|
+
replaceSwcConfig,
|
|
23
23
|
makeWebNodeBuiltinsAlias,
|
|
24
24
|
disablePlugins,
|
|
25
25
|
outputMeteorRspack,
|
|
26
|
+
enablePortableBuild,
|
|
27
|
+
persistDevFiles,
|
|
28
|
+
createPersistCallback,
|
|
26
29
|
} = require('./lib/meteorRspackHelpers.js');
|
|
30
|
+
const { loadUserAndOverrideConfig } = require('./lib/meteorRspackConfigHelpers.js');
|
|
27
31
|
const { prepareMeteorRspackConfig } = require("./lib/meteorRspackConfigFactory");
|
|
32
|
+
const { extractLocalDependencies } = require('./lib/localDependenciesHelpers.js');
|
|
33
|
+
|
|
28
34
|
|
|
29
35
|
// Safe require that doesn't throw if the module isn't found
|
|
30
36
|
function safeRequire(moduleName) {
|
|
@@ -42,7 +48,11 @@ function safeRequire(moduleName) {
|
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
// Persistent filesystem cache strategy
|
|
45
|
-
function createCacheStrategy(
|
|
51
|
+
function createCacheStrategy(
|
|
52
|
+
mode,
|
|
53
|
+
side,
|
|
54
|
+
{ projectConfigPath, configPath, buildContext } = {},
|
|
55
|
+
) {
|
|
46
56
|
// Check for configuration files
|
|
47
57
|
const tsconfigPath = path.join(process.cwd(), 'tsconfig.json');
|
|
48
58
|
const hasTsconfig = fs.existsSync(tsconfigPath);
|
|
@@ -54,6 +64,8 @@ function createCacheStrategy(mode, side, { projectConfigPath, configPath } = {})
|
|
|
54
64
|
const hasSwcrcConfig = fs.existsSync(swcrcPath);
|
|
55
65
|
const swcJsPath = path.join(process.cwd(), 'swc.config.js');
|
|
56
66
|
const hasSwcJsConfig = fs.existsSync(swcJsPath);
|
|
67
|
+
const swcTsPath = path.join(process.cwd(), 'swc.config.ts');
|
|
68
|
+
const hasSwcTsConfig = fs.existsSync(swcTsPath);
|
|
57
69
|
const postcssConfigPath = path.join(process.cwd(), 'postcss.config.js');
|
|
58
70
|
const hasPostcssConfig = fs.existsSync(postcssConfigPath);
|
|
59
71
|
const packageLockPath = path.join(process.cwd(), 'package-lock.json');
|
|
@@ -61,15 +73,22 @@ function createCacheStrategy(mode, side, { projectConfigPath, configPath } = {})
|
|
|
61
73
|
const yarnLockPath = path.join(process.cwd(), 'yarn.lock');
|
|
62
74
|
const hasYarnLock = fs.existsSync(yarnLockPath);
|
|
63
75
|
|
|
76
|
+
// Extract local dependencies from project config (e.g., plugin files)
|
|
77
|
+
const localDependencies = projectConfigPath
|
|
78
|
+
? extractLocalDependencies(projectConfigPath)
|
|
79
|
+
: [];
|
|
80
|
+
|
|
64
81
|
// Build dependencies array
|
|
65
82
|
const buildDependencies = [
|
|
66
83
|
...(projectConfigPath ? [projectConfigPath] : []),
|
|
67
84
|
...(configPath ? [configPath] : []),
|
|
85
|
+
...localDependencies,
|
|
68
86
|
...(hasTsconfig ? [tsconfigPath] : []),
|
|
69
87
|
...(hasBabelRcConfig ? [babelRcConfig] : []),
|
|
70
88
|
...(hasBabelJsConfig ? [babelJsConfig] : []),
|
|
71
89
|
...(hasSwcrcConfig ? [swcrcPath] : []),
|
|
72
90
|
...(hasSwcJsConfig ? [swcJsPath] : []),
|
|
91
|
+
...(hasSwcTsConfig ? [swcTsPath] : []),
|
|
73
92
|
...(hasPostcssConfig ? [postcssConfigPath] : []),
|
|
74
93
|
...(hasPackageLock ? [packageLockPath] : []),
|
|
75
94
|
...(hasYarnLock ? [yarnLockPath] : []),
|
|
@@ -83,7 +102,9 @@ function createCacheStrategy(mode, side, { projectConfigPath, configPath } = {})
|
|
|
83
102
|
type: "persistent",
|
|
84
103
|
storage: {
|
|
85
104
|
type: "filesystem",
|
|
86
|
-
directory: `node_modules/.cache/rspack
|
|
105
|
+
directory: `node_modules/.cache/rspack/${
|
|
106
|
+
[buildContext, side].filter(Boolean).join('-') || 'default'
|
|
107
|
+
}`,
|
|
87
108
|
},
|
|
88
109
|
...(buildDependencies.length > 0 && {
|
|
89
110
|
buildDependencies: buildDependencies,
|
|
@@ -206,15 +227,45 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
206
227
|
const Meteor = { ...inMeteor };
|
|
207
228
|
// Convert string boolean values to actual booleans
|
|
208
229
|
for (const key in Meteor) {
|
|
209
|
-
if (Meteor[key] ===
|
|
230
|
+
if (Meteor[key] === "true" || Meteor[key] === true) {
|
|
210
231
|
Meteor[key] = true;
|
|
211
|
-
} else if (Meteor[key] ===
|
|
232
|
+
} else if (Meteor[key] === "false" || Meteor[key] === false) {
|
|
212
233
|
Meteor[key] = false;
|
|
213
234
|
}
|
|
214
235
|
}
|
|
215
236
|
|
|
216
|
-
const
|
|
217
|
-
const
|
|
237
|
+
const isTestLike = !!Meteor.isTestLike;
|
|
238
|
+
const swcExternalHelpers = !!Meteor.swcExternalHelpers;
|
|
239
|
+
const isNative = !!Meteor.isNative;
|
|
240
|
+
const devServerPort = Meteor.devServerPort || 8080;
|
|
241
|
+
|
|
242
|
+
const projectDir = process.cwd();
|
|
243
|
+
const projectConfigPath =
|
|
244
|
+
Meteor.projectConfigPath || path.resolve(projectDir, "rspack.config.js");
|
|
245
|
+
|
|
246
|
+
// Determine context for bundles and assets
|
|
247
|
+
const meteorLocalDirName = process.env.METEOR_LOCAL_DIR
|
|
248
|
+
? path.basename(process.env.METEOR_LOCAL_DIR.replace(/\\/g, "/"))
|
|
249
|
+
: "";
|
|
250
|
+
const buildContext =
|
|
251
|
+
Meteor.buildContext ||
|
|
252
|
+
process.env.RSPACK_BUILD_CONTEXT ||
|
|
253
|
+
`_build${(meteorLocalDirName && `-${meteorLocalDirName}`) || ""}`;
|
|
254
|
+
const assetsContext =
|
|
255
|
+
Meteor.assetsContext ||
|
|
256
|
+
process.env.RSPACK_ASSETS_CONTEXT ||
|
|
257
|
+
`build-assets${(meteorLocalDirName && `-${meteorLocalDirName}`) || ""}`;
|
|
258
|
+
const chunksContext =
|
|
259
|
+
Meteor.chunksContext ||
|
|
260
|
+
process.env.RSPACK_CHUNKS_CONTEXT ||
|
|
261
|
+
`build-chunks${(meteorLocalDirName && `-${meteorLocalDirName}`) || ""}`;
|
|
262
|
+
|
|
263
|
+
// Compute build paths before loading user config (needed by Meteor helpers below)
|
|
264
|
+
const outputPath = Meteor.outputPath;
|
|
265
|
+
const outputDir = path.dirname(Meteor.outputPath || "");
|
|
266
|
+
Meteor.buildOutputDir = path.resolve(projectDir, buildContext, outputDir);
|
|
267
|
+
|
|
268
|
+
// Meteor flags derived purely from input; independent of loaded user/override configs
|
|
218
269
|
const isTest = !!Meteor.isTest;
|
|
219
270
|
const isClient = !!Meteor.isClient;
|
|
220
271
|
const isServer = !!Meteor.isServer;
|
|
@@ -224,13 +275,8 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
224
275
|
const isTestModule = !!Meteor.isTestModule;
|
|
225
276
|
const isTestEager = !!Meteor.isTestEager;
|
|
226
277
|
const isTestFullApp = !!Meteor.isTestFullApp;
|
|
227
|
-
const isTestLike = !!Meteor.isTestLike;
|
|
228
|
-
const swcExternalHelpers = !!Meteor.swcExternalHelpers;
|
|
229
|
-
const isNative = !!Meteor.isNative;
|
|
230
278
|
const isProfile = !!Meteor.isProfile;
|
|
231
|
-
const
|
|
232
|
-
const projectDir = process.cwd();
|
|
233
|
-
const projectConfigPath = Meteor.projectConfigPath || path.resolve(projectDir, 'rspack.config.js');
|
|
279
|
+
const isVerbose = !!Meteor.isVerbose;
|
|
234
280
|
const configPath = Meteor.configPath;
|
|
235
281
|
const testEntry = Meteor.testEntry;
|
|
236
282
|
|
|
@@ -241,58 +287,70 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
241
287
|
Meteor.isTsxEnabled || (isTypescriptEnabled && isReactEnabled) || false;
|
|
242
288
|
const isBundleVisualizerEnabled = Meteor.isBundleVisualizerEnabled || false;
|
|
243
289
|
const isAngularEnabled = Meteor.isAngularEnabled || false;
|
|
290
|
+
const enableSwcExternalHelpers = !isServer && swcExternalHelpers;
|
|
244
291
|
|
|
245
|
-
//
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const runPath = Meteor.runPath;
|
|
256
|
-
|
|
257
|
-
// Determine banner
|
|
258
|
-
const bannerOutput = JSON.parse(Meteor.bannerOutput || process.env.RSPACK_BANNER || '""');
|
|
259
|
-
|
|
260
|
-
// Determine output directories
|
|
261
|
-
const clientOutputDir = path.resolve(projectDir, 'public');
|
|
262
|
-
const serverOutputDir = path.resolve(projectDir, 'private');
|
|
263
|
-
|
|
264
|
-
// Determine context for bundles and assets
|
|
265
|
-
const buildContext = Meteor.buildContext || '_build';
|
|
266
|
-
const assetsContext = Meteor.assetsContext || 'build-assets';
|
|
267
|
-
const chunksContext = Meteor.chunksContext || 'build-chunks';
|
|
268
|
-
|
|
269
|
-
// Determine build output and pass to Meteor
|
|
270
|
-
const buildOutputDir = path.resolve(projectDir, buildContext, outputDir);
|
|
271
|
-
Meteor.buildOutputDir = buildOutputDir;
|
|
292
|
+
// Defined here so it can be called both before and after the first config load;
|
|
293
|
+
// without loaded configs it falls through to argv/Meteor flags.
|
|
294
|
+
const getModeFromConfig = (userConfig, overrideConfig) => {
|
|
295
|
+
if (overrideConfig?.mode) return overrideConfig.mode;
|
|
296
|
+
if (userConfig?.mode) return userConfig.mode;
|
|
297
|
+
if (argv.mode) return argv.mode;
|
|
298
|
+
if (Meteor.isProduction) return "production";
|
|
299
|
+
if (Meteor.isDevelopment) return "development";
|
|
300
|
+
return null;
|
|
301
|
+
};
|
|
272
302
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
303
|
+
// Initial mode before user/override configs are loaded
|
|
304
|
+
const initialCurrentMode = getModeFromConfig();
|
|
305
|
+
const initialIsProd = initialCurrentMode
|
|
306
|
+
? initialCurrentMode === "production"
|
|
307
|
+
: !!Meteor.isProduction;
|
|
308
|
+
const initialIsDev = initialCurrentMode
|
|
309
|
+
? initialCurrentMode === "development"
|
|
310
|
+
: !!Meteor.isDevelopment || !initialIsProd;
|
|
311
|
+
const initialMode = initialIsProd ? "production" : "development";
|
|
312
|
+
|
|
313
|
+
// Initialized with pre-load values so helpers work during the first config load;
|
|
314
|
+
// reassigned after load once mode is fully resolved.
|
|
315
|
+
let cacheStrategy = createCacheStrategy(
|
|
316
|
+
initialMode,
|
|
317
|
+
(Meteor.isClient && "client") || "server",
|
|
318
|
+
{ projectConfigPath, configPath, buildContext }
|
|
277
319
|
);
|
|
320
|
+
let swcConfigRule = createSwcConfig({
|
|
321
|
+
isTypescriptEnabled,
|
|
322
|
+
isReactEnabled,
|
|
323
|
+
isJsxEnabled,
|
|
324
|
+
isTsxEnabled,
|
|
325
|
+
externalHelpers: enableSwcExternalHelpers,
|
|
326
|
+
isDevEnvironment: isRun && initialIsDev && !isTest && !isNative,
|
|
327
|
+
isClient,
|
|
328
|
+
isAngularEnabled,
|
|
329
|
+
});
|
|
330
|
+
Meteor.swcConfigOptions = swcConfigRule.options;
|
|
278
331
|
|
|
279
332
|
// Expose Meteor's helpers to expand Rspack configs
|
|
280
|
-
Meteor.compileWithMeteor = deps => compileWithMeteor(deps);
|
|
333
|
+
Meteor.compileWithMeteor = (deps) => compileWithMeteor(deps);
|
|
281
334
|
Meteor.compileWithRspack = (deps, options = {}) =>
|
|
282
335
|
compileWithRspack(deps, {
|
|
283
336
|
options: mergeSplitOverlap(Meteor.swcConfigOptions, options),
|
|
284
337
|
});
|
|
285
|
-
Meteor.setCache = enabled =>
|
|
286
|
-
setCache(
|
|
287
|
-
!!enabled,
|
|
288
|
-
enabled === 'memory' ? undefined : cacheStrategy
|
|
289
|
-
);
|
|
338
|
+
Meteor.setCache = (enabled) =>
|
|
339
|
+
setCache(!!enabled, enabled === "memory" ? undefined : cacheStrategy);
|
|
290
340
|
Meteor.splitVendorChunk = () => splitVendorChunk();
|
|
291
|
-
Meteor.extendSwcConfig = (customSwcConfig) =>
|
|
341
|
+
Meteor.extendSwcConfig = (customSwcConfig) =>
|
|
342
|
+
extendSwcConfig(
|
|
343
|
+
mergeSplitOverlap(Meteor.swcConfigOptions, customSwcConfig)
|
|
344
|
+
);
|
|
345
|
+
Meteor.replaceSwcConfig = (customSwcConfig) =>
|
|
346
|
+
replaceSwcConfig(customSwcConfig);
|
|
292
347
|
Meteor.extendConfig = (...configs) => mergeSplitOverlap(...configs);
|
|
293
|
-
Meteor.disablePlugins = matchers =>
|
|
294
|
-
|
|
295
|
-
|
|
348
|
+
Meteor.disablePlugins = (matchers) =>
|
|
349
|
+
prepareMeteorRspackConfig({
|
|
350
|
+
disablePlugins: matchers,
|
|
351
|
+
});
|
|
352
|
+
Meteor.enablePortableBuild = () => enablePortableBuild();
|
|
353
|
+
Meteor.persistDevFiles = (matchers) => persistDevFiles(matchers);
|
|
296
354
|
|
|
297
355
|
// Add HtmlRspackPlugin function to Meteor
|
|
298
356
|
Meteor.HtmlRspackPlugin = (options = {}) => {
|
|
@@ -316,6 +374,52 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
316
374
|
});
|
|
317
375
|
};
|
|
318
376
|
|
|
377
|
+
// First pass: resolve user/override configs early so mode overrides (e.g. "production")
|
|
378
|
+
// are available before computing isProd/isDev and the rest of the build flags.
|
|
379
|
+
// Skipped for Angular since it manages its own mode via the second pass.
|
|
380
|
+
let { nextUserConfig, nextOverrideConfig } = isAngularEnabled
|
|
381
|
+
? {}
|
|
382
|
+
: await loadUserAndOverrideConfig(projectConfigPath, Meteor, argv);
|
|
383
|
+
|
|
384
|
+
// Determine the final mode with loaded configs
|
|
385
|
+
const currentMode = getModeFromConfig(nextUserConfig, nextOverrideConfig);
|
|
386
|
+
const isProd = currentMode
|
|
387
|
+
? currentMode === "production"
|
|
388
|
+
: !!Meteor.isProduction;
|
|
389
|
+
const isDev = currentMode
|
|
390
|
+
? currentMode === "development"
|
|
391
|
+
: !!Meteor.isDevelopment || !isProd;
|
|
392
|
+
const mode = isProd ? "production" : "development";
|
|
393
|
+
const isPortableBuild = !!(
|
|
394
|
+
nextUserConfig?.["meteor.enablePortableBuild"] ||
|
|
395
|
+
nextOverrideConfig?.["meteor.enablePortableBuild"]
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
// Determine entry points
|
|
399
|
+
const entryPath = Meteor.entryPath || "";
|
|
400
|
+
|
|
401
|
+
// Determine output points
|
|
402
|
+
const outputFilename = Meteor.outputFilename;
|
|
403
|
+
|
|
404
|
+
cacheStrategy = createCacheStrategy(
|
|
405
|
+
mode,
|
|
406
|
+
(Meteor.isClient && "client") || "server",
|
|
407
|
+
{ projectConfigPath, configPath }
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
// Determine run point
|
|
411
|
+
const runPath = Meteor.runPath || "";
|
|
412
|
+
|
|
413
|
+
// Determine banner
|
|
414
|
+
const bannerOutput = JSON.parse(
|
|
415
|
+
Meteor.bannerOutput || process.env.RSPACK_BANNER || '""'
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
// Determine output directories
|
|
419
|
+
const clientOutputDir = path.resolve(projectDir, "public");
|
|
420
|
+
const serverOutputDir = path.resolve(projectDir, "private");
|
|
421
|
+
|
|
422
|
+
|
|
319
423
|
// Get Meteor ignore entries
|
|
320
424
|
const meteorIgnoreEntries = getMeteorIgnoreEntries(projectDir);
|
|
321
425
|
|
|
@@ -331,21 +435,17 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
331
435
|
// Set default watch options
|
|
332
436
|
const watchOptions = {
|
|
333
437
|
ignored: [
|
|
334
|
-
...createIgnoreGlobConfig([
|
|
335
|
-
...meteorIgnoreEntries,
|
|
336
|
-
...additionalEntries,
|
|
337
|
-
]),
|
|
438
|
+
...createIgnoreGlobConfig([...meteorIgnoreEntries, ...additionalEntries]),
|
|
338
439
|
],
|
|
339
440
|
};
|
|
340
441
|
|
|
341
442
|
if (Meteor.isDebug || Meteor.isVerbose) {
|
|
342
|
-
console.log(
|
|
343
|
-
console.log(
|
|
443
|
+
console.log("[i] Rspack mode:", mode);
|
|
444
|
+
console.log("[i] Meteor flags:", Meteor);
|
|
344
445
|
}
|
|
345
446
|
|
|
346
|
-
const enableSwcExternalHelpers = !isServer && swcExternalHelpers;
|
|
347
447
|
const isDevEnvironment = isRun && isDev && !isTest && !isNative;
|
|
348
|
-
|
|
448
|
+
swcConfigRule = createSwcConfig({
|
|
349
449
|
isTypescriptEnabled,
|
|
350
450
|
isReactEnabled,
|
|
351
451
|
isJsxEnabled,
|
|
@@ -355,7 +455,6 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
355
455
|
isClient,
|
|
356
456
|
isAngularEnabled,
|
|
357
457
|
});
|
|
358
|
-
// Expose swc config to use in custom configs
|
|
359
458
|
Meteor.swcConfigOptions = swcConfigRule.options;
|
|
360
459
|
|
|
361
460
|
const externals = [
|
|
@@ -364,34 +463,34 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
364
463
|
...(isServer ? [/^bcrypt$/] : []),
|
|
365
464
|
];
|
|
366
465
|
const alias = {
|
|
367
|
-
|
|
466
|
+
"/": path.resolve(process.cwd()),
|
|
368
467
|
};
|
|
369
468
|
const fallback = {
|
|
370
469
|
...(isClient && makeWebNodeBuiltinsAlias()),
|
|
371
470
|
};
|
|
372
471
|
const extensions = [
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
472
|
+
".ts",
|
|
473
|
+
".tsx",
|
|
474
|
+
".mts",
|
|
475
|
+
".cts",
|
|
476
|
+
".js",
|
|
477
|
+
".jsx",
|
|
478
|
+
".mjs",
|
|
479
|
+
".cjs",
|
|
480
|
+
".json",
|
|
481
|
+
".wasm",
|
|
383
482
|
];
|
|
384
483
|
const extraRules = [];
|
|
385
484
|
|
|
386
485
|
const reactRefreshModule = isReactEnabled
|
|
387
|
-
? safeRequire(
|
|
486
|
+
? safeRequire("@rspack/plugin-react-refresh")
|
|
388
487
|
: null;
|
|
389
488
|
|
|
390
489
|
const requireExternalsPlugin = new RequireExternalsPlugin({
|
|
391
490
|
filePath: path.join(buildContext, runPath),
|
|
392
491
|
...(Meteor.isBlazeEnabled && {
|
|
393
492
|
externals: /\.html$/,
|
|
394
|
-
isEagerImport: module => module.endsWith(
|
|
493
|
+
isEagerImport: (module) => module.endsWith(".html"),
|
|
395
494
|
...(isProd && {
|
|
396
495
|
lastImports: [`./${outputFilename}`],
|
|
397
496
|
}),
|
|
@@ -401,25 +500,26 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
401
500
|
|
|
402
501
|
// Handle assets
|
|
403
502
|
const assetExternalsPlugin = new AssetExternalsPlugin();
|
|
404
|
-
const assetModuleFilename = _fileInfo => {
|
|
503
|
+
const assetModuleFilename = (_fileInfo) => {
|
|
405
504
|
const filename = _fileInfo.filename;
|
|
406
|
-
const isPublic = filename.startsWith(
|
|
505
|
+
const isPublic = filename.startsWith("/") || filename.startsWith("public");
|
|
407
506
|
if (isPublic) return `[name][ext][query]`;
|
|
408
507
|
return `${assetsContext}/[hash][ext][query]`;
|
|
409
508
|
};
|
|
410
509
|
|
|
411
510
|
const rsdoctorModule = isBundleVisualizerEnabled
|
|
412
|
-
? safeRequire(
|
|
511
|
+
? safeRequire("@rsdoctor/rspack-plugin")
|
|
413
512
|
: null;
|
|
414
|
-
const doctorPluginConfig =
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
513
|
+
const doctorPluginConfig =
|
|
514
|
+
isRun && isBundleVisualizerEnabled && rsdoctorModule?.RsdoctorRspackPlugin
|
|
515
|
+
? [
|
|
516
|
+
new rsdoctorModule.RsdoctorRspackPlugin({
|
|
517
|
+
port: isClient
|
|
518
|
+
? parseInt(Meteor.rsdoctorClientPort || "8888", 10)
|
|
519
|
+
: parseInt(Meteor.rsdoctorServerPort || "8889", 10),
|
|
520
|
+
}),
|
|
521
|
+
]
|
|
522
|
+
: [];
|
|
423
523
|
const bannerPluginConfig = !isBuild
|
|
424
524
|
? [
|
|
425
525
|
new BannerPlugin({
|
|
@@ -430,9 +530,10 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
430
530
|
: [];
|
|
431
531
|
// Not supported in Meteor yet (Rspack 1.7+ is enabled by default)
|
|
432
532
|
const lazyCompilationConfig = { lazyCompilation: false };
|
|
433
|
-
const
|
|
533
|
+
const shouldLogVerbose = isProfile || isVerbose;
|
|
534
|
+
const loggingConfig = shouldLogVerbose
|
|
434
535
|
? {}
|
|
435
|
-
: { stats:
|
|
536
|
+
: { stats: "errors-warnings", infrastructureLogging: { level: "warn" } };
|
|
436
537
|
|
|
437
538
|
const clientEntry =
|
|
438
539
|
isClient && isTest && isTestEager && isTestFullApp
|
|
@@ -460,11 +561,48 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
460
561
|
: isClient && isTest && testEntry
|
|
461
562
|
? path.resolve(process.cwd(), testEntry)
|
|
462
563
|
: path.resolve(process.cwd(), buildContext, entryPath);
|
|
463
|
-
const clientNameConfig = `[${(isTest &&
|
|
564
|
+
const clientNameConfig = `[${(isTest && "test-") || ""}client-rspack]`;
|
|
565
|
+
|
|
566
|
+
// Default onListening provided by meteor-rspack. Kept as a named
|
|
567
|
+
// reference so we can detect a user-supplied override after merge
|
|
568
|
+
// and compose (run default first, then user's).
|
|
569
|
+
const meteorDefaultOnListening = function (devServer) {
|
|
570
|
+
if (!devServer) return;
|
|
571
|
+
const { host, port } = devServer.options;
|
|
572
|
+
const protocol =
|
|
573
|
+
devServer.options.server?.type === "https" ? "https" : "http";
|
|
574
|
+
const devServerUrl = `${protocol}://${host || "localhost"}:${port}`;
|
|
575
|
+
outputMeteorRspack({ devServerUrl });
|
|
576
|
+
|
|
577
|
+
// Windows-only: webpack-dev-server tracks accepted sockets
|
|
578
|
+
// but doesn't attach 'error'. On Windows, teardown of a
|
|
579
|
+
// closed proxy connection sends RST, producing an unhandled
|
|
580
|
+
// ECONNRESET that crashes the dev server. Unix peers send
|
|
581
|
+
// FIN and never hit this.
|
|
582
|
+
if (process.platform === "win32") {
|
|
583
|
+
const server = devServer.server;
|
|
584
|
+
if (!server || server.__meteorRspackErrorGuard) return;
|
|
585
|
+
server.__meteorRspackErrorGuard = true;
|
|
586
|
+
|
|
587
|
+
server.on("connection", (socket) => {
|
|
588
|
+
if (!socket || socket.__meteorRspackGuarded) return;
|
|
589
|
+
socket.__meteorRspackGuarded = true;
|
|
590
|
+
socket.on("error", (err) => {
|
|
591
|
+
if (err && err.code === "ECONNRESET") return;
|
|
592
|
+
console.warn(
|
|
593
|
+
`[meteor-rspack] dev server socket error: ${
|
|
594
|
+
err && (err.code || err.message)
|
|
595
|
+
}`
|
|
596
|
+
);
|
|
597
|
+
});
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
|
|
464
602
|
// Base client config
|
|
465
603
|
let clientConfig = {
|
|
466
604
|
name: clientNameConfig,
|
|
467
|
-
target:
|
|
605
|
+
target: "web",
|
|
468
606
|
mode,
|
|
469
607
|
entry: clientEntry,
|
|
470
608
|
output: {
|
|
@@ -473,7 +611,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
473
611
|
const chunkName = _module.chunk?.name;
|
|
474
612
|
const isMainChunk = !chunkName || chunkName === "main";
|
|
475
613
|
const chunkSuffix = `${chunksContext}/[id]${
|
|
476
|
-
isProd ?
|
|
614
|
+
isProd ? ".[chunkhash]" : ""
|
|
477
615
|
}.js`;
|
|
478
616
|
if (isDevEnvironment) {
|
|
479
617
|
if (isMainChunk) return outputFilename;
|
|
@@ -482,21 +620,21 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
482
620
|
if (isMainChunk) return `../${buildContext}/${outputPath}`;
|
|
483
621
|
return chunkSuffix;
|
|
484
622
|
},
|
|
485
|
-
libraryTarget:
|
|
486
|
-
publicPath:
|
|
487
|
-
chunkFilename: `${chunksContext}/[id]${isProd ?
|
|
623
|
+
libraryTarget: "commonjs2",
|
|
624
|
+
publicPath: "/",
|
|
625
|
+
chunkFilename: `${chunksContext}/[id]${isProd ? ".[chunkhash]" : ""}.js`,
|
|
488
626
|
assetModuleFilename,
|
|
489
627
|
cssFilename: `${chunksContext}/[name]${
|
|
490
|
-
isProd ?
|
|
628
|
+
isProd ? ".[contenthash]" : ""
|
|
491
629
|
}.css`,
|
|
492
630
|
cssChunkFilename: `${chunksContext}/[id]${
|
|
493
|
-
isProd ?
|
|
631
|
+
isProd ? ".[contenthash]" : ""
|
|
494
632
|
}.css`,
|
|
495
633
|
...(isProd && { clean: { keep: keepOutsideBuild() } }),
|
|
496
634
|
},
|
|
497
635
|
optimization: {
|
|
498
636
|
usedExports: true,
|
|
499
|
-
splitChunks: { chunks:
|
|
637
|
+
splitChunks: { chunks: "async" },
|
|
500
638
|
},
|
|
501
639
|
module: {
|
|
502
640
|
rules: [
|
|
@@ -505,7 +643,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
505
643
|
? [
|
|
506
644
|
{
|
|
507
645
|
test: /\.html$/i,
|
|
508
|
-
loader:
|
|
646
|
+
loader: "ignore-loader",
|
|
509
647
|
},
|
|
510
648
|
]
|
|
511
649
|
: []),
|
|
@@ -523,41 +661,39 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
523
661
|
assetExternalsPlugin,
|
|
524
662
|
].filter(Boolean),
|
|
525
663
|
new DefinePlugin({
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
664
|
+
"Meteor.isClient": JSON.stringify(true),
|
|
665
|
+
"Meteor.isServer": JSON.stringify(false),
|
|
666
|
+
"Meteor.isTest": JSON.stringify(isTestLike && !isTestFullApp),
|
|
667
|
+
"Meteor.isAppTest": JSON.stringify(isTestLike && isTestFullApp),
|
|
668
|
+
...(!isPortableBuild && {
|
|
669
|
+
"Meteor.isDevelopment": JSON.stringify(isDev),
|
|
670
|
+
"Meteor.isProduction": JSON.stringify(isProd),
|
|
671
|
+
}),
|
|
532
672
|
}),
|
|
533
673
|
...bannerPluginConfig,
|
|
534
674
|
Meteor.HtmlRspackPlugin(),
|
|
535
675
|
...doctorPluginConfig,
|
|
536
676
|
new NormalModuleReplacementPlugin(/^node:(.*)$/, (res) => {
|
|
537
|
-
res.request = res.request.replace(/^node:/,
|
|
677
|
+
res.request = res.request.replace(/^node:/, "");
|
|
538
678
|
}),
|
|
539
679
|
],
|
|
540
680
|
watchOptions,
|
|
541
|
-
devtool:
|
|
681
|
+
devtool:
|
|
682
|
+
isDevEnvironment || isNative || isTest
|
|
683
|
+
? "source-map"
|
|
684
|
+
: "hidden-source-map",
|
|
542
685
|
...(isDevEnvironment && {
|
|
543
686
|
devServer: {
|
|
544
687
|
...createRemoteDevServerConfig(),
|
|
545
|
-
static: { directory: clientOutputDir, publicPath:
|
|
688
|
+
static: { directory: clientOutputDir, publicPath: "/__rspack__/" },
|
|
546
689
|
hot: true,
|
|
547
690
|
liveReload: true,
|
|
548
691
|
...(Meteor.isBlazeEnabled && { hot: false }),
|
|
549
|
-
port:
|
|
692
|
+
port: devServerPort,
|
|
550
693
|
devMiddleware: {
|
|
551
|
-
writeToDisk:
|
|
552
|
-
/\.(html)$/.test(filePath) && !filePath.includes('.hot-update.'),
|
|
553
|
-
},
|
|
554
|
-
onListening(devServer) {
|
|
555
|
-
if (!devServer) return;
|
|
556
|
-
const { host, port } = devServer.options;
|
|
557
|
-
const protocol = devServer.options.server?.type === "https" ? "https" : "http";
|
|
558
|
-
const devServerUrl = `${protocol}://${host || "localhost"}:${port}`;
|
|
559
|
-
outputMeteorRspack({ devServerUrl });
|
|
694
|
+
writeToDisk: createPersistCallback({ once: ['sw.js'], always: ['.html'] }),
|
|
560
695
|
},
|
|
696
|
+
onListening: meteorDefaultOnListening,
|
|
561
697
|
},
|
|
562
698
|
}),
|
|
563
699
|
...merge(cacheStrategy, { experiments: { css: true } }),
|
|
@@ -589,18 +725,18 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
589
725
|
: isServer && isTest && testEntry
|
|
590
726
|
? path.resolve(process.cwd(), testEntry)
|
|
591
727
|
: path.resolve(projectDir, buildContext, entryPath);
|
|
592
|
-
const serverNameConfig = `[${(isTest &&
|
|
728
|
+
const serverNameConfig = `[${(isTest && "test-") || ""}server-rspack]`;
|
|
593
729
|
// Base server config
|
|
594
730
|
let serverConfig = {
|
|
595
731
|
name: serverNameConfig,
|
|
596
|
-
target:
|
|
732
|
+
target: "node",
|
|
597
733
|
mode,
|
|
598
734
|
entry: serverEntry,
|
|
599
735
|
output: {
|
|
600
736
|
path: serverOutputDir,
|
|
601
737
|
filename: () => `../${buildContext}/${outputPath}`,
|
|
602
|
-
libraryTarget:
|
|
603
|
-
chunkFilename: `${chunksContext}/[id]${isProd ?
|
|
738
|
+
libraryTarget: "commonjs2",
|
|
739
|
+
chunkFilename: `${chunksContext}/[id]${isProd ? ".[chunkhash]" : ""}.js`,
|
|
604
740
|
assetModuleFilename,
|
|
605
741
|
...(isProd && { clean: { keep: keepOutsideBuild() } }),
|
|
606
742
|
},
|
|
@@ -610,19 +746,34 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
610
746
|
runtimeChunk: false,
|
|
611
747
|
},
|
|
612
748
|
module: {
|
|
613
|
-
rules: [
|
|
749
|
+
rules: [
|
|
750
|
+
swcConfigRule,
|
|
751
|
+
// Mirror the client rule: ignore .html so rspack doesn't try to
|
|
752
|
+
// parse them as JavaScript. Meteor's template compiler handles
|
|
753
|
+
// .html files separately, and RequireExternalsPlugin below wires
|
|
754
|
+
// the imports to Meteor's module system.
|
|
755
|
+
...(Meteor.isBlazeEnabled
|
|
756
|
+
? [
|
|
757
|
+
{
|
|
758
|
+
test: /\.html$/i,
|
|
759
|
+
loader: 'ignore-loader',
|
|
760
|
+
},
|
|
761
|
+
]
|
|
762
|
+
: []),
|
|
763
|
+
...extraRules,
|
|
764
|
+
],
|
|
614
765
|
parser: {
|
|
615
766
|
javascript: {
|
|
616
767
|
// Dynamic imports on the server are treated as bundled in the same chunk
|
|
617
|
-
dynamicImportMode:
|
|
768
|
+
dynamicImportMode: "eager",
|
|
618
769
|
},
|
|
619
770
|
},
|
|
620
771
|
},
|
|
621
772
|
resolve: {
|
|
622
773
|
extensions,
|
|
623
774
|
alias,
|
|
624
|
-
modules: [
|
|
625
|
-
conditionNames: [
|
|
775
|
+
modules: ["node_modules", path.resolve(projectDir)],
|
|
776
|
+
conditionNames: ["import", "require", "node", "default"],
|
|
626
777
|
},
|
|
627
778
|
externals,
|
|
628
779
|
externalsPresets: { node: true },
|
|
@@ -630,18 +781,22 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
630
781
|
new DefinePlugin(
|
|
631
782
|
isTest && (isTestModule || isTestEager)
|
|
632
783
|
? {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
784
|
+
"Meteor.isTest": JSON.stringify(isTest && !isTestFullApp),
|
|
785
|
+
"Meteor.isAppTest": JSON.stringify(isTest && isTestFullApp),
|
|
786
|
+
...(!isPortableBuild && {
|
|
787
|
+
"Meteor.isDevelopment": JSON.stringify(isDev),
|
|
788
|
+
}),
|
|
636
789
|
}
|
|
637
790
|
: {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
791
|
+
"Meteor.isClient": JSON.stringify(false),
|
|
792
|
+
"Meteor.isServer": JSON.stringify(true),
|
|
793
|
+
"Meteor.isTest": JSON.stringify(isTestLike && !isTestFullApp),
|
|
794
|
+
"Meteor.isAppTest": JSON.stringify(isTestLike && isTestFullApp),
|
|
795
|
+
...(!isPortableBuild && {
|
|
796
|
+
"Meteor.isDevelopment": JSON.stringify(isDev),
|
|
797
|
+
"Meteor.isProduction": JSON.stringify(isProd),
|
|
798
|
+
}),
|
|
799
|
+
}
|
|
645
800
|
),
|
|
646
801
|
...bannerPluginConfig,
|
|
647
802
|
requireExternalsPlugin,
|
|
@@ -649,111 +804,21 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
649
804
|
...doctorPluginConfig,
|
|
650
805
|
],
|
|
651
806
|
watchOptions,
|
|
652
|
-
devtool:
|
|
807
|
+
devtool:
|
|
808
|
+
isDevEnvironment || isNative || isTest
|
|
809
|
+
? "source-map"
|
|
810
|
+
: "hidden-source-map",
|
|
653
811
|
...((isDevEnvironment || (isTest && !isTestEager) || isNative) &&
|
|
654
812
|
cacheStrategy),
|
|
655
813
|
...lazyCompilationConfig,
|
|
656
814
|
...loggingConfig,
|
|
657
815
|
};
|
|
658
816
|
|
|
659
|
-
// Helper function to load and process config files
|
|
660
|
-
async function loadAndProcessConfig(configPath, configType, Meteor, argv, isAngularEnabled) {
|
|
661
|
-
try {
|
|
662
|
-
// Load the config file
|
|
663
|
-
let config;
|
|
664
|
-
if (path.extname(configPath) === '.mjs') {
|
|
665
|
-
// For ESM modules, we need to use dynamic import
|
|
666
|
-
const fileUrl = `file://${configPath}`;
|
|
667
|
-
const module = await import(fileUrl);
|
|
668
|
-
config = module.default || module;
|
|
669
|
-
} else {
|
|
670
|
-
// For CommonJS modules, we can use require
|
|
671
|
-
config = require(configPath)?.default || require(configPath);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
// Process the config
|
|
675
|
-
const rawConfig = typeof config === 'function' ? config(Meteor, argv) : config;
|
|
676
|
-
const resolvedConfig = await Promise.resolve(rawConfig);
|
|
677
|
-
const userConfig = resolvedConfig && '0' in resolvedConfig ? resolvedConfig[0] : resolvedConfig;
|
|
678
|
-
|
|
679
|
-
// Define omitted paths and warning function
|
|
680
|
-
const omitPaths = [
|
|
681
|
-
"name",
|
|
682
|
-
"target",
|
|
683
|
-
"entry",
|
|
684
|
-
"output.path",
|
|
685
|
-
"output.filename",
|
|
686
|
-
...(Meteor.isServer ? ["optimization.splitChunks", "optimization.runtimeChunk"] : []),
|
|
687
|
-
].filter(Boolean);
|
|
688
|
-
|
|
689
|
-
const warningFn = path => {
|
|
690
|
-
if (isAngularEnabled) return;
|
|
691
|
-
console.warn(
|
|
692
|
-
`[${configType}] Ignored custom "${path}" — reserved for Meteor-Rspack integration.`,
|
|
693
|
-
);
|
|
694
|
-
};
|
|
695
|
-
|
|
696
|
-
// Clean omitted paths and merge Meteor Rspack fragments
|
|
697
|
-
let nextConfig = cleanOmittedPaths(userConfig, {
|
|
698
|
-
omitPaths,
|
|
699
|
-
warningFn,
|
|
700
|
-
});
|
|
701
|
-
nextConfig = mergeMeteorRspackFragments(nextConfig);
|
|
702
|
-
|
|
703
|
-
return nextConfig;
|
|
704
|
-
} catch (error) {
|
|
705
|
-
console.error(`Error loading ${configType} from ${configPath}:`, error);
|
|
706
|
-
if (configType === 'rspack.config.js') {
|
|
707
|
-
throw error; // Only rethrow for project config
|
|
708
|
-
}
|
|
709
|
-
return null;
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
// Load and apply project-level overrides for the selected build
|
|
714
|
-
// Check if we're in a Meteor package directory by looking at the path
|
|
715
|
-
const isMeteorPackageConfig = projectDir.includes('/packages/rspack');
|
|
716
|
-
// Track if user config overrides stats and infrastructureLogging
|
|
717
|
-
let statsOverrided = false;
|
|
718
|
-
if (fs.existsSync(projectConfigPath) && !isMeteorPackageConfig) {
|
|
719
|
-
// Check if there's a .mjs or .cjs version of the config file
|
|
720
|
-
const mjsConfigPath = projectConfigPath.replace(/\.js$/, '.mjs');
|
|
721
|
-
const cjsConfigPath = projectConfigPath.replace(/\.js$/, '.cjs');
|
|
722
|
-
|
|
723
|
-
let projectConfigPathToUse = projectConfigPath;
|
|
724
|
-
if (fs.existsSync(mjsConfigPath)) {
|
|
725
|
-
projectConfigPathToUse = mjsConfigPath;
|
|
726
|
-
} else if (fs.existsSync(cjsConfigPath)) {
|
|
727
|
-
projectConfigPathToUse = cjsConfigPath;
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
const nextUserConfig = await loadAndProcessConfig(
|
|
731
|
-
projectConfigPathToUse,
|
|
732
|
-
'rspack.config.js',
|
|
733
|
-
Meteor,
|
|
734
|
-
argv,
|
|
735
|
-
isAngularEnabled
|
|
736
|
-
);
|
|
737
|
-
|
|
738
|
-
// Track if user config overrides stats
|
|
739
|
-
if (nextUserConfig) {
|
|
740
|
-
if (nextUserConfig.stats != null) {
|
|
741
|
-
statsOverrided = true;
|
|
742
|
-
}
|
|
743
|
-
if (Meteor.isClient) {
|
|
744
|
-
clientConfig = mergeSplitOverlap(clientConfig, nextUserConfig);
|
|
745
|
-
}
|
|
746
|
-
if (Meteor.isServer) {
|
|
747
|
-
serverConfig = mergeSplitOverlap(serverConfig, nextUserConfig);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
|
|
752
817
|
// Establish Angular overrides to ensure proper integration
|
|
753
818
|
const angularExpandConfig = isAngularEnabled
|
|
754
819
|
? {
|
|
755
820
|
mode: isProd ? "production" : "development",
|
|
756
|
-
devServer: { port:
|
|
821
|
+
devServer: { port: devServerPort },
|
|
757
822
|
stats: { preset: "normal" },
|
|
758
823
|
infrastructureLogging: { level: "info" },
|
|
759
824
|
...(isProd && isClient && { output: { module: false } }),
|
|
@@ -780,34 +845,48 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
780
845
|
}
|
|
781
846
|
: {};
|
|
782
847
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
848
|
+
// Second pass: re-run only when a mode override was detected, so the user config
|
|
849
|
+
// can depend on fully-computed Meteor flags and helpers (swcConfigOptions, buildOutputDir, etc.).
|
|
850
|
+
if (nextUserConfig?.mode || nextOverrideConfig?.mode || isAngularEnabled) {
|
|
851
|
+
({ nextUserConfig, nextOverrideConfig } = await loadUserAndOverrideConfig(
|
|
852
|
+
projectConfigPath,
|
|
853
|
+
Meteor,
|
|
854
|
+
argv
|
|
855
|
+
));
|
|
856
|
+
}
|
|
857
|
+
let statsOverrided = false;
|
|
858
|
+
let config = isClient ? clientConfig : serverConfig;
|
|
859
|
+
if (nextUserConfig) {
|
|
860
|
+
config = mergeSplitOverlap(config, nextUserConfig);
|
|
861
|
+
if (nextUserConfig.stats != null) {
|
|
862
|
+
statsOverrided = true;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
config = mergeSplitOverlap(config, angularExpandConfig);
|
|
787
867
|
config = mergeSplitOverlap(config, testClientExpandConfig);
|
|
788
868
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
}
|
|
869
|
+
if (nextOverrideConfig) {
|
|
870
|
+
config = mergeSplitOverlap(config, nextOverrideConfig);
|
|
871
|
+
if (nextOverrideConfig.stats != null) {
|
|
872
|
+
statsOverrided = true;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// If the user or an override replaced devServer.onListening, compose
|
|
877
|
+
// so our default runs first (attaches the Windows socket guard and
|
|
878
|
+
// reports the dev server URL) and the user's hook runs second.
|
|
879
|
+
if (isClient && config.devServer) {
|
|
880
|
+
const finalOnListening = config.devServer.onListening;
|
|
881
|
+
if (
|
|
882
|
+
typeof finalOnListening === "function" &&
|
|
883
|
+
finalOnListening !== meteorDefaultOnListening
|
|
884
|
+
) {
|
|
885
|
+
const userOnListening = finalOnListening;
|
|
886
|
+
config.devServer.onListening = function (devServer) {
|
|
887
|
+
meteorDefaultOnListening(devServer);
|
|
888
|
+
userOnListening(devServer);
|
|
889
|
+
};
|
|
811
890
|
}
|
|
812
891
|
}
|
|
813
892
|
|
|
@@ -817,22 +896,27 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
817
896
|
delete config.disablePlugins;
|
|
818
897
|
}
|
|
819
898
|
|
|
899
|
+
delete config["meteor.enablePortableBuild"];
|
|
900
|
+
|
|
820
901
|
if (Meteor.isDebug || Meteor.isVerbose) {
|
|
821
|
-
|
|
902
|
+
console.log("Config:", inspect(config, { depth: null, colors: true }));
|
|
822
903
|
}
|
|
823
904
|
|
|
824
905
|
// Check if lazyCompilation is enabled and warn the user
|
|
825
|
-
if (
|
|
906
|
+
if (
|
|
907
|
+
config.lazyCompilation === true ||
|
|
908
|
+
typeof config.lazyCompilation === "object"
|
|
909
|
+
) {
|
|
826
910
|
console.warn(
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
911
|
+
"\n⚠️ Warning: lazyCompilation may not work correctly in the current Meteor-Rspack integration.\n" +
|
|
912
|
+
" This feature will be evaluated for support in future Meteor versions.\n" +
|
|
913
|
+
" If you encounter any issues, please disable it in your rspack config.\n"
|
|
830
914
|
);
|
|
831
915
|
}
|
|
832
916
|
|
|
833
917
|
// Add MeteorRspackOutputPlugin as the last plugin to output compilation info
|
|
834
918
|
const meteorRspackOutputPlugin = new MeteorRspackOutputPlugin({
|
|
835
|
-
getData: (stats, { isRebuild, compilationCount }) => ({
|
|
919
|
+
getData: (stats, { isRebuild, compilationCount, compiler }) => ({
|
|
836
920
|
name: config.name,
|
|
837
921
|
mode: config.mode,
|
|
838
922
|
hasErrors: stats.hasErrors(),
|
|
@@ -841,6 +925,9 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
841
925
|
statsOverrided,
|
|
842
926
|
compilationCount,
|
|
843
927
|
isRebuild,
|
|
928
|
+
...(!isRebuild && compiler && {
|
|
929
|
+
delegatedExtensions: extractDelegatedExtensions(stats, compiler),
|
|
930
|
+
}),
|
|
844
931
|
}),
|
|
845
932
|
});
|
|
846
933
|
config.plugins = [meteorRspackOutputPlugin, ...(config.plugins || [])];
|