@module-federation/vite 1.23.8 → 1.23.10

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.
@@ -1,5 +1,5 @@
1
- import { r as mfWarn, t as createModuleFederationError, u as normalizePathForImport } from "./logger-D67aJYOe.js";
2
- import { d as getNodeModulesSuffix, r as getSharedRuntimeKey } from "./sharedKeyMatcher-C04bVN1q.js";
1
+ import { p as normalizePathForImport, r as mfWarn, t as createModuleFederationError } from "./logger-Ckj1FMRH.js";
2
+ import { d as getNodeModulesSuffix, r as getSharedRuntimeKey } from "./sharedKeyMatcher-B5VKsEVQ.js";
3
3
  import { existsSync, readFileSync, readdirSync, realpathSync } from "fs";
4
4
  import { createRequire } from "module";
5
5
  import * as path$1 from "node:path";
@@ -28,6 +28,14 @@ const REACT_DOM_CLIENT_SHARE = "react-dom/client";
28
28
  function isReactCoreShare(pkg) {
29
29
  return pkg === "react" || pkg.startsWith("react/");
30
30
  }
31
+ /**
32
+ * React and its renderer, including subpath exports. Their wrappers bind
33
+ * synchronously and carry the mixed-mode guard, so the generic deferral of a
34
+ * negotiated singleton's local copy does not apply to them.
35
+ */
36
+ function isReactFamilyShare(pkg) {
37
+ return isReactCoreShare(pkg) || pkg === "react-dom" || pkg.startsWith("react-dom/");
38
+ }
31
39
  //#endregion
32
40
  //#region src/utils/packageUtils.ts
33
41
  const dependencyPresenceCache = /* @__PURE__ */ new Map();
@@ -790,4 +798,4 @@ function watchFileEvents(watcher, listener) {
790
798
  //#region src/utils/dtsConstants.ts
791
799
  const DEFAULT_PUBLIC_TYPES_FOLDER = "@mf-types";
792
800
  //#endregion
793
- export { sharedCacheHelperCode as C, isReactCoreShare as D, REACT_DOM_CLIENT_SHARE as E, setPackageDetectionCwd as S, REACT_CLIENT_INTERNALS_KEY as T, isPackageInstalled as _, getDependencyNames as a, resolveImportPath as b, getIsRolldown as c, getPackageName as d, getPackageNameFromNodeModulePath as f, isPackageExportAvailable as g, isNuxtProjectRoot as h, findPackageInDependents as i, getPackageDetectionCwd as l, hasPackageDependency as m, formatDevServerHostForOrigin as n, getInstalledPackageEntry as o, getSharedCacheDescriptor as p, watchFileEvents as r, getInstalledPackageJson as s, DEFAULT_PUBLIC_TYPES_FOLDER as t, getPackageExportSpecifiersForFile as u, packageNameDecode as v, supportsCodeSplittingGroupDebugName as w, resolveModulePath as x, packageNameEncode as y };
801
+ export { sharedCacheHelperCode as C, isReactCoreShare as D, REACT_DOM_CLIENT_SHARE as E, isReactFamilyShare as O, setPackageDetectionCwd as S, REACT_CLIENT_INTERNALS_KEY as T, isPackageInstalled as _, getDependencyNames as a, resolveImportPath as b, getIsRolldown as c, getPackageName as d, getPackageNameFromNodeModulePath as f, isPackageExportAvailable as g, isNuxtProjectRoot as h, findPackageInDependents as i, getPackageDetectionCwd as l, hasPackageDependency as m, formatDevServerHostForOrigin as n, getInstalledPackageEntry as o, getSharedCacheDescriptor as p, watchFileEvents as r, getInstalledPackageJson as s, DEFAULT_PUBLIC_TYPES_FOLDER as t, getPackageExportSpecifiersForFile as u, packageNameDecode as v, supportsCodeSplittingGroupDebugName as w, resolveModulePath as x, packageNameEncode as y };
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { a as CodeRewriter, c as isAbsoluteUrl, d as rebaseImport, f as resolveHashPlaceholderFileName, i as createCodePositionMap, l as isHttpUrl, o as createSourceMap, r as mfWarn, t as createModuleFederationError, u as normalizePathForImport } from "./logger-D67aJYOe.js";
2
- import { _ as removeTrailingSlash, a as matchesSharedSource, b as stripViteFsPrefix, c as filterId, d as getNodeModulesSuffix, f as isAssetLikeImport, g as normalizeNodeModulePath, h as isViteOptimizableEntry, i as invalidateSharedKeyMatcher, l as getBasePath$1, m as isNuxtClientBase, n as getSharedRequest, p as isNodeModulePath, r as getSharedRuntimeKey, s as ensureTrailingSlash, t as findSharedKey, u as getCommonSharedSubpaths, v as resolvePublicPath, x as toRelativeImport, y as stripQueryAndHash } from "./sharedKeyMatcher-C04bVN1q.js";
3
- import { C as sharedCacheHelperCode, D as isReactCoreShare, E as REACT_DOM_CLIENT_SHARE, S as setPackageDetectionCwd, T as REACT_CLIENT_INTERNALS_KEY, _ as isPackageInstalled, a as getDependencyNames, b as resolveImportPath, c as getIsRolldown, d as getPackageName, f as getPackageNameFromNodeModulePath, g as isPackageExportAvailable, h as isNuxtProjectRoot, i as findPackageInDependents, l as getPackageDetectionCwd, m as hasPackageDependency, n as formatDevServerHostForOrigin, o as getInstalledPackageEntry, p as getSharedCacheDescriptor, r as watchFileEvents, s as getInstalledPackageJson, u as getPackageExportSpecifiersForFile, v as packageNameDecode, w as supportsCodeSplittingGroupDebugName, x as resolveModulePath, y as packageNameEncode } from "./dtsConstants-286VtFnC.js";
1
+ import { a as CodeRewriter, c as VITE_ID_PREFIX, d as isAbsoluteUrl, f as isHttpUrl, h as resolveHashPlaceholderFileName, i as createCodePositionMap, l as VITE_NULL_BYTE_PLACEHOLDER, m as rebaseImport, o as createSourceMap, p as normalizePathForImport, r as mfWarn, t as createModuleFederationError, u as decodeViteId } from "./logger-Ckj1FMRH.js";
2
+ import { _ as removeTrailingSlash, a as matchesSharedSource, b as stripViteFsPrefix, c as filterId, d as getNodeModulesSuffix, f as isAssetLikeImport, g as normalizeNodeModulePath, h as isViteOptimizableEntry, i as invalidateSharedKeyMatcher, l as getBasePath$1, m as isNuxtClientBase, n as getSharedRequest, p as isNodeModulePath, r as getSharedRuntimeKey, s as ensureTrailingSlash, t as findSharedKey, u as getCommonSharedSubpaths, v as resolvePublicPath, x as toRelativeImport, y as stripQueryAndHash } from "./sharedKeyMatcher-B5VKsEVQ.js";
3
+ import { C as sharedCacheHelperCode, D as isReactCoreShare, E as REACT_DOM_CLIENT_SHARE, O as isReactFamilyShare, S as setPackageDetectionCwd, T as REACT_CLIENT_INTERNALS_KEY, _ as isPackageInstalled, a as getDependencyNames, b as resolveImportPath, c as getIsRolldown, d as getPackageName, f as getPackageNameFromNodeModulePath, g as isPackageExportAvailable, h as isNuxtProjectRoot, i as findPackageInDependents, l as getPackageDetectionCwd, m as hasPackageDependency, n as formatDevServerHostForOrigin, o as getInstalledPackageEntry, p as getSharedCacheDescriptor, r as watchFileEvents, s as getInstalledPackageJson, u as getPackageExportSpecifiersForFile, v as packageNameDecode, w as supportsCodeSplittingGroupDebugName, x as resolveModulePath, y as packageNameEncode } from "./dtsConstants-DIcz34LN.js";
4
4
  import { createRequire } from "node:module";
5
5
  import * as fs$2 from "fs";
6
6
  import { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
@@ -852,8 +852,7 @@ function getSuffix(name) {
852
852
  const patternMap = {};
853
853
  const cacheMap = {};
854
854
  const idCacheMap = {};
855
- const VITE_ID_PREFIX = "/@id/";
856
- const VITE_ENCODED_NULL_BYTE_PREFIX = `${VITE_ID_PREFIX}__x00__`;
855
+ const VITE_ENCODED_NULL_BYTE_PREFIX = `${VITE_ID_PREFIX}${VITE_NULL_BYTE_PLACEHOLDER}`;
857
856
  const MF_OWNER_INFIX = "__mf_owner__";
858
857
  function createViteEncodedIdPrefixRegExp(sourcePrefix = "") {
859
858
  return new RegExp(`^(?:${escapeRegExp(VITE_ENCODED_NULL_BYTE_PREFIX)})?${sourcePrefix}`);
@@ -861,11 +860,6 @@ function createViteEncodedIdPrefixRegExp(sourcePrefix = "") {
861
860
  function toViteEncodedId(id) {
862
861
  return `${VITE_ENCODED_NULL_BYTE_PREFIX}${id}`;
863
862
  }
864
- function decodeViteId(id) {
865
- if (!id.startsWith("/@id/")) return id;
866
- const viteId = id.slice(5);
867
- return viteId.startsWith("__x00__") ? `\0${viteId.slice(7)}` : viteId;
868
- }
869
863
  function assertModuleFound(tag, str = "") {
870
864
  const module = VirtualModule.findById(str) ?? VirtualModule.findModule(tag, str);
871
865
  if (!module) throw createModuleFederationError(`Module Federation shared module '${str}' not found. Please ensure it's installed as a dependency in your package.json.`);
@@ -1982,6 +1976,19 @@ function hasCodeMatch(source, regex, codePositions) {
1982
1976
  while ((match = regex.exec(source)) !== null) if (codePositions[match.index]) return true;
1983
1977
  return false;
1984
1978
  }
1979
+ /** True when the code before `index` is a `.`: member access (`obj.export`), not an identifier. */
1980
+ function isMemberName(source, index, codePositions) {
1981
+ let previousCodeIndex = index - 1;
1982
+ while (previousCodeIndex >= 0 && (/\s/.test(source[previousCodeIndex]) || !codePositions[previousCodeIndex])) previousCodeIndex--;
1983
+ return source[previousCodeIndex] === ".";
1984
+ }
1985
+ /** TypeScript `export = value`; an assignment to a member named `export` (`e.export = 'export'`) is not one. */
1986
+ function hasExportAssignment(source, codePositions) {
1987
+ const regex = /\bexport\s*=/g;
1988
+ let match;
1989
+ while ((match = regex.exec(source)) !== null) if (codePositions[match.index] && !isMemberName(source, match.index, codePositions)) return true;
1990
+ return false;
1991
+ }
1985
1992
  /**
1986
1993
  * True when the file contains a top-level static `import`/`export` declaration.
1987
1994
  * Local identifiers named `module` or `exports` (webpack/rspack helpers,
@@ -2000,9 +2007,7 @@ function hasEsmModuleSyntax(source, codePositions) {
2000
2007
  }
2001
2008
  if (!codePositions[match.index]) continue;
2002
2009
  if (braceDepth !== 0) continue;
2003
- let previousCodeIndex = match.index - 1;
2004
- while (previousCodeIndex >= 0 && (/\s/.test(source[previousCodeIndex]) || !codePositions[previousCodeIndex])) previousCodeIndex--;
2005
- if (source[previousCodeIndex] === ".") continue;
2010
+ if (isMemberName(source, match.index, codePositions)) continue;
2006
2011
  let nextCodeIndex = match.index + match[0].length;
2007
2012
  while (nextCodeIndex < source.length && (/\s/.test(source[nextCodeIndex]) || !codePositions[nextCodeIndex])) nextCodeIndex++;
2008
2013
  if (source[nextCodeIndex] === "(") continue;
@@ -2018,9 +2023,7 @@ function hasCommonJsExports(source) {
2018
2023
  let match;
2019
2024
  while ((match = exportsRegex.exec(source)) !== null) {
2020
2025
  if (!codePositions[match.index]) continue;
2021
- let previousCodeIndex = match.index - 1;
2022
- while (previousCodeIndex >= 0 && (/\s/.test(source[previousCodeIndex]) || !codePositions[previousCodeIndex])) previousCodeIndex--;
2023
- if (source[previousCodeIndex] === ".") continue;
2026
+ if (isMemberName(source, match.index, codePositions)) continue;
2024
2027
  return true;
2025
2028
  }
2026
2029
  return false;
@@ -2289,7 +2292,7 @@ function getNamedExportsViaRegex(source, filePath, visited, scanState = { comple
2289
2292
  else for (const name of additionalNames) names.add(name);
2290
2293
  if (hasUnsupportedBindingPattern(source, exportedVariableDeclarationRegex.lastIndex)) scanState.complete = false;
2291
2294
  }
2292
- if (hasCodeMatch(source, /export\s+import\s+/g, codePositions) || hasCodeMatch(source, /export\s*=/g, codePositions)) scanState.complete = false;
2295
+ if (hasCodeMatch(source, /export\s+import\s+/g, codePositions) || hasExportAssignment(source, codePositions)) scanState.complete = false;
2293
2296
  if (hasCodeMatch(source, /export\s+@/g, codePositions)) scanState.complete = false;
2294
2297
  const destructureRegex = /export\s+(?:const|let|var)\s+(\{[^}]*\}|\[[^\]]*\])\s*=/g;
2295
2298
  const bindingNameRegex = new RegExp(`^(${JS_IDENTIFIER_PATTERN})`, "u");
@@ -2373,9 +2376,7 @@ function getNamedExportsViaRegex(source, filePath, visited, scanState = { comple
2373
2376
  while ((match = exportKeywordRegex.exec(source)) !== null) {
2374
2377
  if (!codePositions[match.index]) continue;
2375
2378
  if (recognizedExportStarts.has(match.index)) continue;
2376
- let previousCodeIndex = match.index - 1;
2377
- while (previousCodeIndex >= 0 && (/\s/.test(source[previousCodeIndex]) || !codePositions[previousCodeIndex])) previousCodeIndex--;
2378
- if (source[previousCodeIndex] === ".") continue;
2379
+ if (isMemberName(source, match.index, codePositions)) continue;
2379
2380
  let nextCodeIndex = match.index + match[0].length;
2380
2381
  while (nextCodeIndex < source.length && (/\s/.test(source[nextCodeIndex]) || !codePositions[nextCodeIndex])) nextCodeIndex++;
2381
2382
  if (source[nextCodeIndex] === "(") continue;
@@ -3003,13 +3004,18 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor,
3003
3004
  const declarations = ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ");
3004
3005
  const assignments = [...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ");
3005
3006
  const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
3007
+ const subscribeToLateShare = treeShakingConsumer ? "" : `__mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, (mod) => {
3008
+ exportModule = mod;
3009
+ __mfApplyHostProvidedExports(mod);
3010
+ });
3011
+ `;
3006
3012
  return `${declarations}
3007
3013
  const __mfApplyHostProvidedExports = (exportModule) => {
3008
3014
  ${assignments}
3009
3015
  };
3010
3016
  let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3011
3017
  if (exportModule === undefined) {
3012
- __mfTrackPendingShareLoad(initPromise.then(() => {
3018
+ ${subscribeToLateShare}__mfTrackPendingShareLoad(initPromise.then(() => {
3013
3019
  exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3014
3020
  // A share init() left to its dynamic import is normally bridged before that import runs;
3015
3021
  // bridge it here when this wrapper is reached another way.
@@ -3168,11 +3174,12 @@ function writeLoadShareModule(pkg, shareItem, command, options, exportConditions
3168
3174
  const hasCompleteExportCoverage = detectedNamedExports !== void 0;
3169
3175
  const isSingleton = shareItem.shareConfig.singleton === true;
3170
3176
  const isWorkspaceSingleton = isWorkspacePackage && isSingleton;
3171
- const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(options) && isSingleton || command === "build" && isRemoteContainer(options) && !isSharedSingletonConsumedByPeer(pkg, options, true));
3177
+ const negotiatesSingletonWithRemotes = isSingleton && !isReactFamilyShare(pkg) && options.shareStrategy === "version-first" && hasRemotes(options) && pkg !== "solid-js" && !isSharedSingletonConsumedByPeer(pkg, options, true);
3178
+ const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || negotiatesSingletonWithRemotes || command !== "build" && isRemoteOnlyContainer(options) && isSingleton || command === "build" && isRemoteContainer(options) && !isSharedSingletonConsumedByPeer(pkg, options, true));
3172
3179
  const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(options) && isSingleton;
3173
3180
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, options);
3174
3181
  const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(options) && isSingleton && options.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3175
- const usesDeferredEntryInjectedSingletonFallback = usesEntryInjectedRemoteFallback && !isReactCoreShare(pkg) && (pkg === "react-dom/client" || shareItem.shareConfig.eager !== true && !isSharedSingletonConsumedByPeer(pkg, options, true));
3182
+ const usesDeferredEntryInjectedSingletonFallback = command === "build" && hasCompleteExportCoverage && isSingleton && pkg === "react-dom/client" && !isWorkspaceSingleton && options.hostInitInjectLocation === "entry" && hasRemotes(options) && !hasPackageDependency("vinext") || usesEntryInjectedRemoteFallback && !isReactCoreShare(pkg) && (pkg === "react-dom/client" || shareItem.shareConfig.eager !== true && !isSharedSingletonConsumedByPeer(pkg, options, true));
3176
3183
  const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
3177
3184
  const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
3178
3185
  const rebindsSharedExports = isSingleton || options.shareStrategy === "version-first";
@@ -4024,11 +4031,13 @@ function getMaterializedShares(options) {
4024
4031
  if (request.endsWith("/")) for (const concrete of expandSharedPrefixKey(request, usedForEager)) shares.add(concrete);
4025
4032
  else shares.add(pkg);
4026
4033
  }
4027
- const configured = /* @__PURE__ */ new Map();
4034
+ const sharedKeysByPackage = /* @__PURE__ */ new Map();
4028
4035
  const orderedUsed = getOrderedUsedShares(options);
4029
4036
  for (const pkg of orderedUsed) {
4030
4037
  const packageName = getPackageName(pkg);
4031
- if (!configured.has(packageName) || pkg === packageName) configured.set(packageName, pkg);
4038
+ const keys = sharedKeysByPackage.get(packageName);
4039
+ if (keys) keys.push(pkg);
4040
+ else sharedKeysByPackage.set(packageName, [pkg]);
4032
4041
  }
4033
4042
  const localImports = getLocalShareImports(orderedUsed, options);
4034
4043
  const pending = [...shares];
@@ -4047,13 +4056,11 @@ function getMaterializedShares(options) {
4047
4056
  ...packageJson?.optionalDependencies || {},
4048
4057
  ...packageJson?.peerDependenciesMeta || {}
4049
4058
  };
4050
- for (const dependency of Object.keys(dependencies)) {
4051
- const sharedDependency = configured.get(dependency);
4052
- const dependencyShare = sharedDependency ? getNormalizeShareItem(sharedDependency, options) : void 0;
4053
- if (sharedDependency && !shares.has(sharedDependency) && dependencyShare?.scope === share?.scope) {
4054
- shares.add(sharedDependency);
4055
- pending.push(sharedDependency);
4056
- }
4059
+ for (const dependency of Object.keys(dependencies)) for (const sharedDependency of sharedKeysByPackage.get(dependency) ?? []) {
4060
+ if (shares.has(sharedDependency)) continue;
4061
+ if (getNormalizeShareItem(sharedDependency, options)?.scope !== share?.scope) continue;
4062
+ shares.add(sharedDependency);
4063
+ pending.push(sharedDependency);
4057
4064
  }
4058
4065
  }
4059
4066
  const sorted = [...shares].sort((a, b) => {
@@ -4446,8 +4453,10 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
4446
4453
  const seedOrder = seedBatches.flat();
4447
4454
  const seedIndex = new Map(seedOrder.map((pkg, index) => [pkg, index]));
4448
4455
  const seedPrerequisites = Object.fromEntries(Array.from(getSharePrerequisites(seedOrder, options)).filter(([, prerequisites]) => prerequisites.length > 0).map(([pkg, prerequisites]) => [seedIndex.get(pkg), prerequisites.map((prerequisite) => seedIndex.get(prerequisite))]));
4456
+ const versionFirstDeferredSeeds = shareStrategy === "version-first" && hasRemotes(options) ? seedOrder.filter((pkg) => !isReactFamilyShare(pkg)) : [];
4449
4457
  return `
4450
4458
  const __mfSeedOrder = ${toSafeJsLiteral(seedOrder)};
4459
+ const __mfVersionFirstDeferredSeeds = new Set(${toSafeJsLiteral(versionFirstDeferredSeeds)});
4451
4460
  const __mfSeedBatches = ${toSafeJsLiteral(seedBatches)};
4452
4461
  const __mfSeedIndex = new Map(__mfSeedOrder.map((pkg, index) => [pkg, index]));
4453
4462
  const __mfSeedPrerequisites = ${toSafeJsLiteral(seedPrerequisites)};
@@ -4467,8 +4476,16 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
4467
4476
  };
4468
4477
  var __mfSeedLocalShared = async (seedKeys) => {
4469
4478
  const requested = new Set(seedKeys);
4479
+ // A dependent of a share left to the late bridge would evaluate against an empty
4480
+ // wrapper (#1541); leave it to its wrapper's own fallback load instead.
4481
+ const skipped = new Set();
4470
4482
  for (const batch of __mfSeedBatches) await Promise.all(batch.filter((pkg) => requested.has(pkg)).map(async (pkg) => {
4471
4483
  const share = usedShared[pkg];
4484
+ const seedIndex = __mfSeedIndex.get(pkg);
4485
+ if ((__mfSeedPrerequisites[seedIndex] || []).some((dependency) => skipped.has(dependency))) {
4486
+ skipped.add(seedIndex);
4487
+ return;
4488
+ }
4472
4489
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
4473
4490
  if (
4474
4491
  share.shareConfig?.import === false ||
@@ -4539,7 +4556,10 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
4539
4556
  isWebpackProvider(externalProvider) &&
4540
4557
  (share.shareConfig?.singleton ||
4541
4558
  __mfFindSharedProviderEntry(initialShared[pkg], externalProvider)?.version === share.version)
4542
- ) return;
4559
+ ) {
4560
+ skipped.add(seedIndex);
4561
+ return;
4562
+ }
4543
4563
  }
4544
4564
  const providerKey = cacheDescriptor.canonical;
4545
4565
  const resolved = await __mfInitializeProviderOnce(providerKey, async () => {
@@ -4560,6 +4580,10 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
4560
4580
  value: true,
4561
4581
  enumerable: false
4562
4582
  });
4583
+ // The init map is page-wide: another container may have run this provider
4584
+ // init and seeded the result under its own name. Keep that owner, or this
4585
+ // container would later treat a sibling's copy as its own provisional seed.
4586
+ if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) return;
4563
4587
  __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, exportModule, mfName);
4564
4588
  }));
4565
4589
  };
@@ -4602,6 +4626,13 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
4602
4626
  : __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor);
4603
4627
  if (cachedShare !== undefined) return false;
4604
4628
  if (share.treeShaking || share.shareConfig?.import === false) return true;
4629
+ // version-first negotiates a singleton against this container's remotes, which only
4630
+ // register during initializeSharing(). Seeding the local copy before that evaluates it
4631
+ // even when a remote's higher version is selected, so a package with top-level side
4632
+ // effects (custom element registration, polyfills) runs twice (#1527). Wait for the
4633
+ // remotes; the deferred pass seeds the local copy only when no remote outranks it.
4634
+ // The React family keeps the eager seed its synchronous wrappers rely on.
4635
+ if (__mfVersionFirstDeferredSeeds.has(pkg) && share.shareConfig?.singleton) return true;
4605
4636
  if (typeof __mfSelectExternalSharedProvider !== 'function') return false;
4606
4637
  return Boolean(__mfSelectExternalSharedProvider(
4607
4638
  initialShared[pkg],
@@ -4933,7 +4964,14 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4933
4964
  return __mfExposesMap
4934
4965
  }
4935
4966
 
4967
+ // Hosts that call get() without awaiting init() must still see the shares that
4968
+ // init binds asynchronously: get() waits until no init() call is in flight.
4969
+ let __mfInitsInFlight = 0;
4970
+ let __mfInitsSettled = Promise.resolve();
4971
+ let __mfSettleInits = () => {};
4936
4972
  async function init(shared = {}, initScope = [], remoteEntryInitOptions = {}) {
4973
+ if (__mfInitsInFlight++ === 0) __mfInitsSettled = new Promise((resolve) => (__mfSettleInits = resolve));
4974
+ try {
4937
4975
  ${sharedCacheHelperCode}
4938
4976
  const getShareScope = (scopeName) => remoteEntryInitOptions.shareScopeMap?.[scopeName] ?? (${hasMultipleShareScopes} ? (shared?.[scopeName] || {}) : shared);
4939
4977
  const getShareScopeNames = (share) => {
@@ -5809,16 +5847,26 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5809
5847
  };` : ""}
5810
5848
  initResolve(initRes)
5811
5849
  return initRes
5850
+ } finally {
5851
+ if (--__mfInitsInFlight === 0) __mfSettleInits();
5852
+ }
5812
5853
  }
5813
5854
 
5814
5855
  async function getExposes(moduleName) {
5856
+ // init() failures surface from init() itself; get() only waits for it to settle.
5857
+ if (__mfInitsInFlight) await __mfInitsSettled
5815
5858
  const exposesMap = await getExposesMap()
5816
5859
  if (!(moduleName in exposesMap)) throw new Error(\`[Module Federation] Module \${moduleName} does not exist in container.\`)
5817
5860
  if (__mfLateBridgeShared) await __mfLateBridgeShared()
5818
5861
  if (__mfModuleCache.pendingShareLoads) {
5819
5862
  await Promise.all(__mfModuleCache.pendingShareLoads)
5820
5863
  }
5821
- return (exposesMap[moduleName])().then(res => () => res)
5864
+ const res = await exposesMap[moduleName]()
5865
+ // Wrappers evaluated by the expose import may queue share loads only now (#1535).
5866
+ if (__mfModuleCache.pendingShareLoads) {
5867
+ await Promise.all(__mfModuleCache.pendingShareLoads)
5868
+ }
5869
+ return () => res
5822
5870
  }
5823
5871
  ${guardHostAutoInit ? `let __mfInitPromise;
5824
5872
  function __mfGuardedInit(shared, initScope, remoteEntryInitOptions) {
@@ -5910,6 +5958,16 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5910
5958
  if (lateKeys.length) __mfHostInitShareBatches.push(lateKeys);
5911
5959
  }
5912
5960
  ${hostInitSharedProviderHelperCode}
5961
+ // Hosts on one page share the module cache. Negotiate one host at a time so
5962
+ // none adopts another's half-upgraded set of singletons.
5963
+ const __mfPinnedShareOwners = (__mfModuleCache.pinnedShareOwners ||= new Set());
5964
+ const __mfPreviousHostShareInit = __mfModuleCache.hostShareInit;
5965
+ let __mfReleaseHostShareInit;
5966
+ __mfModuleCache.hostShareInit = new Promise((resolve) => {
5967
+ __mfReleaseHostShareInit = resolve;
5968
+ });
5969
+ await __mfPreviousHostShareInit;
5970
+ try {
5913
5971
  for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
5914
5972
  await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
5915
5973
  const share = usedShared[pkg];
@@ -5920,6 +5978,20 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5920
5978
  // a generic full-module key here.
5921
5979
  if (share.treeShaking) return;
5922
5980
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
5981
+ // Another host on the page may hold this singleton in the module cache. Its
5982
+ // app, e.g. its react-dom, is bound to that copy, so this host adopts it and
5983
+ // pins that host's seeds: re-negotiation may then no longer upgrade them.
5984
+ const __mfKeepsCachedSingleton = () => {
5985
+ if (!share.shareConfig?.singleton) return false;
5986
+ if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) === undefined) return false;
5987
+ const owner = __mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor);
5988
+ if (owner === undefined) return false;
5989
+ if (owner === ${cacheOwner}) return __mfPinnedShareOwners.has(owner);
5990
+ if ((runtime.options?.remotes || []).some((remote) => remote.name === owner)) return false;
5991
+ __mfPinnedShareOwners.add(owner);
5992
+ return true;
5993
+ };
5994
+ if (__mfKeepsCachedSingleton()) return;
5923
5995
  if (
5924
5996
  __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined &&
5925
5997
  ${_command === "serve" ? `__mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) !== undefined &&
@@ -5968,6 +6040,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5968
6040
  customShareInfo: { shareConfig: share.shareConfig }
5969
6041
  }).then(async (factory) => {
5970
6042
  if (factory === false) return;
6043
+ if (__mfKeepsCachedSingleton()) return;
5971
6044
  const mod = typeof factory === "function" ? factory() : factory;
5972
6045
  let resolved = __mfNormalizeRuntimeShare(await Promise.resolve(mod));
5973
6046
  ${preferLocalVinextReact ? `if (
@@ -5990,6 +6063,9 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5990
6063
  });
5991
6064
  }));
5992
6065
  }
6066
+ } finally {
6067
+ __mfReleaseHostShareInit();
6068
+ }
5993
6069
  ` : ""}
5994
6070
  // The seed called this container's get() directly, so the Runtime's
5995
6071
  // provider never learned it is in use and a remote could load its own
@@ -6533,7 +6609,7 @@ function escapeHtmlAttr(value) {
6533
6609
  function getExistingHrefSet(html) {
6534
6610
  return new Set(Array.from(html.matchAll(/\bhref\s*=\s*["']([^"']+)["']/gi), (match) => match[1]));
6535
6611
  }
6536
- function injectHostInitPreloads(html, bundle, resolvePath, externalHrefs = []) {
6612
+ function injectHostInitPreloads(html, bundle, resolvePath, externalHrefs = [], isExtraSeed = () => false) {
6537
6613
  const existingHrefs = getExistingHrefSet(html);
6538
6614
  const hrefs = [];
6539
6615
  for (const href of externalHrefs) {
@@ -6542,7 +6618,7 @@ function injectHostInitPreloads(html, bundle, resolvePath, externalHrefs = []) {
6542
6618
  hrefs.push(href);
6543
6619
  }
6544
6620
  const chunksByFileName = getChunksByFileName(bundle);
6545
- const seeds = Array.from(chunksByFileName.values()).filter(isHostInitPreloadSeed);
6621
+ const seeds = Array.from(chunksByFileName.values()).filter((chunk) => isHostInitPreloadSeed(chunk) || isExtraSeed(chunk));
6546
6622
  for (const fileName of collectPreloadChunkFiles(chunksByFileName, seeds)) {
6547
6623
  const href = resolvePath(fileName);
6548
6624
  if (existingHrefs.has(href)) continue;
@@ -6551,7 +6627,9 @@ function injectHostInitPreloads(html, bundle, resolvePath, externalHrefs = []) {
6551
6627
  }
6552
6628
  if (hrefs.length === 0) return html;
6553
6629
  const tags = hrefs.map((href) => `<link rel="modulepreload" crossorigin href="${escapeHtmlAttr(href)}">`).join("");
6554
- return html.includes("</head>") ? html.replace("</head>", `${tags}</head>`) : `${tags}${html}`;
6630
+ if (html.includes("</head>")) return html.replace("</head>", `${tags}</head>`);
6631
+ const script = html.search(/<script\b[^>]*\btype=["']module["']/i);
6632
+ return script === -1 ? `${tags}${html}` : html.slice(0, script) + tags + html.slice(script);
6555
6633
  }
6556
6634
  function appendRemoteEntryWarmup(bundle, entryFileName) {
6557
6635
  const chunksByFileName = getChunksByFileName(bundle);
@@ -6742,7 +6820,7 @@ const __mfCurrentScript = document.currentScript;
6742
6820
  const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(normalizedOptions));
6743
6821
  return Array.from(new Set(remoteSources.flatMap((remote) => {
6744
6822
  const registration = getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions);
6745
- return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) && !/\.json(?:[?#]|$)/i.test(registration.entry) ? [registration.entry] : [];
6823
+ return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\//.test(registration.entry) && !/\.json(?:[?#]|$)/i.test(registration.entry) ? [registration.entry] : [];
6746
6824
  })));
6747
6825
  }
6748
6826
  async function warmupDevEntryGraph(entryUrl) {
@@ -7122,7 +7200,8 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7122
7200
  const remoteEntryFile = findRemoteEntryFile(fileName, bundle);
7123
7201
  if (remoteEntryFile) appendRemoteEntryWarmup(bundle, remoteEntryFile);
7124
7202
  }
7125
- if (!injectHtml()) return;
7203
+ const preloadsEntryHtml = inject === "entry" && waitsForInit && !viteConfig.build.ssr && viteConfig.build.modulePreload !== false;
7204
+ if (!injectHtml() && !preloadsEntryHtml) return;
7126
7205
  if (!emitFileId) return;
7127
7206
  const htmlFileNames = Object.keys(bundle).filter((fileName) => fileName.endsWith(".html"));
7128
7207
  if (htmlFileNames.length === 0) return;
@@ -7151,6 +7230,14 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7151
7230
  };
7152
7231
  const basePrefix = viteConfig.base?.replace(/\/$/, "") ?? "";
7153
7232
  const stripBase = (p) => basePrefix && p.startsWith(basePrefix + "/") ? p.slice(basePrefix.length) : p;
7233
+ if (!injectHtml()) {
7234
+ for (const fileName of htmlFileNames) {
7235
+ const htmlAsset = bundle[fileName];
7236
+ if (htmlAsset.type === "chunk") continue;
7237
+ htmlAsset.source = injectHostInitPreloads(htmlAsset.source.toString(), bundle, (builtFileName) => resolvePath(builtFileName, fileName), getRemoteEntryPreloadUrls(), (chunk) => !!chunk.facadeModuleId && hasEntryBootstrapParam(chunk.facadeModuleId));
7238
+ }
7239
+ return;
7240
+ }
7154
7241
  let bootstrapIndex = 0;
7155
7242
  for (const fileName of htmlFileNames) {
7156
7243
  let htmlAsset = bundle[fileName];
@@ -8375,7 +8462,7 @@ function ${helperName}(names) {
8375
8462
  }
8376
8463
  //#endregion
8377
8464
  //#region package.json
8378
- var version$1 = "1.23.8";
8465
+ var version$1 = "1.23.10";
8379
8466
  //#endregion
8380
8467
  //#region src/virtualModules/virtualExposesSSR.ts
8381
8468
  /**
@@ -9659,9 +9746,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9659
9746
  let dependencyInvalidationVersion = 0;
9660
9747
  let reactIslandExposes = /* @__PURE__ */ new Set();
9661
9748
  let isTanStackStart = false;
9662
- const isHostAutoInitId = (id) => {
9663
- return id.split("?")[0].includes(getHostAutoInitPath(options));
9664
- };
9749
+ const isHostAutoInitId = (id) => isOwnedHostAutoInitId(id, options);
9665
9750
  const getEnvironmentConditions = (context) => context.environment?.config?.resolve?.conditions;
9666
9751
  const isSsrBuild = (context) => isServerBuildContext(context, viteConfig);
9667
9752
  const loadRemoteEntryCode = (context) => getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(context), isSsrBuild(context)));
@@ -9738,7 +9823,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9738
9823
  if (id === remoteEntryId) return remoteEntryId;
9739
9824
  if (id === virtualExposesId) return virtualExposesId;
9740
9825
  if (_command === "serve" && isHostAutoInitId(id)) return id;
9741
- if (importer === remoteEntryId && !id.startsWith(".") && !id.startsWith("/") && !id.startsWith("\0") && !id.startsWith("virtual:")) {
9826
+ if ((importer === remoteEntryId || importer !== void 0 && isHostAutoInitId(importer)) && !id.startsWith(".") && !id.startsWith("/") && !id.startsWith("\0") && !id.startsWith("virtual:")) {
9742
9827
  const importPath = typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url);
9743
9828
  const resolved = await this.resolve(id, importPath, { skipSelf: true });
9744
9829
  if (resolved) return resolved;
@@ -10374,8 +10459,9 @@ function proxySharedModule(options) {
10374
10459
  configureServer(server) {
10375
10460
  devServer = server;
10376
10461
  setLocalSharedImportMapInvalidator(() => {
10377
- const module = server.moduleGraph.getModuleById(getResolvedLocalSharedImportMapId(federationOptions));
10378
- if (module) server.moduleGraph.invalidateModule(module);
10462
+ const graph = server.environments?.client?.moduleGraph ?? server.moduleGraph;
10463
+ const module = graph.getModuleById(getResolvedLocalSharedImportMapId(federationOptions));
10464
+ if (module) graph.invalidateModule(module);
10379
10465
  }, federationOptions);
10380
10466
  },
10381
10467
  resolveId(source) {
@@ -10506,49 +10592,52 @@ function proxySharedModule(options) {
10506
10592
  {
10507
10593
  name: "proxyPreBuildShared:resolve-shared-loadShare",
10508
10594
  enforce: "pre",
10509
- async resolveId(source, importer, resolveOptions) {
10510
- if (isSharedEntryLookup(source, importer, resolveOptions) || resolveOptions.custom?.__mfTreeShakingGraph) return;
10511
- const sharedSource = await sharedSourceResolver.resolve(this, source, resolveOptions);
10512
- if (!sharedSource) return;
10513
- const key = findSharedKey(sharedSource, shared);
10514
- if (!key) return;
10515
- const shouldSkipTaggedImporterProxy = (sharedKey, tag) => {
10516
- if (!importer?.includes(tag)) return false;
10517
- const taggedModule = VirtualModule.findModule(tag, importer);
10518
- if (!taggedModule) return true;
10519
- return taggedModule.name === sharedKey || matchesSharedSource(sharedSource, taggedModule.name);
10520
- };
10521
- const importerPackage = getSharedPackageFromFile(importer, shared);
10522
- if (importerPackage === getPackageName(key) && keepsOwnPackageEdge(importer, shared)) return;
10523
- if (importerPackage && shared[key].shareConfig.import !== false) {
10524
- const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
10525
- const request = getSharedRequest(key, shared[key]);
10526
- const runtimeDependencyRequest = request.endsWith("/") && matchesSharedSource(sharedSource, key, shared[key]) ? sharedSource : request;
10527
- if (importerIsUnsharedWorkspacePackage ? isSharedPackageRuntimeDependency(runtimeDependencyRequest, importerPackage, getRuntimeDependencyConditions(this, resolveOptions)) : isSharedPackageDependency(request, importerPackage)) return;
10528
- }
10529
- if (useDirectReactImport && key === "react") return;
10530
- if (isAssetLikeImport(source)) return;
10531
- if (isBuildConfigImporter(importer)) return;
10532
- if (useDirectReactImport && source === "react") return;
10533
- if (importer && importer.includes("localSharedImportMap")) return;
10534
- if (importer && (importer.includes("hostAutoInit") || importer.includes("__H_A_I__"))) return;
10535
- if (shouldSkipTaggedImporterProxy(key, "__loadShare__")) return;
10536
- if (shouldSkipTaggedImporterProxy(key, "__prebuild__")) return;
10537
- const shareSource = key === "vue" && sharedSource.startsWith("vue/dist/") ? key : sharedSource;
10538
- if (shouldKeepSharedImportLocal(shareSource, importer, key, shared, importerPackage, federationOptions)) {
10539
- const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
10540
- return tryResolveFromProjectRoot(localSource) || localSource;
10541
- }
10542
- const loadSharePath = getLoadShareModulePath(shareSource, federationOptions);
10543
- if (!materializedLoadShareSources.has(shareSource)) {
10544
- materializedLoadShareSources.add(shareSource);
10545
- writeLoadShareModule(shareSource, shared[key], _command, federationOptions);
10546
- if (shared[key].shareConfig.import !== false) writePreBuildLibPath(shareSource, shared[key], federationOptions);
10547
- addUsedShares(shareSource, federationOptions);
10548
- writeLocalSharedImportMap(federationOptions);
10549
- refreshHostAutoInit(federationOptions);
10595
+ resolveId: {
10596
+ order: "pre",
10597
+ async handler(source, importer, resolveOptions) {
10598
+ if (isSharedEntryLookup(source, importer, resolveOptions) || resolveOptions.custom?.__mfTreeShakingGraph) return;
10599
+ const sharedSource = await sharedSourceResolver.resolve(this, source, resolveOptions);
10600
+ if (!sharedSource) return;
10601
+ const key = findSharedKey(sharedSource, shared);
10602
+ if (!key) return;
10603
+ const shouldSkipTaggedImporterProxy = (sharedKey, tag) => {
10604
+ if (!importer?.includes(tag)) return false;
10605
+ const taggedModule = VirtualModule.findModule(tag, importer);
10606
+ if (!taggedModule) return true;
10607
+ return taggedModule.name === sharedKey || matchesSharedSource(sharedSource, taggedModule.name);
10608
+ };
10609
+ const importerPackage = getSharedPackageFromFile(importer, shared);
10610
+ if (importerPackage === getPackageName(key) && keepsOwnPackageEdge(importer, shared)) return;
10611
+ if (importerPackage && shared[key].shareConfig.import !== false) {
10612
+ const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
10613
+ const request = getSharedRequest(key, shared[key]);
10614
+ const runtimeDependencyRequest = request.endsWith("/") && matchesSharedSource(sharedSource, key, shared[key]) ? sharedSource : request;
10615
+ if (importerIsUnsharedWorkspacePackage ? isSharedPackageRuntimeDependency(runtimeDependencyRequest, importerPackage, getRuntimeDependencyConditions(this, resolveOptions)) : isSharedPackageDependency(request, importerPackage)) return;
10616
+ }
10617
+ if (useDirectReactImport && key === "react") return;
10618
+ if (isAssetLikeImport(source)) return;
10619
+ if (isBuildConfigImporter(importer)) return;
10620
+ if (useDirectReactImport && source === "react") return;
10621
+ if (importer && importer.includes("localSharedImportMap")) return;
10622
+ if (importer && (importer.includes("hostAutoInit") || importer.includes("__H_A_I__"))) return;
10623
+ if (shouldSkipTaggedImporterProxy(key, "__loadShare__")) return;
10624
+ if (shouldSkipTaggedImporterProxy(key, "__prebuild__")) return;
10625
+ const shareSource = key === "vue" && sharedSource.startsWith("vue/dist/") ? key : sharedSource;
10626
+ if (shouldKeepSharedImportLocal(shareSource, importer, key, shared, importerPackage, federationOptions)) {
10627
+ const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
10628
+ return tryResolveFromProjectRoot(localSource) || localSource;
10629
+ }
10630
+ const loadSharePath = getLoadShareModulePath(shareSource, federationOptions);
10631
+ if (!materializedLoadShareSources.has(shareSource)) {
10632
+ materializedLoadShareSources.add(shareSource);
10633
+ writeLoadShareModule(shareSource, shared[key], _command, federationOptions);
10634
+ if (shared[key].shareConfig.import !== false) writePreBuildLibPath(shareSource, shared[key], federationOptions);
10635
+ addUsedShares(shareSource, federationOptions);
10636
+ writeLocalSharedImportMap(federationOptions);
10637
+ refreshHostAutoInit(federationOptions);
10638
+ }
10639
+ return this.resolve(loadSharePath, importer, { skipSelf: true });
10550
10640
  }
10551
- return this.resolve(loadSharePath, importer, { skipSelf: true });
10552
10641
  }
10553
10642
  },
10554
10643
  {
@@ -11193,7 +11282,7 @@ function pluginSSRRemoteEntry(options) {
11193
11282
  } catch {}
11194
11283
  }
11195
11284
  const fetchedId = body.data.name === "fetchModule" ? body.data.data[0] : void 0;
11196
- const shared = typeof fetchedId === "string" && !!findSharedKey(fetchedId, options.shared);
11285
+ const shared = typeof fetchedId === "string" && !!findSharedKey(decodeViteId(fetchedId).replace(/^\0+/, ""), options.shared);
11197
11286
  res.setHeader("Content-Type", "application/json");
11198
11287
  res.end(JSON.stringify(shared ? {
11199
11288
  ...result,
@@ -12226,7 +12315,7 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
12226
12315
  function materializeSharedRequest(options, request) {
12227
12316
  addUsedShares(request, options);
12228
12317
  const packageName = getPackageName(request);
12229
- if (packageName !== request && findSharedKey(packageName, options.shared)) addUsedShares(packageName, options);
12318
+ if (packageName !== request && findSharedKey(packageName, options.shared) && isPackageExportAvailable(packageName)) addUsedShares(packageName, options);
12230
12319
  }
12231
12320
  function materializeAutomaticJsxRuntime(options, runtime) {
12232
12321
  if (!findSharedKey(runtime, options.shared)) return false;
@@ -12242,6 +12331,7 @@ function createEarlyVirtualModulesPlugin(options) {
12242
12331
  const { shared, remotes } = options;
12243
12332
  const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
12244
12333
  let hasClientJsxSource = false;
12334
+ let scanBuildEntryImports;
12245
12335
  return {
12246
12336
  name: "vite:module-federation-early-init",
12247
12337
  enforce: "pre",
@@ -12270,10 +12360,8 @@ function createEarlyVirtualModulesPlugin(options) {
12270
12360
  config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
12271
12361
  }
12272
12362
  }
12273
- if (!config.build?.ssr && (hasShared(options) || hasRemotes(options))) {
12274
- const hasJsxSource = registerEntryImports(options, root, _command === "serve", resolvedConfiguredEntryFiles);
12275
- if (_command === "serve") hasClientJsxSource = hasJsxSource;
12276
- }
12363
+ if (!config.build?.ssr && (hasShared(options) || hasRemotes(options))) if (_command === "serve") hasClientJsxSource = registerEntryImports(options, root, true, resolvedConfiguredEntryFiles);
12364
+ else scanBuildEntryImports = () => registerEntryImports(options, root, false, resolvedConfiguredEntryFiles);
12277
12365
  if (hasShared(options)) {
12278
12366
  if (_command === "serve") {
12279
12367
  excludeSharedSubDependencies(shared);
@@ -12465,6 +12553,9 @@ export default __mfShared.default ?? __mfShared;`
12465
12553
  }
12466
12554
  }
12467
12555
  },
12556
+ buildStart() {
12557
+ scanBuildEntryImports?.();
12558
+ },
12468
12559
  configResolved(config) {
12469
12560
  if (hasClientJsxSource) {
12470
12561
  const automaticJsxRuntime = getAutomaticJsxRuntime(config);
@@ -12530,7 +12621,7 @@ function withoutDynamicRemoteTypeHints(options) {
12530
12621
  }
12531
12622
  function loadPluginDts(options) {
12532
12623
  if (options.dts === false) return [];
12533
- return [import("./pluginDts-DvTJxjaE.js").then(({ default: pluginDts }) => pluginDts(options))];
12624
+ return [import("./pluginDts-CSCuhD4x.js").then(({ default: pluginDts }) => pluginDts(options))];
12534
12625
  }
12535
12626
  const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
12536
12627
  function isInjectExternalRuntimeCorePlugin(specifier) {
@@ -65,6 +65,13 @@ function resolveHashPlaceholderFileName(fileName) {
65
65
  const normalized = fileName.replace(HASH_PLACEHOLDER_RE, "");
66
66
  return hasFileExtension(normalized) ? normalized : `${normalized}.js`;
67
67
  }
68
+ const VITE_ID_PREFIX = "/@id/";
69
+ const VITE_NULL_BYTE_PLACEHOLDER = "__x00__";
70
+ function decodeViteId(id) {
71
+ if (!id.startsWith("/@id/")) return id;
72
+ const viteId = id.slice(5);
73
+ return viteId.startsWith("__x00__") ? `\0${viteId.slice(7)}` : viteId;
74
+ }
68
75
  //#endregion
69
76
  //#region src/utils/codeRewriter.ts
70
77
  const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -457,4 +464,4 @@ const moduleFederationConsole = {
457
464
  const mfWarn = moduleFederationConsole.warn;
458
465
  const mfError = moduleFederationConsole.error;
459
466
  //#endregion
460
- export { CodeRewriter as a, isAbsoluteUrl as c, rebaseImport as d, resolveHashPlaceholderFileName as f, createCodePositionMap as i, isHttpUrl as l, mfError as n, createSourceMap as o, mfWarn as r, EXTERNAL_URL_RE as s, createModuleFederationError as t, normalizePathForImport as u };
467
+ export { CodeRewriter as a, VITE_ID_PREFIX as c, isAbsoluteUrl as d, isHttpUrl as f, resolveHashPlaceholderFileName as h, createCodePositionMap as i, VITE_NULL_BYTE_PLACEHOLDER as l, rebaseImport as m, mfError as n, createSourceMap as o, normalizePathForImport as p, mfWarn as r, EXTERNAL_URL_RE as s, createModuleFederationError as t, decodeViteId as u };
@@ -1,5 +1,5 @@
1
- import { l as isHttpUrl, n as mfError, t as createModuleFederationError, u as normalizePathForImport } from "./logger-D67aJYOe.js";
2
- import { b as resolveImportPath, m as hasPackageDependency, r as watchFileEvents } from "./dtsConstants-286VtFnC.js";
1
+ import { f as isHttpUrl, n as mfError, p as normalizePathForImport, t as createModuleFederationError } from "./logger-Ckj1FMRH.js";
2
+ import { b as resolveImportPath, m as hasPackageDependency, r as watchFileEvents } from "./dtsConstants-DIcz34LN.js";
3
3
  import fs from "fs";
4
4
  import * as path$1 from "node:path";
5
5
  import { normalizeOptions } from "@module-federation/sdk";
@@ -1,4 +1,4 @@
1
- import { u as normalizePathForImport } from "./logger-D67aJYOe.js";
1
+ import { p as normalizePathForImport } from "./logger-Ckj1FMRH.js";
2
2
  import * as path$1 from "node:path";
3
3
  //#region src/utils/pathNormalization.ts
4
4
  const COMMON_SHARED_SUBPATHS = {
@@ -1,4 +1,4 @@
1
- import { a as CodeRewriter, i as createCodePositionMap, l as isHttpUrl, r as mfWarn, s as EXTERNAL_URL_RE } from "./logger-D67aJYOe.js";
1
+ import { a as CodeRewriter, f as isHttpUrl, i as createCodePositionMap, r as mfWarn, s as EXTERNAL_URL_RE, u as decodeViteId } from "./logger-Ckj1FMRH.js";
2
2
  import { simpleJoinRemoteEntry } from "@module-federation/sdk";
3
3
  //#region src/utils/fetchWithTimeout.ts
4
4
  const DEFAULT_SSR_FETCH_TIMEOUT_MS = 1e4;
@@ -225,7 +225,8 @@ async function resolveEsmSubpath(id, base) {
225
225
  if (!existsSync(packageJson)) continue;
226
226
  const { exports } = JSON.parse(readFileSync(packageJson, "utf8"));
227
227
  const target = getEsmExportTarget(exports?.[subpath]);
228
- return target && join(dirname(packageJson), target);
228
+ const esmPath = target && join(dirname(packageJson), target);
229
+ return esmPath && existsSync(esmPath) ? esmPath : void 0;
229
230
  }
230
231
  }
231
232
  /**
@@ -235,15 +236,17 @@ async function resolveEsmSubpath(id, base) {
235
236
  */
236
237
  async function resolveSharedPath(id, resolvedShared) {
237
238
  if (typeof id !== "string") return null;
238
- const matchedKey = findResolvedSharedKey(id, resolvedShared);
239
+ const normalizedId = decodeViteId(id);
240
+ const matchedKey = findResolvedSharedKey(normalizedId, resolvedShared);
239
241
  if (!matchedKey) return null;
240
242
  const resolved = resolvedShared[matchedKey];
241
243
  if (!resolved) return null;
242
- if (matchedKey === id || EXTERNAL_URL_RE.test(resolved)) return resolved;
244
+ if (EXTERNAL_URL_RE.test(resolved)) return resolved;
245
+ if (matchedKey === normalizedId) return await resolveEsmSubpath(normalizedId, resolved).catch(() => void 0) ?? resolved;
243
246
  const { createRequire } = await _module();
244
247
  const { join } = await _path();
245
248
  for (const base of [resolved, join(process.cwd(), "noop.js")]) try {
246
- return await resolveEsmSubpath(id, base).catch(() => void 0) ?? createRequire(base).resolve(id);
249
+ return await resolveEsmSubpath(normalizedId, base).catch(() => void 0) ?? createRequire(base).resolve(normalizedId);
247
250
  } catch {}
248
251
  return null;
249
252
  }
@@ -789,14 +792,14 @@ function findSsrModuleSpecifiers(code) {
789
792
  function isNodeModuleSpecifier(specifier) {
790
793
  return specifier === "node:module" || specifier === "module";
791
794
  }
792
- function transformSsrCode(code, base, specifiers, sharedPkgMap, requireShimUrl, tempFileUrlMap) {
795
+ function transformSsrCode(code, base, specifiers, sharedImports, requireShimUrl, tempFileUrlMap) {
793
796
  const rewriter = new CodeRewriter(code);
794
797
  for (const { start, end, value } of specifiers) {
795
798
  if (requireShimUrl && isNodeModuleSpecifier(value)) {
796
799
  rewriter.overwrite(start, end, `"${requireShimUrl}"`);
797
800
  continue;
798
801
  }
799
- const resolvedShared = sharedPkgMap?.get(value);
802
+ const resolvedShared = sharedImports?.get(value);
800
803
  const relativeUrl = isRelativeSpecifier(value) ? new URL(value, base).href : void 0;
801
804
  const absoluteHttpUrl = isHttpUrl(value) ? value : void 0;
802
805
  const httpUrl = relativeUrl ?? absoluteHttpUrl;
@@ -805,14 +808,17 @@ function transformSsrCode(code, base, specifiers, sharedPkgMap, requireShimUrl,
805
808
  }
806
809
  return neutralizeBrowserPreloadHelpers(rewriter.toString());
807
810
  }
808
- async function materializeSharedSubpaths(specifiers, sharedPkgMap) {
811
+ async function resolveSharedImports(specifiers, sharedPkgMap) {
809
812
  const uniqueSpecifiers = new Set(specifiers.map(({ value }) => value));
810
813
  const resolvedShared = Object.fromEntries(sharedPkgMap);
814
+ const sharedImports = /* @__PURE__ */ new Map();
811
815
  for (const specifier of uniqueSpecifiers) {
812
- if (sharedPkgMap.has(specifier)) continue;
813
816
  const resolved = await resolveSharedPath(specifier, resolvedShared);
814
- if (resolved) sharedPkgMap.set(specifier, resolved);
817
+ if (!resolved) continue;
818
+ sharedImports.set(specifier, resolved);
819
+ if (!sharedPkgMap.has(specifier)) sharedPkgMap.set(specifier, resolved);
815
820
  }
821
+ return sharedImports;
816
822
  }
817
823
  function isVitePreloadHelperSpecifier(specifier) {
818
824
  return specifier.includes("preload-helper");
@@ -870,9 +876,9 @@ async function fetchEsmToTempFile(url, graph) {
870
876
  const tmpPath = await fetchEsmToTempFile(u, graph);
871
877
  subMap.set(u, getTempFileImportUrl(tmpPath, versionKey));
872
878
  }));
873
- if (sharedPkgMap) await materializeSharedSubpaths(specifiers, sharedPkgMap);
879
+ const sharedImports = sharedPkgMap && await resolveSharedImports(specifiers, sharedPkgMap);
874
880
  const requireShimUrl = sharedPkgMap?.size && specifiers.some(({ value }) => isNodeModuleSpecifier(value)) ? await getRequireShimUrl(tmpDir, sharedPkgMap, contextKey) : void 0;
875
- code = transformSsrCode(code, base, specifiers, sharedPkgMap, requireShimUrl, subMap);
881
+ code = transformSsrCode(code, base, specifiers, sharedImports, requireShimUrl, subMap);
876
882
  const { writeFileSync } = await _fs();
877
883
  writeFileSync(tmpFile, code, "utf8");
878
884
  return tmpFile;
@@ -916,7 +922,7 @@ async function importTempModule(filePath, versionKey) {
916
922
  }
917
923
  let warnedVmUnavailable = false;
918
924
  function getVmStrategyModule() {
919
- if (!loaderState.vmStrategyModulePromise) loaderState.vmStrategyModulePromise = import("./ssrVmStrategy-D1cSKUV-.js");
925
+ if (!loaderState.vmStrategyModulePromise) loaderState.vmStrategyModulePromise = import("./ssrVmStrategy-uJaUmHLS.js");
920
926
  return loaderState.vmStrategyModulePromise;
921
927
  }
922
928
  /**
@@ -1,6 +1,6 @@
1
- import { l as isHttpUrl, s as EXTERNAL_URL_RE } from "./logger-D67aJYOe.js";
2
- import { t as findSharedKey } from "./sharedKeyMatcher-C04bVN1q.js";
3
- import { d as readResponseTextBounded, i as resolveSharedPath, l as fetchWithTimeout, n as SsrEntryHttpError, r as neutralizeBrowserPreloadHelpers, u as getBodyPreview } from "./ssrEntryLoader-DKpOrW8D.js";
1
+ import { f as isHttpUrl, s as EXTERNAL_URL_RE } from "./logger-Ckj1FMRH.js";
2
+ import { t as findSharedKey } from "./sharedKeyMatcher-B5VKsEVQ.js";
3
+ import { d as readResponseTextBounded, i as resolveSharedPath, l as fetchWithTimeout, n as SsrEntryHttpError, r as neutralizeBrowserPreloadHelpers, u as getBodyPreview } from "./ssrEntryLoader--NkahIOF.js";
4
4
  //#region src/utils/ssrVmStrategy.ts
5
5
  /**
6
6
  * vm.SourceTextModule strategy for loading remote SSR entries.
@@ -1,2 +1,2 @@
1
- import { a as revalidate, i as resolveSharedPath, n as SsrEntryHttpError, o as ssrEntryLoaderPlugin, r as neutralizeBrowserPreloadHelpers, t as SSR_ENTRY_LOADER_STATE_KEY } from "../ssrEntryLoader-DKpOrW8D.js";
1
+ import { a as revalidate, i as resolveSharedPath, n as SsrEntryHttpError, o as ssrEntryLoaderPlugin, r as neutralizeBrowserPreloadHelpers, t as SSR_ENTRY_LOADER_STATE_KEY } from "../ssrEntryLoader--NkahIOF.js";
2
2
  export { SSR_ENTRY_LOADER_STATE_KEY, SsrEntryHttpError, ssrEntryLoaderPlugin as default, neutralizeBrowserPreloadHelpers, resolveSharedPath, revalidate };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/vite",
3
- "version": "1.23.8",
3
+ "version": "1.23.10",
4
4
  "description": "Vite plugin for Module Federation",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -77,9 +77,9 @@
77
77
  "vite": "^5.1.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
78
78
  },
79
79
  "dependencies": {
80
- "@module-federation/dts-plugin": "2.9.2",
81
- "@module-federation/runtime": "2.9.2",
82
- "@module-federation/sdk": "2.9.2"
80
+ "@module-federation/dts-plugin": "2.9.3",
81
+ "@module-federation/runtime": "2.9.3",
82
+ "@module-federation/sdk": "2.9.3"
83
83
  },
84
84
  "devDependencies": {
85
85
  "@playwright/test": "1.62.0",