@module-federation/vite 1.14.2 → 1.14.4
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/index.cjs +235 -87
- package/lib/index.mjs +235 -87
- package/package.json +4 -4
package/lib/index.cjs
CHANGED
|
@@ -152,6 +152,56 @@ function removePathFromNpmPackage(packageString) {
|
|
|
152
152
|
const match = packageString.match(/^(?:@[^/]+\/)?[^/]+/);
|
|
153
153
|
return match ? match[0] : packageString;
|
|
154
154
|
}
|
|
155
|
+
function getInstalledPackageJson(pkg, opts) {
|
|
156
|
+
const cwd = opts?.cwd || getPackageDetectionCwd();
|
|
157
|
+
const packageName = opts?.packageName || removePathFromNpmPackage(pkg);
|
|
158
|
+
try {
|
|
159
|
+
const projectRequire = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(cwd, "package.json")}`));
|
|
160
|
+
let resolvedPath;
|
|
161
|
+
try {
|
|
162
|
+
resolvedPath = projectRequire.resolve(pkg);
|
|
163
|
+
} catch {
|
|
164
|
+
resolvedPath = projectRequire.resolve(packageName);
|
|
165
|
+
}
|
|
166
|
+
let currentDir = pathe.default.dirname(resolvedPath);
|
|
167
|
+
const rootDir = pathe.default.parse(currentDir).root;
|
|
168
|
+
while (true) {
|
|
169
|
+
const packageJsonPath = pathe.default.join(currentDir, "package.json");
|
|
170
|
+
if ((0, fs.existsSync)(packageJsonPath)) {
|
|
171
|
+
const packageJsonContent = (0, fs.readFileSync)(packageJsonPath, "utf-8");
|
|
172
|
+
try {
|
|
173
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
174
|
+
if (packageJson.name === packageName) return {
|
|
175
|
+
path: packageJsonPath,
|
|
176
|
+
dir: currentDir,
|
|
177
|
+
packageJson
|
|
178
|
+
};
|
|
179
|
+
} catch (error) {
|
|
180
|
+
if (!(error instanceof SyntaxError)) throw error;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (currentDir === rootDir) break;
|
|
184
|
+
currentDir = pathe.default.dirname(currentDir);
|
|
185
|
+
}
|
|
186
|
+
} catch {
|
|
187
|
+
let currentDir = cwd;
|
|
188
|
+
const rootDir = pathe.default.parse(currentDir).root;
|
|
189
|
+
while (true) {
|
|
190
|
+
const packageJsonPath = pathe.default.join(currentDir, "node_modules", packageName, "package.json");
|
|
191
|
+
if ((0, fs.existsSync)(packageJsonPath)) try {
|
|
192
|
+
return {
|
|
193
|
+
path: packageJsonPath,
|
|
194
|
+
dir: pathe.default.dirname(packageJsonPath),
|
|
195
|
+
packageJson: JSON.parse((0, fs.readFileSync)(packageJsonPath, "utf-8"))
|
|
196
|
+
};
|
|
197
|
+
} catch {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (currentDir === rootDir) break;
|
|
201
|
+
currentDir = pathe.default.dirname(currentDir);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
155
205
|
/**
|
|
156
206
|
* Detect whether the current runtime is Vite 8+ by checking for a Vite version flag
|
|
157
207
|
* on the plugin hook context, with Rolldown metadata kept as a compatibility fallback.
|
|
@@ -956,6 +1006,12 @@ function inferVersionFromRequiredVersion(requiredVersion) {
|
|
|
956
1006
|
if (!requiredVersion) return void 0;
|
|
957
1007
|
return requiredVersion.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0];
|
|
958
1008
|
}
|
|
1009
|
+
function getLitExportSubpathShares(sharedName) {
|
|
1010
|
+
if (sharedName !== "lit") return [];
|
|
1011
|
+
const exportsField = getInstalledPackageJson(sharedName, { packageName: sharedName })?.packageJson.exports;
|
|
1012
|
+
if (!exportsField || typeof exportsField === "string") return [];
|
|
1013
|
+
return Object.keys(exportsField).filter((key) => key.startsWith("./") && key !== "." && !key.includes("*")).map((key) => `${sharedName}/${key.slice(2)}`);
|
|
1014
|
+
}
|
|
959
1015
|
function normalizeShareItem(key, shareItem) {
|
|
960
1016
|
let version;
|
|
961
1017
|
if (!(typeof shareItem === "object" && shareItem.import === false)) try {
|
|
@@ -1000,14 +1056,21 @@ function normalizeShareItem(key, shareItem) {
|
|
|
1000
1056
|
function normalizeShared(shared) {
|
|
1001
1057
|
if (!shared) return {};
|
|
1002
1058
|
const result = {};
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
result[key] = normalizeShareItem(key,
|
|
1059
|
+
const sourceEntries = [];
|
|
1060
|
+
if (Array.isArray(shared)) shared.forEach((key) => {
|
|
1061
|
+
result[key] = normalizeShareItem(key, key);
|
|
1062
|
+
sourceEntries.push([key, key]);
|
|
1063
|
+
});
|
|
1064
|
+
else if (typeof shared === "object") Object.keys(shared).forEach((key) => {
|
|
1065
|
+
const value = shared[key];
|
|
1066
|
+
result[key] = normalizeShareItem(key, value);
|
|
1067
|
+
sourceEntries.push([key, value]);
|
|
1068
|
+
});
|
|
1069
|
+
sourceEntries.forEach(([key, value]) => {
|
|
1070
|
+
for (const subpathShare of getLitExportSubpathShares(key)) {
|
|
1071
|
+
if (result[subpathShare]) continue;
|
|
1072
|
+
result[subpathShare] = normalizeShareItem(subpathShare, value);
|
|
1073
|
+
}
|
|
1011
1074
|
});
|
|
1012
1075
|
return result;
|
|
1013
1076
|
}
|
|
@@ -1239,6 +1302,16 @@ function generateExposes(options) {
|
|
|
1239
1302
|
return `
|
|
1240
1303
|
const cssAssetMap = ${JSON.stringify(options.bundleAllCSS ? EXPOSES_CSS_MAP_PLACEHOLDER : {})};
|
|
1241
1304
|
const injectedCssHrefs = new Set();
|
|
1305
|
+
let exposeLoadQueue = Promise.resolve();
|
|
1306
|
+
|
|
1307
|
+
async function importExposedModule(loader) {
|
|
1308
|
+
const currentLoad = exposeLoadQueue.then(loader, loader);
|
|
1309
|
+
exposeLoadQueue = currentLoad.then(
|
|
1310
|
+
() => undefined,
|
|
1311
|
+
() => undefined
|
|
1312
|
+
);
|
|
1313
|
+
return currentLoad;
|
|
1314
|
+
}
|
|
1242
1315
|
|
|
1243
1316
|
async function injectCssAssets(exposeKey) {
|
|
1244
1317
|
if (typeof document === "undefined") {
|
|
@@ -1283,7 +1356,9 @@ function generateExposes(options) {
|
|
|
1283
1356
|
return `
|
|
1284
1357
|
${JSON.stringify(key)}: async () => {
|
|
1285
1358
|
await injectCssAssets(${JSON.stringify(key)})
|
|
1286
|
-
const importModule = await
|
|
1359
|
+
const importModule = await importExposedModule(
|
|
1360
|
+
() => import(${JSON.stringify(options.exposes[key].import)})
|
|
1361
|
+
)
|
|
1287
1362
|
const exportModule = {}
|
|
1288
1363
|
Object.assign(exportModule, importModule)
|
|
1289
1364
|
Object.defineProperty(exportModule, "__esModule", {
|
|
@@ -1455,52 +1530,6 @@ function resolvePackageEntryFromProjectRoot(pkg) {
|
|
|
1455
1530
|
return;
|
|
1456
1531
|
}
|
|
1457
1532
|
}
|
|
1458
|
-
function getInstalledPackageJsonPath(pkg) {
|
|
1459
|
-
try {
|
|
1460
|
-
const packageName = removePathFromNpmPackage(pkg);
|
|
1461
|
-
const projectRequire = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`));
|
|
1462
|
-
let resolvedPath;
|
|
1463
|
-
try {
|
|
1464
|
-
resolvedPath = projectRequire.resolve(pkg);
|
|
1465
|
-
} catch {
|
|
1466
|
-
resolvedPath = projectRequire.resolve(packageName);
|
|
1467
|
-
}
|
|
1468
|
-
let currentDir = pathe.default.dirname(resolvedPath);
|
|
1469
|
-
const rootDir = pathe.default.parse(currentDir).root;
|
|
1470
|
-
while (currentDir !== rootDir) {
|
|
1471
|
-
const packageJsonPath = pathe.default.join(currentDir, "package.json");
|
|
1472
|
-
if ((0, fs.existsSync)(packageJsonPath)) {
|
|
1473
|
-
const packageJsonContent = (0, fs.readFileSync)(packageJsonPath, "utf-8");
|
|
1474
|
-
try {
|
|
1475
|
-
if (JSON.parse(packageJsonContent).name === packageName) return packageJsonPath;
|
|
1476
|
-
} catch (error) {
|
|
1477
|
-
if (!(error instanceof SyntaxError)) throw error;
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
currentDir = pathe.default.dirname(currentDir);
|
|
1481
|
-
}
|
|
1482
|
-
const rootPackageJsonPath = pathe.default.join(rootDir, "package.json");
|
|
1483
|
-
if ((0, fs.existsSync)(rootPackageJsonPath)) {
|
|
1484
|
-
const rootPackageJsonContent = (0, fs.readFileSync)(rootPackageJsonPath, "utf-8");
|
|
1485
|
-
try {
|
|
1486
|
-
if (JSON.parse(rootPackageJsonContent).name === packageName) return rootPackageJsonPath;
|
|
1487
|
-
} catch (error) {
|
|
1488
|
-
if (!(error instanceof SyntaxError)) throw error;
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
} catch {
|
|
1492
|
-
const packageName = removePathFromNpmPackage(pkg);
|
|
1493
|
-
let currentDir = getPackageDetectionCwd();
|
|
1494
|
-
const rootDir = pathe.default.parse(currentDir).root;
|
|
1495
|
-
while (currentDir !== rootDir) {
|
|
1496
|
-
const packageJsonPath = pathe.default.join(currentDir, "node_modules", packageName, "package.json");
|
|
1497
|
-
if ((0, fs.existsSync)(packageJsonPath)) return packageJsonPath;
|
|
1498
|
-
currentDir = pathe.default.dirname(currentDir);
|
|
1499
|
-
}
|
|
1500
|
-
const rootPackageJsonPath = pathe.default.join(rootDir, "node_modules", packageName, "package.json");
|
|
1501
|
-
return (0, fs.existsSync)(rootPackageJsonPath) ? rootPackageJsonPath : void 0;
|
|
1502
|
-
}
|
|
1503
|
-
}
|
|
1504
1533
|
function resolveImportTarget(exportsField) {
|
|
1505
1534
|
if (typeof exportsField === "string") return exportsField;
|
|
1506
1535
|
if (!exportsField || typeof exportsField !== "object") return void 0;
|
|
@@ -1521,14 +1550,14 @@ function resolveImportTarget(exportsField) {
|
|
|
1521
1550
|
function getPackageEsmEntryPath(pkg) {
|
|
1522
1551
|
try {
|
|
1523
1552
|
const resolvedEntryPath = resolvePackageEntryFromProjectRoot(pkg);
|
|
1524
|
-
const
|
|
1525
|
-
if (!
|
|
1553
|
+
const installedPackageJson = getInstalledPackageJson(pkg);
|
|
1554
|
+
if (!installedPackageJson) return resolvedEntryPath;
|
|
1526
1555
|
const packageName = removePathFromNpmPackage(pkg);
|
|
1527
|
-
const packageJson =
|
|
1556
|
+
const packageJson = installedPackageJson.packageJson;
|
|
1528
1557
|
const subpath = pkg === packageName ? "." : `.${pkg.slice(packageName.length)}`;
|
|
1529
1558
|
const target = resolveImportTarget(typeof packageJson.exports === "string" ? subpath === "." ? packageJson.exports : void 0 : packageJson.exports?.[subpath] ?? (subpath === "." ? packageJson.exports?.["."] ?? (packageJson.exports && !Object.keys(packageJson.exports).some((key) => key.startsWith(".")) ? packageJson.exports : void 0) : void 0)) || packageJson.module;
|
|
1530
1559
|
if (!target) return resolvedEntryPath;
|
|
1531
|
-
return pathe.default.resolve(
|
|
1560
|
+
return pathe.default.resolve(installedPackageJson.dir, target);
|
|
1532
1561
|
} catch {
|
|
1533
1562
|
return resolvePackageEntryFromProjectRoot(pkg);
|
|
1534
1563
|
}
|
|
@@ -1672,8 +1701,11 @@ function getSharedImportSource(pkg, shareItem) {
|
|
|
1672
1701
|
}
|
|
1673
1702
|
const LOAD_SHARE_TAG = "__loadShare__";
|
|
1674
1703
|
const loadShareCacheMap = {};
|
|
1704
|
+
function shouldUseEsmLoadShare(pkg, command, isRolldown) {
|
|
1705
|
+
return command === "build" || !!isRolldown || pkg === "lit" || pkg.startsWith("lit/");
|
|
1706
|
+
}
|
|
1675
1707
|
function getLoadShareImportId(pkg, isRolldown, command) {
|
|
1676
|
-
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG,
|
|
1708
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, shouldUseEsmLoadShare(pkg, command, isRolldown) ? ".mjs" : ".js");
|
|
1677
1709
|
return loadShareCacheMap[pkg].getImportId();
|
|
1678
1710
|
}
|
|
1679
1711
|
function getLoadShareModulePath(pkg, isRolldown, command) {
|
|
@@ -1681,8 +1713,8 @@ function getLoadShareModulePath(pkg, isRolldown, command) {
|
|
|
1681
1713
|
return loadShareCacheMap[pkg].getPath();
|
|
1682
1714
|
}
|
|
1683
1715
|
function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
1684
|
-
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG,
|
|
1685
|
-
const useESM = command
|
|
1716
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, shouldUseEsmLoadShare(pkg, command, isRolldown) ? ".mjs" : ".js");
|
|
1717
|
+
const useESM = shouldUseEsmLoadShare(pkg, command, isRolldown);
|
|
1686
1718
|
const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
|
|
1687
1719
|
const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
1688
1720
|
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
@@ -1716,6 +1748,7 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1716
1748
|
const devImportSource = concreteSharedImportSource || pkg;
|
|
1717
1749
|
const localProviderPath = getLocalProviderImportPath(pkg);
|
|
1718
1750
|
const isWorkspacePackage = isWorkspaceFilePath(localProviderPath) || isWorkspaceFilePath(concreteSharedImportSource);
|
|
1751
|
+
const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
|
|
1719
1752
|
const providerImportId = localProviderPath || concreteSharedImportSource || sharedImportSource;
|
|
1720
1753
|
const namedExports = getPackageNamedExports(pkg);
|
|
1721
1754
|
let exportLine;
|
|
@@ -1724,8 +1757,8 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1724
1757
|
const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
|
|
1725
1758
|
exportLine = useESM ? `export default exportModule.default ?? exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.map((name, i) => `"${name}": __mf_${i}`).join(", ")} });`;
|
|
1726
1759
|
} else exportLine = useESM ? `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}` : "module.exports = exportModule";
|
|
1727
|
-
const prebuildImportLine = isWorkspacePackage && command !== "build" ? "" : `import ${escapeGeneratedStringLiteral(sharedImportSource)};`;
|
|
1728
|
-
const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
1760
|
+
const prebuildImportLine = isWorkspacePackage && command !== "build" || skipServePrebuildWarmup ? "" : `import ${escapeGeneratedStringLiteral(sharedImportSource)};`;
|
|
1761
|
+
const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
1729
1762
|
loadShareCacheMap[pkg].writeSync(`
|
|
1730
1763
|
${prebuildImportLine}
|
|
1731
1764
|
${devDynamicImportLine}
|
|
@@ -2619,6 +2652,37 @@ var PromiseStore = class {
|
|
|
2619
2652
|
function getPrebuildResolutionSource(pkgName, shareItem) {
|
|
2620
2653
|
return getConcreteSharedImportSource(pkgName, shareItem) || pkgName;
|
|
2621
2654
|
}
|
|
2655
|
+
/**
|
|
2656
|
+
* Reads the dependencies of an installed package from its package.json.
|
|
2657
|
+
*/
|
|
2658
|
+
function getPackageDependencies(pkg) {
|
|
2659
|
+
const packageName = removePathFromNpmPackage(pkg);
|
|
2660
|
+
const cwd = getPackageDetectionCwd();
|
|
2661
|
+
const candidates = [pathe.default.join(cwd, "node_modules", packageName, "package.json")];
|
|
2662
|
+
for (const candidate of candidates) if ((0, fs.existsSync)(candidate)) try {
|
|
2663
|
+
const json = JSON.parse((0, fs.readFileSync)(candidate, "utf-8"));
|
|
2664
|
+
return Object.keys(json.dependencies || {});
|
|
2665
|
+
} catch {}
|
|
2666
|
+
return [];
|
|
2667
|
+
}
|
|
2668
|
+
/**
|
|
2669
|
+
* In dev mode, detects shared packages that are sub-dependencies of other
|
|
2670
|
+
* shared packages and removes them to avoid initialization order issues.
|
|
2671
|
+
* For example, `lit` depends on `lit-html`, `lit-element`, and
|
|
2672
|
+
* `@lit/reactive-element` — sharing them separately causes the child modules
|
|
2673
|
+
* to load before their parent, resulting in `undefined` class extends errors.
|
|
2674
|
+
*/
|
|
2675
|
+
function excludeSharedSubDependencies(shared) {
|
|
2676
|
+
const sharedKeys = new Set(Object.keys(shared));
|
|
2677
|
+
for (const parentKey of sharedKeys) {
|
|
2678
|
+
const deps = getPackageDependencies(parentKey);
|
|
2679
|
+
for (const dep of deps) if (sharedKeys.has(dep) && dep !== parentKey) {
|
|
2680
|
+
mfWarn(`"${dep}" is a dependency of shared package "${parentKey}" and is also shared separately. This may cause initialization order issues in dev mode. Consider sharing only "${parentKey}".\n Auto-excluding "${dep}" from shared modules for dev mode.`);
|
|
2681
|
+
delete shared[dep];
|
|
2682
|
+
sharedKeys.delete(dep);
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2622
2686
|
function proxySharedModule(options) {
|
|
2623
2687
|
const { shared = {} } = options;
|
|
2624
2688
|
let _config;
|
|
@@ -2644,6 +2708,7 @@ function proxySharedModule(options) {
|
|
|
2644
2708
|
const isRolldown = getIsRolldown(this);
|
|
2645
2709
|
_command = command;
|
|
2646
2710
|
useDirectReactImport = isVinext || isAstro;
|
|
2711
|
+
if (command === "serve") excludeSharedSubDependencies(shared);
|
|
2647
2712
|
config.resolve.alias.push(...Object.keys(shared).filter((key) => !(useDirectReactImport && key === "react")).map((key) => {
|
|
2648
2713
|
const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
|
|
2649
2714
|
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -3028,6 +3093,7 @@ function pluginRemoteNamedExports(options) {
|
|
|
3028
3093
|
name: "module-federation-remote-named-exports",
|
|
3029
3094
|
enforce: "post",
|
|
3030
3095
|
async transform(code, id) {
|
|
3096
|
+
if (!getIsRolldown(this)) return;
|
|
3031
3097
|
if (remoteNames.length === 0) return;
|
|
3032
3098
|
if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
|
|
3033
3099
|
if (!JS_EXTENSIONS_RE.test(id)) return;
|
|
@@ -3241,6 +3307,44 @@ function escapeUnsafeJsSourceChars(str) {
|
|
|
3241
3307
|
return UNSAFE_JS_SOURCE_CHAR_MAP[char] ?? char;
|
|
3242
3308
|
});
|
|
3243
3309
|
}
|
|
3310
|
+
function insertAfterLastTopLevelImport(code, snippet) {
|
|
3311
|
+
let cursor = 0;
|
|
3312
|
+
let lastImportEnd = -1;
|
|
3313
|
+
const skipTrivia = () => {
|
|
3314
|
+
while (cursor < code.length) {
|
|
3315
|
+
if (/\s/.test(code[cursor])) {
|
|
3316
|
+
cursor++;
|
|
3317
|
+
continue;
|
|
3318
|
+
}
|
|
3319
|
+
if (code.startsWith("//", cursor)) {
|
|
3320
|
+
const lineEnd = code.indexOf("\n", cursor);
|
|
3321
|
+
cursor = lineEnd === -1 ? code.length : lineEnd + 1;
|
|
3322
|
+
continue;
|
|
3323
|
+
}
|
|
3324
|
+
if (code.startsWith("/*", cursor)) {
|
|
3325
|
+
const commentEnd = code.indexOf("*/", cursor + 2);
|
|
3326
|
+
cursor = commentEnd === -1 ? code.length : commentEnd + 2;
|
|
3327
|
+
continue;
|
|
3328
|
+
}
|
|
3329
|
+
break;
|
|
3330
|
+
}
|
|
3331
|
+
};
|
|
3332
|
+
while (cursor < code.length) {
|
|
3333
|
+
skipTrivia();
|
|
3334
|
+
if (!code.startsWith("import", cursor) || !/[\s"'*{]/.test(code[cursor + 6] ?? "")) break;
|
|
3335
|
+
const statementEnd = code.indexOf(";", cursor);
|
|
3336
|
+
if (statementEnd !== -1) {
|
|
3337
|
+
lastImportEnd = statementEnd + 1;
|
|
3338
|
+
cursor = statementEnd + 1;
|
|
3339
|
+
continue;
|
|
3340
|
+
}
|
|
3341
|
+
const lineEnd = code.indexOf("\n", cursor);
|
|
3342
|
+
lastImportEnd = lineEnd === -1 ? code.length : lineEnd + 1;
|
|
3343
|
+
cursor = lastImportEnd;
|
|
3344
|
+
}
|
|
3345
|
+
if (lastImportEnd === -1) return;
|
|
3346
|
+
return code.slice(0, lastImportEnd) + snippet + code.slice(lastImportEnd);
|
|
3347
|
+
}
|
|
3244
3348
|
/**
|
|
3245
3349
|
* Plugin that runs FIRST to create virtual module files in the config hook.
|
|
3246
3350
|
* This prevents 504 "Outdated Optimize Dep" errors by ensuring files exist
|
|
@@ -3248,6 +3352,7 @@ function escapeUnsafeJsSourceChars(str) {
|
|
|
3248
3352
|
*/
|
|
3249
3353
|
function createEarlyVirtualModulesPlugin(options) {
|
|
3250
3354
|
const { shared, remotes, virtualModuleDir } = options;
|
|
3355
|
+
const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
|
|
3251
3356
|
return {
|
|
3252
3357
|
name: "vite:module-federation-early-init",
|
|
3253
3358
|
enforce: "pre",
|
|
@@ -3283,8 +3388,13 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
3283
3388
|
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(key, shareItem);
|
|
3284
3389
|
addUsedShares(key);
|
|
3285
3390
|
if (_command === "serve" && shareItem.shareConfig?.import !== false) {
|
|
3286
|
-
|
|
3287
|
-
|
|
3391
|
+
const optimizeDeps = config.optimizeDeps ??= {};
|
|
3392
|
+
optimizeDeps.include ??= [];
|
|
3393
|
+
optimizeDeps.exclude ??= [];
|
|
3394
|
+
const shouldBypassOptimizeDep = isLitShare(key);
|
|
3395
|
+
if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
|
|
3396
|
+
if (!isRolldown && !shouldBypassOptimizeDep) optimizeDeps.include.push(getLoadShareImportId(key, isRolldown, _command));
|
|
3397
|
+
optimizeDeps.include.push(getPreBuildLibImportId(key));
|
|
3288
3398
|
}
|
|
3289
3399
|
}
|
|
3290
3400
|
writeLocalSharedImportMap();
|
|
@@ -3302,6 +3412,7 @@ function federation(mfUserOptions) {
|
|
|
3302
3412
|
const virtualExposesId = getVirtualExposesId(options);
|
|
3303
3413
|
let command;
|
|
3304
3414
|
let depsDir = "/node_modules/.vite/deps/";
|
|
3415
|
+
let desiredRolldownOutput;
|
|
3305
3416
|
return [
|
|
3306
3417
|
createEarlyVirtualModulesPlugin(options),
|
|
3307
3418
|
...isVinext ? [{
|
|
@@ -3392,12 +3503,22 @@ function federation(mfUserOptions) {
|
|
|
3392
3503
|
};
|
|
3393
3504
|
}
|
|
3394
3505
|
let warnedAboutCodeSplitting = false;
|
|
3506
|
+
let warnedAboutCodeSplittingGroups = false;
|
|
3395
3507
|
const ensureCodeSplitting = (output) => {
|
|
3396
|
-
if (output?.codeSplitting
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3508
|
+
if (output?.codeSplitting === false) {
|
|
3509
|
+
delete output.codeSplitting;
|
|
3510
|
+
if (warnedAboutCodeSplitting) return;
|
|
3511
|
+
warnedAboutCodeSplitting = true;
|
|
3512
|
+
mfWarn("Ignoring `output.codeSplitting = false` because module federation requires chunk splitting.");
|
|
3513
|
+
return;
|
|
3514
|
+
}
|
|
3515
|
+
if (!output?.codeSplitting || typeof output.codeSplitting !== "object") return;
|
|
3516
|
+
if (!("groups" in output.codeSplitting)) return;
|
|
3517
|
+
delete output.codeSplitting.groups;
|
|
3518
|
+
if (Object.keys(output.codeSplitting).length === 0) delete output.codeSplitting;
|
|
3519
|
+
if (warnedAboutCodeSplittingGroups) return;
|
|
3520
|
+
warnedAboutCodeSplittingGroups = true;
|
|
3521
|
+
mfWarn("Ignoring `output.codeSplitting.groups` because it conflicts with module federation. Grouping shared dependency init wrappers with their dependent modules can break runtime init order and cause standalone remotes to fail before mount.");
|
|
3401
3522
|
};
|
|
3402
3523
|
let warnedAboutManualChunks = false;
|
|
3403
3524
|
const applyManualChunks = (output) => {
|
|
@@ -3405,7 +3526,7 @@ function federation(mfUserOptions) {
|
|
|
3405
3526
|
const isPatchedByPlugin = !!(output.manualChunks && patchedManualChunks.has(output.manualChunks));
|
|
3406
3527
|
if (output.manualChunks && !isPatchedByPlugin && !warnedAboutManualChunks) {
|
|
3407
3528
|
warnedAboutManualChunks = true;
|
|
3408
|
-
mfWarn("Ignoring `
|
|
3529
|
+
mfWarn("Ignoring `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.");
|
|
3409
3530
|
}
|
|
3410
3531
|
const mfManualChunks = function(id) {
|
|
3411
3532
|
if (id.includes(runtimeInitId)) return "runtimeInit";
|
|
@@ -3418,10 +3539,46 @@ function federation(mfUserOptions) {
|
|
|
3418
3539
|
output.manualChunks = mfManualChunks;
|
|
3419
3540
|
};
|
|
3420
3541
|
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
3421
|
-
|
|
3542
|
+
const rollupOutput = config.build.rollupOptions.output;
|
|
3543
|
+
if (Array.isArray(rollupOutput)) rollupOutput.forEach((output) => applyManualChunks(output));
|
|
3544
|
+
else applyManualChunks(config.build.rollupOptions.output ||= {});
|
|
3422
3545
|
const buildWithRolldown = config.build;
|
|
3423
3546
|
buildWithRolldown.rolldownOptions = buildWithRolldown.rolldownOptions || {};
|
|
3424
|
-
|
|
3547
|
+
const rolldownOutput = buildWithRolldown.rolldownOptions.output;
|
|
3548
|
+
const snapshotRolldownOutput = (output) => ({
|
|
3549
|
+
entryFileNames: output.entryFileNames,
|
|
3550
|
+
chunkFileNames: output.chunkFileNames,
|
|
3551
|
+
assetFileNames: output.assetFileNames
|
|
3552
|
+
});
|
|
3553
|
+
if (Array.isArray(rolldownOutput)) {
|
|
3554
|
+
rolldownOutput.forEach((output) => applyManualChunks(output));
|
|
3555
|
+
desiredRolldownOutput = rolldownOutput.map((output) => snapshotRolldownOutput(output));
|
|
3556
|
+
} else {
|
|
3557
|
+
applyManualChunks(buildWithRolldown.rolldownOptions.output ||= {});
|
|
3558
|
+
desiredRolldownOutput = [snapshotRolldownOutput(buildWithRolldown.rolldownOptions.output)];
|
|
3559
|
+
}
|
|
3560
|
+
},
|
|
3561
|
+
async buildApp(builder) {
|
|
3562
|
+
if (!desiredRolldownOutput) return;
|
|
3563
|
+
const applyRolldownOutput = (output, restoredOutput) => {
|
|
3564
|
+
if (!output || !restoredOutput) return;
|
|
3565
|
+
if (restoredOutput.entryFileNames !== void 0) output.entryFileNames = restoredOutput.entryFileNames;
|
|
3566
|
+
if (restoredOutput.chunkFileNames !== void 0) output.chunkFileNames = restoredOutput.chunkFileNames;
|
|
3567
|
+
if (restoredOutput.assetFileNames !== void 0) output.assetFileNames = restoredOutput.assetFileNames;
|
|
3568
|
+
};
|
|
3569
|
+
for (const environment of Object.values(builder.environments)) {
|
|
3570
|
+
const getRolldownOptions = environment?.getRolldownOptions;
|
|
3571
|
+
if (typeof getRolldownOptions !== "function") continue;
|
|
3572
|
+
environment.getRolldownOptions = async () => {
|
|
3573
|
+
const rolldownOptions = await getRolldownOptions.call(environment);
|
|
3574
|
+
if (Array.isArray(rolldownOptions.output)) rolldownOptions.output.forEach((output, index) => applyRolldownOutput(output, desiredRolldownOutput?.[index]));
|
|
3575
|
+
else {
|
|
3576
|
+
rolldownOptions.output ||= {};
|
|
3577
|
+
applyRolldownOutput(rolldownOptions.output, desiredRolldownOutput[0]);
|
|
3578
|
+
}
|
|
3579
|
+
return rolldownOptions;
|
|
3580
|
+
};
|
|
3581
|
+
}
|
|
3425
3582
|
},
|
|
3426
3583
|
load(id) {
|
|
3427
3584
|
if (id.startsWith("\0")) return;
|
|
@@ -3475,11 +3632,9 @@ function federation(mfUserOptions) {
|
|
|
3475
3632
|
for (const v of importedFromLoadShare) if (new RegExp("\\(" + v + "\\(\\)\\s*,\\s*\\w+\\(\\w+\\)\\)").test(code)) allInits.push(v);
|
|
3476
3633
|
if (allInits.length === 0) continue;
|
|
3477
3634
|
const awaits = allInits.map((v) => `await ${v}();`).join("");
|
|
3478
|
-
const
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
if (lastFromEnd !== -1) {
|
|
3482
|
-
chunk.code = code.slice(0, lastFromEnd) + awaits + code.slice(lastFromEnd);
|
|
3635
|
+
const codeWithAwaits = insertAfterLastTopLevelImport(code, awaits);
|
|
3636
|
+
if (codeWithAwaits) {
|
|
3637
|
+
chunk.code = codeWithAwaits;
|
|
3483
3638
|
continue;
|
|
3484
3639
|
}
|
|
3485
3640
|
const exportIdx = code.search(/\bexport\s*[{d]/);
|
|
@@ -3610,14 +3765,7 @@ function federation(mfUserOptions) {
|
|
|
3610
3765
|
})) return;
|
|
3611
3766
|
if (/await\s+init_\w+__loadShare__/.test(code)) return;
|
|
3612
3767
|
if (code.includes("__esmMin")) return;
|
|
3613
|
-
|
|
3614
|
-
const topLevelImportRe = /^import\s/gm;
|
|
3615
|
-
let lastImportIdx = -1;
|
|
3616
|
-
let importMatch;
|
|
3617
|
-
while ((importMatch = topLevelImportRe.exec(code)) !== null) lastImportIdx = importMatch.index;
|
|
3618
|
-
if (lastImportIdx === -1) return;
|
|
3619
|
-
const lineEnd = code.indexOf("\n", lastImportIdx);
|
|
3620
|
-
return code.slice(0, lineEnd + 1) + awaits + "\n" + code.slice(lineEnd + 1);
|
|
3768
|
+
return insertAfterLastTopLevelImport(code, [...initFns].map((fn) => `await ${fn}();`).join("\n") + "\n");
|
|
3621
3769
|
}
|
|
3622
3770
|
},
|
|
3623
3771
|
PluginDevProxyModuleTopLevelAwait(),
|
package/lib/index.mjs
CHANGED
|
@@ -130,6 +130,56 @@ function removePathFromNpmPackage(packageString) {
|
|
|
130
130
|
const match = packageString.match(/^(?:@[^/]+\/)?[^/]+/);
|
|
131
131
|
return match ? match[0] : packageString;
|
|
132
132
|
}
|
|
133
|
+
function getInstalledPackageJson(pkg, opts) {
|
|
134
|
+
const cwd = opts?.cwd || getPackageDetectionCwd();
|
|
135
|
+
const packageName = opts?.packageName || removePathFromNpmPackage(pkg);
|
|
136
|
+
try {
|
|
137
|
+
const projectRequire = createRequire$1(new URL(`file://${path.join(cwd, "package.json")}`));
|
|
138
|
+
let resolvedPath;
|
|
139
|
+
try {
|
|
140
|
+
resolvedPath = projectRequire.resolve(pkg);
|
|
141
|
+
} catch {
|
|
142
|
+
resolvedPath = projectRequire.resolve(packageName);
|
|
143
|
+
}
|
|
144
|
+
let currentDir = path.dirname(resolvedPath);
|
|
145
|
+
const rootDir = path.parse(currentDir).root;
|
|
146
|
+
while (true) {
|
|
147
|
+
const packageJsonPath = path.join(currentDir, "package.json");
|
|
148
|
+
if (existsSync(packageJsonPath)) {
|
|
149
|
+
const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
|
|
150
|
+
try {
|
|
151
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
152
|
+
if (packageJson.name === packageName) return {
|
|
153
|
+
path: packageJsonPath,
|
|
154
|
+
dir: currentDir,
|
|
155
|
+
packageJson
|
|
156
|
+
};
|
|
157
|
+
} catch (error) {
|
|
158
|
+
if (!(error instanceof SyntaxError)) throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (currentDir === rootDir) break;
|
|
162
|
+
currentDir = path.dirname(currentDir);
|
|
163
|
+
}
|
|
164
|
+
} catch {
|
|
165
|
+
let currentDir = cwd;
|
|
166
|
+
const rootDir = path.parse(currentDir).root;
|
|
167
|
+
while (true) {
|
|
168
|
+
const packageJsonPath = path.join(currentDir, "node_modules", packageName, "package.json");
|
|
169
|
+
if (existsSync(packageJsonPath)) try {
|
|
170
|
+
return {
|
|
171
|
+
path: packageJsonPath,
|
|
172
|
+
dir: path.dirname(packageJsonPath),
|
|
173
|
+
packageJson: JSON.parse(readFileSync(packageJsonPath, "utf-8"))
|
|
174
|
+
};
|
|
175
|
+
} catch {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (currentDir === rootDir) break;
|
|
179
|
+
currentDir = path.dirname(currentDir);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
133
183
|
/**
|
|
134
184
|
* Detect whether the current runtime is Vite 8+ by checking for a Vite version flag
|
|
135
185
|
* on the plugin hook context, with Rolldown metadata kept as a compatibility fallback.
|
|
@@ -934,6 +984,12 @@ function inferVersionFromRequiredVersion(requiredVersion) {
|
|
|
934
984
|
if (!requiredVersion) return void 0;
|
|
935
985
|
return requiredVersion.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0];
|
|
936
986
|
}
|
|
987
|
+
function getLitExportSubpathShares(sharedName) {
|
|
988
|
+
if (sharedName !== "lit") return [];
|
|
989
|
+
const exportsField = getInstalledPackageJson(sharedName, { packageName: sharedName })?.packageJson.exports;
|
|
990
|
+
if (!exportsField || typeof exportsField === "string") return [];
|
|
991
|
+
return Object.keys(exportsField).filter((key) => key.startsWith("./") && key !== "." && !key.includes("*")).map((key) => `${sharedName}/${key.slice(2)}`);
|
|
992
|
+
}
|
|
937
993
|
function normalizeShareItem(key, shareItem) {
|
|
938
994
|
let version;
|
|
939
995
|
if (!(typeof shareItem === "object" && shareItem.import === false)) try {
|
|
@@ -977,14 +1033,21 @@ function normalizeShareItem(key, shareItem) {
|
|
|
977
1033
|
function normalizeShared(shared) {
|
|
978
1034
|
if (!shared) return {};
|
|
979
1035
|
const result = {};
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
result[key] = normalizeShareItem(key,
|
|
1036
|
+
const sourceEntries = [];
|
|
1037
|
+
if (Array.isArray(shared)) shared.forEach((key) => {
|
|
1038
|
+
result[key] = normalizeShareItem(key, key);
|
|
1039
|
+
sourceEntries.push([key, key]);
|
|
1040
|
+
});
|
|
1041
|
+
else if (typeof shared === "object") Object.keys(shared).forEach((key) => {
|
|
1042
|
+
const value = shared[key];
|
|
1043
|
+
result[key] = normalizeShareItem(key, value);
|
|
1044
|
+
sourceEntries.push([key, value]);
|
|
1045
|
+
});
|
|
1046
|
+
sourceEntries.forEach(([key, value]) => {
|
|
1047
|
+
for (const subpathShare of getLitExportSubpathShares(key)) {
|
|
1048
|
+
if (result[subpathShare]) continue;
|
|
1049
|
+
result[subpathShare] = normalizeShareItem(subpathShare, value);
|
|
1050
|
+
}
|
|
988
1051
|
});
|
|
989
1052
|
return result;
|
|
990
1053
|
}
|
|
@@ -1216,6 +1279,16 @@ function generateExposes(options) {
|
|
|
1216
1279
|
return `
|
|
1217
1280
|
const cssAssetMap = ${JSON.stringify(options.bundleAllCSS ? EXPOSES_CSS_MAP_PLACEHOLDER : {})};
|
|
1218
1281
|
const injectedCssHrefs = new Set();
|
|
1282
|
+
let exposeLoadQueue = Promise.resolve();
|
|
1283
|
+
|
|
1284
|
+
async function importExposedModule(loader) {
|
|
1285
|
+
const currentLoad = exposeLoadQueue.then(loader, loader);
|
|
1286
|
+
exposeLoadQueue = currentLoad.then(
|
|
1287
|
+
() => undefined,
|
|
1288
|
+
() => undefined
|
|
1289
|
+
);
|
|
1290
|
+
return currentLoad;
|
|
1291
|
+
}
|
|
1219
1292
|
|
|
1220
1293
|
async function injectCssAssets(exposeKey) {
|
|
1221
1294
|
if (typeof document === "undefined") {
|
|
@@ -1260,7 +1333,9 @@ function generateExposes(options) {
|
|
|
1260
1333
|
return `
|
|
1261
1334
|
${JSON.stringify(key)}: async () => {
|
|
1262
1335
|
await injectCssAssets(${JSON.stringify(key)})
|
|
1263
|
-
const importModule = await
|
|
1336
|
+
const importModule = await importExposedModule(
|
|
1337
|
+
() => import(${JSON.stringify(options.exposes[key].import)})
|
|
1338
|
+
)
|
|
1264
1339
|
const exportModule = {}
|
|
1265
1340
|
Object.assign(exportModule, importModule)
|
|
1266
1341
|
Object.defineProperty(exportModule, "__esModule", {
|
|
@@ -1432,52 +1507,6 @@ function resolvePackageEntryFromProjectRoot(pkg) {
|
|
|
1432
1507
|
return;
|
|
1433
1508
|
}
|
|
1434
1509
|
}
|
|
1435
|
-
function getInstalledPackageJsonPath(pkg) {
|
|
1436
|
-
try {
|
|
1437
|
-
const packageName = removePathFromNpmPackage(pkg);
|
|
1438
|
-
const projectRequire = createRequire$1(new URL(`file://${path.join(getPackageDetectionCwd(), "package.json")}`));
|
|
1439
|
-
let resolvedPath;
|
|
1440
|
-
try {
|
|
1441
|
-
resolvedPath = projectRequire.resolve(pkg);
|
|
1442
|
-
} catch {
|
|
1443
|
-
resolvedPath = projectRequire.resolve(packageName);
|
|
1444
|
-
}
|
|
1445
|
-
let currentDir = path.dirname(resolvedPath);
|
|
1446
|
-
const rootDir = path.parse(currentDir).root;
|
|
1447
|
-
while (currentDir !== rootDir) {
|
|
1448
|
-
const packageJsonPath = path.join(currentDir, "package.json");
|
|
1449
|
-
if (existsSync(packageJsonPath)) {
|
|
1450
|
-
const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
|
|
1451
|
-
try {
|
|
1452
|
-
if (JSON.parse(packageJsonContent).name === packageName) return packageJsonPath;
|
|
1453
|
-
} catch (error) {
|
|
1454
|
-
if (!(error instanceof SyntaxError)) throw error;
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
currentDir = path.dirname(currentDir);
|
|
1458
|
-
}
|
|
1459
|
-
const rootPackageJsonPath = path.join(rootDir, "package.json");
|
|
1460
|
-
if (existsSync(rootPackageJsonPath)) {
|
|
1461
|
-
const rootPackageJsonContent = readFileSync(rootPackageJsonPath, "utf-8");
|
|
1462
|
-
try {
|
|
1463
|
-
if (JSON.parse(rootPackageJsonContent).name === packageName) return rootPackageJsonPath;
|
|
1464
|
-
} catch (error) {
|
|
1465
|
-
if (!(error instanceof SyntaxError)) throw error;
|
|
1466
|
-
}
|
|
1467
|
-
}
|
|
1468
|
-
} catch {
|
|
1469
|
-
const packageName = removePathFromNpmPackage(pkg);
|
|
1470
|
-
let currentDir = getPackageDetectionCwd();
|
|
1471
|
-
const rootDir = path.parse(currentDir).root;
|
|
1472
|
-
while (currentDir !== rootDir) {
|
|
1473
|
-
const packageJsonPath = path.join(currentDir, "node_modules", packageName, "package.json");
|
|
1474
|
-
if (existsSync(packageJsonPath)) return packageJsonPath;
|
|
1475
|
-
currentDir = path.dirname(currentDir);
|
|
1476
|
-
}
|
|
1477
|
-
const rootPackageJsonPath = path.join(rootDir, "node_modules", packageName, "package.json");
|
|
1478
|
-
return existsSync(rootPackageJsonPath) ? rootPackageJsonPath : void 0;
|
|
1479
|
-
}
|
|
1480
|
-
}
|
|
1481
1510
|
function resolveImportTarget(exportsField) {
|
|
1482
1511
|
if (typeof exportsField === "string") return exportsField;
|
|
1483
1512
|
if (!exportsField || typeof exportsField !== "object") return void 0;
|
|
@@ -1498,14 +1527,14 @@ function resolveImportTarget(exportsField) {
|
|
|
1498
1527
|
function getPackageEsmEntryPath(pkg) {
|
|
1499
1528
|
try {
|
|
1500
1529
|
const resolvedEntryPath = resolvePackageEntryFromProjectRoot(pkg);
|
|
1501
|
-
const
|
|
1502
|
-
if (!
|
|
1530
|
+
const installedPackageJson = getInstalledPackageJson(pkg);
|
|
1531
|
+
if (!installedPackageJson) return resolvedEntryPath;
|
|
1503
1532
|
const packageName = removePathFromNpmPackage(pkg);
|
|
1504
|
-
const packageJson =
|
|
1533
|
+
const packageJson = installedPackageJson.packageJson;
|
|
1505
1534
|
const subpath = pkg === packageName ? "." : `.${pkg.slice(packageName.length)}`;
|
|
1506
1535
|
const target = resolveImportTarget(typeof packageJson.exports === "string" ? subpath === "." ? packageJson.exports : void 0 : packageJson.exports?.[subpath] ?? (subpath === "." ? packageJson.exports?.["."] ?? (packageJson.exports && !Object.keys(packageJson.exports).some((key) => key.startsWith(".")) ? packageJson.exports : void 0) : void 0)) || packageJson.module;
|
|
1507
1536
|
if (!target) return resolvedEntryPath;
|
|
1508
|
-
return path.resolve(
|
|
1537
|
+
return path.resolve(installedPackageJson.dir, target);
|
|
1509
1538
|
} catch {
|
|
1510
1539
|
return resolvePackageEntryFromProjectRoot(pkg);
|
|
1511
1540
|
}
|
|
@@ -1649,8 +1678,11 @@ function getSharedImportSource(pkg, shareItem) {
|
|
|
1649
1678
|
}
|
|
1650
1679
|
const LOAD_SHARE_TAG = "__loadShare__";
|
|
1651
1680
|
const loadShareCacheMap = {};
|
|
1681
|
+
function shouldUseEsmLoadShare(pkg, command, isRolldown) {
|
|
1682
|
+
return command === "build" || !!isRolldown || pkg === "lit" || pkg.startsWith("lit/");
|
|
1683
|
+
}
|
|
1652
1684
|
function getLoadShareImportId(pkg, isRolldown, command) {
|
|
1653
|
-
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG,
|
|
1685
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, shouldUseEsmLoadShare(pkg, command, isRolldown) ? ".mjs" : ".js");
|
|
1654
1686
|
return loadShareCacheMap[pkg].getImportId();
|
|
1655
1687
|
}
|
|
1656
1688
|
function getLoadShareModulePath(pkg, isRolldown, command) {
|
|
@@ -1658,8 +1690,8 @@ function getLoadShareModulePath(pkg, isRolldown, command) {
|
|
|
1658
1690
|
return loadShareCacheMap[pkg].getPath();
|
|
1659
1691
|
}
|
|
1660
1692
|
function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
1661
|
-
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG,
|
|
1662
|
-
const useESM = command
|
|
1693
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, shouldUseEsmLoadShare(pkg, command, isRolldown) ? ".mjs" : ".js");
|
|
1694
|
+
const useESM = shouldUseEsmLoadShare(pkg, command, isRolldown);
|
|
1663
1695
|
const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
|
|
1664
1696
|
const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
1665
1697
|
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
@@ -1693,6 +1725,7 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1693
1725
|
const devImportSource = concreteSharedImportSource || pkg;
|
|
1694
1726
|
const localProviderPath = getLocalProviderImportPath(pkg);
|
|
1695
1727
|
const isWorkspacePackage = isWorkspaceFilePath(localProviderPath) || isWorkspaceFilePath(concreteSharedImportSource);
|
|
1728
|
+
const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
|
|
1696
1729
|
const providerImportId = localProviderPath || concreteSharedImportSource || sharedImportSource;
|
|
1697
1730
|
const namedExports = getPackageNamedExports(pkg);
|
|
1698
1731
|
let exportLine;
|
|
@@ -1701,8 +1734,8 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1701
1734
|
const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
|
|
1702
1735
|
exportLine = useESM ? `export default exportModule.default ?? exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.map((name, i) => `"${name}": __mf_${i}`).join(", ")} });`;
|
|
1703
1736
|
} else exportLine = useESM ? `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}` : "module.exports = exportModule";
|
|
1704
|
-
const prebuildImportLine = isWorkspacePackage && command !== "build" ? "" : `import ${escapeGeneratedStringLiteral(sharedImportSource)};`;
|
|
1705
|
-
const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
1737
|
+
const prebuildImportLine = isWorkspacePackage && command !== "build" || skipServePrebuildWarmup ? "" : `import ${escapeGeneratedStringLiteral(sharedImportSource)};`;
|
|
1738
|
+
const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
1706
1739
|
loadShareCacheMap[pkg].writeSync(`
|
|
1707
1740
|
${prebuildImportLine}
|
|
1708
1741
|
${devDynamicImportLine}
|
|
@@ -2596,6 +2629,37 @@ var PromiseStore = class {
|
|
|
2596
2629
|
function getPrebuildResolutionSource(pkgName, shareItem) {
|
|
2597
2630
|
return getConcreteSharedImportSource(pkgName, shareItem) || pkgName;
|
|
2598
2631
|
}
|
|
2632
|
+
/**
|
|
2633
|
+
* Reads the dependencies of an installed package from its package.json.
|
|
2634
|
+
*/
|
|
2635
|
+
function getPackageDependencies(pkg) {
|
|
2636
|
+
const packageName = removePathFromNpmPackage(pkg);
|
|
2637
|
+
const cwd = getPackageDetectionCwd();
|
|
2638
|
+
const candidates = [path.join(cwd, "node_modules", packageName, "package.json")];
|
|
2639
|
+
for (const candidate of candidates) if (existsSync(candidate)) try {
|
|
2640
|
+
const json = JSON.parse(readFileSync(candidate, "utf-8"));
|
|
2641
|
+
return Object.keys(json.dependencies || {});
|
|
2642
|
+
} catch {}
|
|
2643
|
+
return [];
|
|
2644
|
+
}
|
|
2645
|
+
/**
|
|
2646
|
+
* In dev mode, detects shared packages that are sub-dependencies of other
|
|
2647
|
+
* shared packages and removes them to avoid initialization order issues.
|
|
2648
|
+
* For example, `lit` depends on `lit-html`, `lit-element`, and
|
|
2649
|
+
* `@lit/reactive-element` — sharing them separately causes the child modules
|
|
2650
|
+
* to load before their parent, resulting in `undefined` class extends errors.
|
|
2651
|
+
*/
|
|
2652
|
+
function excludeSharedSubDependencies(shared) {
|
|
2653
|
+
const sharedKeys = new Set(Object.keys(shared));
|
|
2654
|
+
for (const parentKey of sharedKeys) {
|
|
2655
|
+
const deps = getPackageDependencies(parentKey);
|
|
2656
|
+
for (const dep of deps) if (sharedKeys.has(dep) && dep !== parentKey) {
|
|
2657
|
+
mfWarn(`"${dep}" is a dependency of shared package "${parentKey}" and is also shared separately. This may cause initialization order issues in dev mode. Consider sharing only "${parentKey}".\n Auto-excluding "${dep}" from shared modules for dev mode.`);
|
|
2658
|
+
delete shared[dep];
|
|
2659
|
+
sharedKeys.delete(dep);
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2599
2663
|
function proxySharedModule(options) {
|
|
2600
2664
|
const { shared = {} } = options;
|
|
2601
2665
|
let _config;
|
|
@@ -2621,6 +2685,7 @@ function proxySharedModule(options) {
|
|
|
2621
2685
|
const isRolldown = getIsRolldown(this);
|
|
2622
2686
|
_command = command;
|
|
2623
2687
|
useDirectReactImport = isVinext || isAstro;
|
|
2688
|
+
if (command === "serve") excludeSharedSubDependencies(shared);
|
|
2624
2689
|
config.resolve.alias.push(...Object.keys(shared).filter((key) => !(useDirectReactImport && key === "react")).map((key) => {
|
|
2625
2690
|
const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
|
|
2626
2691
|
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -3005,6 +3070,7 @@ function pluginRemoteNamedExports(options) {
|
|
|
3005
3070
|
name: "module-federation-remote-named-exports",
|
|
3006
3071
|
enforce: "post",
|
|
3007
3072
|
async transform(code, id) {
|
|
3073
|
+
if (!getIsRolldown(this)) return;
|
|
3008
3074
|
if (remoteNames.length === 0) return;
|
|
3009
3075
|
if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
|
|
3010
3076
|
if (!JS_EXTENSIONS_RE.test(id)) return;
|
|
@@ -3218,6 +3284,44 @@ function escapeUnsafeJsSourceChars(str) {
|
|
|
3218
3284
|
return UNSAFE_JS_SOURCE_CHAR_MAP[char] ?? char;
|
|
3219
3285
|
});
|
|
3220
3286
|
}
|
|
3287
|
+
function insertAfterLastTopLevelImport(code, snippet) {
|
|
3288
|
+
let cursor = 0;
|
|
3289
|
+
let lastImportEnd = -1;
|
|
3290
|
+
const skipTrivia = () => {
|
|
3291
|
+
while (cursor < code.length) {
|
|
3292
|
+
if (/\s/.test(code[cursor])) {
|
|
3293
|
+
cursor++;
|
|
3294
|
+
continue;
|
|
3295
|
+
}
|
|
3296
|
+
if (code.startsWith("//", cursor)) {
|
|
3297
|
+
const lineEnd = code.indexOf("\n", cursor);
|
|
3298
|
+
cursor = lineEnd === -1 ? code.length : lineEnd + 1;
|
|
3299
|
+
continue;
|
|
3300
|
+
}
|
|
3301
|
+
if (code.startsWith("/*", cursor)) {
|
|
3302
|
+
const commentEnd = code.indexOf("*/", cursor + 2);
|
|
3303
|
+
cursor = commentEnd === -1 ? code.length : commentEnd + 2;
|
|
3304
|
+
continue;
|
|
3305
|
+
}
|
|
3306
|
+
break;
|
|
3307
|
+
}
|
|
3308
|
+
};
|
|
3309
|
+
while (cursor < code.length) {
|
|
3310
|
+
skipTrivia();
|
|
3311
|
+
if (!code.startsWith("import", cursor) || !/[\s"'*{]/.test(code[cursor + 6] ?? "")) break;
|
|
3312
|
+
const statementEnd = code.indexOf(";", cursor);
|
|
3313
|
+
if (statementEnd !== -1) {
|
|
3314
|
+
lastImportEnd = statementEnd + 1;
|
|
3315
|
+
cursor = statementEnd + 1;
|
|
3316
|
+
continue;
|
|
3317
|
+
}
|
|
3318
|
+
const lineEnd = code.indexOf("\n", cursor);
|
|
3319
|
+
lastImportEnd = lineEnd === -1 ? code.length : lineEnd + 1;
|
|
3320
|
+
cursor = lastImportEnd;
|
|
3321
|
+
}
|
|
3322
|
+
if (lastImportEnd === -1) return;
|
|
3323
|
+
return code.slice(0, lastImportEnd) + snippet + code.slice(lastImportEnd);
|
|
3324
|
+
}
|
|
3221
3325
|
/**
|
|
3222
3326
|
* Plugin that runs FIRST to create virtual module files in the config hook.
|
|
3223
3327
|
* This prevents 504 "Outdated Optimize Dep" errors by ensuring files exist
|
|
@@ -3225,6 +3329,7 @@ function escapeUnsafeJsSourceChars(str) {
|
|
|
3225
3329
|
*/
|
|
3226
3330
|
function createEarlyVirtualModulesPlugin(options) {
|
|
3227
3331
|
const { shared, remotes, virtualModuleDir } = options;
|
|
3332
|
+
const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
|
|
3228
3333
|
return {
|
|
3229
3334
|
name: "vite:module-federation-early-init",
|
|
3230
3335
|
enforce: "pre",
|
|
@@ -3260,8 +3365,13 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
3260
3365
|
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(key, shareItem);
|
|
3261
3366
|
addUsedShares(key);
|
|
3262
3367
|
if (_command === "serve" && shareItem.shareConfig?.import !== false) {
|
|
3263
|
-
|
|
3264
|
-
|
|
3368
|
+
const optimizeDeps = config.optimizeDeps ??= {};
|
|
3369
|
+
optimizeDeps.include ??= [];
|
|
3370
|
+
optimizeDeps.exclude ??= [];
|
|
3371
|
+
const shouldBypassOptimizeDep = isLitShare(key);
|
|
3372
|
+
if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
|
|
3373
|
+
if (!isRolldown && !shouldBypassOptimizeDep) optimizeDeps.include.push(getLoadShareImportId(key, isRolldown, _command));
|
|
3374
|
+
optimizeDeps.include.push(getPreBuildLibImportId(key));
|
|
3265
3375
|
}
|
|
3266
3376
|
}
|
|
3267
3377
|
writeLocalSharedImportMap();
|
|
@@ -3279,6 +3389,7 @@ function federation(mfUserOptions) {
|
|
|
3279
3389
|
const virtualExposesId = getVirtualExposesId(options);
|
|
3280
3390
|
let command;
|
|
3281
3391
|
let depsDir = "/node_modules/.vite/deps/";
|
|
3392
|
+
let desiredRolldownOutput;
|
|
3282
3393
|
return [
|
|
3283
3394
|
createEarlyVirtualModulesPlugin(options),
|
|
3284
3395
|
...isVinext ? [{
|
|
@@ -3369,12 +3480,22 @@ function federation(mfUserOptions) {
|
|
|
3369
3480
|
};
|
|
3370
3481
|
}
|
|
3371
3482
|
let warnedAboutCodeSplitting = false;
|
|
3483
|
+
let warnedAboutCodeSplittingGroups = false;
|
|
3372
3484
|
const ensureCodeSplitting = (output) => {
|
|
3373
|
-
if (output?.codeSplitting
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3485
|
+
if (output?.codeSplitting === false) {
|
|
3486
|
+
delete output.codeSplitting;
|
|
3487
|
+
if (warnedAboutCodeSplitting) return;
|
|
3488
|
+
warnedAboutCodeSplitting = true;
|
|
3489
|
+
mfWarn("Ignoring `output.codeSplitting = false` because module federation requires chunk splitting.");
|
|
3490
|
+
return;
|
|
3491
|
+
}
|
|
3492
|
+
if (!output?.codeSplitting || typeof output.codeSplitting !== "object") return;
|
|
3493
|
+
if (!("groups" in output.codeSplitting)) return;
|
|
3494
|
+
delete output.codeSplitting.groups;
|
|
3495
|
+
if (Object.keys(output.codeSplitting).length === 0) delete output.codeSplitting;
|
|
3496
|
+
if (warnedAboutCodeSplittingGroups) return;
|
|
3497
|
+
warnedAboutCodeSplittingGroups = true;
|
|
3498
|
+
mfWarn("Ignoring `output.codeSplitting.groups` because it conflicts with module federation. Grouping shared dependency init wrappers with their dependent modules can break runtime init order and cause standalone remotes to fail before mount.");
|
|
3378
3499
|
};
|
|
3379
3500
|
let warnedAboutManualChunks = false;
|
|
3380
3501
|
const applyManualChunks = (output) => {
|
|
@@ -3382,7 +3503,7 @@ function federation(mfUserOptions) {
|
|
|
3382
3503
|
const isPatchedByPlugin = !!(output.manualChunks && patchedManualChunks.has(output.manualChunks));
|
|
3383
3504
|
if (output.manualChunks && !isPatchedByPlugin && !warnedAboutManualChunks) {
|
|
3384
3505
|
warnedAboutManualChunks = true;
|
|
3385
|
-
mfWarn("Ignoring `
|
|
3506
|
+
mfWarn("Ignoring `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.");
|
|
3386
3507
|
}
|
|
3387
3508
|
const mfManualChunks = function(id) {
|
|
3388
3509
|
if (id.includes(runtimeInitId)) return "runtimeInit";
|
|
@@ -3395,10 +3516,46 @@ function federation(mfUserOptions) {
|
|
|
3395
3516
|
output.manualChunks = mfManualChunks;
|
|
3396
3517
|
};
|
|
3397
3518
|
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
3398
|
-
|
|
3519
|
+
const rollupOutput = config.build.rollupOptions.output;
|
|
3520
|
+
if (Array.isArray(rollupOutput)) rollupOutput.forEach((output) => applyManualChunks(output));
|
|
3521
|
+
else applyManualChunks(config.build.rollupOptions.output ||= {});
|
|
3399
3522
|
const buildWithRolldown = config.build;
|
|
3400
3523
|
buildWithRolldown.rolldownOptions = buildWithRolldown.rolldownOptions || {};
|
|
3401
|
-
|
|
3524
|
+
const rolldownOutput = buildWithRolldown.rolldownOptions.output;
|
|
3525
|
+
const snapshotRolldownOutput = (output) => ({
|
|
3526
|
+
entryFileNames: output.entryFileNames,
|
|
3527
|
+
chunkFileNames: output.chunkFileNames,
|
|
3528
|
+
assetFileNames: output.assetFileNames
|
|
3529
|
+
});
|
|
3530
|
+
if (Array.isArray(rolldownOutput)) {
|
|
3531
|
+
rolldownOutput.forEach((output) => applyManualChunks(output));
|
|
3532
|
+
desiredRolldownOutput = rolldownOutput.map((output) => snapshotRolldownOutput(output));
|
|
3533
|
+
} else {
|
|
3534
|
+
applyManualChunks(buildWithRolldown.rolldownOptions.output ||= {});
|
|
3535
|
+
desiredRolldownOutput = [snapshotRolldownOutput(buildWithRolldown.rolldownOptions.output)];
|
|
3536
|
+
}
|
|
3537
|
+
},
|
|
3538
|
+
async buildApp(builder) {
|
|
3539
|
+
if (!desiredRolldownOutput) return;
|
|
3540
|
+
const applyRolldownOutput = (output, restoredOutput) => {
|
|
3541
|
+
if (!output || !restoredOutput) return;
|
|
3542
|
+
if (restoredOutput.entryFileNames !== void 0) output.entryFileNames = restoredOutput.entryFileNames;
|
|
3543
|
+
if (restoredOutput.chunkFileNames !== void 0) output.chunkFileNames = restoredOutput.chunkFileNames;
|
|
3544
|
+
if (restoredOutput.assetFileNames !== void 0) output.assetFileNames = restoredOutput.assetFileNames;
|
|
3545
|
+
};
|
|
3546
|
+
for (const environment of Object.values(builder.environments)) {
|
|
3547
|
+
const getRolldownOptions = environment?.getRolldownOptions;
|
|
3548
|
+
if (typeof getRolldownOptions !== "function") continue;
|
|
3549
|
+
environment.getRolldownOptions = async () => {
|
|
3550
|
+
const rolldownOptions = await getRolldownOptions.call(environment);
|
|
3551
|
+
if (Array.isArray(rolldownOptions.output)) rolldownOptions.output.forEach((output, index) => applyRolldownOutput(output, desiredRolldownOutput?.[index]));
|
|
3552
|
+
else {
|
|
3553
|
+
rolldownOptions.output ||= {};
|
|
3554
|
+
applyRolldownOutput(rolldownOptions.output, desiredRolldownOutput[0]);
|
|
3555
|
+
}
|
|
3556
|
+
return rolldownOptions;
|
|
3557
|
+
};
|
|
3558
|
+
}
|
|
3402
3559
|
},
|
|
3403
3560
|
load(id) {
|
|
3404
3561
|
if (id.startsWith("\0")) return;
|
|
@@ -3452,11 +3609,9 @@ function federation(mfUserOptions) {
|
|
|
3452
3609
|
for (const v of importedFromLoadShare) if (new RegExp("\\(" + v + "\\(\\)\\s*,\\s*\\w+\\(\\w+\\)\\)").test(code)) allInits.push(v);
|
|
3453
3610
|
if (allInits.length === 0) continue;
|
|
3454
3611
|
const awaits = allInits.map((v) => `await ${v}();`).join("");
|
|
3455
|
-
const
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
if (lastFromEnd !== -1) {
|
|
3459
|
-
chunk.code = code.slice(0, lastFromEnd) + awaits + code.slice(lastFromEnd);
|
|
3612
|
+
const codeWithAwaits = insertAfterLastTopLevelImport(code, awaits);
|
|
3613
|
+
if (codeWithAwaits) {
|
|
3614
|
+
chunk.code = codeWithAwaits;
|
|
3460
3615
|
continue;
|
|
3461
3616
|
}
|
|
3462
3617
|
const exportIdx = code.search(/\bexport\s*[{d]/);
|
|
@@ -3587,14 +3742,7 @@ function federation(mfUserOptions) {
|
|
|
3587
3742
|
})) return;
|
|
3588
3743
|
if (/await\s+init_\w+__loadShare__/.test(code)) return;
|
|
3589
3744
|
if (code.includes("__esmMin")) return;
|
|
3590
|
-
|
|
3591
|
-
const topLevelImportRe = /^import\s/gm;
|
|
3592
|
-
let lastImportIdx = -1;
|
|
3593
|
-
let importMatch;
|
|
3594
|
-
while ((importMatch = topLevelImportRe.exec(code)) !== null) lastImportIdx = importMatch.index;
|
|
3595
|
-
if (lastImportIdx === -1) return;
|
|
3596
|
-
const lineEnd = code.indexOf("\n", lastImportIdx);
|
|
3597
|
-
return code.slice(0, lineEnd + 1) + awaits + "\n" + code.slice(lineEnd + 1);
|
|
3745
|
+
return insertAfterLastTopLevelImport(code, [...initFns].map((fn) => `await ${fn}();`).join("\n") + "\n");
|
|
3598
3746
|
}
|
|
3599
3747
|
},
|
|
3600
3748
|
PluginDevProxyModuleTopLevelAwait(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/vite",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.4",
|
|
4
4
|
"description": "Vite plugin for Module Federation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.cjs",
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@module-federation/dts-plugin": "2.3.
|
|
74
|
-
"@module-federation/runtime": "2.3.
|
|
75
|
-
"@module-federation/sdk": "2.3.
|
|
73
|
+
"@module-federation/dts-plugin": "2.3.3",
|
|
74
|
+
"@module-federation/runtime": "2.3.3",
|
|
75
|
+
"@module-federation/sdk": "2.3.3",
|
|
76
76
|
"@rollup/pluginutils": "^5.3.0",
|
|
77
77
|
"defu": "^6.1.4",
|
|
78
78
|
"es-module-lexer": "^2.0.0",
|