@meteorjs/rspack 0.0.59 → 0.0.60
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/meteorRspackConfigFactory.js +28 -25
- package/lib/meteorRspackHelpers.js +25 -0
- package/package.json +1 -1
- package/rspack.config.js +61 -6
|
@@ -42,11 +42,17 @@ function prepareMeteorRspackConfig(customConfig, opts = {}) {
|
|
|
42
42
|
* Merge all `{prefix}<n>` fragments into `config` using `mergeSplitOverlap`,
|
|
43
43
|
* then remove those temporary keys. Mutates `config`.
|
|
44
44
|
*
|
|
45
|
-
*
|
|
45
|
+
* Position-aware merge:
|
|
46
|
+
* Walk the config in insertion order and fold:
|
|
47
|
+
* - for a fragment key: out = mergeSplitOverlap(out, fragment)
|
|
48
|
+
* - for a normal key: out = mergeSplitOverlap(out, { [key]: value })
|
|
49
|
+
*
|
|
50
|
+
* Result: fragments behave like spreads at their exact position;
|
|
51
|
+
* later inline keys override earlier ones (including fragments).
|
|
46
52
|
*
|
|
47
53
|
* @param {object} config
|
|
48
54
|
* @param {{ prefix?: string }} [opts]
|
|
49
|
-
* @returns {object}
|
|
55
|
+
* @returns {object} same (mutated) config
|
|
50
56
|
*/
|
|
51
57
|
function mergeMeteorRspackFragments(config, opts = {}) {
|
|
52
58
|
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
@@ -54,39 +60,36 @@ function mergeMeteorRspackFragments(config, opts = {}) {
|
|
|
54
60
|
}
|
|
55
61
|
const prefix = opts.prefix || DEFAULT_PREFIX;
|
|
56
62
|
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
.map((k) => [k, parseInt(k.slice(prefix.length), 10)])
|
|
61
|
-
.sort((a, b) => a[1] - b[1])
|
|
62
|
-
.map(([k]) => k);
|
|
63
|
+
let out = {};
|
|
64
|
+
for (const key of Object.keys(config)) {
|
|
65
|
+
const val = config[key];
|
|
63
66
|
|
|
64
|
-
|
|
67
|
+
const isFragment =
|
|
68
|
+
typeof key === "string" &&
|
|
69
|
+
key.startsWith(prefix) &&
|
|
70
|
+
/^\d+$/.test(key.slice(prefix.length));
|
|
65
71
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
if (isFragment) {
|
|
73
|
+
if (!val || typeof val !== "object" || Array.isArray(val)) {
|
|
74
|
+
throw new Error(`Fragment "${key}" must be a plain object`);
|
|
75
|
+
}
|
|
76
|
+
out = mergeSplitOverlap(out, val);
|
|
77
|
+
} else {
|
|
78
|
+
out = mergeSplitOverlap(out, { [key]: val });
|
|
71
79
|
}
|
|
72
|
-
const merged = mergeSplitOverlap(config, fragment);
|
|
73
|
-
|
|
74
|
-
// Keep object identity: replace contents of `config` with `merged`
|
|
75
|
-
replaceObject(config, merged);
|
|
76
80
|
}
|
|
77
81
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
// keep object identity; fragments disappear because `out` doesn't include them
|
|
83
|
+
replaceObject(config, out);
|
|
81
84
|
return config;
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
function replaceObject(target, source) {
|
|
85
|
-
for (const
|
|
86
|
-
if (!(
|
|
88
|
+
for (const k of Object.keys(target)) {
|
|
89
|
+
if (!(k in source)) delete target[k];
|
|
87
90
|
}
|
|
88
|
-
for (const
|
|
89
|
-
target[
|
|
91
|
+
for (const k of Object.keys(source)) {
|
|
92
|
+
target[k] = source[k];
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
|
|
@@ -54,6 +54,30 @@ function compileWithRspack(deps, { options = {} } = {}) {
|
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Enable or disable Rspack cache config
|
|
59
|
+
* Usage: setCache(false)
|
|
60
|
+
*
|
|
61
|
+
* @param {boolean} enabled
|
|
62
|
+
* @param {Record<string, object>} cacheConfig
|
|
63
|
+
* @returns {Record<string, object>} `{ meteorRspackConfigX: { cache: {} } }`
|
|
64
|
+
*/
|
|
65
|
+
function setCache(
|
|
66
|
+
enabled,
|
|
67
|
+
cacheConfig = { cache: true, experiments: { cache: true } },
|
|
68
|
+
) {
|
|
69
|
+
return prepareMeteorRspackConfig(
|
|
70
|
+
enabled
|
|
71
|
+
? cacheConfig
|
|
72
|
+
: {
|
|
73
|
+
cache: false, // disable cache
|
|
74
|
+
experiments: {
|
|
75
|
+
cache: false, // disable persistent cache (experimental flag)
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
57
81
|
/**
|
|
58
82
|
* Build an alias map that disables ALL Node core modules in a web build.
|
|
59
83
|
* - Includes both 'fs' and 'node:fs' keys
|
|
@@ -77,5 +101,6 @@ function makeWebNodeBuiltinsAlias(extras = []) {
|
|
|
77
101
|
module.exports = {
|
|
78
102
|
compileWithMeteor,
|
|
79
103
|
compileWithRspack,
|
|
104
|
+
setCache,
|
|
80
105
|
makeWebNodeBuiltinsAlias,
|
|
81
106
|
};
|
package/package.json
CHANGED
package/rspack.config.js
CHANGED
|
@@ -14,6 +14,7 @@ const { mergeMeteorRspackFragments } = require("./lib/meteorRspackConfigFactory.
|
|
|
14
14
|
const {
|
|
15
15
|
compileWithMeteor,
|
|
16
16
|
compileWithRspack,
|
|
17
|
+
setCache,
|
|
17
18
|
makeWebNodeBuiltinsAlias,
|
|
18
19
|
} = require('./lib/meteorRspackHelpers.js');
|
|
19
20
|
|
|
@@ -137,6 +138,43 @@ function createSwcConfig({
|
|
|
137
138
|
};
|
|
138
139
|
}
|
|
139
140
|
|
|
141
|
+
function createRemoteDevServerConfig() {
|
|
142
|
+
const rootUrl = process.env.ROOT_URL;
|
|
143
|
+
let hostname;
|
|
144
|
+
let protocol;
|
|
145
|
+
let port;
|
|
146
|
+
|
|
147
|
+
if (rootUrl) {
|
|
148
|
+
try {
|
|
149
|
+
const url = new URL(rootUrl);
|
|
150
|
+
// Detect if it's remote (not localhost or 127.x)
|
|
151
|
+
const isLocal =
|
|
152
|
+
url.hostname.includes('localhost') ||
|
|
153
|
+
url.hostname.startsWith('127.') ||
|
|
154
|
+
url.hostname.endsWith('.local');
|
|
155
|
+
if (!isLocal) {
|
|
156
|
+
hostname = url.hostname;
|
|
157
|
+
protocol = url.protocol === 'https:' ? 'wss' : 'ws';
|
|
158
|
+
port = url.port ? Number(url.port) : (url.protocol === 'https:' ? 443 : 80);
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
client: {
|
|
162
|
+
webSocketURL: {
|
|
163
|
+
hostname,
|
|
164
|
+
port,
|
|
165
|
+
protocol,
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
} catch (err) {
|
|
171
|
+
console.warn(`Invalid ROOT_URL "${rootUrl}", falling back to localhost`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// If local doesn't provide any extra config
|
|
176
|
+
return {};
|
|
177
|
+
}
|
|
140
178
|
|
|
141
179
|
// Keep files outside of build folders
|
|
142
180
|
function keepOutsideBuild() {
|
|
@@ -218,12 +256,23 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
218
256
|
const buildOutputDir = path.resolve(projectDir, buildContext, outputDir);
|
|
219
257
|
Meteor.buildOutputDir = buildOutputDir;
|
|
220
258
|
|
|
259
|
+
const cacheStrategy = createCacheStrategy(
|
|
260
|
+
mode,
|
|
261
|
+
(Meteor.isClient && 'client') || 'server',
|
|
262
|
+
{ projectConfigPath, configPath }
|
|
263
|
+
);
|
|
264
|
+
|
|
221
265
|
// Expose Meteor's helpers to expand Rspack configs
|
|
222
266
|
Meteor.compileWithMeteor = deps => compileWithMeteor(deps);
|
|
223
267
|
Meteor.compileWithRspack = deps =>
|
|
224
268
|
compileWithRspack(deps, {
|
|
225
269
|
options: Meteor.swcConfigOptions,
|
|
226
270
|
});
|
|
271
|
+
Meteor.setCache = enabled =>
|
|
272
|
+
setCache(
|
|
273
|
+
!!enabled,
|
|
274
|
+
enabled === 'memory' ? undefined : cacheStrategy
|
|
275
|
+
);
|
|
227
276
|
|
|
228
277
|
// Add HtmlRspackPlugin function to Meteor
|
|
229
278
|
Meteor.HtmlRspackPlugin = (options = {}) => {
|
|
@@ -432,6 +481,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
432
481
|
devtool: isDevEnvironment || isNative || isTest ? 'source-map' : 'hidden-source-map',
|
|
433
482
|
...(isDevEnvironment && {
|
|
434
483
|
devServer: {
|
|
484
|
+
...createRemoteDevServerConfig(),
|
|
435
485
|
static: { directory: clientOutputDir, publicPath: '/__rspack__/' },
|
|
436
486
|
hot: true,
|
|
437
487
|
liveReload: true,
|
|
@@ -443,7 +493,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
443
493
|
},
|
|
444
494
|
},
|
|
445
495
|
}),
|
|
446
|
-
...merge(
|
|
496
|
+
...merge(cacheStrategy, { experiments: { css: true } })
|
|
447
497
|
};
|
|
448
498
|
|
|
449
499
|
|
|
@@ -526,7 +576,7 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
526
576
|
watchOptions,
|
|
527
577
|
devtool: isDevEnvironment || isNative || isTest ? 'source-map' : 'hidden-source-map',
|
|
528
578
|
...((isDevEnvironment || (isTest && !isTestEager) || isNative) &&
|
|
529
|
-
|
|
579
|
+
cacheStrategy),
|
|
530
580
|
};
|
|
531
581
|
|
|
532
582
|
// Load and apply project-level overrides for the selected build
|
|
@@ -583,22 +633,27 @@ module.exports = async function (inMeteor = {}, argv = {}) {
|
|
|
583
633
|
);
|
|
584
634
|
};
|
|
585
635
|
|
|
636
|
+
let nextUserConfig = cleanOmittedPaths(userConfig, {
|
|
637
|
+
omitPaths,
|
|
638
|
+
warningFn,
|
|
639
|
+
});
|
|
640
|
+
nextUserConfig = mergeMeteorRspackFragments(nextUserConfig);
|
|
641
|
+
|
|
586
642
|
if (Meteor.isClient) {
|
|
587
643
|
clientConfig = mergeSplitOverlap(
|
|
588
644
|
clientConfig,
|
|
589
|
-
|
|
645
|
+
nextUserConfig
|
|
590
646
|
);
|
|
591
647
|
}
|
|
592
648
|
if (Meteor.isServer) {
|
|
593
649
|
serverConfig = mergeSplitOverlap(
|
|
594
650
|
serverConfig,
|
|
595
|
-
|
|
651
|
+
nextUserConfig
|
|
596
652
|
);
|
|
597
653
|
}
|
|
598
654
|
}
|
|
599
655
|
|
|
600
|
-
const
|
|
601
|
-
const config = mergeMeteorRspackFragments(sideConfig);
|
|
656
|
+
const config = isClient ? clientConfig : serverConfig;
|
|
602
657
|
|
|
603
658
|
if (Meteor.isDebug || Meteor.isVerbose) {
|
|
604
659
|
console.log('Config:', inspect(config, { depth: null, colors: true }));
|