@module-federation/vite 1.13.4 → 1.13.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/lib/index.cjs +276 -12
- package/lib/index.mjs +276 -12
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -23,6 +23,8 @@ This plugin makes Module Federation work together with [Vite](https://vitejs.dev
|
|
|
23
23
|
|
|
24
24
|
### [More examples here](https://github.com/module-federation/vite/tree/main/examples)<br>
|
|
25
25
|
|
|
26
|
+
Includes a pure runtime host example in [`examples/vite-runtime-register`](./examples/vite-runtime-register).
|
|
27
|
+
|
|
26
28
|
## Try this crazy example with all these bundlers together
|
|
27
29
|
|
|
28
30
|
<img src="./docs/multi-example.png"/>
|
|
@@ -168,6 +170,16 @@ const RemoteMFE = defineAsyncComponent( 👈
|
|
|
168
170
|
</template>
|
|
169
171
|
```
|
|
170
172
|
|
|
173
|
+
## ⚠️ `codeSplitting: false` is not supported
|
|
174
|
+
|
|
175
|
+
Do not set `build.rolldownOptions.output.codeSplitting` to `false` with this plugin — it will be **automatically ignored**.
|
|
176
|
+
Module federation requires chunk splitting to isolate shared dependencies and remote entries into separate chunks.
|
|
177
|
+
|
|
178
|
+
## ⚠️ `manualChunks` is not supported
|
|
179
|
+
|
|
180
|
+
Do not use `build.rollupOptions.output.manualChunks` with this plugin — it will be **automatically ignored**.
|
|
181
|
+
Module federation transforms shared dependency imports with top-level `await`, and grouping these transformed modules into a single chunk creates circular async dependencies that cause the application to silently hang.
|
|
182
|
+
|
|
171
183
|
### So far so good 🎉
|
|
172
184
|
|
|
173
185
|
Now you are ready to use Module Federation in Vite!
|
package/lib/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ let _module_federation_dts_plugin = require("@module-federation/dts-plugin");
|
|
|
36
36
|
let _module_federation_dts_plugin_core = require("@module-federation/dts-plugin/core");
|
|
37
37
|
let node_module = require("node:module");
|
|
38
38
|
let url = require("url");
|
|
39
|
+
let es_module_lexer = require("es-module-lexer");
|
|
39
40
|
//#region src/utils/mapCodeToCodeWithSourcemap.ts
|
|
40
41
|
async function mapCodeToCodeWithSourcemap(code) {
|
|
41
42
|
const resolvedCode = await code;
|
|
@@ -151,7 +152,7 @@ function removePathFromNpmPackage(packageString) {
|
|
|
151
152
|
return match ? match[0] : packageString;
|
|
152
153
|
}
|
|
153
154
|
/**
|
|
154
|
-
* Detect whether the current
|
|
155
|
+
* Detect whether the current runtime is Vite 8+ (with rolldown internally) by checking
|
|
155
156
|
* for `meta.rolldownVersion` on the plugin hook context.
|
|
156
157
|
*/
|
|
157
158
|
function getIsRolldown(ctx) {
|
|
@@ -380,15 +381,17 @@ function checkAliasConflicts(options) {
|
|
|
380
381
|
};
|
|
381
382
|
}
|
|
382
383
|
//#endregion
|
|
383
|
-
//#region src/
|
|
384
|
-
/**
|
|
385
|
-
* Solve the problem that dev mode dependency prebunding does not support top-level await syntax
|
|
386
|
-
*/
|
|
384
|
+
//#region src/utils/loadWalk.ts
|
|
387
385
|
let walkPromise = null;
|
|
388
386
|
function loadWalk() {
|
|
389
387
|
walkPromise ||= import("estree-walker").then(({ walk }) => walk);
|
|
390
388
|
return walkPromise;
|
|
391
389
|
}
|
|
390
|
+
//#endregion
|
|
391
|
+
//#region src/plugins/pluginDevProxyModuleTopLevelAwait.ts
|
|
392
|
+
/**
|
|
393
|
+
* Solve the problem that dev mode dependency prebunding does not support top-level await syntax
|
|
394
|
+
*/
|
|
392
395
|
function PluginDevProxyModuleTopLevelAwait() {
|
|
393
396
|
const filterFunction = (0, _rollup_pluginutils.createFilter)();
|
|
394
397
|
const processedFlag = "/* already-processed-by-dev-proxy-module-top-level-await */";
|
|
@@ -1197,7 +1200,7 @@ function generateRemotes(id, command, isRolldown) {
|
|
|
1197
1200
|
const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
|
|
1198
1201
|
const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
1199
1202
|
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
1200
|
-
const exportLine = command === "serve" && useESM ? "export default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
|
|
1203
|
+
const exportLine = command === "serve" && useESM ? "export const __moduleExports = exportModule;\nexport default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
|
|
1201
1204
|
return `
|
|
1202
1205
|
${importLine}
|
|
1203
1206
|
const res = initPromise.then(runtime => runtime.loadRemote(${JSON.stringify(id)}))
|
|
@@ -2233,6 +2236,265 @@ function pluginProxyRemotes_default(options) {
|
|
|
2233
2236
|
};
|
|
2234
2237
|
}
|
|
2235
2238
|
//#endregion
|
|
2239
|
+
//#region src/plugins/pluginRemoteNamedExports.ts
|
|
2240
|
+
/**
|
|
2241
|
+
* Transforms consumer-side imports of remote modules so that named exports
|
|
2242
|
+
* are accessible even when the bundler does not support syntheticNamedExports
|
|
2243
|
+
* (Rolldown / Vite 8+).
|
|
2244
|
+
*
|
|
2245
|
+
* The remote proxy module exports:
|
|
2246
|
+
* export const __moduleExports = exportModule; // full namespace
|
|
2247
|
+
* export default exportModule.default ?? exportModule; // unwrapped default
|
|
2248
|
+
*
|
|
2249
|
+
* This plugin rewrites consumer code:
|
|
2250
|
+
* import { foo } from "remote/xxx"
|
|
2251
|
+
* → import { __moduleExports as __mf_ns_0 } from "remote/xxx"; const { foo } = __mf_ns_0;
|
|
2252
|
+
*
|
|
2253
|
+
* import("remote/xxx")
|
|
2254
|
+
* → import("remote/xxx").then(…) // spreads __moduleExports into namespace
|
|
2255
|
+
*
|
|
2256
|
+
* NOTE: `export * from "remote/xxx"` is not supported — Rolldown cannot
|
|
2257
|
+
* statically resolve the set of exported names from a federated remote at
|
|
2258
|
+
* build time. Use explicit named re-exports instead.
|
|
2259
|
+
*/
|
|
2260
|
+
const JS_EXTENSIONS_RE = /\.(?:[mc]?[jt]sx?|vue|svelte)(?:\?|$)/;
|
|
2261
|
+
function wrapDynamicImport(original) {
|
|
2262
|
+
return `${original}.then(function(__mf_m__) {\n if (!__mf_m__ || !__mf_m__.__moduleExports) return __mf_m__;\n var __mf_ns__ = Object.create(null);\n Object.defineProperty(__mf_ns__, Symbol.toStringTag, { value: "Module" });\n var __mf_e__ = __mf_m__.__moduleExports;\n Object.keys(__mf_e__).forEach(function(k) { if (k !== "__esModule") __mf_ns__[k] = __mf_e__[k] });\n if ("default" in __mf_m__) __mf_ns__.default = __mf_m__.default;\n return __mf_ns__;\n})`;
|
|
2263
|
+
}
|
|
2264
|
+
function applyRewrites(code, imports, id) {
|
|
2265
|
+
if (imports.length === 0) return;
|
|
2266
|
+
const ms = new magic_string.default(code);
|
|
2267
|
+
let changed = false;
|
|
2268
|
+
let counter = 0;
|
|
2269
|
+
for (const imp of imports) switch (imp.kind) {
|
|
2270
|
+
case "static": {
|
|
2271
|
+
const src = JSON.stringify(imp.source);
|
|
2272
|
+
if (imp.namespaceLocal && !imp.defaultLocal && imp.named.length === 0) ms.overwrite(imp.start, imp.end, `import { __moduleExports as ${imp.namespaceLocal} } from ${src};`);
|
|
2273
|
+
else {
|
|
2274
|
+
const nsId = `__mf_ns_${counter++}`;
|
|
2275
|
+
const importParts = [];
|
|
2276
|
+
if (imp.defaultLocal) importParts.push(`default as ${imp.defaultLocal}`);
|
|
2277
|
+
importParts.push(`__moduleExports as ${nsId}`);
|
|
2278
|
+
const destructParts = imp.named.map((s) => s.imported === s.local ? s.local : `${s.imported}: ${s.local}`);
|
|
2279
|
+
let rewrite = `import { ${importParts.join(", ")} } from ${src};`;
|
|
2280
|
+
if (destructParts.length > 0) rewrite += `\nconst { ${destructParts.join(", ")} } = ${nsId};`;
|
|
2281
|
+
ms.overwrite(imp.start, imp.end, rewrite);
|
|
2282
|
+
}
|
|
2283
|
+
changed = true;
|
|
2284
|
+
break;
|
|
2285
|
+
}
|
|
2286
|
+
case "reexport": {
|
|
2287
|
+
const src = JSON.stringify(imp.source);
|
|
2288
|
+
const nsId = `__mf_ns_${counter++}`;
|
|
2289
|
+
const vars = imp.specifiers.map((s) => {
|
|
2290
|
+
const tmp = `__mf_re_${counter++}`;
|
|
2291
|
+
return {
|
|
2292
|
+
...s,
|
|
2293
|
+
tmp
|
|
2294
|
+
};
|
|
2295
|
+
});
|
|
2296
|
+
const importLine = `import { __moduleExports as ${nsId} } from ${src};`;
|
|
2297
|
+
const varLines = vars.map((v) => `const ${v.tmp} = ${nsId}[${JSON.stringify(v.local)}];`).join("\n");
|
|
2298
|
+
const exportLine = `export { ${vars.map((v) => `${v.tmp} as ${v.exported}`).join(", ")} };`;
|
|
2299
|
+
ms.overwrite(imp.start, imp.end, `${importLine}\n${varLines}\n${exportLine}`);
|
|
2300
|
+
changed = true;
|
|
2301
|
+
break;
|
|
2302
|
+
}
|
|
2303
|
+
case "export-all":
|
|
2304
|
+
console.warn(`[module-federation] "export * from '${imp.source}'" is not supported with Rolldown — use explicit named re-exports instead. (${id})`);
|
|
2305
|
+
break;
|
|
2306
|
+
case "dynamic":
|
|
2307
|
+
ms.overwrite(imp.start, imp.end, wrapDynamicImport(imp.originalText));
|
|
2308
|
+
changed = true;
|
|
2309
|
+
break;
|
|
2310
|
+
}
|
|
2311
|
+
if (!changed) return;
|
|
2312
|
+
return {
|
|
2313
|
+
code: ms.toString(),
|
|
2314
|
+
map: ms.generateMap({ hires: true })
|
|
2315
|
+
};
|
|
2316
|
+
}
|
|
2317
|
+
async function collectFromAST(ast, code, isRemoteImport) {
|
|
2318
|
+
const walk = await loadWalk();
|
|
2319
|
+
const result = [];
|
|
2320
|
+
walk(ast, { enter(node) {
|
|
2321
|
+
if (node.type === "ImportDeclaration" && node.source?.value) {
|
|
2322
|
+
if (!isRemoteImport(node.source.value)) return;
|
|
2323
|
+
const specifiers = node.specifiers || [];
|
|
2324
|
+
const named = specifiers.filter((s) => s.type === "ImportSpecifier" && s.importKind !== "type").map((s) => ({
|
|
2325
|
+
imported: s.imported.name ?? s.imported.value,
|
|
2326
|
+
local: s.local.name
|
|
2327
|
+
}));
|
|
2328
|
+
const defaultSpec = specifiers.find((s) => s.type === "ImportDefaultSpecifier");
|
|
2329
|
+
const nsSpec = specifiers.find((s) => s.type === "ImportNamespaceSpecifier");
|
|
2330
|
+
if (named.length === 0 && !nsSpec) return;
|
|
2331
|
+
result.push({
|
|
2332
|
+
kind: "static",
|
|
2333
|
+
source: node.source.value,
|
|
2334
|
+
start: node.start,
|
|
2335
|
+
end: node.end,
|
|
2336
|
+
named,
|
|
2337
|
+
defaultLocal: defaultSpec?.local.name,
|
|
2338
|
+
namespaceLocal: nsSpec?.local.name
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
if (node.type === "ExportNamedDeclaration" && node.source?.value && isRemoteImport(node.source.value)) {
|
|
2342
|
+
const specifiers = (node.specifiers || []).filter((s) => s.exportKind !== "type").map((s) => ({
|
|
2343
|
+
local: s.local.name ?? s.local.value,
|
|
2344
|
+
exported: s.exported.name ?? s.exported.value
|
|
2345
|
+
}));
|
|
2346
|
+
if (specifiers.length === 0) return;
|
|
2347
|
+
result.push({
|
|
2348
|
+
kind: "reexport",
|
|
2349
|
+
source: node.source.value,
|
|
2350
|
+
start: node.start,
|
|
2351
|
+
end: node.end,
|
|
2352
|
+
specifiers
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
if (node.type === "ExportAllDeclaration" && node.source?.value && isRemoteImport(node.source.value)) {
|
|
2356
|
+
this.skip();
|
|
2357
|
+
result.push({
|
|
2358
|
+
kind: "export-all",
|
|
2359
|
+
source: node.source.value,
|
|
2360
|
+
start: node.start,
|
|
2361
|
+
end: node.end
|
|
2362
|
+
});
|
|
2363
|
+
}
|
|
2364
|
+
if (node.type === "ImportExpression") {
|
|
2365
|
+
const source = node.source;
|
|
2366
|
+
if (source.type !== "Literal" && source.type !== "StringLiteral" && source.type !== "TemplateLiteral") return;
|
|
2367
|
+
const value = source.type === "TemplateLiteral" ? source.quasis?.length === 1 ? source.quasis[0].value?.cooked : void 0 : source.value;
|
|
2368
|
+
if (!value || !isRemoteImport(value)) return;
|
|
2369
|
+
result.push({
|
|
2370
|
+
kind: "dynamic",
|
|
2371
|
+
start: node.start,
|
|
2372
|
+
end: node.end,
|
|
2373
|
+
originalText: code.slice(node.start, node.end)
|
|
2374
|
+
});
|
|
2375
|
+
}
|
|
2376
|
+
} });
|
|
2377
|
+
return result;
|
|
2378
|
+
}
|
|
2379
|
+
async function collectFromEsLexer(code, isRemoteImport) {
|
|
2380
|
+
await es_module_lexer.init;
|
|
2381
|
+
let imports;
|
|
2382
|
+
try {
|
|
2383
|
+
[imports] = (0, es_module_lexer.parse)(code);
|
|
2384
|
+
} catch {
|
|
2385
|
+
return;
|
|
2386
|
+
}
|
|
2387
|
+
const result = [];
|
|
2388
|
+
for (const imp of imports) {
|
|
2389
|
+
if (imp.d === -2) continue;
|
|
2390
|
+
if (!imp.n || !isRemoteImport(imp.n)) continue;
|
|
2391
|
+
const stmtText = code.slice(imp.ss, imp.se);
|
|
2392
|
+
if (imp.d >= 0) {
|
|
2393
|
+
result.push({
|
|
2394
|
+
kind: "dynamic",
|
|
2395
|
+
start: imp.ss,
|
|
2396
|
+
end: imp.se,
|
|
2397
|
+
originalText: stmtText
|
|
2398
|
+
});
|
|
2399
|
+
continue;
|
|
2400
|
+
}
|
|
2401
|
+
if (/^\s*export\s*\*\s/.test(stmtText)) {
|
|
2402
|
+
result.push({
|
|
2403
|
+
kind: "export-all",
|
|
2404
|
+
source: imp.n,
|
|
2405
|
+
start: imp.ss,
|
|
2406
|
+
end: imp.se
|
|
2407
|
+
});
|
|
2408
|
+
continue;
|
|
2409
|
+
}
|
|
2410
|
+
if (/^\s*export\s/.test(stmtText)) {
|
|
2411
|
+
const braceMatch = stmtText.match(/\{([^}]*)\}/);
|
|
2412
|
+
if (!braceMatch) continue;
|
|
2413
|
+
const specs = braceMatch[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
2414
|
+
if (specs.length === 0) continue;
|
|
2415
|
+
const specifiers = specs.map((s) => {
|
|
2416
|
+
const asMatch = s.match(/^(\w+)\s+as\s+(\w+)$/);
|
|
2417
|
+
return {
|
|
2418
|
+
local: asMatch ? asMatch[1] : s,
|
|
2419
|
+
exported: asMatch ? asMatch[2] : s
|
|
2420
|
+
};
|
|
2421
|
+
});
|
|
2422
|
+
result.push({
|
|
2423
|
+
kind: "reexport",
|
|
2424
|
+
source: imp.n,
|
|
2425
|
+
start: imp.ss,
|
|
2426
|
+
end: imp.se,
|
|
2427
|
+
specifiers
|
|
2428
|
+
});
|
|
2429
|
+
continue;
|
|
2430
|
+
}
|
|
2431
|
+
const importMatch = stmtText.match(/^import\s+([\s\S]*?)\s+from\s/);
|
|
2432
|
+
if (!importMatch) continue;
|
|
2433
|
+
const specifiersPart = importMatch[1].trim();
|
|
2434
|
+
if (/^type\s/.test(specifiersPart)) continue;
|
|
2435
|
+
const nsMatch = specifiersPart.match(/^\*\s+as\s+(\w+)$/);
|
|
2436
|
+
if (nsMatch) {
|
|
2437
|
+
result.push({
|
|
2438
|
+
kind: "static",
|
|
2439
|
+
source: imp.n,
|
|
2440
|
+
start: imp.ss,
|
|
2441
|
+
end: imp.se,
|
|
2442
|
+
named: [],
|
|
2443
|
+
namespaceLocal: nsMatch[1]
|
|
2444
|
+
});
|
|
2445
|
+
continue;
|
|
2446
|
+
}
|
|
2447
|
+
const braceMatch = specifiersPart.match(/\{([^}]*)\}/);
|
|
2448
|
+
if (!braceMatch) continue;
|
|
2449
|
+
const namedSpecifiers = braceMatch[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0 && !s.startsWith("type "));
|
|
2450
|
+
if (namedSpecifiers.length === 0) continue;
|
|
2451
|
+
const defaultMatch = specifiersPart.match(/^(\w+)\s*,/);
|
|
2452
|
+
const named = namedSpecifiers.map((s) => {
|
|
2453
|
+
const asMatch = s.match(/^(\w+)\s+as\s+(\w+)$/);
|
|
2454
|
+
return {
|
|
2455
|
+
imported: asMatch ? asMatch[1] : s,
|
|
2456
|
+
local: asMatch ? asMatch[2] : s
|
|
2457
|
+
};
|
|
2458
|
+
});
|
|
2459
|
+
result.push({
|
|
2460
|
+
kind: "static",
|
|
2461
|
+
source: imp.n,
|
|
2462
|
+
start: imp.ss,
|
|
2463
|
+
end: imp.se,
|
|
2464
|
+
named,
|
|
2465
|
+
defaultLocal: defaultMatch?.[1]
|
|
2466
|
+
});
|
|
2467
|
+
}
|
|
2468
|
+
return result;
|
|
2469
|
+
}
|
|
2470
|
+
function pluginRemoteNamedExports(options) {
|
|
2471
|
+
const remoteNames = Object.keys(options.remotes);
|
|
2472
|
+
let rolldown;
|
|
2473
|
+
function isRemoteImport(source) {
|
|
2474
|
+
return remoteNames.some((name) => source === name || source.startsWith(name + "/"));
|
|
2475
|
+
}
|
|
2476
|
+
return {
|
|
2477
|
+
name: "module-federation-remote-named-exports",
|
|
2478
|
+
enforce: "pre",
|
|
2479
|
+
async transform(code, id) {
|
|
2480
|
+
rolldown ??= getIsRolldown(this);
|
|
2481
|
+
if (!rolldown) return;
|
|
2482
|
+
if (remoteNames.length === 0) return;
|
|
2483
|
+
if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
|
|
2484
|
+
if (!JS_EXTENSIONS_RE.test(id)) return;
|
|
2485
|
+
if (!remoteNames.some((name) => code.includes(name))) return;
|
|
2486
|
+
let imports;
|
|
2487
|
+
try {
|
|
2488
|
+
imports = await collectFromAST(this.parse(code), code, isRemoteImport);
|
|
2489
|
+
} catch {
|
|
2490
|
+
imports = await collectFromEsLexer(code, isRemoteImport);
|
|
2491
|
+
}
|
|
2492
|
+
if (!imports) return;
|
|
2493
|
+
return applyRewrites(code, imports, id);
|
|
2494
|
+
}
|
|
2495
|
+
};
|
|
2496
|
+
}
|
|
2497
|
+
//#endregion
|
|
2236
2498
|
//#region src/utils/PromiseStore.ts
|
|
2237
2499
|
/**
|
|
2238
2500
|
* example:
|
|
@@ -2339,7 +2601,7 @@ function proxySharedModule(options) {
|
|
|
2339
2601
|
},
|
|
2340
2602
|
configResolved(config) {
|
|
2341
2603
|
_config = config;
|
|
2342
|
-
const isRolldown =
|
|
2604
|
+
const isRolldown = getIsRolldown(this);
|
|
2343
2605
|
Object.keys(shared).forEach((key) => {
|
|
2344
2606
|
if (key.endsWith("/")) return;
|
|
2345
2607
|
if (isVinext && key === "react") {
|
|
@@ -2650,6 +2912,7 @@ function federation(mfUserOptions) {
|
|
|
2650
2912
|
virtualExposesId
|
|
2651
2913
|
}),
|
|
2652
2914
|
pluginProxyRemotes_default(options),
|
|
2915
|
+
pluginRemoteNamedExports(options),
|
|
2653
2916
|
...pluginModuleParseEnd_default((id) => {
|
|
2654
2917
|
return id.includes(getHostAutoInitImportId()) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath());
|
|
2655
2918
|
}, {
|
|
@@ -2685,19 +2948,19 @@ function federation(mfUserOptions) {
|
|
|
2685
2948
|
warnedAboutCodeSplitting = true;
|
|
2686
2949
|
mfWarn("Ignoring `build.rolldownOptions.output.codeSplitting = false` because module federation requires chunk splitting.");
|
|
2687
2950
|
};
|
|
2951
|
+
let warnedAboutManualChunks = false;
|
|
2688
2952
|
const applyManualChunks = (output) => {
|
|
2689
2953
|
ensureCodeSplitting(output);
|
|
2690
|
-
|
|
2954
|
+
if (output.manualChunks && !warnedAboutManualChunks) {
|
|
2955
|
+
warnedAboutManualChunks = true;
|
|
2956
|
+
mfWarn("Ignoring `build.rollupOptions.output.manualChunks` because it conflicts with module federation. Module federation transforms shared dependency imports with top-level await, and grouping these transformed modules into a single chunk creates circular async dependencies that cause the application to silently hang.");
|
|
2957
|
+
}
|
|
2691
2958
|
output.manualChunks = function(id) {
|
|
2692
2959
|
if (id.includes(runtimeInitId)) return "runtimeInit";
|
|
2693
2960
|
if (id.includes("__loadShare__")) {
|
|
2694
2961
|
const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
|
|
2695
2962
|
return match ? match[1] : "loadShare";
|
|
2696
2963
|
}
|
|
2697
|
-
if (typeof existingManualChunks === "function") return existingManualChunks.apply(this, arguments);
|
|
2698
|
-
if (existingManualChunks && typeof existingManualChunks === "object") {
|
|
2699
|
-
for (const [key, ids] of Object.entries(existingManualChunks)) if (Array.isArray(ids) && ids.some((v) => id.includes(v))) return key;
|
|
2700
|
-
}
|
|
2701
2964
|
};
|
|
2702
2965
|
};
|
|
2703
2966
|
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
@@ -2729,6 +2992,7 @@ function federation(mfUserOptions) {
|
|
|
2729
2992
|
* @see https://rollupjs.org/plugin-development/#synthetic-named-exports
|
|
2730
2993
|
*/
|
|
2731
2994
|
code = code.replace("export default exportModule", "export const __moduleExports = exportModule;\nexport default exportModule.__esModule ? exportModule.default : exportModule");
|
|
2995
|
+
if (getIsRolldown(this)) return { code };
|
|
2732
2996
|
return {
|
|
2733
2997
|
code,
|
|
2734
2998
|
syntheticNamedExports: "__moduleExports"
|
package/lib/index.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import { normalizeOptions } from "@module-federation/sdk";
|
|
|
11
11
|
import { consumeTypesAPI, generateTypesAPI, isTSProject, normalizeConsumeTypesOptions, normalizeDtsOptions, normalizeGenerateTypesOptions } from "@module-federation/dts-plugin";
|
|
12
12
|
import { rpc } from "@module-federation/dts-plugin/core";
|
|
13
13
|
import { fileURLToPath } from "url";
|
|
14
|
+
import { init, parse as parse$1 } from "es-module-lexer";
|
|
14
15
|
//#region \0rolldown/runtime.js
|
|
15
16
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
16
17
|
//#endregion
|
|
@@ -129,7 +130,7 @@ function removePathFromNpmPackage(packageString) {
|
|
|
129
130
|
return match ? match[0] : packageString;
|
|
130
131
|
}
|
|
131
132
|
/**
|
|
132
|
-
* Detect whether the current
|
|
133
|
+
* Detect whether the current runtime is Vite 8+ (with rolldown internally) by checking
|
|
133
134
|
* for `meta.rolldownVersion` on the plugin hook context.
|
|
134
135
|
*/
|
|
135
136
|
function getIsRolldown(ctx) {
|
|
@@ -358,15 +359,17 @@ function checkAliasConflicts(options) {
|
|
|
358
359
|
};
|
|
359
360
|
}
|
|
360
361
|
//#endregion
|
|
361
|
-
//#region src/
|
|
362
|
-
/**
|
|
363
|
-
* Solve the problem that dev mode dependency prebunding does not support top-level await syntax
|
|
364
|
-
*/
|
|
362
|
+
//#region src/utils/loadWalk.ts
|
|
365
363
|
let walkPromise = null;
|
|
366
364
|
function loadWalk() {
|
|
367
365
|
walkPromise ||= import("estree-walker").then(({ walk }) => walk);
|
|
368
366
|
return walkPromise;
|
|
369
367
|
}
|
|
368
|
+
//#endregion
|
|
369
|
+
//#region src/plugins/pluginDevProxyModuleTopLevelAwait.ts
|
|
370
|
+
/**
|
|
371
|
+
* Solve the problem that dev mode dependency prebunding does not support top-level await syntax
|
|
372
|
+
*/
|
|
370
373
|
function PluginDevProxyModuleTopLevelAwait() {
|
|
371
374
|
const filterFunction = createFilter();
|
|
372
375
|
const processedFlag = "/* already-processed-by-dev-proxy-module-top-level-await */";
|
|
@@ -1174,7 +1177,7 @@ function generateRemotes(id, command, isRolldown) {
|
|
|
1174
1177
|
const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
|
|
1175
1178
|
const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
1176
1179
|
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
1177
|
-
const exportLine = command === "serve" && useESM ? "export default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
|
|
1180
|
+
const exportLine = command === "serve" && useESM ? "export const __moduleExports = exportModule;\nexport default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
|
|
1178
1181
|
return `
|
|
1179
1182
|
${importLine}
|
|
1180
1183
|
const res = initPromise.then(runtime => runtime.loadRemote(${JSON.stringify(id)}))
|
|
@@ -2210,6 +2213,265 @@ function pluginProxyRemotes_default(options) {
|
|
|
2210
2213
|
};
|
|
2211
2214
|
}
|
|
2212
2215
|
//#endregion
|
|
2216
|
+
//#region src/plugins/pluginRemoteNamedExports.ts
|
|
2217
|
+
/**
|
|
2218
|
+
* Transforms consumer-side imports of remote modules so that named exports
|
|
2219
|
+
* are accessible even when the bundler does not support syntheticNamedExports
|
|
2220
|
+
* (Rolldown / Vite 8+).
|
|
2221
|
+
*
|
|
2222
|
+
* The remote proxy module exports:
|
|
2223
|
+
* export const __moduleExports = exportModule; // full namespace
|
|
2224
|
+
* export default exportModule.default ?? exportModule; // unwrapped default
|
|
2225
|
+
*
|
|
2226
|
+
* This plugin rewrites consumer code:
|
|
2227
|
+
* import { foo } from "remote/xxx"
|
|
2228
|
+
* → import { __moduleExports as __mf_ns_0 } from "remote/xxx"; const { foo } = __mf_ns_0;
|
|
2229
|
+
*
|
|
2230
|
+
* import("remote/xxx")
|
|
2231
|
+
* → import("remote/xxx").then(…) // spreads __moduleExports into namespace
|
|
2232
|
+
*
|
|
2233
|
+
* NOTE: `export * from "remote/xxx"` is not supported — Rolldown cannot
|
|
2234
|
+
* statically resolve the set of exported names from a federated remote at
|
|
2235
|
+
* build time. Use explicit named re-exports instead.
|
|
2236
|
+
*/
|
|
2237
|
+
const JS_EXTENSIONS_RE = /\.(?:[mc]?[jt]sx?|vue|svelte)(?:\?|$)/;
|
|
2238
|
+
function wrapDynamicImport(original) {
|
|
2239
|
+
return `${original}.then(function(__mf_m__) {\n if (!__mf_m__ || !__mf_m__.__moduleExports) return __mf_m__;\n var __mf_ns__ = Object.create(null);\n Object.defineProperty(__mf_ns__, Symbol.toStringTag, { value: "Module" });\n var __mf_e__ = __mf_m__.__moduleExports;\n Object.keys(__mf_e__).forEach(function(k) { if (k !== "__esModule") __mf_ns__[k] = __mf_e__[k] });\n if ("default" in __mf_m__) __mf_ns__.default = __mf_m__.default;\n return __mf_ns__;\n})`;
|
|
2240
|
+
}
|
|
2241
|
+
function applyRewrites(code, imports, id) {
|
|
2242
|
+
if (imports.length === 0) return;
|
|
2243
|
+
const ms = new MagicString(code);
|
|
2244
|
+
let changed = false;
|
|
2245
|
+
let counter = 0;
|
|
2246
|
+
for (const imp of imports) switch (imp.kind) {
|
|
2247
|
+
case "static": {
|
|
2248
|
+
const src = JSON.stringify(imp.source);
|
|
2249
|
+
if (imp.namespaceLocal && !imp.defaultLocal && imp.named.length === 0) ms.overwrite(imp.start, imp.end, `import { __moduleExports as ${imp.namespaceLocal} } from ${src};`);
|
|
2250
|
+
else {
|
|
2251
|
+
const nsId = `__mf_ns_${counter++}`;
|
|
2252
|
+
const importParts = [];
|
|
2253
|
+
if (imp.defaultLocal) importParts.push(`default as ${imp.defaultLocal}`);
|
|
2254
|
+
importParts.push(`__moduleExports as ${nsId}`);
|
|
2255
|
+
const destructParts = imp.named.map((s) => s.imported === s.local ? s.local : `${s.imported}: ${s.local}`);
|
|
2256
|
+
let rewrite = `import { ${importParts.join(", ")} } from ${src};`;
|
|
2257
|
+
if (destructParts.length > 0) rewrite += `\nconst { ${destructParts.join(", ")} } = ${nsId};`;
|
|
2258
|
+
ms.overwrite(imp.start, imp.end, rewrite);
|
|
2259
|
+
}
|
|
2260
|
+
changed = true;
|
|
2261
|
+
break;
|
|
2262
|
+
}
|
|
2263
|
+
case "reexport": {
|
|
2264
|
+
const src = JSON.stringify(imp.source);
|
|
2265
|
+
const nsId = `__mf_ns_${counter++}`;
|
|
2266
|
+
const vars = imp.specifiers.map((s) => {
|
|
2267
|
+
const tmp = `__mf_re_${counter++}`;
|
|
2268
|
+
return {
|
|
2269
|
+
...s,
|
|
2270
|
+
tmp
|
|
2271
|
+
};
|
|
2272
|
+
});
|
|
2273
|
+
const importLine = `import { __moduleExports as ${nsId} } from ${src};`;
|
|
2274
|
+
const varLines = vars.map((v) => `const ${v.tmp} = ${nsId}[${JSON.stringify(v.local)}];`).join("\n");
|
|
2275
|
+
const exportLine = `export { ${vars.map((v) => `${v.tmp} as ${v.exported}`).join(", ")} };`;
|
|
2276
|
+
ms.overwrite(imp.start, imp.end, `${importLine}\n${varLines}\n${exportLine}`);
|
|
2277
|
+
changed = true;
|
|
2278
|
+
break;
|
|
2279
|
+
}
|
|
2280
|
+
case "export-all":
|
|
2281
|
+
console.warn(`[module-federation] "export * from '${imp.source}'" is not supported with Rolldown — use explicit named re-exports instead. (${id})`);
|
|
2282
|
+
break;
|
|
2283
|
+
case "dynamic":
|
|
2284
|
+
ms.overwrite(imp.start, imp.end, wrapDynamicImport(imp.originalText));
|
|
2285
|
+
changed = true;
|
|
2286
|
+
break;
|
|
2287
|
+
}
|
|
2288
|
+
if (!changed) return;
|
|
2289
|
+
return {
|
|
2290
|
+
code: ms.toString(),
|
|
2291
|
+
map: ms.generateMap({ hires: true })
|
|
2292
|
+
};
|
|
2293
|
+
}
|
|
2294
|
+
async function collectFromAST(ast, code, isRemoteImport) {
|
|
2295
|
+
const walk = await loadWalk();
|
|
2296
|
+
const result = [];
|
|
2297
|
+
walk(ast, { enter(node) {
|
|
2298
|
+
if (node.type === "ImportDeclaration" && node.source?.value) {
|
|
2299
|
+
if (!isRemoteImport(node.source.value)) return;
|
|
2300
|
+
const specifiers = node.specifiers || [];
|
|
2301
|
+
const named = specifiers.filter((s) => s.type === "ImportSpecifier" && s.importKind !== "type").map((s) => ({
|
|
2302
|
+
imported: s.imported.name ?? s.imported.value,
|
|
2303
|
+
local: s.local.name
|
|
2304
|
+
}));
|
|
2305
|
+
const defaultSpec = specifiers.find((s) => s.type === "ImportDefaultSpecifier");
|
|
2306
|
+
const nsSpec = specifiers.find((s) => s.type === "ImportNamespaceSpecifier");
|
|
2307
|
+
if (named.length === 0 && !nsSpec) return;
|
|
2308
|
+
result.push({
|
|
2309
|
+
kind: "static",
|
|
2310
|
+
source: node.source.value,
|
|
2311
|
+
start: node.start,
|
|
2312
|
+
end: node.end,
|
|
2313
|
+
named,
|
|
2314
|
+
defaultLocal: defaultSpec?.local.name,
|
|
2315
|
+
namespaceLocal: nsSpec?.local.name
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
if (node.type === "ExportNamedDeclaration" && node.source?.value && isRemoteImport(node.source.value)) {
|
|
2319
|
+
const specifiers = (node.specifiers || []).filter((s) => s.exportKind !== "type").map((s) => ({
|
|
2320
|
+
local: s.local.name ?? s.local.value,
|
|
2321
|
+
exported: s.exported.name ?? s.exported.value
|
|
2322
|
+
}));
|
|
2323
|
+
if (specifiers.length === 0) return;
|
|
2324
|
+
result.push({
|
|
2325
|
+
kind: "reexport",
|
|
2326
|
+
source: node.source.value,
|
|
2327
|
+
start: node.start,
|
|
2328
|
+
end: node.end,
|
|
2329
|
+
specifiers
|
|
2330
|
+
});
|
|
2331
|
+
}
|
|
2332
|
+
if (node.type === "ExportAllDeclaration" && node.source?.value && isRemoteImport(node.source.value)) {
|
|
2333
|
+
this.skip();
|
|
2334
|
+
result.push({
|
|
2335
|
+
kind: "export-all",
|
|
2336
|
+
source: node.source.value,
|
|
2337
|
+
start: node.start,
|
|
2338
|
+
end: node.end
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
if (node.type === "ImportExpression") {
|
|
2342
|
+
const source = node.source;
|
|
2343
|
+
if (source.type !== "Literal" && source.type !== "StringLiteral" && source.type !== "TemplateLiteral") return;
|
|
2344
|
+
const value = source.type === "TemplateLiteral" ? source.quasis?.length === 1 ? source.quasis[0].value?.cooked : void 0 : source.value;
|
|
2345
|
+
if (!value || !isRemoteImport(value)) return;
|
|
2346
|
+
result.push({
|
|
2347
|
+
kind: "dynamic",
|
|
2348
|
+
start: node.start,
|
|
2349
|
+
end: node.end,
|
|
2350
|
+
originalText: code.slice(node.start, node.end)
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2353
|
+
} });
|
|
2354
|
+
return result;
|
|
2355
|
+
}
|
|
2356
|
+
async function collectFromEsLexer(code, isRemoteImport) {
|
|
2357
|
+
await init;
|
|
2358
|
+
let imports;
|
|
2359
|
+
try {
|
|
2360
|
+
[imports] = parse$1(code);
|
|
2361
|
+
} catch {
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
const result = [];
|
|
2365
|
+
for (const imp of imports) {
|
|
2366
|
+
if (imp.d === -2) continue;
|
|
2367
|
+
if (!imp.n || !isRemoteImport(imp.n)) continue;
|
|
2368
|
+
const stmtText = code.slice(imp.ss, imp.se);
|
|
2369
|
+
if (imp.d >= 0) {
|
|
2370
|
+
result.push({
|
|
2371
|
+
kind: "dynamic",
|
|
2372
|
+
start: imp.ss,
|
|
2373
|
+
end: imp.se,
|
|
2374
|
+
originalText: stmtText
|
|
2375
|
+
});
|
|
2376
|
+
continue;
|
|
2377
|
+
}
|
|
2378
|
+
if (/^\s*export\s*\*\s/.test(stmtText)) {
|
|
2379
|
+
result.push({
|
|
2380
|
+
kind: "export-all",
|
|
2381
|
+
source: imp.n,
|
|
2382
|
+
start: imp.ss,
|
|
2383
|
+
end: imp.se
|
|
2384
|
+
});
|
|
2385
|
+
continue;
|
|
2386
|
+
}
|
|
2387
|
+
if (/^\s*export\s/.test(stmtText)) {
|
|
2388
|
+
const braceMatch = stmtText.match(/\{([^}]*)\}/);
|
|
2389
|
+
if (!braceMatch) continue;
|
|
2390
|
+
const specs = braceMatch[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
2391
|
+
if (specs.length === 0) continue;
|
|
2392
|
+
const specifiers = specs.map((s) => {
|
|
2393
|
+
const asMatch = s.match(/^(\w+)\s+as\s+(\w+)$/);
|
|
2394
|
+
return {
|
|
2395
|
+
local: asMatch ? asMatch[1] : s,
|
|
2396
|
+
exported: asMatch ? asMatch[2] : s
|
|
2397
|
+
};
|
|
2398
|
+
});
|
|
2399
|
+
result.push({
|
|
2400
|
+
kind: "reexport",
|
|
2401
|
+
source: imp.n,
|
|
2402
|
+
start: imp.ss,
|
|
2403
|
+
end: imp.se,
|
|
2404
|
+
specifiers
|
|
2405
|
+
});
|
|
2406
|
+
continue;
|
|
2407
|
+
}
|
|
2408
|
+
const importMatch = stmtText.match(/^import\s+([\s\S]*?)\s+from\s/);
|
|
2409
|
+
if (!importMatch) continue;
|
|
2410
|
+
const specifiersPart = importMatch[1].trim();
|
|
2411
|
+
if (/^type\s/.test(specifiersPart)) continue;
|
|
2412
|
+
const nsMatch = specifiersPart.match(/^\*\s+as\s+(\w+)$/);
|
|
2413
|
+
if (nsMatch) {
|
|
2414
|
+
result.push({
|
|
2415
|
+
kind: "static",
|
|
2416
|
+
source: imp.n,
|
|
2417
|
+
start: imp.ss,
|
|
2418
|
+
end: imp.se,
|
|
2419
|
+
named: [],
|
|
2420
|
+
namespaceLocal: nsMatch[1]
|
|
2421
|
+
});
|
|
2422
|
+
continue;
|
|
2423
|
+
}
|
|
2424
|
+
const braceMatch = specifiersPart.match(/\{([^}]*)\}/);
|
|
2425
|
+
if (!braceMatch) continue;
|
|
2426
|
+
const namedSpecifiers = braceMatch[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0 && !s.startsWith("type "));
|
|
2427
|
+
if (namedSpecifiers.length === 0) continue;
|
|
2428
|
+
const defaultMatch = specifiersPart.match(/^(\w+)\s*,/);
|
|
2429
|
+
const named = namedSpecifiers.map((s) => {
|
|
2430
|
+
const asMatch = s.match(/^(\w+)\s+as\s+(\w+)$/);
|
|
2431
|
+
return {
|
|
2432
|
+
imported: asMatch ? asMatch[1] : s,
|
|
2433
|
+
local: asMatch ? asMatch[2] : s
|
|
2434
|
+
};
|
|
2435
|
+
});
|
|
2436
|
+
result.push({
|
|
2437
|
+
kind: "static",
|
|
2438
|
+
source: imp.n,
|
|
2439
|
+
start: imp.ss,
|
|
2440
|
+
end: imp.se,
|
|
2441
|
+
named,
|
|
2442
|
+
defaultLocal: defaultMatch?.[1]
|
|
2443
|
+
});
|
|
2444
|
+
}
|
|
2445
|
+
return result;
|
|
2446
|
+
}
|
|
2447
|
+
function pluginRemoteNamedExports(options) {
|
|
2448
|
+
const remoteNames = Object.keys(options.remotes);
|
|
2449
|
+
let rolldown;
|
|
2450
|
+
function isRemoteImport(source) {
|
|
2451
|
+
return remoteNames.some((name) => source === name || source.startsWith(name + "/"));
|
|
2452
|
+
}
|
|
2453
|
+
return {
|
|
2454
|
+
name: "module-federation-remote-named-exports",
|
|
2455
|
+
enforce: "pre",
|
|
2456
|
+
async transform(code, id) {
|
|
2457
|
+
rolldown ??= getIsRolldown(this);
|
|
2458
|
+
if (!rolldown) return;
|
|
2459
|
+
if (remoteNames.length === 0) return;
|
|
2460
|
+
if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
|
|
2461
|
+
if (!JS_EXTENSIONS_RE.test(id)) return;
|
|
2462
|
+
if (!remoteNames.some((name) => code.includes(name))) return;
|
|
2463
|
+
let imports;
|
|
2464
|
+
try {
|
|
2465
|
+
imports = await collectFromAST(this.parse(code), code, isRemoteImport);
|
|
2466
|
+
} catch {
|
|
2467
|
+
imports = await collectFromEsLexer(code, isRemoteImport);
|
|
2468
|
+
}
|
|
2469
|
+
if (!imports) return;
|
|
2470
|
+
return applyRewrites(code, imports, id);
|
|
2471
|
+
}
|
|
2472
|
+
};
|
|
2473
|
+
}
|
|
2474
|
+
//#endregion
|
|
2213
2475
|
//#region src/utils/PromiseStore.ts
|
|
2214
2476
|
/**
|
|
2215
2477
|
* example:
|
|
@@ -2316,7 +2578,7 @@ function proxySharedModule(options) {
|
|
|
2316
2578
|
},
|
|
2317
2579
|
configResolved(config) {
|
|
2318
2580
|
_config = config;
|
|
2319
|
-
const isRolldown =
|
|
2581
|
+
const isRolldown = getIsRolldown(this);
|
|
2320
2582
|
Object.keys(shared).forEach((key) => {
|
|
2321
2583
|
if (key.endsWith("/")) return;
|
|
2322
2584
|
if (isVinext && key === "react") {
|
|
@@ -2627,6 +2889,7 @@ function federation(mfUserOptions) {
|
|
|
2627
2889
|
virtualExposesId
|
|
2628
2890
|
}),
|
|
2629
2891
|
pluginProxyRemotes_default(options),
|
|
2892
|
+
pluginRemoteNamedExports(options),
|
|
2630
2893
|
...pluginModuleParseEnd_default((id) => {
|
|
2631
2894
|
return id.includes(getHostAutoInitImportId()) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath());
|
|
2632
2895
|
}, {
|
|
@@ -2662,19 +2925,19 @@ function federation(mfUserOptions) {
|
|
|
2662
2925
|
warnedAboutCodeSplitting = true;
|
|
2663
2926
|
mfWarn("Ignoring `build.rolldownOptions.output.codeSplitting = false` because module federation requires chunk splitting.");
|
|
2664
2927
|
};
|
|
2928
|
+
let warnedAboutManualChunks = false;
|
|
2665
2929
|
const applyManualChunks = (output) => {
|
|
2666
2930
|
ensureCodeSplitting(output);
|
|
2667
|
-
|
|
2931
|
+
if (output.manualChunks && !warnedAboutManualChunks) {
|
|
2932
|
+
warnedAboutManualChunks = true;
|
|
2933
|
+
mfWarn("Ignoring `build.rollupOptions.output.manualChunks` because it conflicts with module federation. Module federation transforms shared dependency imports with top-level await, and grouping these transformed modules into a single chunk creates circular async dependencies that cause the application to silently hang.");
|
|
2934
|
+
}
|
|
2668
2935
|
output.manualChunks = function(id) {
|
|
2669
2936
|
if (id.includes(runtimeInitId)) return "runtimeInit";
|
|
2670
2937
|
if (id.includes("__loadShare__")) {
|
|
2671
2938
|
const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
|
|
2672
2939
|
return match ? match[1] : "loadShare";
|
|
2673
2940
|
}
|
|
2674
|
-
if (typeof existingManualChunks === "function") return existingManualChunks.apply(this, arguments);
|
|
2675
|
-
if (existingManualChunks && typeof existingManualChunks === "object") {
|
|
2676
|
-
for (const [key, ids] of Object.entries(existingManualChunks)) if (Array.isArray(ids) && ids.some((v) => id.includes(v))) return key;
|
|
2677
|
-
}
|
|
2678
2941
|
};
|
|
2679
2942
|
};
|
|
2680
2943
|
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
@@ -2706,6 +2969,7 @@ function federation(mfUserOptions) {
|
|
|
2706
2969
|
* @see https://rollupjs.org/plugin-development/#synthetic-named-exports
|
|
2707
2970
|
*/
|
|
2708
2971
|
code = code.replace("export default exportModule", "export const __moduleExports = exportModule;\nexport default exportModule.__esModule ? exportModule.default : exportModule");
|
|
2972
|
+
if (getIsRolldown(this)) return { code };
|
|
2709
2973
|
return {
|
|
2710
2974
|
code,
|
|
2711
2975
|
syntheticNamedExports: "__moduleExports"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/vite",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.5",
|
|
4
4
|
"description": "Vite plugin for Module Federation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.cjs",
|
|
@@ -30,10 +30,13 @@
|
|
|
30
30
|
"dev-rv": "pnpm clean && pnpm -filter 'examples-rust-vite*' run dev",
|
|
31
31
|
"preview-rv": "pnpm clean && pnpm -filter 'examples-rust-vite*' run preview",
|
|
32
32
|
"dev-vv": "pnpm clean && pnpm -filter 'examples-vite-vite*' run dev",
|
|
33
|
-
"preview-vv": "pnpm clean && pnpm -filter 'examples-vite-vite*' --parallel run preview",
|
|
33
|
+
"preview-vv": "pnpm clean && pnpm run build:shared-lib && pnpm -filter 'examples-vite-vite*' --parallel run preview",
|
|
34
|
+
"preview-vv:ci": "pnpm run build:shared-lib && pnpm -filter 'examples-vite-vite*' --parallel run preview",
|
|
35
|
+
"build:shared-lib": "pnpm --filter @vite-vite/shared-lib run build",
|
|
36
|
+
"multi-example:ci": "pnpm -filter 'multi-example-*' --parallel run start",
|
|
34
37
|
"mixed-vv:1": "pnpm clean && pnpm -filter 'examples-vite-vite*' run mixed:1",
|
|
35
38
|
"mixed-vv:2": "pnpm clean && pnpm -filter 'examples-vite-vite*' run mixed:2",
|
|
36
|
-
"multi-example": "pnpm clean && pnpm --filter
|
|
39
|
+
"multi-example": "pnpm clean && pnpm --filter 'multi-example-*' --parallel run start",
|
|
37
40
|
"test": "vitest run --dir src",
|
|
38
41
|
"test:integration": "vitest run integration",
|
|
39
42
|
"e2e": "playwright test",
|
|
@@ -72,7 +75,7 @@
|
|
|
72
75
|
"@module-federation/sdk": "2.2.3",
|
|
73
76
|
"@rollup/pluginutils": "^5.3.0",
|
|
74
77
|
"defu": "^6.1.4",
|
|
75
|
-
"es-module-lexer": "^
|
|
78
|
+
"es-module-lexer": "^2.0.0",
|
|
76
79
|
"estree-walker": "^3.0.3",
|
|
77
80
|
"magic-string": "^0.30.21",
|
|
78
81
|
"pathe": "^2.0.3"
|