@meteorjs/rspack 1.1.0-beta.9 → 2.0.0
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 +299 -259
- package/scripts/bump-version.js +89 -0
- package/scripts/publish-beta.sh +4 -0
|
@@ -132,10 +132,14 @@ function splitVendorChunk() {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
/**
|
|
135
|
-
* Extend SWC loader config
|
|
136
|
-
*
|
|
135
|
+
* Extend SWC loader config by smart-merging custom options on top of Meteor's
|
|
136
|
+
* defaults (via `mergeSplitOverlap`). Only the properties you specify are
|
|
137
|
+
* overridden; everything else is preserved.
|
|
137
138
|
*
|
|
138
|
-
*
|
|
139
|
+
* Usage: Meteor.extendSwcConfig({ jsc: { parser: { decorators: true } } })
|
|
140
|
+
*
|
|
141
|
+
* @param {object} swcConfig - SWC loader options to merge with defaults
|
|
142
|
+
* @returns {Record<string, object>} config fragment for spreading into rspack config
|
|
139
143
|
*/
|
|
140
144
|
function extendSwcConfig(swcConfig) {
|
|
141
145
|
return prepareMeteorRspackConfig({
|
|
@@ -152,6 +156,44 @@ function extendSwcConfig(swcConfig) {
|
|
|
152
156
|
});
|
|
153
157
|
}
|
|
154
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Replace the SWC loader config entirely, discarding Meteor's defaults.
|
|
161
|
+
* Use this when you need full control over SWC options and don't want any
|
|
162
|
+
* automatic merging with Meteor's built-in configuration.
|
|
163
|
+
*
|
|
164
|
+
* Usage: Meteor.replaceSwcConfig({ jsc: { parser: { syntax: 'typescript' }, target: 'es2020' } })
|
|
165
|
+
*
|
|
166
|
+
* @param {object} swcConfig - Complete SWC loader options (replaces defaults)
|
|
167
|
+
* @returns {Record<string, object>} config fragment for spreading into rspack config
|
|
168
|
+
*/
|
|
169
|
+
function replaceSwcConfig(swcConfig) {
|
|
170
|
+
return prepareMeteorRspackConfig({
|
|
171
|
+
module: {
|
|
172
|
+
rules: [
|
|
173
|
+
{
|
|
174
|
+
test: /\.(?:[mc]?js|jsx|[mc]?ts|tsx)$/i,
|
|
175
|
+
exclude: /node_modules|\.meteor\/local/,
|
|
176
|
+
loader: 'builtin:swc-loader',
|
|
177
|
+
options: swcConfig,
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Signal that `Meteor.isDevelopment` and `Meteor.isProduction` should be omitted
|
|
186
|
+
* from DefinePlugin, making the bundle portable across Meteor environments.
|
|
187
|
+
* Usage: return Meteor.enablePortableBuild() in your rspack.config.js
|
|
188
|
+
*
|
|
189
|
+
* @returns {Record<string, object>} config fragment with `meteor.enablePortableBuild: true`
|
|
190
|
+
*/
|
|
191
|
+
function enablePortableBuild() {
|
|
192
|
+
return prepareMeteorRspackConfig({
|
|
193
|
+
"meteor.enablePortableBuild": true,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
155
197
|
/**
|
|
156
198
|
* Remove plugins from a Rspack config by name, RegExp, predicate, or array of them.
|
|
157
199
|
* When using a function predicate, it receives both the plugin and its index in the plugins array.
|
|
@@ -202,6 +244,92 @@ function disablePlugins(config, matchers) {
|
|
|
202
244
|
return config;
|
|
203
245
|
}
|
|
204
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Create a `writeToDisk` callback that persists specific files to disk
|
|
249
|
+
* during development.
|
|
250
|
+
*
|
|
251
|
+
* Accepts an array (defaults to "always" strategy) or an object with
|
|
252
|
+
* `once` and/or `always` keys for mixed strategies.
|
|
253
|
+
*
|
|
254
|
+
* Matchers can be:
|
|
255
|
+
* - **string**: matched with `endsWith` (e.g. `'sw.js'`, `'.html'`)
|
|
256
|
+
* - **RegExp**: tested against the full file path
|
|
257
|
+
* - **function**: `(filePath: string) => boolean`
|
|
258
|
+
*
|
|
259
|
+
* Strategies:
|
|
260
|
+
* - `always`: Write on every build (default). Use for files that should
|
|
261
|
+
* always reflect the latest build output.
|
|
262
|
+
* - `once`: Write on the first build only. Skipped on HMR rebuilds to
|
|
263
|
+
* avoid triggering service worker re-registration or file
|
|
264
|
+
* watcher restarts.
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* // Simple: array defaults to "always"
|
|
268
|
+
* ...Meteor.persistDevFiles(['manifest.json'])
|
|
269
|
+
*
|
|
270
|
+
* // Mixed strategies with strings, regex, and functions
|
|
271
|
+
* ...Meteor.persistDevFiles({
|
|
272
|
+
* once: ['sw.js', /\.worker\.js$/],
|
|
273
|
+
* always: ['manifest.json', (filePath) => filePath.includes('/custom/')],
|
|
274
|
+
* })
|
|
275
|
+
*
|
|
276
|
+
* @param {(string|RegExp|Function)[] | { once?: (string|RegExp|Function)[], always?: (string|RegExp|Function)[] }} matchers
|
|
277
|
+
* @returns {Record<string, object>} config fragment with devServer.devMiddleware.writeToDisk
|
|
278
|
+
*/
|
|
279
|
+
/**
|
|
280
|
+
* Build the writeToDisk callback from matchers.
|
|
281
|
+
* Shared by persistDevFiles (fragment) and internal usage (direct).
|
|
282
|
+
* @private
|
|
283
|
+
*/
|
|
284
|
+
function createPersistCallback(matchers) {
|
|
285
|
+
const once = [];
|
|
286
|
+
const always = [];
|
|
287
|
+
|
|
288
|
+
if (Array.isArray(matchers)) {
|
|
289
|
+
always.push(...matchers);
|
|
290
|
+
} else {
|
|
291
|
+
if (matchers.once) once.push(...matchers.once);
|
|
292
|
+
if (matchers.always) always.push(...matchers.always);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// HTML files are always persisted, Meteor's web server relies on them
|
|
296
|
+
if (!always.includes('.html')) {
|
|
297
|
+
always.push('.html');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const match = (filePath, pattern) => {
|
|
301
|
+
if (typeof pattern === 'function') return pattern(filePath);
|
|
302
|
+
if (typeof pattern === 'string') return filePath.endsWith(pattern);
|
|
303
|
+
return pattern.test(filePath);
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const written = new Set();
|
|
307
|
+
|
|
308
|
+
return (filePath) => {
|
|
309
|
+
for (const pattern of always) {
|
|
310
|
+
if (match(filePath, pattern)) return true;
|
|
311
|
+
}
|
|
312
|
+
for (let i = 0; i < once.length; i++) {
|
|
313
|
+
if (match(filePath, once[i])) {
|
|
314
|
+
if (written.has(i)) return false;
|
|
315
|
+
written.add(i);
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return false;
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function persistDevFiles(matchers) {
|
|
324
|
+
return prepareMeteorRspackConfig({
|
|
325
|
+
devServer: {
|
|
326
|
+
devMiddleware: {
|
|
327
|
+
writeToDisk: createPersistCallback(matchers),
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
205
333
|
function outputMeteorRspack(data) {
|
|
206
334
|
const jsonString = JSON.stringify(data);
|
|
207
335
|
const output = `[Meteor-Rspack]${jsonString}[/Meteor-Rspack]`;
|
|
@@ -214,7 +342,11 @@ module.exports = {
|
|
|
214
342
|
setCache,
|
|
215
343
|
splitVendorChunk,
|
|
216
344
|
extendSwcConfig,
|
|
345
|
+
replaceSwcConfig,
|
|
217
346
|
makeWebNodeBuiltinsAlias,
|
|
218
347
|
disablePlugins,
|
|
219
348
|
outputMeteorRspack,
|
|
349
|
+
enablePortableBuild,
|
|
350
|
+
persistDevFiles,
|
|
351
|
+
createPersistCallback,
|
|
220
352
|
};
|
package/lib/swc.js
CHANGED
|
@@ -9,11 +9,38 @@ const vm = require('vm');
|
|
|
9
9
|
function getMeteorAppSwcrc(file = '.swcrc') {
|
|
10
10
|
try {
|
|
11
11
|
const filePath = `${process.cwd()}/${file}`;
|
|
12
|
-
if (file.endsWith('.js')) {
|
|
12
|
+
if (file.endsWith('.js') || file.endsWith('.ts')) {
|
|
13
13
|
let content = fs.readFileSync(filePath, 'utf-8');
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
if (file.endsWith('.ts')) {
|
|
16
|
+
try {
|
|
17
|
+
const swc = require('@swc/core');
|
|
18
|
+
const result = swc.transformSync(content, {
|
|
19
|
+
jsc: {
|
|
20
|
+
parser: {
|
|
21
|
+
syntax: 'typescript',
|
|
22
|
+
},
|
|
23
|
+
target: 'es2015',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
content = result.code;
|
|
27
|
+
} catch (swcError) {
|
|
28
|
+
content = content
|
|
29
|
+
.replace(/import\s+type\s+.*?from\s+['"][^'"]+['"];?/g, '')
|
|
30
|
+
.replace(/import\s+.*?from\s+['"][^'"]+['"];?/g, '')
|
|
31
|
+
.replace(/import\s+['"][^'"]+['"];?/g, '')
|
|
32
|
+
.replace(/export\s+default\s+/, 'module.exports = ')
|
|
33
|
+
.replace(/export\s+/g, '')
|
|
34
|
+
.replace(/:\s*\w+(\[\])?(\s*=)/g, '$2')
|
|
35
|
+
.replace(/\(([^)]*?):\s*\w+(\[\])?\)/g, '($1)')
|
|
36
|
+
.replace(/\):\s*\w+(\[\])?\s*\{/g, ') {')
|
|
37
|
+
.replace(/interface\s+\w+\s*\{[^}]*\}/g, '')
|
|
38
|
+
.replace(/type\s+\w+\s*=\s*[^;]+;/g, '')
|
|
39
|
+
.replace(/as\s+\w+(\[\])?/g, '');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
15
43
|
if (content.includes('export default')) {
|
|
16
|
-
// Transform ES module syntax to CommonJS
|
|
17
44
|
content = content.replace(/export\s+default\s+/, 'module.exports = ');
|
|
18
45
|
}
|
|
19
46
|
const script = new vm.Script(`
|
|
@@ -27,7 +54,9 @@ function getMeteorAppSwcrc(file = '.swcrc') {
|
|
|
27
54
|
})()
|
|
28
55
|
`);
|
|
29
56
|
const context = vm.createContext({ process });
|
|
30
|
-
|
|
57
|
+
const result = script.runInContext(context);
|
|
58
|
+
// Handle CJS interop wrapper (e.g. { __esModule: true, default: config })
|
|
59
|
+
return result && result.__esModule && result.default ? result.default : result;
|
|
31
60
|
} else {
|
|
32
61
|
// For .swcrc and other JSON files, parse as JSON
|
|
33
62
|
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
@@ -45,12 +74,13 @@ function getMeteorAppSwcrc(file = '.swcrc') {
|
|
|
45
74
|
function getMeteorAppSwcConfig() {
|
|
46
75
|
const hasSwcRc = fs.existsSync(`${process.cwd()}/.swcrc`);
|
|
47
76
|
const hasSwcJs = !hasSwcRc && fs.existsSync(`${process.cwd()}/swc.config.js`);
|
|
77
|
+
const hasSwcTs = !hasSwcRc && !hasSwcJs && fs.existsSync(`${process.cwd()}/swc.config.ts`);
|
|
48
78
|
|
|
49
|
-
if (!hasSwcRc && !hasSwcJs) {
|
|
79
|
+
if (!hasSwcRc && !hasSwcJs && !hasSwcTs) {
|
|
50
80
|
return undefined;
|
|
51
81
|
}
|
|
52
82
|
|
|
53
|
-
const swcFile = hasSwcJs ? 'swc.config.js' : '.swcrc';
|
|
83
|
+
const swcFile = hasSwcTs ? 'swc.config.ts' : hasSwcJs ? 'swc.config.js' : '.swcrc';
|
|
54
84
|
const config = getMeteorAppSwcrc(swcFile);
|
|
55
85
|
|
|
56
86
|
// Set baseUrl to process.cwd() if it exists
|
package/lib/test.js
CHANGED
|
@@ -2,6 +2,10 @@ const fs = require('fs');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const { createIgnoreRegex, createIgnoreGlobConfig } = require("./ignore.js");
|
|
4
4
|
|
|
5
|
+
// Normalize a path to always use forward slashes (POSIX style).
|
|
6
|
+
// Module identifiers in bundled JS must use '/' regardless of OS.
|
|
7
|
+
const toPosix = (p) => p.replace(/\\/g, '/');
|
|
8
|
+
|
|
5
9
|
/**
|
|
6
10
|
* Generates eager test files dynamically
|
|
7
11
|
* @param {Object} options - Options for generating the test file
|
|
@@ -42,7 +46,6 @@ const generateEagerTestFile = ({
|
|
|
42
46
|
const excludeFoldersRegex = createIgnoreRegex(
|
|
43
47
|
createIgnoreGlobConfig(ignoreEntries)
|
|
44
48
|
);
|
|
45
|
-
console.log("inMeteorIgnoreEntries", inMeteorIgnoreEntries);
|
|
46
49
|
// Create regex from meteor ignore entries
|
|
47
50
|
const excludeMeteorIgnoreRegex = inMeteorIgnoreEntries.length > 0
|
|
48
51
|
? createIgnoreRegex(createIgnoreGlobConfig(inMeteorIgnoreEntries))
|
|
@@ -58,14 +61,14 @@ const generateEagerTestFile = ({
|
|
|
58
61
|
: "/\\.(?:test|spec)s?\\.[^.]+$/";
|
|
59
62
|
|
|
60
63
|
const content = `${
|
|
61
|
-
globalImportPath ? `import '${globalImportPath}';\n\n` : ""
|
|
64
|
+
globalImportPath ? `import '${toPosix(globalImportPath)}';\n\n` : ""
|
|
62
65
|
}${
|
|
63
66
|
excludeMeteorIgnoreRegex
|
|
64
67
|
? `const MeteorIgnoreRegex = ${excludeMeteorIgnoreRegex.toString()};`
|
|
65
68
|
: ""
|
|
66
69
|
}
|
|
67
70
|
{
|
|
68
|
-
const ctx = import.meta.webpackContext('${projectDir}', {
|
|
71
|
+
const ctx = import.meta.webpackContext('${toPosix(projectDir)}', {
|
|
69
72
|
recursive: true,
|
|
70
73
|
regExp: ${regExp},
|
|
71
74
|
exclude: ${excludeFoldersRegex.toString()},
|
|
@@ -81,9 +84,9 @@ const generateEagerTestFile = ({
|
|
|
81
84
|
}).forEach(ctx);
|
|
82
85
|
${
|
|
83
86
|
extraEntry
|
|
84
|
-
? `const extra = import.meta.webpackContext('${path.dirname(
|
|
87
|
+
? `const extra = import.meta.webpackContext('${toPosix(path.dirname(
|
|
85
88
|
extraEntry
|
|
86
|
-
)}', {
|
|
89
|
+
))}', {
|
|
87
90
|
recursive: false,
|
|
88
91
|
regExp: ${new RegExp(`${path.basename(extraEntry)}$`).toString()},
|
|
89
92
|
mode: 'eager',
|
package/package.json
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meteorjs/rspack",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Configuration logic for using Rspack in Meteor projects",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"author": "",
|
|
8
8
|
"license": "ISC",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"bump": "node ./scripts/bump-version.js",
|
|
11
|
+
"publish:beta": "bash ./scripts/publish-beta.sh"
|
|
12
|
+
},
|
|
9
13
|
"dependencies": {
|
|
10
14
|
"fast-deep-equal": "^3.1.3",
|
|
11
15
|
"ignore-loader": "^0.1.2",
|
|
12
16
|
"node-polyfill-webpack-plugin": "^4.1.0",
|
|
13
17
|
"webpack-merge": "^6.0.1"
|
|
14
18
|
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"semver": "^7.7.4"
|
|
21
|
+
},
|
|
15
22
|
"peerDependencies": {
|
|
16
23
|
"@rspack/cli": ">=1.3.0",
|
|
17
|
-
"@rspack/core": ">=1.3.0"
|
|
24
|
+
"@rspack/core": ">=1.3.0",
|
|
25
|
+
"@swc/core": ">=1.3.0"
|
|
18
26
|
}
|
|
19
27
|
}
|
|
@@ -6,6 +6,96 @@
|
|
|
6
6
|
|
|
7
7
|
const { outputMeteorRspack } = require('../lib/meteorRspackHelpers');
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Extracts file extensions that rspack is configured to handle
|
|
11
|
+
* from the resolved module.rules test patterns.
|
|
12
|
+
* @param {import('@rspack/core').Compiler} compiler
|
|
13
|
+
* @returns {Set<string>} Set of extensions like .css, .less, .scss
|
|
14
|
+
*/
|
|
15
|
+
function extractConfiguredExtensions(compiler) {
|
|
16
|
+
const delegatableExtensions = ['.css', '.less', '.scss', '.sass', '.styl'];
|
|
17
|
+
const found = new Set();
|
|
18
|
+
|
|
19
|
+
function inspectRules(rules) {
|
|
20
|
+
for (const rule of rules) {
|
|
21
|
+
if (!rule) continue;
|
|
22
|
+
if (rule.test) {
|
|
23
|
+
const testStr = rule.test instanceof RegExp
|
|
24
|
+
? rule.test.source
|
|
25
|
+
: String(rule.test);
|
|
26
|
+
for (const ext of delegatableExtensions) {
|
|
27
|
+
const escaped = ext.replace('.', '\\.');
|
|
28
|
+
if (testStr.includes(escaped)) {
|
|
29
|
+
found.add(ext);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (rule.oneOf) inspectRules(rule.oneOf);
|
|
34
|
+
if (rule.rules) inspectRules(rule.rules);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
inspectRules(compiler.options.module?.rules || []);
|
|
39
|
+
return found;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Extracts file extensions that rspack both has rules for AND actually compiled
|
|
44
|
+
* from files within entry folder paths (e.g. client/, server/).
|
|
45
|
+
* An extension is only delegated if Rspack compiled a file with that extension
|
|
46
|
+
* from an entry folder. Files in non-entry folders (e.g. imports/) don't count,
|
|
47
|
+
* since delegation only ignores entry folder files for Meteor.
|
|
48
|
+
* @param {import('@rspack/core').Stats} stats
|
|
49
|
+
* @param {import('@rspack/core').Compiler} compiler
|
|
50
|
+
* @returns {string[]} Array of extensions like ['.css', '.less', '.scss']
|
|
51
|
+
*/
|
|
52
|
+
function extractDelegatedExtensions(stats, compiler) {
|
|
53
|
+
const configured = extractConfiguredExtensions(compiler);
|
|
54
|
+
if (configured.size === 0) return [];
|
|
55
|
+
|
|
56
|
+
const path = require('path');
|
|
57
|
+
const fs = require('fs');
|
|
58
|
+
const appRoot = compiler.options.context || process.cwd();
|
|
59
|
+
|
|
60
|
+
// Read entry folders from package.json meteor.mainModule
|
|
61
|
+
const entryFolders = new Set();
|
|
62
|
+
try {
|
|
63
|
+
const pkgPath = path.join(appRoot, 'package.json');
|
|
64
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
65
|
+
const mainModule = pkg?.meteor?.mainModule || {};
|
|
66
|
+
for (const entry of Object.values(mainModule)) {
|
|
67
|
+
if (typeof entry === 'string') {
|
|
68
|
+
const folder = entry.split('/')[0];
|
|
69
|
+
if (folder) entryFolders.add(folder);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
// If we can't read package.json, fall back to config-only
|
|
74
|
+
return Array.from(configured);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (entryFolders.size === 0) return Array.from(configured);
|
|
78
|
+
|
|
79
|
+
const found = new Set();
|
|
80
|
+
|
|
81
|
+
for (const module of stats.compilation.modules) {
|
|
82
|
+
const resource = module.resource || module.userRequest;
|
|
83
|
+
if (!resource) continue;
|
|
84
|
+
|
|
85
|
+
const relativePath = path.relative(appRoot, resource);
|
|
86
|
+
const topFolder = relativePath.split(path.sep)[0];
|
|
87
|
+
if (!entryFolders.has(topFolder)) continue;
|
|
88
|
+
|
|
89
|
+
const ext = path.extname(resource);
|
|
90
|
+
if (configured.has(ext)) {
|
|
91
|
+
found.add(ext);
|
|
92
|
+
if (found.size === configured.size) break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return Array.from(found);
|
|
97
|
+
}
|
|
98
|
+
|
|
9
99
|
class MeteorRspackOutputPlugin {
|
|
10
100
|
constructor(options = {}) {
|
|
11
101
|
this.pluginName = 'MeteorRspackOutputPlugin';
|
|
@@ -26,6 +116,7 @@ class MeteorRspackOutputPlugin {
|
|
|
26
116
|
...(this.getData(stats, {
|
|
27
117
|
compilationCount: this.compilationCount,
|
|
28
118
|
isRebuild: this.compilationCount > 1,
|
|
119
|
+
compiler,
|
|
29
120
|
}) || {}),
|
|
30
121
|
};
|
|
31
122
|
outputMeteorRspack(data);
|
|
@@ -33,4 +124,4 @@ class MeteorRspackOutputPlugin {
|
|
|
33
124
|
}
|
|
34
125
|
}
|
|
35
126
|
|
|
36
|
-
module.exports = { MeteorRspackOutputPlugin };
|
|
127
|
+
module.exports = { MeteorRspackOutputPlugin, extractDelegatedExtensions };
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const path = require('path');
|
|
12
12
|
|
|
13
|
+
// Normalize a path to always use forward slashes (POSIX style).
|
|
14
|
+
// Module identifiers in bundled JS must use '/' regardless of OS.
|
|
15
|
+
const toPosix = (p) => p.replace(/\\/g, '/');
|
|
16
|
+
|
|
13
17
|
class RequireExternalsPlugin {
|
|
14
18
|
constructor({
|
|
15
19
|
filePath,
|
|
@@ -46,7 +50,7 @@ class RequireExternalsPlugin {
|
|
|
46
50
|
// Prepare paths
|
|
47
51
|
this.filePath = path.resolve(process.cwd(), filePath);
|
|
48
52
|
this.backRoot = '../'.repeat(
|
|
49
|
-
filePath.replace(
|
|
53
|
+
filePath.replace(/^\.?[/\\]+/, '').split(/[/\\]/).length - 1
|
|
50
54
|
);
|
|
51
55
|
|
|
52
56
|
// Initialize funcCount based on existing helpers in the file
|
|
@@ -96,14 +100,16 @@ class RequireExternalsPlugin {
|
|
|
96
100
|
pkg &&
|
|
97
101
|
(path.isAbsolute(pkg) ||
|
|
98
102
|
pkg.startsWith('./') ||
|
|
103
|
+
pkg.startsWith('.\\') ||
|
|
99
104
|
pkg.startsWith('../') ||
|
|
105
|
+
pkg.startsWith('..\\') ||
|
|
100
106
|
!!depInfo.ext)
|
|
101
107
|
) {
|
|
102
108
|
const module = this.externalsMeta.get(pkg);
|
|
103
109
|
if (module) {
|
|
104
|
-
return `${this.backRoot}${module.relativeRequest}`;
|
|
110
|
+
return `${this.backRoot}${toPosix(module.relativeRequest)}`;
|
|
105
111
|
}
|
|
106
|
-
return `${this.backRoot}${name}`;
|
|
112
|
+
return `${this.backRoot}${toPosix(name)}`;
|
|
107
113
|
}
|
|
108
114
|
|
|
109
115
|
return pkg;
|
|
@@ -132,7 +138,7 @@ class RequireExternalsPlugin {
|
|
|
132
138
|
this.externalsMeta.set(externalRequest, {
|
|
133
139
|
originalRequest: request,
|
|
134
140
|
externalRequest,
|
|
135
|
-
relativeRequest: path.join(relContext, request),
|
|
141
|
+
relativeRequest: toPosix(path.join(relContext, request)),
|
|
136
142
|
});
|
|
137
143
|
|
|
138
144
|
// tell Rspack "don't bundle this, import it at runtime"
|