@module-federation/vite 1.16.13 → 1.16.14

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.
Files changed (2) hide show
  1. package/lib/index.js +99 -56
  2. package/package.json +4 -4
package/lib/index.js CHANGED
@@ -380,7 +380,9 @@ function normalizeShared(shared) {
380
380
  if (Array.isArray(shared)) shared.forEach((key) => {
381
381
  if (isModuleFederationRuntimePackage(key)) return;
382
382
  const normalizedKey = normalizeSharedKey(key);
383
+ const hadConfiguredPackageSubpath = (result[normalizedKey]?.shareConfig)?.__mfConfiguredPackageSubpath === true;
383
384
  result[normalizedKey] = normalizeShareItem(normalizedKey, normalizedKey);
385
+ if (key.endsWith("/") || hadConfiguredPackageSubpath) result[normalizedKey].shareConfig.__mfConfiguredPackageSubpath = true;
384
386
  explicitSharedKeys.add(normalizedKey);
385
387
  sourceEntries.push([normalizedKey, normalizedKey]);
386
388
  });
@@ -388,7 +390,9 @@ function normalizeShared(shared) {
388
390
  if (isModuleFederationRuntimePackage(key)) return;
389
391
  const normalizedKey = normalizeSharedKey(key);
390
392
  const value = shared[key];
393
+ const hadConfiguredPackageSubpath = (result[normalizedKey]?.shareConfig)?.__mfConfiguredPackageSubpath === true;
391
394
  result[normalizedKey] = normalizeShareItem(normalizedKey, value);
395
+ if (key.endsWith("/") || hadConfiguredPackageSubpath) result[normalizedKey].shareConfig.__mfConfiguredPackageSubpath = true;
392
396
  explicitSharedKeys.add(normalizedKey);
393
397
  sourceEntries.push([normalizedKey, value]);
394
398
  });
@@ -1142,6 +1146,15 @@ function getWorkspacePackageJson(pkg) {
1142
1146
  fromResolvedEntry: resolved
1143
1147
  })?.packageJson;
1144
1148
  }
1149
+ function getSharedDependencyGraphPackageJson(pkg) {
1150
+ const installedPackageJson = getInstalledPackageJson(pkg, { packageName: getPackageName(pkg) })?.packageJson;
1151
+ if (installedPackageJson) return installedPackageJson;
1152
+ try {
1153
+ const packageJsonPath = createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(`${getPackageName(pkg)}/package.json`);
1154
+ return JSON.parse(readFileSync(packageJsonPath, "utf-8"));
1155
+ } catch {}
1156
+ return getWorkspacePackageJson(pkg);
1157
+ }
1145
1158
  function getDependencyNames(packageJson) {
1146
1159
  if (!packageJson) return [];
1147
1160
  const names = /* @__PURE__ */ new Set();
@@ -1156,7 +1169,7 @@ function getDependencyNames(packageJson) {
1156
1169
  }
1157
1170
  return Array.from(names);
1158
1171
  }
1159
- function isWorkspaceSingletonConsumedByPeer(pkg) {
1172
+ function isSharedSingletonConsumedByPeer(pkg) {
1160
1173
  const shared = getNormalizeModuleFederationOptions()?.shared || {};
1161
1174
  const sharedKeyByPackageName = /* @__PURE__ */ new Map();
1162
1175
  Object.entries(shared).filter(([, item]) => item.shareConfig.singleton === true).forEach(([key]) => {
@@ -1164,7 +1177,7 @@ function isWorkspaceSingletonConsumedByPeer(pkg) {
1164
1177
  if (!sharedKeyByPackageName.get(packageName) || key === packageName) sharedKeyByPackageName.set(packageName, key);
1165
1178
  });
1166
1179
  const reachesPkg = (current, seen) => {
1167
- const packageJson = getWorkspacePackageJson(current);
1180
+ const packageJson = getSharedDependencyGraphPackageJson(current);
1168
1181
  for (const dependency of getDependencyNames(packageJson)) {
1169
1182
  const sharedDependency = sharedKeyByPackageName.get(dependency);
1170
1183
  if (!sharedDependency) continue;
@@ -1177,6 +1190,10 @@ function isWorkspaceSingletonConsumedByPeer(pkg) {
1177
1190
  };
1178
1191
  return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && reachesPkg(sharedPkg, new Set([sharedPkg])));
1179
1192
  }
1193
+ function isRemoteOnlyContainer() {
1194
+ const options = getNormalizeModuleFederationOptions();
1195
+ return Object.keys(options.exposes || {}).length > 0 && Object.keys(options.remotes || {}).length === 0;
1196
+ }
1180
1197
  function tryResolveImportFromPackageRoot(pkg, root) {
1181
1198
  try {
1182
1199
  return resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(root, "package.json"))).resolve(pkg), root);
@@ -1330,22 +1347,21 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
1330
1347
  const __mf_default = exportModule.default ?? exportModule;${namedExportAssignments}
1331
1348
  export { __mf_default as default };${namedExportLine}`;
1332
1349
  }
1333
- function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, eagerLocalFallback) {
1350
+ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor) {
1334
1351
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1335
1352
  const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
1336
1353
  const assignments = namedExports.length > 0 ? [...namedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = mod.default ?? mod;"].join("\n ") : "__mf_default = mod.default ?? mod;";
1337
1354
  const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1338
- const applyLocalFallback = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1339
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1340
- __mfApplyLazyShareExports(exportModule);`;
1341
- const body = `${declarations}
1355
+ return `${declarations}
1342
1356
  const __mfApplyLazyShareExports = (mod) => {
1343
1357
  ${assignments}
1344
1358
  };
1345
1359
  let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1346
1360
  if (exportModule === undefined) {
1347
- ${eagerLocalFallback ? applyLocalFallback : `if (import.meta.env.SSR) {
1348
- ${applyLocalFallback}
1361
+ if (import.meta.env.SSR) {
1362
+ ${`exportModule = __mfNormalizeShareModule(__mfLocalShare);
1363
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1364
+ __mfApplyLazyShareExports(exportModule);`}
1349
1365
  } else {
1350
1366
  (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() =>
1351
1367
  import(${escapeGeneratedStringLiteral(importSource)}).then((mod) => {
@@ -1354,13 +1370,11 @@ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cache
1354
1370
  __mfApplyLazyShareExports(exportModule);
1355
1371
  })
1356
1372
  ));
1357
- }`}
1373
+ }
1358
1374
  } else {
1359
1375
  __mfApplyLazyShareExports(exportModule);
1360
1376
  }
1361
1377
  export { __mf_default as default };${namedExportLine}`;
1362
- return eagerLocalFallback ? `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(importSource)};
1363
- ${body}` : body;
1364
1378
  }
1365
1379
  const WORKSPACE_SINGLETON_SSR_LOCAL_SHARE = "__mfNormalizeShareModule(__mfLocalShare)";
1366
1380
  function prependWorkspaceSingletonSsrImport(code) {
@@ -1434,17 +1448,21 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1434
1448
  const devImportSource = concreteSharedImportSource || pkg;
1435
1449
  const localProviderPath = getLocalProviderImportPath(pkg);
1436
1450
  const isWorkspacePackage = isWorkspacePackageEntry(pkg, localProviderPath) || isWorkspacePackageEntry(pkg, concreteSharedImportSource);
1437
- const lazyLocalFallbackSource = concreteSharedImportSource || localProviderPath || sharedImportSource;
1451
+ const lazyLocalFallbackSource = command !== "build" ? concreteSharedImportSource || localProviderPath || devImportSource : concreteSharedImportSource || localProviderPath || sharedImportSource;
1438
1452
  const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
1439
1453
  const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
1440
- const usesEagerWorkspaceFallback = isWorkspaceSingleton && isWorkspaceSingletonConsumedByPeer(pkg);
1454
+ const isDefaultShareScope = shareItem.scope === void 0 || shareItem.scope === "default" || Array.isArray(shareItem.scope) && shareItem.scope[0] === "default";
1455
+ const usesDeferredSingletonFallback = isWorkspaceSingleton || command !== "build" && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && !isDefaultShareScope;
1456
+ const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg);
1457
+ const usesEntryInjectedRemoteFallback = command !== "build" && !isWorkspaceSingleton && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && getNormalizeModuleFederationOptions().hostInitInjectLocation === "entry" && isConsumedByPeerSingleton;
1458
+ const usesEagerWorkspaceFallback = isWorkspaceSingleton && isConsumedByPeerSingleton;
1441
1459
  const namedExports = getSharedNamedExports(pkg, shareItem);
1442
1460
  let exportLine;
1443
1461
  let initBlock = "";
1444
- if (usesEagerWorkspaceFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor);
1445
- else if (isWorkspaceSingleton) {
1462
+ if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor);
1463
+ else if (usesDeferredSingletonFallback) {
1446
1464
  importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
1447
- exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, command !== "build");
1465
+ exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor);
1448
1466
  } else if (namedExports.length > 0) {
1449
1467
  const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1450
1468
  const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
@@ -1465,9 +1483,9 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1465
1483
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1466
1484
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);`;
1467
1485
  }
1468
- const prebuildImportLine = isWorkspaceSingleton || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
1469
- const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
1470
- const moduleBody = isWorkspaceSingleton ? `
1486
+ const prebuildImportLine = usesDeferredSingletonFallback || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
1487
+ const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
1488
+ const moduleBody = usesDeferredSingletonFallback ? `
1471
1489
  ${prebuildImportLine}
1472
1490
  ${devDynamicImportLine}
1473
1491
  ${importLine}
@@ -1600,29 +1618,14 @@ function generateLocalSharedImportMap() {
1600
1618
  }
1601
1619
  `;
1602
1620
  }
1603
- function generateUsedSharedPreloadConfig() {
1604
- return `{
1605
- ${getOrderedUsedShares().map((pkg) => {
1606
- const shareItem = getShareItemForPreload(pkg);
1607
- if (!shareItem) return null;
1608
- return `${JSON.stringify(pkg)}: {
1609
- version: ${JSON.stringify(shareItem.version)},
1610
- scope: ${JSON.stringify(shareItem.scope)},
1611
- shareConfig: {
1612
- singleton: ${shareItem.shareConfig.singleton},
1613
- requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
1614
- strictVersion: ${shareItem.shareConfig.strictVersion},
1615
- ${shareItem.shareConfig.import === false ? "import: false," : ""}
1616
- }
1617
- }`;
1618
- }).filter((item) => item !== null).join(",\n")}
1619
- }`;
1620
- }
1621
1621
  function getOrderedUsedShares() {
1622
1622
  const shares = new Set(getUsedShares());
1623
1623
  try {
1624
1624
  Object.keys(getNormalizeModuleFederationOptions().shared).forEach((pkg) => {
1625
- if (!pkg.endsWith("/")) shares.add(pkg);
1625
+ if (!pkg.endsWith("/")) {
1626
+ shares.add(pkg);
1627
+ return;
1628
+ }
1626
1629
  });
1627
1630
  } catch {}
1628
1631
  return orderSharedDependenciesFirst(Array.from(shares).sort((a, b) => {
@@ -1725,12 +1728,31 @@ const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbo
1725
1728
  function hasImportFalseShared$1(options) {
1726
1729
  return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
1727
1730
  }
1728
- function generateDirectSharedCacheSeedCode(command = "build") {
1729
- return getOrderedUsedShares().map((pkg) => {
1730
- const shareItem = getShareItemForPreload(pkg);
1731
- if (!shareItem || shareItem.shareConfig.import === false) return null;
1732
- return generateSharedCacheSeedItem(pkg, shareItem, command === "serve" ? getLocalSharedPackagePath(pkg, shareItem) : getDirectSharedCacheSeedImportPath(pkg, shareItem));
1733
- }).filter((item) => item !== null).join("\n");
1731
+ function generateRuntimeSharedCacheSeedCode() {
1732
+ return `
1733
+ for (const [pkg, share] of Object.entries(usedShared)) {
1734
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
1735
+ if (share.shareConfig?.import === false || __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) {
1736
+ continue;
1737
+ }
1738
+ const singletonCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, true, share.version, share.scope);
1739
+ const singletonModule = __mfReadSharedCache(__mfModuleCache.share, singletonCacheDescriptor);
1740
+ if (singletonModule !== undefined) {
1741
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, singletonModule);
1742
+ continue;
1743
+ }
1744
+ const factory = await share.get();
1745
+ const mod = typeof factory === "function" ? factory() : factory;
1746
+ const resolved = await Promise.resolve(mod);
1747
+ ${normalizeRuntimeShareCode}
1748
+ const normalizedModule = __mfNormalizeRuntimeShare(resolved);
1749
+ const exportModule = normalizedModule === resolved ? {...resolved} : normalizedModule;
1750
+ Object.defineProperty(exportModule, "__esModule", {
1751
+ value: true,
1752
+ enumerable: false
1753
+ });
1754
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, exportModule);
1755
+ }`;
1734
1756
  }
1735
1757
  function getBrowserImportPath(importPath) {
1736
1758
  if (/^(?:[a-zA-Z]:[\\/]|\/)/.test(importPath) && !importPath.startsWith("/@")) return `/@fs/${importPath}`;
@@ -1880,7 +1902,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1880
1902
  __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, singletonModule);
1881
1903
  }
1882
1904
  }
1883
- ${generateDirectSharedCacheSeedCode(command)}
1905
+ ${generateRuntimeSharedCacheSeedCode()}
1884
1906
  const __browserPlugins = [${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => `${item[0]}(${item[2]})`).join(", ")}];
1885
1907
  const __ssrPlugins = typeof globalThis.window === 'undefined'
1886
1908
  ? await Promise.all([${pluginImportNames.filter((item) => isSsrOnlyPlugin(item[1])).map((item) => {
@@ -1956,7 +1978,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
1956
1978
  ${generateHostAutoInitSharedCacheSeedCode(_command)}
1957
1979
  const remoteEntry = await import(${remoteEntryImport});
1958
1980
  const runtime = await remoteEntry.init();
1959
- const usedShared = ${generateUsedSharedPreloadConfig()};
1981
+ const {usedShared} = await import("${getLocalSharedImportMapPath()}");
1960
1982
  ${normalizeRuntimeShareCode}
1961
1983
  ${shouldPreloadShares ? `
1962
1984
  for (const [pkg, share] of Object.entries(usedShared)) {
@@ -4116,11 +4138,37 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4116
4138
  function isRemoteImport(source) {
4117
4139
  return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
4118
4140
  }
4119
- function collectRemoteDependencies(code) {
4120
- const dependencies = /* @__PURE__ */ new Set();
4141
+ function collectImportSources(code) {
4142
+ const sources = /* @__PURE__ */ new Set();
4121
4143
  for (const match of code.matchAll(/(?:^|[;\n\r])\s*import\s+(?:[\s\S]*?\s+from\s+)?["']([^"']+)["']|import\(\s*["']([^"']+)["']\s*\)/g)) {
4122
4144
  const source = match[1] || match[2];
4123
- if (source && isRemoteImport(source)) dependencies.add(source);
4145
+ if (source) sources.add(source);
4146
+ }
4147
+ return Array.from(sources).sort();
4148
+ }
4149
+ function shouldScanResolvedImport(id) {
4150
+ if (!id || id.includes("\0")) return false;
4151
+ if (id.includes("/node_modules/") || id.includes("\\node_modules\\")) return false;
4152
+ return /\.(?:[cm]?[jt]sx?|vue|svelte)(?:\?|$)/.test(id);
4153
+ }
4154
+ async function collectRemoteDependencies(ctx, id, seen = /* @__PURE__ */ new Set()) {
4155
+ if (seen.has(id) || !shouldScanResolvedImport(id)) return [];
4156
+ seen.add(id);
4157
+ let code;
4158
+ try {
4159
+ code = readFileSync$1(id, "utf8");
4160
+ } catch {
4161
+ return [];
4162
+ }
4163
+ const dependencies = /* @__PURE__ */ new Set();
4164
+ for (const source of collectImportSources(code)) {
4165
+ if (isRemoteImport(source)) {
4166
+ dependencies.add(source);
4167
+ continue;
4168
+ }
4169
+ const resolved = await ctx.resolve(source, id);
4170
+ if (!resolved?.id || !shouldScanResolvedImport(resolved.id)) continue;
4171
+ for (const dependency of await collectRemoteDependencies(ctx, resolved.id, seen)) dependencies.add(dependency);
4124
4172
  }
4125
4173
  return Array.from(dependencies).sort();
4126
4174
  }
@@ -4128,12 +4176,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4128
4176
  const next = {};
4129
4177
  for (const [exposeKey, expose] of Object.entries(options.exposes)) {
4130
4178
  const resolved = await ctx.resolve(expose.import);
4131
- if (!resolved?.id || resolved.id.includes("\0")) continue;
4132
- try {
4133
- next[exposeKey] = collectRemoteDependencies(readFileSync$1(resolved.id, "utf8"));
4134
- } catch {
4135
- next[exposeKey] = [];
4136
- }
4179
+ next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id) : [];
4137
4180
  }
4138
4181
  exposeRemoteDependencies = next;
4139
4182
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/vite",
3
- "version": "1.16.13",
3
+ "version": "1.16.14",
4
4
  "description": "Vite plugin for Module Federation",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -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.6.0",
74
- "@module-federation/runtime": "2.6.0",
75
- "@module-federation/sdk": "2.6.0"
73
+ "@module-federation/dts-plugin": "2.7.0",
74
+ "@module-federation/runtime": "2.7.0",
75
+ "@module-federation/sdk": "2.7.0"
76
76
  },
77
77
  "devDependencies": {
78
78
  "@playwright/test": "1.58.2",