@module-federation/vite 1.21.6 → 1.22.1

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.js CHANGED
@@ -1,6 +1,6 @@
1
+ import { _ as stripViteFsPrefix, a as ensureTrailingSlash, c as getCommonSharedSubpaths, d as isNodeModulePath, f as isNuxtClientBase, g as stripQueryAndHash, h as resolvePublicPath, l as getNodeModulesSuffix, m as normalizeNodeModulePath, n as invalidateSharedKeyMatcher, o as filterId, p as isViteOptimizableEntry, r as matchesSharedSource, s as getBasePath$1, t as findSharedKey, u as isAssetLikeImport } from "./sharedKeyMatcher-BRzBCbuR.js";
1
2
  import { i as resolveHashPlaceholderFileName, n as normalizePathForImport, r as rebaseImport } from "./buildPaths-BoaQTkxt.js";
2
- import { a as getPackageDetectionCwd, c as getSharedCacheDescriptor, d as packageNameDecode, f as packageNameEncode, g as createModuleFederationError, h as sharedCacheHelperCode, i as getIsRolldown, l as hasPackageDependency, m as setPackageDetectionCwd, n as getInstalledPackageEntry, o as getPackageName, p as resolveImportPath, r as getInstalledPackageJson, s as getPackageNameFromNodeModulePath, u as isNuxtProjectRoot, v as mfWarn } from "./dtsConstants-BsaLBaaK.js";
3
- import { a as filterId, c as getCommonSharedSubpaths, d as isNodeModulePath, f as isNuxtClientBase, h as resolvePublicPath, i as ensureTrailingSlash, l as getMatchingNodeModuleSubpath, m as normalizeNodeModulePath, n as invalidateSharedKeyMatcher, o as getBasePath$1, p as isViteOptimizableEntry, r as matchesSharedSource, s as getCommonSharedSubpathFromNodeModulePath, t as findSharedKey, u as isAssetLikeImport } from "./sharedKeyMatcher-DiUzRVH1.js";
3
+ import { _ as sharedCacheHelperCode, a as getPackageDetectionCwd, b as mfWarn, c as getSharedCacheDescriptor, d as isPackageExportAvailable, f as isPackageInstalled, g as setPackageDetectionCwd, h as resolveImportPath, i as getIsRolldown, l as hasPackageDependency, m as packageNameEncode, n as getInstalledPackageEntry, o as getPackageName, p as packageNameDecode, r as getInstalledPackageJson, s as getPackageNameFromNodeModulePath, u as isNuxtProjectRoot, v as createModuleFederationError } from "./dtsConstants-dDsHZFC1.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";
@@ -373,6 +373,38 @@ async function mapCodeToCodeWithSourcemap(code) {
373
373
  };
374
374
  }
375
375
  //#endregion
376
+ //#region src/utils/remoteConsumerTarget.ts
377
+ function getPluginEnvironmentName(ctx) {
378
+ if (ctx == null || typeof ctx !== "object") return void 0;
379
+ const environment = ctx["environment"];
380
+ if (environment == null || typeof environment !== "object") return void 0;
381
+ const name = environment["name"];
382
+ return typeof name === "string" ? name : void 0;
383
+ }
384
+ /**
385
+ * Classify a plugin hook context's Vite environment. Environment names are
386
+ * user-defined, so Vite's `config.consumer` is the semantic role; fall back to
387
+ * the name only when it is missing (Vite 5–7). Returns `undefined` when the hook
388
+ * has no environment context at all.
389
+ */
390
+ function resolveEnvironmentConsumerTarget(ctx) {
391
+ if (ctx == null || typeof ctx !== "object") return void 0;
392
+ const environment = ctx["environment"];
393
+ if (environment == null || typeof environment !== "object") return void 0;
394
+ const consumer = environment.config?.consumer;
395
+ if (consumer === "client" || consumer === "server") return consumer;
396
+ const envName = getPluginEnvironmentName(ctx);
397
+ return !envName || envName === "client" ? "client" : "server";
398
+ }
399
+ /** Vite 5–7 hooks have no environment context and keep their client build behavior. */
400
+ function isClientEnvironment(ctx) {
401
+ return resolveEnvironmentConsumerTarget(ctx) !== "server";
402
+ }
403
+ function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
404
+ if (!hasMultiEnvironment) return "unified";
405
+ return resolveEnvironmentConsumerTarget(ctx) ?? "client";
406
+ }
407
+ //#endregion
376
408
  //#region src/utils/codePositionMap.ts
377
409
  const REGEX_PREFIX_KEYWORDS = /* @__PURE__ */ new Set([
378
410
  "await",
@@ -399,7 +431,7 @@ function isJsxClosingTagSlash(code, slashIndex) {
399
431
  return code[cursor] === ">";
400
432
  }
401
433
  /** Mark comments, string/template literals, and regular expressions as non-code. */
402
- function createCodePositionMap(code) {
434
+ function createCodePositionMap(code, onComment) {
403
435
  const positions = Array(code.length).fill(true);
404
436
  const mask = (start, end) => {
405
437
  for (let index = start; index < end; index++) positions[index] = false;
@@ -417,6 +449,7 @@ function createCodePositionMap(code) {
417
449
  index += 2;
418
450
  while (index < code.length && code[index] !== "\n" && code[index] !== "\r") index++;
419
451
  mask(start, index);
452
+ onComment?.(start, index);
420
453
  continue;
421
454
  }
422
455
  if (char === "/" && next === "*") {
@@ -425,6 +458,7 @@ function createCodePositionMap(code) {
425
458
  while (index < code.length && !(code[index] === "*" && code[index + 1] === "/")) index++;
426
459
  index = Math.min(code.length, index + 2);
427
460
  mask(start, index);
461
+ onComment?.(start, index);
428
462
  continue;
429
463
  }
430
464
  if (char === "\"" || char === "'" || char === "`") {
@@ -730,8 +764,8 @@ function normalizeRemoteItem(key, remote) {
730
764
  * @param {string} sharedName
731
765
  * @returns {string | undefined}
732
766
  */
733
- function searchPackageVersion(sharedName) {
734
- const version = getInstalledPackageJson(sharedName)?.packageJson.version;
767
+ function searchPackageVersion(sharedName, cwd) {
768
+ const version = getInstalledPackageJson(sharedName, { cwd })?.packageJson.version;
735
769
  return typeof version === "string" ? version : void 0;
736
770
  }
737
771
  function inferVersionFromRequiredVersion(requiredVersion) {
@@ -766,36 +800,88 @@ const PACKAGE_SPECIFIER_PROTOCOL_RE = /^[a-z][a-z\d+.-]*:/i;
766
800
  function isProtocolRequiredVersion(requiredVersion) {
767
801
  return PACKAGE_SPECIFIER_PROTOCOL_RE.test(requiredVersion.trim());
768
802
  }
803
+ const SEMVER_COMPARATOR_RE = /^(?:[<>=~^]*v?(?:\d+|[xX*])(?:\.(?:\d+|[xX*]))*(?:[-+][\w.-]+)?|[<>=~^]+|[xX*]|-)$/;
804
+ function isSemverRange(range) {
805
+ return range.split("||").every((alternative) => {
806
+ const comparators = alternative.trim().split(/\s+/).filter(Boolean);
807
+ return comparators.length > 0 && comparators.every((c) => SEMVER_COMPARATOR_RE.test(c));
808
+ });
809
+ }
810
+ function isUsableRequiredVersion(requiredVersion) {
811
+ return requiredVersion.trim() !== "" && !isProtocolRequiredVersion(requiredVersion) && isSemverRange(requiredVersion);
812
+ }
813
+ /** Bare specifiers name an installed package; relative/absolute paths do not. */
814
+ function isBareSpecifier(specifier) {
815
+ return !specifier.startsWith(".") && !specifier.startsWith("\0") && !path$1.isAbsolute(specifier) && !PACKAGE_SPECIFIER_PROTOCOL_RE.test(specifier);
816
+ }
817
+ function readProjectPackageJson(cwd, cache) {
818
+ if (cache.has(cwd)) return cache.get(cwd);
819
+ let packageJson;
820
+ try {
821
+ packageJson = JSON.parse(fs$2.readFileSync(path$1.join(cwd, "package.json"), "utf8"));
822
+ } catch {}
823
+ cache.set(cwd, packageJson);
824
+ return packageJson;
825
+ }
769
826
  function getLitExportSubpathShares(sharedName) {
770
827
  if (sharedName !== "lit") return [];
771
828
  const exportsField = getInstalledPackageJson(sharedName, { packageName: sharedName })?.packageJson.exports;
772
829
  if (!exportsField || typeof exportsField === "string") return [];
773
830
  return Object.keys(exportsField).filter((key) => key.startsWith("./") && key !== "." && !key.includes("*")).map((key) => `${sharedName}/${key.slice(2)}`);
774
831
  }
832
+ const sharedVersionConfigs = /* @__PURE__ */ new WeakMap();
833
+ function resolveSharedVersion(key, config, cwd, packageJsonCache = /* @__PURE__ */ new Map(), fallbackVersion) {
834
+ const source = typeof config.import === "string" && isBareSpecifier(config.import) ? config.import : key;
835
+ const version = config.version || searchPackageVersion(source, cwd) || inferVersionFromRequiredVersion(config.requiredVersion) || fallbackVersion;
836
+ let requiredVersion = config.requiredVersion;
837
+ if (requiredVersion === void 0 && !config.version) {
838
+ const packageJson = readProjectPackageJson(cwd, packageJsonCache);
839
+ const packageName = getPackageName(source);
840
+ requiredVersion = packageJson?.dependencies?.[packageName] ?? packageJson?.devDependencies?.[packageName] ?? packageJson?.peerDependencies?.[packageName] ?? packageJson?.optionalDependencies?.[packageName];
841
+ }
842
+ if (requiredVersion === false || typeof requiredVersion === "string" && isUsableRequiredVersion(requiredVersion)) return {
843
+ version,
844
+ requiredVersion
845
+ };
846
+ return {
847
+ version,
848
+ requiredVersion: config.import === false || config.version ? "*" : version ? `^${version}` : "*"
849
+ };
850
+ }
851
+ function resolveSharedVersions(shared, root) {
852
+ const packageJsonCache = /* @__PURE__ */ new Map();
853
+ for (const [key, item] of Object.entries(shared)) {
854
+ const config = sharedVersionConfigs.get(item);
855
+ if (!config) continue;
856
+ const { version, requiredVersion } = resolveSharedVersion(key, config, root, packageJsonCache, item.version);
857
+ item.version = version;
858
+ item.shareConfig.requiredVersion = requiredVersion;
859
+ }
860
+ }
775
861
  function normalizeShareItem(key, shareItem) {
776
- const isImportFalse = typeof shareItem === "object" && shareItem.import === false;
777
- const explicitVersion = typeof shareItem === "object" ? shareItem.version : void 0;
778
- const inferredVersion = typeof shareItem === "object" ? inferVersionFromRequiredVersion(shareItem.requiredVersion) : void 0;
779
862
  const treeShaking = typeof shareItem === "object" ? shareItem.treeShaking : void 0;
780
863
  if (treeShaking && treeShaking.mode !== "server-calc" && treeShaking.mode !== "runtime-infer") throw createModuleFederationError(`Invalid shared config for "${key}": treeShaking.mode must be either "server-calc" or "runtime-infer".`);
781
864
  if (treeShaking && typeof shareItem === "object" && shareItem.eager) throw createModuleFederationError(`Invalid shared config for "${key}": cannot use both "eager: true" and "treeShaking.mode" simultaneously. Choose one strategy.`);
782
865
  if (treeShaking?.mode === "runtime-infer" && typeof shareItem === "object" && shareItem.singleton) mfWarn(`Shared singleton "${key}" uses runtime-infer tree shaking, which may load both a tree-shaken bundle and a full bundle when consumers require different exports. Prefer server-calc for singleton dependencies. If runtime-infer is required, expand usedExports to reduce this risk.`);
783
- const version = explicitVersion || searchPackageVersion(key) || inferredVersion;
784
- if (typeof shareItem === "string") return {
785
- name: shareItem,
786
- version,
787
- scope: "default",
788
- from: "",
789
- shareConfig: {
790
- import: void 0,
791
- singleton: false,
792
- eager: false,
793
- requiredVersion: version ? `^${version}` : "*"
794
- }
795
- };
796
- const userRequiredVersion = shareItem.requiredVersion;
797
- const keepUserRequiredVersion = userRequiredVersion === false || typeof userRequiredVersion === "string" && userRequiredVersion.trim() !== "" && !isProtocolRequiredVersion(userRequiredVersion);
798
- return {
866
+ const config = typeof shareItem === "object" ? shareItem : {};
867
+ const { version, requiredVersion } = resolveSharedVersion(key, config, getPackageDetectionCwd());
868
+ if (typeof shareItem === "string") {
869
+ const result = {
870
+ name: shareItem,
871
+ version,
872
+ scope: "default",
873
+ from: "",
874
+ shareConfig: {
875
+ import: void 0,
876
+ singleton: false,
877
+ eager: false,
878
+ requiredVersion
879
+ }
880
+ };
881
+ sharedVersionConfigs.set(result, { ...config });
882
+ return result;
883
+ }
884
+ const result = {
799
885
  name: key,
800
886
  from: "",
801
887
  version,
@@ -804,12 +890,14 @@ function normalizeShareItem(key, shareItem) {
804
890
  import: shareItem.import,
805
891
  singleton: shareItem.singleton || false,
806
892
  eager: shareItem.eager || false,
807
- requiredVersion: keepUserRequiredVersion ? userRequiredVersion : isImportFalse || shareItem.version ? "*" : version ? `^${version}` : "*",
893
+ requiredVersion,
808
894
  strictVersion: !!shareItem.strictVersion,
809
895
  ...shareItem.suppressMissingImportWarning ? { suppressMissingImportWarning: true } : {},
810
896
  ...treeShaking ? { treeShaking: { ...treeShaking } } : {}
811
897
  }
812
898
  };
899
+ sharedVersionConfigs.set(result, { ...config });
900
+ return result;
813
901
  }
814
902
  /**
815
903
  * Trailing-slash keys are package namespace prefixes (`lodash/`, `@scope/ui/`).
@@ -887,6 +975,11 @@ function normalizeExperiments(experiments) {
887
975
  ssrMode: experiments?.ssrMode === "ISLAND" ? "ISLAND" : void 0
888
976
  };
889
977
  }
978
+ function normalizeSsrEntryLoader(ssrEntryLoader) {
979
+ const strategy = ssrEntryLoader?.strategy;
980
+ if (strategy !== "temp-file" && strategy !== "vm") return void 0;
981
+ return { strategy };
982
+ }
890
983
  let config;
891
984
  let explicitSharedKeys = /* @__PURE__ */ new Set();
892
985
  const explicitSharedKeysByOptions = /* @__PURE__ */ new WeakMap();
@@ -905,11 +998,27 @@ function resolveRuntimeImplementation() {
905
998
  function getNormalizeModuleFederationOptions() {
906
999
  return config;
907
1000
  }
1001
+ function hasRemotes(options = getNormalizeModuleFederationOptions()) {
1002
+ return Object.keys(options.remotes || {}).length > 0;
1003
+ }
1004
+ function hasShared(options = getNormalizeModuleFederationOptions()) {
1005
+ return Object.keys(options.shared || {}).length > 0;
1006
+ }
1007
+ function isRemoteContainer(options = getNormalizeModuleFederationOptions()) {
1008
+ return Object.keys(options.exposes || {}).length > 0;
1009
+ }
1010
+ function isRemoteOnlyContainer(options = getNormalizeModuleFederationOptions()) {
1011
+ return isRemoteContainer(options) && !hasRemotes(options);
1012
+ }
1013
+ function isLocalOnlyContainer(options = getNormalizeModuleFederationOptions()) {
1014
+ return !isRemoteContainer(options) && !hasRemotes(options);
1015
+ }
908
1016
  function isExplicitSharedKey(key, options) {
909
1017
  return (options ? explicitSharedKeysByOptions.get(options) : explicitSharedKeys)?.has(key) ?? false;
910
1018
  }
911
1019
  function getNormalizeShareItem(key, options = getNormalizeModuleFederationOptions()) {
912
- return options.shared[key] || options.shared[getPackageName(key)] || options.shared[getPackageName(key) + "/"];
1020
+ const matchedKey = findSharedKey(key, options.shared);
1021
+ return options.shared[key] || (matchedKey ? options.shared[matchedKey] : void 0) || options.shared[getPackageName(key)] || options.shared[getPackageName(key) + "/"];
913
1022
  }
914
1023
  function normalizeModuleFederationOptions(options) {
915
1024
  warnOnReservedInternalNamePrefix(options.name, "containerName");
@@ -945,6 +1054,7 @@ function normalizeModuleFederationOptions(options) {
945
1054
  varFilename: options.varFilename,
946
1055
  target: options.target,
947
1056
  ssrExternals: options.ssrExternals,
1057
+ ssrEntryLoader: normalizeSsrEntryLoader(options.ssrEntryLoader),
948
1058
  disableRemote: options.disableRemote,
949
1059
  disableShared: options.disableShared,
950
1060
  disableSnapshot: options.disableSnapshot,
@@ -1022,11 +1132,14 @@ var VirtualModule = class VirtualModule {
1022
1132
  cacheMap[this.tag][this.name] = this;
1023
1133
  }
1024
1134
  getImportId() {
1025
- const importIdKey = `${this.scopeName ?? getNormalizeModuleFederationOptions().internalName}${this.tag}${this.name}${this.tag}`;
1135
+ const mfName = this.scopeName ?? getNormalizeModuleFederationOptions().internalName;
1136
+ const importIdKey = `${mfName}${this.tag}${this.name}${this.tag}`;
1026
1137
  if (this.importId && this.importIdKey === importIdKey) return this.importId;
1027
1138
  if (this.importId) delete idCacheMap[this.importId];
1028
1139
  this.importIdKey = importIdKey;
1029
- this.importId = `virtual:mf:${packageNameEncode(importIdKey)}${this.suffix}`;
1140
+ const namePart = packageNameEncode(this.name);
1141
+ const mfNamePart = packageNameEncode(mfName);
1142
+ this.importId = `virtual:mf:${mfNamePart}${this.tag}${namePart}${this.tag}${this.suffix}`;
1030
1143
  idCacheMap[this.importId] = this;
1031
1144
  return this.importId;
1032
1145
  }
@@ -1163,161 +1276,431 @@ function isParsableExpression(source) {
1163
1276
  }
1164
1277
  }
1165
1278
  //#endregion
1166
- //#region src/utils/reactIsland.ts
1167
- const SOURCE_EXTENSIONS$1 = [
1168
- ".tsx",
1169
- ".jsx",
1170
- ".ts",
1171
- ".js",
1172
- ".mts",
1173
- ".mjs",
1174
- ".cts",
1175
- ".cjs"
1176
- ];
1177
- function stripQueryAndHash$2(id) {
1178
- return id.split(/[?#]/, 1)[0];
1279
+ //#region src/utils/treeShaking.ts
1280
+ function shouldAnalyzeSharedExports(shareItem) {
1281
+ return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
1179
1282
  }
1180
- function resolveSourceFile(importPath, root) {
1181
- const cleanImport = stripQueryAndHash$2(importPath);
1182
- if (!cleanImport.startsWith(".") && !path$1.isAbsolute(cleanImport)) return;
1183
- const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
1184
- return [
1185
- candidate,
1186
- ...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
1187
- ...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
1188
- ].find((filePath) => {
1189
- try {
1190
- return fs$1.statSync(filePath).isFile();
1191
- } catch {
1192
- return false;
1193
- }
1194
- });
1283
+ const legacyTreeShakingState = {
1284
+ inferredUsage: /* @__PURE__ */ new Map(),
1285
+ buildMode: false
1286
+ };
1287
+ const treeShakingStates = /* @__PURE__ */ new WeakMap();
1288
+ function getTreeShakingState(options) {
1289
+ if (!options) return legacyTreeShakingState;
1290
+ let state = treeShakingStates.get(options);
1291
+ if (!state) {
1292
+ state = {
1293
+ inferredUsage: /* @__PURE__ */ new Map(),
1294
+ buildMode: false
1295
+ };
1296
+ treeShakingStates.set(options, state);
1297
+ }
1298
+ return state;
1195
1299
  }
1196
- function localDefaultReexport(source) {
1197
- const match = source.match(/export\s*{\s*(?:default(?:\s+as\s+default)?|[A-Za-z_$][\w$]*\s+as\s+default)\s*}\s*from\s*["']([^"']+)["']/);
1198
- return match?.[1]?.startsWith(".") ? match[1] : void 0;
1300
+ function setTreeShakingBuildMode(enabled, options) {
1301
+ getTreeShakingState(options).buildMode = enabled;
1199
1302
  }
1200
- function isReactComponentSource(source, filePath = "component.tsx") {
1201
- if (!(/\bexport\s+default\b/.test(source) || /\bexport\s*{[^}]*\bdefault\b[^}]*}(?:\s*from\s*["'][^"']+["'])?/.test(source))) return false;
1202
- const extension = path$1.extname(stripQueryAndHash$2(filePath)).toLowerCase();
1203
- const canContainJsx = extension === ".tsx" || extension === ".jsx";
1204
- const hasJsx = /<>|<\s*[A-Za-z][\w.:-]*(?:\s[^<>]*?)?\s*\/?>/.test(source);
1205
- const importsReact = /\bfrom\s*["']react["']|\brequire\(\s*["']react["']\s*\)/.test(source);
1206
- const usesReactApi = /\b(?:React\.)?(?:createElement|jsx|jsxs)\s*\(/.test(source);
1207
- const isClientModule = /^\s*["']use client["']\s*;?/m.test(source);
1208
- return canContainJsx && hasJsx || importsReact && (hasJsx || usesReactApi || isClientModule);
1303
+ function resetTreeShakingExports(options) {
1304
+ getTreeShakingState(options).inferredUsage.clear();
1209
1305
  }
1210
- function isReactComponentFile(filePath, seen = /* @__PURE__ */ new Set()) {
1211
- const normalizedPath = path$1.resolve(filePath);
1212
- if (seen.has(normalizedPath)) return false;
1213
- seen.add(normalizedPath);
1214
- let source;
1215
- try {
1216
- source = fs$1.readFileSync(normalizedPath, "utf8");
1217
- } catch {
1218
- return false;
1306
+ function getOrCreateExportRecord(sharedKey, request, options) {
1307
+ const inferredUsage = getTreeShakingState(options).inferredUsage;
1308
+ let byRequest = inferredUsage.get(sharedKey);
1309
+ if (!byRequest) {
1310
+ byRequest = /* @__PURE__ */ new Map();
1311
+ inferredUsage.set(sharedKey, byRequest);
1219
1312
  }
1220
- if (isReactComponentSource(source, normalizedPath)) return true;
1221
- const reexport = localDefaultReexport(source);
1222
- if (!reexport) return false;
1223
- const reexportPath = resolveSourceFile(reexport, path$1.dirname(normalizedPath));
1224
- return reexportPath ? isReactComponentFile(reexportPath, seen) : false;
1225
- }
1226
- /**
1227
- * React is shared by the normal MF runtime when explicitly configured. When it
1228
- * is local, UI exposes can safely advertise an island capability in addition
1229
- * to their unchanged default export.
1230
- */
1231
- function getReactIslandExposes(options, root) {
1232
- if (options.experiments.ssrMode !== "ISLAND") return /* @__PURE__ */ new Set();
1233
- if (Object.hasOwn(options.shared, "react")) return /* @__PURE__ */ new Set();
1234
- const islandExposes = /* @__PURE__ */ new Set();
1235
- for (const [key, expose] of Object.entries(options.exposes)) {
1236
- const sourceFile = resolveSourceFile(expose.import, root);
1237
- if (sourceFile && isReactComponentFile(sourceFile)) islandExposes.add(key);
1313
+ let record = byRequest.get(request);
1314
+ if (!record) {
1315
+ record = {
1316
+ requiresFullBundle: false,
1317
+ usedExports: /* @__PURE__ */ new Set()
1318
+ };
1319
+ byRequest.set(request, record);
1238
1320
  }
1239
- return islandExposes;
1240
- }
1241
- function generateReactIslandBrowserDefinition(enabled) {
1242
- if (!enabled) return "";
1243
- return `
1244
- exportModule.__mf_island = {
1245
- version: 1,
1246
- renderToHtml() {
1247
- return Promise.reject(new Error("[Module Federation] renderToHtml is only available in the SSR remote entry"));
1248
- },
1249
- hydrate(element, props) {
1250
- const root = element && element.hasAttribute && element.hasAttribute("data-mf-island-state")
1251
- ? element
1252
- : element && element.querySelector
1253
- ? element.querySelector("[data-mf-island-state]") || element
1254
- : element;
1255
- if (!root) {
1256
- return Promise.reject(new Error("[Module Federation] Cannot hydrate an island without a root element"));
1257
- }
1258
- let serverProps = {};
1259
- const encodedState = root.getAttribute && root.getAttribute("data-mf-island-state");
1260
- if (encodedState) {
1261
- try {
1262
- serverProps = JSON.parse(decodeURIComponent(encodedState));
1263
- } catch {
1264
- serverProps = {};
1265
- }
1266
- }
1267
- const finalProps = Object.assign({}, serverProps, props || {});
1268
- return Promise.all([import("react"), import("react-dom/client")]).then(([React, ReactDOMClient]) => {
1269
- if (typeof ReactDOMClient.hydrateRoot !== "function") {
1270
- throw new Error("[Module Federation] react-dom/client does not provide hydrateRoot");
1271
- }
1272
- return ReactDOMClient.hydrateRoot(
1273
- root,
1274
- React.createElement(importModule.default, finalProps)
1275
- );
1276
- });
1277
- }
1278
- }`;
1321
+ return record;
1279
1322
  }
1280
- function generateReactIslandSSRDefinition(enabled) {
1281
- if (!enabled) return "";
1282
- return `
1283
- exportModule.__mf_island = {
1284
- version: 1,
1285
- async renderToHtml(props) {
1286
- if (typeof importModule.default !== "function" && typeof importModule.default !== "object") {
1287
- throw new Error("[Module Federation] A React island expose must have a default component export");
1288
- }
1289
- const loadedProps = typeof importModule.load === "function" ? await importModule.load() : {};
1290
- const finalProps = Object.assign({}, loadedProps || {}, props || {});
1291
- const [React, ReactDOMServer] = await Promise.all([
1292
- import("react"),
1293
- import("react-dom/server")
1294
- ]);
1295
- const body = ReactDOMServer.renderToString(
1296
- React.createElement(importModule.default, finalProps)
1297
- );
1298
- const state = encodeURIComponent(JSON.stringify(finalProps));
1299
- return '<div data-mf-island-state="' + state + '">' + body + '</div>';
1300
- },
1301
- hydrate() {
1302
- return Promise.reject(new Error("[Module Federation] hydrate is only available in the browser remote entry"));
1303
- }
1304
- }`;
1323
+ function recordTreeShakingExports(sharedKey, exports, request = sharedKey, options) {
1324
+ const record = getOrCreateExportRecord(sharedKey, request, options);
1325
+ exports.forEach((name) => record.usedExports.add(name));
1305
1326
  }
1306
- const REACT_ISLAND_CLIENT_ID_PREFIX = "virtual:mf-react-island-client:";
1307
- const REACT_ISLAND_SERVER_ID_PREFIX = "virtual:mf-react-island-server:";
1308
- const RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX = `\0${REACT_ISLAND_CLIENT_ID_PREFIX}`;
1309
- const RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX = `\0${REACT_ISLAND_SERVER_ID_PREFIX}`;
1310
- function encodeIslandRemoteId(remoteId) {
1311
- return encodeURIComponent(remoteId);
1327
+ function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey, options) {
1328
+ getOrCreateExportRecord(sharedKey, request, options).requiresFullBundle = true;
1312
1329
  }
1313
- function decodeIslandRemoteId(encodedRemoteId) {
1314
- return decodeURIComponent(encodedRemoteId);
1330
+ function getExportRecords(sharedKey, request, options) {
1331
+ const inferredUsage = getTreeShakingState(options).inferredUsage;
1332
+ if (sharedKey) {
1333
+ const records = inferredUsage.get(sharedKey);
1334
+ const wildcard = records?.get("*");
1335
+ const exact = records?.get(request);
1336
+ return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
1337
+ }
1338
+ const records = [];
1339
+ inferredUsage.forEach((byRequest, configuredKey) => {
1340
+ const wildcard = byRequest.get("*");
1341
+ const exact = byRequest.get(request);
1342
+ const keyBase = configuredKey.endsWith("/") ? configuredKey.slice(0, -1) : configuredKey;
1343
+ const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
1344
+ if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
1345
+ if (exact && exact !== wildcard) records.push(exact);
1346
+ });
1347
+ return records;
1315
1348
  }
1316
- function getReactIslandImportRemoteId(source) {
1317
- const queryIndex = source.indexOf("?");
1318
- if (queryIndex === -1) return;
1319
- if (!new URLSearchParams(source.slice(queryIndex + 1)).has("mf-island")) return;
1320
- return source.slice(0, queryIndex);
1349
+ /**
1350
+ * Return the analyzed requirement for one concrete shared request.
1351
+ *
1352
+ * Callers that know the configured share key should pass it explicitly. The
1353
+ * fallback lookup across keys keeps aliases/backwards-compatible callers
1354
+ * working, while still keeping each concrete request's exports isolated.
1355
+ */
1356
+ function getSharedExportUsage(request, shareItem, sharedKey, options) {
1357
+ const treeShaking = shareItem?.shareConfig.treeShaking;
1358
+ if (!shouldAnalyzeSharedExports(shareItem) || !getTreeShakingState(options).buildMode) return;
1359
+ const records = getExportRecords(sharedKey, request, options);
1360
+ if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
1361
+ const configured = treeShaking?.usedExports ?? [];
1362
+ const result = new Set(configured);
1363
+ records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
1364
+ if (result.size > 0) return {
1365
+ kind: "exports",
1366
+ usedExports: [...result].sort()
1367
+ };
1368
+ return records.length > 0 ? {
1369
+ kind: "exports",
1370
+ usedExports: []
1371
+ } : { kind: "unknown" };
1372
+ }
1373
+ function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
1374
+ if (!shareItem?.shareConfig.treeShaking) return void 0;
1375
+ return getSharedExportUsage(request, shareItem, sharedKey, options);
1376
+ }
1377
+ function getModuleSource(node) {
1378
+ if (!node || typeof node !== "object") return void 0;
1379
+ const source = node;
1380
+ if (source.type === "Literal" && typeof source.value === "string") return source.value;
1381
+ if (source.type === "StringLiteral" && typeof source.value === "string") return source.value;
1382
+ if (source.type !== "TemplateLiteral") return void 0;
1383
+ const expressions = Array.isArray(source.expressions) ? source.expressions : [];
1384
+ const quasis = Array.isArray(source.quasis) ? source.quasis : [];
1385
+ if (expressions.length > 0 || quasis.length !== 1) return void 0;
1386
+ const value = quasis[0]?.value;
1387
+ return typeof value?.cooked === "string" ? value.cooked : typeof value?.raw === "string" ? value.raw : void 0;
1388
+ }
1389
+ function getExportedName(node) {
1390
+ if (!node || typeof node !== "object") return void 0;
1391
+ const exported = node;
1392
+ if (exported.type === "Identifier" && typeof exported.name === "string") return exported.name;
1393
+ if ((exported.type === "Literal" || exported.type === "StringLiteral") && typeof exported.value === "string") return exported.value;
1394
+ }
1395
+ function isTypeOnly(node) {
1396
+ return node.importKind === "type" || node.exportKind === "type";
1397
+ }
1398
+ function forEachAstNode(root, visit) {
1399
+ const stack = [root];
1400
+ const seen = /* @__PURE__ */ new Set();
1401
+ while (stack.length > 0) {
1402
+ const value = stack.pop();
1403
+ if (!value || typeof value !== "object") continue;
1404
+ if (seen.has(value)) continue;
1405
+ seen.add(value);
1406
+ if (Array.isArray(value)) {
1407
+ for (let index = value.length - 1; index >= 0; index--) stack.push(value[index]);
1408
+ continue;
1409
+ }
1410
+ const node = value;
1411
+ if (typeof node.type === "string") visit(node);
1412
+ Object.entries(node).forEach(([key, child]) => {
1413
+ if (key !== "parent" && key !== "loc") stack.push(child);
1414
+ });
1415
+ }
1416
+ }
1417
+ function collectImportDeclaration(node, source, record, markUnsafe) {
1418
+ if (isTypeOnly(node)) return;
1419
+ const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1420
+ if (specifiers.length === 0) {
1421
+ markUnsafe(source);
1422
+ return;
1423
+ }
1424
+ const names = [];
1425
+ for (const specifier of specifiers) {
1426
+ if (isTypeOnly(specifier)) continue;
1427
+ if (specifier.type === "ImportNamespaceSpecifier") {
1428
+ markUnsafe(source);
1429
+ return;
1430
+ }
1431
+ if (specifier.type === "ImportDefaultSpecifier") {
1432
+ names.push("default");
1433
+ continue;
1434
+ }
1435
+ if (specifier.type === "ImportSpecifier") {
1436
+ const imported = specifier.imported;
1437
+ if (imported?.type === "Literal" || imported?.type === "StringLiteral") {
1438
+ markUnsafe(source);
1439
+ return;
1440
+ }
1441
+ const name = getExportedName(specifier.imported);
1442
+ if (!name) {
1443
+ markUnsafe(source);
1444
+ return;
1445
+ }
1446
+ names.push(name);
1447
+ continue;
1448
+ }
1449
+ markUnsafe(source);
1450
+ return;
1451
+ }
1452
+ record(names, source);
1453
+ }
1454
+ function collectReExport(node, source, record, markUnsafe) {
1455
+ if (isTypeOnly(node)) return;
1456
+ if (node.type === "ExportAllDeclaration") {
1457
+ markUnsafe(source);
1458
+ return;
1459
+ }
1460
+ const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1461
+ if (specifiers.length === 0) {
1462
+ markUnsafe(source);
1463
+ return;
1464
+ }
1465
+ const names = [];
1466
+ for (const specifier of specifiers) {
1467
+ if (isTypeOnly(specifier)) continue;
1468
+ if (specifier.type !== "ExportSpecifier") {
1469
+ markUnsafe(source);
1470
+ return;
1471
+ }
1472
+ const local = specifier.local;
1473
+ if (local?.type === "Literal" || local?.type === "StringLiteral") {
1474
+ markUnsafe(source);
1475
+ return;
1476
+ }
1477
+ const name = getExportedName(specifier.local);
1478
+ if (!name) {
1479
+ markUnsafe(source);
1480
+ return;
1481
+ }
1482
+ names.push(name);
1483
+ }
1484
+ record(names, source);
1485
+ }
1486
+ /**
1487
+ * Collect the exports required by a consumer's ESM graph.
1488
+ *
1489
+ * Parsing the module avoids treating import-looking text in comments, strings,
1490
+ * templates, or regular expressions as real dependencies. If parsing fails,
1491
+ * every configured share whose exports are analyzed is conservatively marked
1492
+ * as requiring its full export surface instead of guessing from source text.
1493
+ *
1494
+ * Generated federation wrappers are excluded because their imports describe
1495
+ * the wrapper implementation, not the consumer's requirements.
1496
+ */
1497
+ async function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe) {
1498
+ const normalizedId = normalizePathForImport(id);
1499
+ if (normalizedId.includes("__prebuild__") || normalizedId.includes("__loadShare__") || normalizedId.includes("__mf_tree_shaking_graph__")) return;
1500
+ let ast;
1501
+ try {
1502
+ ast = parseAst(code);
1503
+ } catch {
1504
+ Object.entries(shared).forEach(([sharedKey, shareItem]) => {
1505
+ if (shouldAnalyzeSharedExports(shareItem)) markUnsafe(sharedKey, "*");
1506
+ });
1507
+ return;
1508
+ }
1509
+ const pending = [];
1510
+ const withSharedSource = (source, use) => {
1511
+ const apply = (key) => {
1512
+ if (key && shouldAnalyzeSharedExports(shared[key])) use(key);
1513
+ };
1514
+ const key = findSharedKey(source, shared);
1515
+ if (key instanceof Promise) pending.push(key.then(apply));
1516
+ else apply(key);
1517
+ };
1518
+ const recordSource = (names, source) => {
1519
+ withSharedSource(source, (key) => record(key, names, source));
1520
+ };
1521
+ const markSourceUnsafe = (source) => {
1522
+ withSharedSource(source, (key) => markUnsafe(key, source));
1523
+ };
1524
+ forEachAstNode(ast, (node) => {
1525
+ if (node.type === "ImportDeclaration") {
1526
+ const source = getModuleSource(node.source);
1527
+ if (source) collectImportDeclaration(node, source, recordSource, markSourceUnsafe);
1528
+ return;
1529
+ }
1530
+ if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
1531
+ const source = getModuleSource(node.source);
1532
+ if (source) collectReExport(node, source, recordSource, markSourceUnsafe);
1533
+ return;
1534
+ }
1535
+ if (node.type === "ImportExpression") {
1536
+ const source = getModuleSource(node.source);
1537
+ if (source) markSourceUnsafe(source);
1538
+ return;
1539
+ }
1540
+ if (node.type === "CallExpression") {
1541
+ const callee = node.callee;
1542
+ const args = Array.isArray(node.arguments) ? node.arguments : [];
1543
+ if (callee?.type === "Identifier" && callee.name === "require" && args.length > 0) {
1544
+ const source = getModuleSource(args[0]);
1545
+ if (source) markSourceUnsafe(source);
1546
+ }
1547
+ }
1548
+ });
1549
+ await Promise.all(pending);
1550
+ }
1551
+ //#endregion
1552
+ //#region src/utils/reactIsland.ts
1553
+ const SOURCE_EXTENSIONS$1 = [
1554
+ ".tsx",
1555
+ ".jsx",
1556
+ ".ts",
1557
+ ".js",
1558
+ ".mts",
1559
+ ".mjs",
1560
+ ".cts",
1561
+ ".cjs"
1562
+ ];
1563
+ function resolveSourceFile(importPath, root) {
1564
+ const cleanImport = stripQueryAndHash(importPath);
1565
+ if (!cleanImport.startsWith(".") && !path$1.isAbsolute(cleanImport)) return;
1566
+ const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
1567
+ return [
1568
+ candidate,
1569
+ ...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
1570
+ ...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
1571
+ ].find((filePath) => {
1572
+ try {
1573
+ return fs$1.statSync(filePath).isFile();
1574
+ } catch {
1575
+ return false;
1576
+ }
1577
+ });
1578
+ }
1579
+ function localDefaultReexport(source) {
1580
+ const match = source.match(/export\s*{\s*(?:default(?:\s+as\s+default)?|[A-Za-z_$][\w$]*\s+as\s+default)\s*}\s*from\s*["']([^"']+)["']/);
1581
+ return match?.[1]?.startsWith(".") ? match[1] : void 0;
1582
+ }
1583
+ function isReactComponentSource(source, filePath = "component.tsx") {
1584
+ if (!(/\bexport\s+default\b/.test(source) || /\bexport\s*{[^}]*\bdefault\b[^}]*}(?:\s*from\s*["'][^"']+["'])?/.test(source))) return false;
1585
+ const extension = path$1.extname(stripQueryAndHash(filePath)).toLowerCase();
1586
+ const canContainJsx = extension === ".tsx" || extension === ".jsx";
1587
+ const hasJsx = /<>|<\s*[A-Za-z][\w.:-]*(?:\s[^<>]*?)?\s*\/?>/.test(source);
1588
+ const importsReact = /\bfrom\s*["']react["']|\brequire\(\s*["']react["']\s*\)/.test(source);
1589
+ const usesReactApi = /\b(?:React\.)?(?:createElement|jsx|jsxs)\s*\(/.test(source);
1590
+ const isClientModule = /^\s*["']use client["']\s*;?/m.test(source);
1591
+ return canContainJsx && hasJsx || importsReact && (hasJsx || usesReactApi || isClientModule);
1592
+ }
1593
+ function isReactComponentFile(filePath, seen = /* @__PURE__ */ new Set()) {
1594
+ const normalizedPath = path$1.resolve(filePath);
1595
+ if (seen.has(normalizedPath)) return false;
1596
+ seen.add(normalizedPath);
1597
+ let source;
1598
+ try {
1599
+ source = fs$1.readFileSync(normalizedPath, "utf8");
1600
+ } catch {
1601
+ return false;
1602
+ }
1603
+ if (isReactComponentSource(source, normalizedPath)) return true;
1604
+ const reexport = localDefaultReexport(source);
1605
+ if (!reexport) return false;
1606
+ const reexportPath = resolveSourceFile(reexport, path$1.dirname(normalizedPath));
1607
+ return reexportPath ? isReactComponentFile(reexportPath, seen) : false;
1608
+ }
1609
+ /**
1610
+ * React is shared by the normal MF runtime when explicitly configured. When it
1611
+ * is local, UI exposes can safely advertise an island capability in addition
1612
+ * to their unchanged default export.
1613
+ */
1614
+ function getReactIslandExposes(options, root) {
1615
+ if (options.experiments.ssrMode !== "ISLAND") return /* @__PURE__ */ new Set();
1616
+ if (Object.hasOwn(options.shared, "react")) return /* @__PURE__ */ new Set();
1617
+ const islandExposes = /* @__PURE__ */ new Set();
1618
+ for (const [key, expose] of Object.entries(options.exposes)) {
1619
+ const sourceFile = resolveSourceFile(expose.import, root);
1620
+ if (sourceFile && isReactComponentFile(sourceFile)) islandExposes.add(key);
1621
+ }
1622
+ return islandExposes;
1623
+ }
1624
+ function generateReactIslandBrowserDefinition(enabled) {
1625
+ if (!enabled) return "";
1626
+ return `
1627
+ exportModule.__mf_island = {
1628
+ version: 1,
1629
+ renderToHtml() {
1630
+ return Promise.reject(new Error("[Module Federation] renderToHtml is only available in the SSR remote entry"));
1631
+ },
1632
+ hydrate(element, props) {
1633
+ const root = element && element.hasAttribute && element.hasAttribute("data-mf-island-state")
1634
+ ? element
1635
+ : element && element.querySelector
1636
+ ? element.querySelector("[data-mf-island-state]") || element
1637
+ : element;
1638
+ if (!root) {
1639
+ return Promise.reject(new Error("[Module Federation] Cannot hydrate an island without a root element"));
1640
+ }
1641
+ let serverProps = {};
1642
+ const encodedState = root.getAttribute && root.getAttribute("data-mf-island-state");
1643
+ if (encodedState) {
1644
+ try {
1645
+ serverProps = JSON.parse(decodeURIComponent(encodedState));
1646
+ } catch {
1647
+ serverProps = {};
1648
+ }
1649
+ }
1650
+ const finalProps = Object.assign({}, serverProps, props || {});
1651
+ return Promise.all([import("react"), import("react-dom/client")]).then(([React, ReactDOMClient]) => {
1652
+ if (typeof ReactDOMClient.hydrateRoot !== "function") {
1653
+ throw new Error("[Module Federation] react-dom/client does not provide hydrateRoot");
1654
+ }
1655
+ return ReactDOMClient.hydrateRoot(
1656
+ root,
1657
+ React.createElement(importModule.default, finalProps)
1658
+ );
1659
+ });
1660
+ }
1661
+ }`;
1662
+ }
1663
+ function generateReactIslandSSRDefinition(enabled) {
1664
+ if (!enabled) return "";
1665
+ return `
1666
+ exportModule.__mf_island = {
1667
+ version: 1,
1668
+ async renderToHtml(props) {
1669
+ if (typeof importModule.default !== "function" && typeof importModule.default !== "object") {
1670
+ throw new Error("[Module Federation] A React island expose must have a default component export");
1671
+ }
1672
+ const loadedProps = typeof importModule.load === "function" ? await importModule.load() : {};
1673
+ const finalProps = Object.assign({}, loadedProps || {}, props || {});
1674
+ const [React, ReactDOMServer] = await Promise.all([
1675
+ import("react"),
1676
+ import("react-dom/server")
1677
+ ]);
1678
+ const body = ReactDOMServer.renderToString(
1679
+ React.createElement(importModule.default, finalProps)
1680
+ );
1681
+ const state = encodeURIComponent(JSON.stringify(finalProps));
1682
+ return '<div data-mf-island-state="' + state + '">' + body + '</div>';
1683
+ },
1684
+ hydrate() {
1685
+ return Promise.reject(new Error("[Module Federation] hydrate is only available in the browser remote entry"));
1686
+ }
1687
+ }`;
1688
+ }
1689
+ const REACT_ISLAND_CLIENT_ID_PREFIX = "virtual:mf-react-island-client:";
1690
+ const REACT_ISLAND_SERVER_ID_PREFIX = "virtual:mf-react-island-server:";
1691
+ const RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX = `\0${REACT_ISLAND_CLIENT_ID_PREFIX}`;
1692
+ const RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX = `\0${REACT_ISLAND_SERVER_ID_PREFIX}`;
1693
+ function encodeIslandRemoteId(remoteId) {
1694
+ return encodeURIComponent(remoteId);
1695
+ }
1696
+ function decodeIslandRemoteId(encodedRemoteId) {
1697
+ return decodeURIComponent(encodedRemoteId);
1698
+ }
1699
+ function getReactIslandImportRemoteId(source) {
1700
+ const queryIndex = source.indexOf("?");
1701
+ if (queryIndex === -1) return;
1702
+ if (!new URLSearchParams(source.slice(queryIndex + 1)).has("mf-island")) return;
1703
+ return source.slice(0, queryIndex);
1321
1704
  }
1322
1705
  function getReactIslandServerImportId(remoteId) {
1323
1706
  return `${REACT_ISLAND_SERVER_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
@@ -1741,328 +2124,59 @@ for (const __mfShareKey of Object.keys(__mfModuleCache.share)) {
1741
2124
  }
1742
2125
  }
1743
2126
  }
1744
- `;
1745
- }
1746
- function getRuntimeInitPromiseBootstrapCode(enableSsrInit = false, ownerImportId, ssrRemotes, hostInitImportId = ownerImportId) {
1747
- return getRuntimeInitStateBootstrapCode({
1748
- globalKeyVar: "__mfPromiseGlobalKey",
1749
- stateVar: "__mfPromiseState",
1750
- exposedConst: "initPromise",
1751
- exposedProperty: "initPromise",
1752
- enableSsrInit,
1753
- ownerImportId,
1754
- hostInitImportId,
1755
- ssrRemotes
1756
- });
1757
- }
1758
- function getRuntimeInitResolveBootstrapCode(enableSsrInit = false, ownerImportId, ssrRemotes, hostInitImportId = ownerImportId) {
1759
- return getRuntimeInitStateBootstrapCode({
1760
- globalKeyVar: "__mfResolveGlobalKey",
1761
- stateVar: "__mfResolveState",
1762
- exposedConst: "initResolve",
1763
- exposedProperty: "initResolve",
1764
- enableSsrInit,
1765
- ownerImportId,
1766
- hostInitImportId,
1767
- ssrRemotes
1768
- });
1769
- }
1770
- function writeRuntimeInitStatus(command, enableSsrInit = false, hostInitImportId, options, ssrRemotes = _ssrRemotes) {
1771
- const exportStatement = command === "build" ? `const { initPromise, initResolve, initReject, moduleCache } = globalThis[globalKey];
1772
- export { initPromise, initResolve, initReject, moduleCache };` : `module.exports = globalThis[globalKey];`;
1773
- const ownerImportId = options ? getRuntimeInitStatusImportId(options) : hostInitImportId;
1774
- getRuntimeInitModule(options).writeSync(`
1775
- ${getRuntimeInitBootstrapCode(enableSsrInit, ownerImportId, ssrRemotes, hostInitImportId)}
1776
- ${exportStatement}
1777
- `);
1778
- }
1779
- //#endregion
1780
- //#region src/plugins/pluginReactMixedModeGuard.ts
1781
- function createReactMixedModeRuntimeGuard() {
1782
- return `const __mfReactInternals = mod["__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE"];
1783
- if (__mfReactInternals && "A" in __mfReactInternals) {
1784
- let __mfReactDispatcher = __mfReactInternals.A;
1785
- Object.defineProperty(__mfReactInternals, "A", {
1786
- configurable: true,
1787
- enumerable: true,
1788
- get: () => __mfReactDispatcher,
1789
- set: (next) => {
1790
- if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
1791
- __mfReactDispatcher = next;
1792
- },
1793
- });
1794
- __mfReactInternals.A = __mfReactDispatcher;
1795
- }`;
1796
- }
1797
- //#endregion
1798
- //#region src/utils/treeShaking.ts
1799
- function shouldAnalyzeSharedExports(shareItem) {
1800
- return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
1801
- }
1802
- const legacyTreeShakingState = {
1803
- inferredUsage: /* @__PURE__ */ new Map(),
1804
- buildMode: false
1805
- };
1806
- const treeShakingStates = /* @__PURE__ */ new WeakMap();
1807
- function getTreeShakingState(options) {
1808
- if (!options) return legacyTreeShakingState;
1809
- let state = treeShakingStates.get(options);
1810
- if (!state) {
1811
- state = {
1812
- inferredUsage: /* @__PURE__ */ new Map(),
1813
- buildMode: false
1814
- };
1815
- treeShakingStates.set(options, state);
1816
- }
1817
- return state;
1818
- }
1819
- function setTreeShakingBuildMode(enabled, options) {
1820
- getTreeShakingState(options).buildMode = enabled;
1821
- }
1822
- function resetTreeShakingExports(options) {
1823
- getTreeShakingState(options).inferredUsage.clear();
1824
- }
1825
- function getOrCreateExportRecord(sharedKey, request, options) {
1826
- const inferredUsage = getTreeShakingState(options).inferredUsage;
1827
- let byRequest = inferredUsage.get(sharedKey);
1828
- if (!byRequest) {
1829
- byRequest = /* @__PURE__ */ new Map();
1830
- inferredUsage.set(sharedKey, byRequest);
1831
- }
1832
- let record = byRequest.get(request);
1833
- if (!record) {
1834
- record = {
1835
- requiresFullBundle: false,
1836
- usedExports: /* @__PURE__ */ new Set()
1837
- };
1838
- byRequest.set(request, record);
1839
- }
1840
- return record;
1841
- }
1842
- function recordTreeShakingExports(sharedKey, exports, request = sharedKey, options) {
1843
- const record = getOrCreateExportRecord(sharedKey, request, options);
1844
- exports.forEach((name) => record.usedExports.add(name));
1845
- }
1846
- function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey, options) {
1847
- getOrCreateExportRecord(sharedKey, request, options).requiresFullBundle = true;
1848
- }
1849
- function getExportRecords(sharedKey, request, options) {
1850
- const inferredUsage = getTreeShakingState(options).inferredUsage;
1851
- if (sharedKey) {
1852
- const records = inferredUsage.get(sharedKey);
1853
- const wildcard = records?.get("*");
1854
- const exact = records?.get(request);
1855
- return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
1856
- }
1857
- const records = [];
1858
- inferredUsage.forEach((byRequest, configuredKey) => {
1859
- const wildcard = byRequest.get("*");
1860
- const exact = byRequest.get(request);
1861
- const keyBase = configuredKey.endsWith("/") ? configuredKey.slice(0, -1) : configuredKey;
1862
- const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
1863
- if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
1864
- if (exact && exact !== wildcard) records.push(exact);
1865
- });
1866
- return records;
1867
- }
1868
- /**
1869
- * Return the analyzed requirement for one concrete shared request.
1870
- *
1871
- * Callers that know the configured share key should pass it explicitly. The
1872
- * fallback lookup across keys keeps aliases/backwards-compatible callers
1873
- * working, while still keeping each concrete request's exports isolated.
1874
- */
1875
- function getSharedExportUsage(request, shareItem, sharedKey, options) {
1876
- const treeShaking = shareItem?.shareConfig.treeShaking;
1877
- if (!shouldAnalyzeSharedExports(shareItem) || !getTreeShakingState(options).buildMode) return;
1878
- const records = getExportRecords(sharedKey, request, options);
1879
- if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
1880
- const configured = treeShaking?.usedExports ?? [];
1881
- const result = new Set(configured);
1882
- records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
1883
- if (result.size > 0) return {
1884
- kind: "exports",
1885
- usedExports: [...result].sort()
1886
- };
1887
- return records.length > 0 ? {
1888
- kind: "exports",
1889
- usedExports: []
1890
- } : { kind: "unknown" };
1891
- }
1892
- function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
1893
- if (!shareItem?.shareConfig.treeShaking) return void 0;
1894
- return getSharedExportUsage(request, shareItem, sharedKey, options);
1895
- }
1896
- function getModuleSource(node) {
1897
- if (!node || typeof node !== "object") return void 0;
1898
- const source = node;
1899
- if (source.type === "Literal" && typeof source.value === "string") return source.value;
1900
- if (source.type === "StringLiteral" && typeof source.value === "string") return source.value;
1901
- if (source.type !== "TemplateLiteral") return void 0;
1902
- const expressions = Array.isArray(source.expressions) ? source.expressions : [];
1903
- const quasis = Array.isArray(source.quasis) ? source.quasis : [];
1904
- if (expressions.length > 0 || quasis.length !== 1) return void 0;
1905
- const value = quasis[0]?.value;
1906
- return typeof value?.cooked === "string" ? value.cooked : typeof value?.raw === "string" ? value.raw : void 0;
1907
- }
1908
- function getExportedName(node) {
1909
- if (!node || typeof node !== "object") return void 0;
1910
- const exported = node;
1911
- if (exported.type === "Identifier" && typeof exported.name === "string") return exported.name;
1912
- if ((exported.type === "Literal" || exported.type === "StringLiteral") && typeof exported.value === "string") return exported.value;
1913
- }
1914
- function isTypeOnly(node) {
1915
- return node.importKind === "type" || node.exportKind === "type";
1916
- }
1917
- function forEachAstNode(root, visit) {
1918
- const stack = [root];
1919
- const seen = /* @__PURE__ */ new Set();
1920
- while (stack.length > 0) {
1921
- const value = stack.pop();
1922
- if (!value || typeof value !== "object") continue;
1923
- if (seen.has(value)) continue;
1924
- seen.add(value);
1925
- if (Array.isArray(value)) {
1926
- for (let index = value.length - 1; index >= 0; index--) stack.push(value[index]);
1927
- continue;
1928
- }
1929
- const node = value;
1930
- if (typeof node.type === "string") visit(node);
1931
- Object.entries(node).forEach(([key, child]) => {
1932
- if (key !== "parent" && key !== "loc") stack.push(child);
1933
- });
1934
- }
1935
- }
1936
- function collectImportDeclaration(node, source, record, markUnsafe) {
1937
- if (isTypeOnly(node)) return;
1938
- const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1939
- if (specifiers.length === 0) {
1940
- markUnsafe(source);
1941
- return;
1942
- }
1943
- const names = [];
1944
- for (const specifier of specifiers) {
1945
- if (isTypeOnly(specifier)) continue;
1946
- if (specifier.type === "ImportNamespaceSpecifier") {
1947
- markUnsafe(source);
1948
- return;
1949
- }
1950
- if (specifier.type === "ImportDefaultSpecifier") {
1951
- names.push("default");
1952
- continue;
1953
- }
1954
- if (specifier.type === "ImportSpecifier") {
1955
- const imported = specifier.imported;
1956
- if (imported?.type === "Literal" || imported?.type === "StringLiteral") {
1957
- markUnsafe(source);
1958
- return;
1959
- }
1960
- const name = getExportedName(specifier.imported);
1961
- if (!name) {
1962
- markUnsafe(source);
1963
- return;
1964
- }
1965
- names.push(name);
1966
- continue;
1967
- }
1968
- markUnsafe(source);
1969
- return;
1970
- }
1971
- record(names, source);
1972
- }
1973
- function collectReExport(node, source, record, markUnsafe) {
1974
- if (isTypeOnly(node)) return;
1975
- if (node.type === "ExportAllDeclaration") {
1976
- markUnsafe(source);
1977
- return;
1978
- }
1979
- const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1980
- if (specifiers.length === 0) {
1981
- markUnsafe(source);
1982
- return;
1983
- }
1984
- const names = [];
1985
- for (const specifier of specifiers) {
1986
- if (isTypeOnly(specifier)) continue;
1987
- if (specifier.type !== "ExportSpecifier") {
1988
- markUnsafe(source);
1989
- return;
1990
- }
1991
- const local = specifier.local;
1992
- if (local?.type === "Literal" || local?.type === "StringLiteral") {
1993
- markUnsafe(source);
1994
- return;
1995
- }
1996
- const name = getExportedName(specifier.local);
1997
- if (!name) {
1998
- markUnsafe(source);
1999
- return;
2000
- }
2001
- names.push(name);
2002
- }
2003
- record(names, source);
2127
+ `;
2004
2128
  }
2005
- /**
2006
- * Collect the exports required by a consumer's ESM graph.
2007
- *
2008
- * Parsing the module avoids treating import-looking text in comments, strings,
2009
- * templates, or regular expressions as real dependencies. If parsing fails,
2010
- * every configured share whose exports are analyzed is conservatively marked
2011
- * as requiring its full export surface instead of guessing from source text.
2012
- *
2013
- * Generated federation wrappers are excluded because their imports describe
2014
- * the wrapper implementation, not the consumer's requirements.
2015
- */
2016
- function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe) {
2017
- const normalizedId = normalizePathForImport(id);
2018
- if (normalizedId.includes("__prebuild__") || normalizedId.includes("__loadShare__") || normalizedId.includes("__mf_tree_shaking_graph__")) return;
2019
- let ast;
2020
- try {
2021
- ast = parseAst(code);
2022
- } catch {
2023
- Object.entries(shared).forEach(([sharedKey, shareItem]) => {
2024
- if (shouldAnalyzeSharedExports(shareItem)) markUnsafe(sharedKey, "*");
2025
- });
2026
- return;
2027
- }
2028
- const matchShared = (source) => {
2029
- const sharedKey = findSharedKey(source, shared);
2030
- return sharedKey && shouldAnalyzeSharedExports(shared[sharedKey]) ? sharedKey : void 0;
2031
- };
2032
- const recordSource = (names, source) => {
2033
- const sharedKey = matchShared(source);
2034
- if (sharedKey) record(sharedKey, names, source);
2035
- };
2036
- const markSourceUnsafe = (source) => {
2037
- const sharedKey = matchShared(source);
2038
- if (sharedKey) markUnsafe(sharedKey, source);
2039
- };
2040
- forEachAstNode(ast, (node) => {
2041
- if (node.type === "ImportDeclaration") {
2042
- const source = getModuleSource(node.source);
2043
- if (source) collectImportDeclaration(node, source, recordSource, markSourceUnsafe);
2044
- return;
2045
- }
2046
- if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
2047
- const source = getModuleSource(node.source);
2048
- if (source) collectReExport(node, source, recordSource, markSourceUnsafe);
2049
- return;
2050
- }
2051
- if (node.type === "ImportExpression") {
2052
- const source = getModuleSource(node.source);
2053
- if (source) markSourceUnsafe(source);
2054
- return;
2055
- }
2056
- if (node.type === "CallExpression") {
2057
- const callee = node.callee;
2058
- const args = Array.isArray(node.arguments) ? node.arguments : [];
2059
- if (callee?.type === "Identifier" && callee.name === "require" && args.length > 0) {
2060
- const source = getModuleSource(args[0]);
2061
- if (source) markSourceUnsafe(source);
2062
- }
2063
- }
2129
+ function getRuntimeInitPromiseBootstrapCode(enableSsrInit = false, ownerImportId, ssrRemotes, hostInitImportId = ownerImportId) {
2130
+ return getRuntimeInitStateBootstrapCode({
2131
+ globalKeyVar: "__mfPromiseGlobalKey",
2132
+ stateVar: "__mfPromiseState",
2133
+ exposedConst: "initPromise",
2134
+ exposedProperty: "initPromise",
2135
+ enableSsrInit,
2136
+ ownerImportId,
2137
+ hostInitImportId,
2138
+ ssrRemotes
2139
+ });
2140
+ }
2141
+ function getRuntimeInitResolveBootstrapCode(enableSsrInit = false, ownerImportId, ssrRemotes, hostInitImportId = ownerImportId) {
2142
+ return getRuntimeInitStateBootstrapCode({
2143
+ globalKeyVar: "__mfResolveGlobalKey",
2144
+ stateVar: "__mfResolveState",
2145
+ exposedConst: "initResolve",
2146
+ exposedProperty: "initResolve",
2147
+ enableSsrInit,
2148
+ ownerImportId,
2149
+ hostInitImportId,
2150
+ ssrRemotes
2064
2151
  });
2065
2152
  }
2153
+ function writeRuntimeInitStatus(command, enableSsrInit = false, hostInitImportId, options, ssrRemotes = _ssrRemotes) {
2154
+ const exportStatement = command === "build" ? `const { initPromise, initResolve, initReject, moduleCache } = globalThis[globalKey];
2155
+ export { initPromise, initResolve, initReject, moduleCache };` : `module.exports = globalThis[globalKey];`;
2156
+ const ownerImportId = options ? getRuntimeInitStatusImportId(options) : hostInitImportId;
2157
+ getRuntimeInitModule(options).writeSync(`
2158
+ ${getRuntimeInitBootstrapCode(enableSsrInit, ownerImportId, ssrRemotes, hostInitImportId)}
2159
+ ${exportStatement}
2160
+ `);
2161
+ }
2162
+ //#endregion
2163
+ //#region src/plugins/pluginReactMixedModeGuard.ts
2164
+ function createReactMixedModeRuntimeGuard() {
2165
+ return `const __mfReactInternals = mod["__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE"];
2166
+ if (__mfReactInternals && "A" in __mfReactInternals) {
2167
+ let __mfReactDispatcher = __mfReactInternals.A;
2168
+ Object.defineProperty(__mfReactInternals, "A", {
2169
+ configurable: true,
2170
+ enumerable: true,
2171
+ get: () => __mfReactDispatcher,
2172
+ set: (next) => {
2173
+ if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
2174
+ __mfReactDispatcher = next;
2175
+ },
2176
+ });
2177
+ __mfReactInternals.A = __mfReactDispatcher;
2178
+ }`;
2179
+ }
2066
2180
  //#endregion
2067
2181
  //#region src/utils/typeArgumentScanner.ts
2068
2182
  function getTypeArgumentStartContext(source, start) {
@@ -2191,8 +2305,12 @@ function getPackageEsmEntryPath(pkg) {
2191
2305
  }
2192
2306
  const packageNamedExportsCache = /* @__PURE__ */ new Map();
2193
2307
  const sharedExportInspectionCache = /* @__PURE__ */ new Map();
2308
+ const sharedMutableExportsCache = /* @__PURE__ */ new Map();
2194
2309
  function invalidateSharedExportInspectionCache(filePath) {
2195
- if (!/(?:^|[/\\])node_modules(?:[/\\]|$)/.test(filePath)) sharedExportInspectionCache.clear();
2310
+ if (!/(?:^|[/\\])node_modules(?:[/\\]|$)/.test(filePath)) {
2311
+ sharedExportInspectionCache.clear();
2312
+ sharedMutableExportsCache.clear();
2313
+ }
2196
2314
  }
2197
2315
  const DEFAULT_SHARED_EXPORT_CONDITIONS = [
2198
2316
  "browser",
@@ -2200,6 +2318,18 @@ const DEFAULT_SHARED_EXPORT_CONDITIONS = [
2200
2318
  "module",
2201
2319
  "default"
2202
2320
  ];
2321
+ function getSharedExportSource(source) {
2322
+ const parts = [];
2323
+ let offset = 0;
2324
+ const codePositions = createCodePositionMap(source, (start, end) => {
2325
+ parts.push(source.slice(offset, start), source.slice(start, end).replace(/[^\r\n\u2028\u2029]/g, " "));
2326
+ offset = end;
2327
+ });
2328
+ return {
2329
+ source: parts.length ? parts.join("") + source.slice(offset) : source,
2330
+ codePositions
2331
+ };
2332
+ }
2203
2333
  function hasCodeMatch(source, regex, codePositions) {
2204
2334
  regex.lastIndex = 0;
2205
2335
  let match;
@@ -2244,8 +2374,7 @@ function getMutableExportsFromFile(entryPath, exportConditions = DEFAULT_SHARED_
2244
2374
  if (!entryPath || visited.has(entryPath)) return [];
2245
2375
  visited.add(entryPath);
2246
2376
  try {
2247
- const source = readFileSync(entryPath, "utf-8");
2248
- const codePositions = createCodePositionMap(source);
2377
+ const { source, codePositions } = getSharedExportSource(readFileSync(entryPath, "utf-8"));
2249
2378
  const mutableBindings = /* @__PURE__ */ new Set();
2250
2379
  const mutableExports = /* @__PURE__ */ new Set();
2251
2380
  let match;
@@ -2278,7 +2407,7 @@ function getMutableExportsFromFile(entryPath, exportConditions = DEFAULT_SHARED_
2278
2407
  if (isValidEsmExportName(exported) && (mutableBindings.has(local) || reExportedMutable.has(local))) mutableExports.add(exported);
2279
2408
  }
2280
2409
  }
2281
- const starExportRegex = /export\s+\*\s+from\s+['"]([^'"]+)['"]/g;
2410
+ const starExportRegex = /export\s*\*\s*from\s*['"]([^'"]+)['"]/g;
2282
2411
  while ((match = starExportRegex.exec(source)) !== null) {
2283
2412
  if (!codePositions[match.index]) continue;
2284
2413
  const resolved = resolveReExportModule(entryPath, match[1], exportConditions);
@@ -2293,10 +2422,18 @@ function getMutableExportsFromFile(entryPath, exportConditions = DEFAULT_SHARED_
2293
2422
  }
2294
2423
  function getSharedMutableExports(pkg, shareItem, exportConditions = DEFAULT_SHARED_EXPORT_CONDITIONS) {
2295
2424
  const configuredImport = shareItem?.shareConfig.import;
2296
- return getMutableExportsFromFile(typeof configuredImport === "string" ? resolveConfiguredImportPath(configuredImport, exportConditions) : getInstalledPackageEntry(pkg, {
2425
+ const entryPath = typeof configuredImport === "string" ? resolveConfiguredImportPath(configuredImport, exportConditions) : getInstalledPackageEntry(pkg, {
2297
2426
  conditions: exportConditions,
2298
2427
  resolveSubpathWithRequire: false
2299
- }), exportConditions);
2428
+ });
2429
+ if (!entryPath) return [];
2430
+ const cacheKey = `${entryPath}\0${exportConditions.join("\0")}`;
2431
+ let mutableExports = sharedMutableExportsCache.get(cacheKey);
2432
+ if (!mutableExports) {
2433
+ mutableExports = getMutableExportsFromFile(entryPath, exportConditions);
2434
+ sharedMutableExportsCache.set(cacheKey, mutableExports);
2435
+ }
2436
+ return mutableExports;
2300
2437
  }
2301
2438
  function resolveConfiguredImportPath(importSource, exportConditions = DEFAULT_SHARED_EXPORT_CONDITIONS) {
2302
2439
  if (path$1.isAbsolute(importSource)) return resolveFileLikeModule(importSource);
@@ -2551,7 +2688,9 @@ function hasUnsupportedBindingPattern(source, start) {
2551
2688
  }
2552
2689
  function getNamedExportsViaRegex(source, filePath, visited, scanState = { complete: true }, exportConditions = DEFAULT_SHARED_EXPORT_CONDITIONS) {
2553
2690
  const names = /* @__PURE__ */ new Set();
2554
- const codePositions = createCodePositionMap(source);
2691
+ const inspected = getSharedExportSource(source);
2692
+ source = inspected.source;
2693
+ const codePositions = inspected.codePositions;
2555
2694
  const recognizedExportStarts = /* @__PURE__ */ new Set();
2556
2695
  visited = visited || /* @__PURE__ */ new Set();
2557
2696
  if (filePath) visited.add(filePath);
@@ -2609,15 +2748,15 @@ function getNamedExportsViaRegex(source, filePath, visited, scanState = { comple
2609
2748
  else if (name === "default" || name === "__esModule") {} else scanState.complete = false;
2610
2749
  }
2611
2750
  }
2612
- const namespaceReExportRegex = new RegExp(`export\\s+\\*\\s+as\\s+(${JS_IDENTIFIER_PATTERN})\\s+from\\s+['"][^'"]+['"]`, "gu");
2751
+ const namespaceReExportRegex = new RegExp(`export\\s*\\*\\s*as\\s+(${JS_IDENTIFIER_PATTERN})\\s*from\\s*['"][^'"]+['"]`, "gu");
2613
2752
  while ((match = namespaceReExportRegex.exec(source)) !== null) {
2614
2753
  if (!codePositions[match.index]) continue;
2615
2754
  recognizedExportStarts.add(match.index);
2616
2755
  if (isValidEsmExportName(match[1])) names.add(match[1]);
2617
2756
  }
2618
- if (hasCodeMatch(source, /export\s+\*\s+as\s+['"]/g, codePositions)) scanState.complete = false;
2757
+ if (hasCodeMatch(source, /export\s*\*\s*as\s*['"]/g, codePositions)) scanState.complete = false;
2619
2758
  if (filePath) {
2620
- const starExportRegex = /export\s+\*\s+from\s+['"]([^'"]+)['"]/g;
2759
+ const starExportRegex = /export\s*\*\s*from\s*['"]([^'"]+)['"]/g;
2621
2760
  while ((match = starExportRegex.exec(source)) !== null) {
2622
2761
  if (!codePositions[match.index]) continue;
2623
2762
  recognizedExportStarts.add(match.index);
@@ -2852,12 +2991,6 @@ function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFedera
2852
2991
  };
2853
2992
  return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && reachesPkg(sharedPkg, /* @__PURE__ */ new Set([sharedPkg])));
2854
2993
  }
2855
- function isRemoteOnlyContainer(options = getNormalizeModuleFederationOptions()) {
2856
- return Object.keys(options.exposes || {}).length > 0 && Object.keys(options.remotes || {}).length === 0;
2857
- }
2858
- function isLocalOnlyContainer(options = getNormalizeModuleFederationOptions()) {
2859
- return Object.keys(options.exposes || {}).length === 0 && Object.keys(options.remotes || {}).length === 0;
2860
- }
2861
2994
  function tryResolveImportFromPackageRoot(pkg, root) {
2862
2995
  try {
2863
2996
  return resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(root, "package.json"))).resolve(pkg), root);
@@ -3378,11 +3511,10 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3378
3511
  const liveNamedExportLine = liveNamedExports.length ? `export { ${liveNamedExports.join(", ")} } from ${escapeGeneratedStringLiteral(sharedImportSource)};` : "";
3379
3512
  const hasCompleteExportCoverage = detectedNamedExports !== void 0;
3380
3513
  const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
3381
- const isDefaultShareScope = shareItem.scope === void 0 || shareItem.scope === "default" || Array.isArray(shareItem.scope) && shareItem.scope[0] === "default";
3382
- const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer(resolvedOptions) && (shareItem.shareConfig.singleton === true || isDefaultShareScope) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3514
+ const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteContainer(resolvedOptions) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3383
3515
  const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
3384
3516
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
3385
- const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3517
+ const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3386
3518
  const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
3387
3519
  const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
3388
3520
  const reactMixedModeGuard = pkg === "react" ? createReactMixedModeRuntimeGuard() : "";
@@ -3566,6 +3698,7 @@ function generateLocalSharedImportMap(options) {
3566
3698
  const useDirectReactImport = shouldUseDirectReactImport();
3567
3699
  const orderedShares = getOrderedUsedShares(options);
3568
3700
  const sharesToMaterialize = new Set(getMaterializedShares(options));
3701
+ const hasConsumeOnlyShare = orderedShares.some((pkg) => getNormalizeShareItem(pkg, resolvedOptions)?.shareConfig.import === false);
3569
3702
  return `
3570
3703
  import {loadShare} from "@module-federation/runtime";
3571
3704
  ${orderedShares.map((pkg, index) => {
@@ -3574,12 +3707,47 @@ function generateLocalSharedImportMap(options) {
3574
3707
  return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3575
3708
  }).filter(Boolean).join("\n")}
3576
3709
  ${normalizeRuntimeShareCode}
3710
+ const __mfGetCachedReactFamily = (keys, reactKeys, localVersion, requiredExport) => {
3711
+ const cache = globalThis.__mf_module_cache__?.share;
3712
+ const react = reactKeys.map((key) => cache?.[key]).find((value) => value !== undefined);
3713
+ const reactVersion = react?.version ?? react?.default?.version;
3714
+ const actual = String(reactVersion || '').split(/[^0-9]+/).map(Number);
3715
+ const expected = String(localVersion || '').split(/[^0-9]+/).map(Number);
3716
+ for (let index = 0; index < Math.max(actual.length, expected.length); index++) {
3717
+ if ((actual[index] || 0) < (expected[index] || 0)) return undefined;
3718
+ if ((actual[index] || 0) > (expected[index] || 0)) break;
3719
+ }
3720
+ for (const key of keys) {
3721
+ const cached = cache?.[key];
3722
+ if (cached === undefined) continue;
3723
+ if (!requiredExport || typeof cached?.[requiredExport] === 'function' || typeof cached?.default?.[requiredExport] === 'function') return cached;
3724
+ }
3725
+ return undefined;
3726
+ };
3727
+ ${hasConsumeOnlyShare ? `// A consume-only share has no local module: its entry is the same shape for every key, so one helper builds it instead of a literal per key
3728
+ const __mfHostOnly = (name) => async () => {
3729
+ throw new Error(\`[Module Federation] Shared module '\${name}' must be provided by host\`);
3730
+ };
3731
+ const __mfConsumeOnly = (name, version, scope, materialize, shareConfig) => ({
3732
+ name,
3733
+ version,
3734
+ scope: [scope],
3735
+ loaded: false,
3736
+ materialize,
3737
+ eager: shareConfig.eager,
3738
+ from: ${toSafeJsLiteral(resolvedOptions.name)},
3739
+ canLiveRebind: true,
3740
+ get: __mfHostOnly(name),
3741
+ shareConfig: { ...shareConfig, import: false },
3742
+ });` : ""}
3577
3743
  const importMap = {
3578
3744
  ${orderedShares.map((pkg, index) => {
3579
3745
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3746
+ if (shareItem?.shareConfig.import === false) return `
3747
+ ${toSafeJsLiteral(pkg)}: __mfHostOnly(${toSafeJsLiteral(pkg)})`;
3580
3748
  return `
3581
3749
  ${toSafeJsLiteral(pkg)}: async () => {
3582
- ${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${toSafeJsLiteral(pkg)}}' must be provided by host\`);` : shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
3750
+ ${shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
3583
3751
  return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))});
3584
3752
  return pkg;`}
3585
3753
  }
@@ -3590,9 +3758,20 @@ function generateLocalSharedImportMap(options) {
3590
3758
  ${orderedShares.map((key) => {
3591
3759
  const shareItem = getNormalizeShareItem(key, resolvedOptions);
3592
3760
  if (!shareItem) return null;
3761
+ const isReactFamily = key.startsWith("react/") || key === "react-dom/client";
3762
+ const cacheKeys = [key, ...key === "react-dom/client" ? ["react-dom"] : []].flatMap((pkg) => {
3763
+ const descriptor = getSharedCacheDescriptor(pkg, shareItem);
3764
+ return [descriptor.canonical, ...descriptor.aliases ?? []];
3765
+ });
3766
+ const reactCacheKeys = ["react"].flatMap((pkg) => {
3767
+ const descriptor = getSharedCacheDescriptor(pkg, shareItem);
3768
+ return [descriptor.canonical, ...descriptor.aliases ?? []];
3769
+ });
3593
3770
  const detectedNamedExports = getSharedNamedExports(key, shareItem);
3594
3771
  const canLiveRebind = shareItem.shareConfig.import === false || detectedNamedExports !== void 0;
3595
3772
  const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
3773
+ if (shareItem.shareConfig.import === false && !treeShakingConfig) return `
3774
+ ${toSafeJsLiteral(key)}: __mfConsumeOnly(${toSafeJsLiteral(key)}, ${toSafeJsLiteral(shareItem.version)}, ${toSafeJsLiteral(shareItem.scope)}, ${sharesToMaterialize.has(key)}, {singleton: ${shareItem.shareConfig.singleton}, requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)}, strictVersion: ${shareItem.shareConfig.strictVersion}, eager: ${Boolean(shareItem.shareConfig.eager)}})`;
3596
3775
  const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, options) : void 0;
3597
3776
  const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
3598
3777
  const treeShakingUsedExports = resolvedOptions.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
@@ -3609,26 +3788,54 @@ function generateLocalSharedImportMap(options) {
3609
3788
  eager: ${Boolean(shareItem.shareConfig.eager)},
3610
3789
  from: ${toSafeJsLiteral(resolvedOptions.name)},
3611
3790
  canLiveRebind: ${canLiveRebind},
3612
- async get () {
3791
+ get () {
3613
3792
  if (${shareItem.shareConfig.import === false}) {
3614
3793
  throw new Error(\`[Module Federation] Shared module '\${${toSafeJsLiteral(key)}}' must be provided by host\`);
3615
3794
  }
3616
- usedShared[${toSafeJsLiteral(key)}].loaded = true
3617
- const {${toSafeJsLiteral(key)}: pkgDynamicImport} = importMap
3618
- const res = await pkgDynamicImport()
3619
- const exportModule = ${toSafeJsLiteral(useDirectReactImport)} && ${toSafeJsLiteral(key)} === "react"
3620
- ? (res?.default ?? res)
3621
- : __mfNormalizeRuntimeShare({...res})
3622
- // All npm packages pre-built by vite will be converted to esm
3623
- if (exportModule.__esModule !== true) {
3624
- Object.defineProperty(exportModule, "__esModule", {
3625
- value: true,
3626
- enumerable: false
3627
- })
3628
- }
3629
- return function () {
3630
- return exportModule
3795
+ // A webpack consumer built with eager: true calls get() synchronously and needs the
3796
+ // factory, not a promise: once the module is loaded, hand the same factory back directly,
3797
+ // and while it is loading hand every caller the same pending promise.
3798
+ const share = usedShared[${toSafeJsLiteral(key)}]
3799
+ if (share.lib) return share.lib
3800
+ if (share.loading) return share.loading
3801
+ const cachedSingleton = ${shareItem.shareConfig.singleton && isReactFamily}
3802
+ ? __mfGetCachedReactFamily(
3803
+ ${toSafeJsLiteral(cacheKeys)},
3804
+ ${toSafeJsLiteral(reactCacheKeys)},
3805
+ ${toSafeJsLiteral(shareItem.version)},
3806
+ ${toSafeJsLiteral(key === "react-dom/client" ? "createRoot" : void 0)}
3807
+ )
3808
+ : undefined
3809
+ if (cachedSingleton !== undefined) {
3810
+ share.lib = function () { return cachedSingleton }
3811
+ share.loaded = true
3812
+ return share.lib
3631
3813
  }
3814
+ share.loading = (async () => {
3815
+ try {
3816
+ const {${toSafeJsLiteral(key)}: pkgDynamicImport} = importMap
3817
+ const res = await pkgDynamicImport()
3818
+ const exportModule = ${toSafeJsLiteral(useDirectReactImport)} && ${toSafeJsLiteral(key)} === "react"
3819
+ ? (res?.default ?? res)
3820
+ : __mfNormalizeRuntimeShare({...res})
3821
+ // All npm packages pre-built by vite will be converted to esm
3822
+ if (exportModule.__esModule !== true) {
3823
+ Object.defineProperty(exportModule, "__esModule", {
3824
+ value: true,
3825
+ enumerable: false
3826
+ })
3827
+ }
3828
+ share.lib = function () {
3829
+ return exportModule
3830
+ }
3831
+ share.loaded = true
3832
+ return share.lib
3833
+ } finally {
3834
+ // A failed import must not pin the rejection: the next get() retries
3835
+ share.loading = undefined
3836
+ }
3837
+ })()
3838
+ return share.loading
3632
3839
  },
3633
3840
  shareConfig: {
3634
3841
  singleton: ${shareItem.shareConfig.singleton},
@@ -3673,10 +3880,11 @@ function generateLocalSharedImportMap(options) {
3673
3880
  }
3674
3881
  `;
3675
3882
  }
3676
- /** Expand `pkg/` → package root + matching usedShares; never returns the prefix string. */
3883
+ /** Expand `pkg/` → package root (if importable) + matching usedShares; never returns the prefix string. */
3677
3884
  function expandSharedPrefixKey(prefixKey, used) {
3678
3885
  const base = prefixKey.slice(0, -1);
3679
- const expanded = /* @__PURE__ */ new Set([base]);
3886
+ const baseImportable = isPackageInstalled(base) && isPackageExportAvailable(base);
3887
+ const expanded = new Set(baseImportable ? [base] : []);
3680
3888
  for (const pkg of used) {
3681
3889
  if (pkg.endsWith("/")) continue;
3682
3890
  if (pkg === base || pkg.startsWith(`${base}/`)) expanded.add(pkg);
@@ -3854,6 +4062,8 @@ const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
3854
4062
  };`;
3855
4063
  const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbol("mf.originalSharedProvider");
3856
4064
  const __mfResolveShareHook = { emit: (params) => params };
4065
+ const __mfGetShareScopeNames = (share) =>
4066
+ Array.isArray(share.scope) ? share.scope : [share.scope || "default"];
3857
4067
  const __mfCreateProviderSelectionVersions = (versions, strategy) => {
3858
4068
  if (strategy !== "version-first") return versions;
3859
4069
  const selectionVersions = {};
@@ -3895,7 +4105,7 @@ const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbo
3895
4105
  Object.entries(versions).filter(([, provider]) => provider?.shareConfig?.import !== false)
3896
4106
  );
3897
4107
  if (Object.keys(candidates).length === 0) return undefined;
3898
- const scopes = Array.isArray(share.scope) ? share.scope : [share.scope || "default"];
4108
+ const scopes = __mfGetShareScopeNames(share);
3899
4109
  const selectionVersions = __mfCreateProviderSelectionVersions(candidates, strategy);
3900
4110
  const shareScopeMap = {};
3901
4111
  for (const scope of scopes) {
@@ -4054,10 +4264,26 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4054
4264
  );
4055
4265
  return;
4056
4266
  }
4057
- const pendingExternalProvider = typeof __mfGetPendingExternalSharedProvider === 'function'
4058
- ? __mfGetPendingExternalSharedProvider(pkg, share)
4267
+ const externalProvider = typeof __mfGetExternalSharedProvider === 'function'
4268
+ ? __mfGetExternalSharedProvider(pkg, share)
4059
4269
  : undefined;
4060
- if (pendingExternalProvider && !pendingExternalProvider.lib && !pendingExternalProvider.loaded) {
4270
+ if (externalProvider) {
4271
+ let externalFactory = externalProvider.lib;
4272
+ if (!externalFactory && externalProvider.loading) externalFactory = await externalProvider.loading;
4273
+ if (!externalFactory && externalProvider.loaded && typeof externalProvider.get === 'function') {
4274
+ externalFactory = await externalProvider.get();
4275
+ }
4276
+ if (externalFactory) {
4277
+ const externalModule = typeof externalFactory === "function" ? externalFactory() : externalFactory;
4278
+ const externalResolved = await Promise.resolve(externalModule);
4279
+ ${normalizeRuntimeShareCode}
4280
+ __mfWriteSharedCache(
4281
+ __mfModuleCache.share,
4282
+ cacheDescriptor,
4283
+ __mfNormalizeRuntimeShare(externalResolved),
4284
+ externalProvider.from
4285
+ );
4286
+ }
4061
4287
  return;
4062
4288
  }
4063
4289
  const providerKey = cacheDescriptor.canonical;
@@ -4339,10 +4565,10 @@ function generateTreeShakingSnapshotPluginCode(enabled) {
4339
4565
  });`;
4340
4566
  }
4341
4567
  function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build", exportConditions) {
4342
- const needsSharedProviderSelectionHelper = Object.keys(options.shared ?? {}).length > 0;
4568
+ const needsSharedProviderSelectionHelper = hasShared(options);
4343
4569
  const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
4344
4570
  const hasMultipleShareScopes = Array.isArray(options.shareScope);
4345
- const guardHostAutoInit = command === "build" && Object.keys(options.exposes ?? {}).length > 0 && Object.keys(options.remotes ?? {}).length > 0;
4571
+ const guardHostAutoInit = command === "build" && isRemoteContainer(options) && hasRemotes(options);
4346
4572
  const materializedShareBatches = toSafeJsLiteral(getShareBatches(options, false));
4347
4573
  const runtimeImports = [
4348
4574
  "init as runtimeInit",
@@ -4397,6 +4623,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4397
4623
  import {${runtimeImports}} from "@module-federation/runtime";
4398
4624
  ${runtimeHelperImports.length ? `import {${runtimeHelperImports.join(", ")}} from "@module-federation/runtime/helpers";` : ""}
4399
4625
  ${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
4626
+ import __mfExposesMap from "${virtualExposesId}"
4400
4627
  ${command === "build" ? getRuntimeInitResolveBootstrapCode(false, getRuntimeInitStatusImportId(options)) : getRuntimeInitBootstrapCode(false, getRuntimeInitStatusImportId(options), void 0, void 0, exportConditions) + "\n const { initResolve } = globalThis[globalKey];"}
4401
4628
  ${getRuntimeModuleCacheBootstrapCode(exportConditions)}
4402
4629
  const initTokens = {}
@@ -4405,7 +4632,6 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4405
4632
  const mfName = ${toSafeJsLiteral(options.name)}
4406
4633
  const __mfMaterializedShareBatches = ${materializedShareBatches}
4407
4634
  let localSharedImportMapPromise
4408
- let exposesMapPromise
4409
4635
  let __mfLateBridgeShared
4410
4636
  const shouldRetrySharedInitError = ${command !== "build"} && ((error) => {
4411
4637
  const message = String((error && error.message) || error || '');
@@ -4439,12 +4665,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4439
4665
  }
4440
4666
 
4441
4667
  async function getExposesMap() {
4442
- if (!exposesMapPromise) {
4443
- exposesMapPromise = retrySharedInit(() => import("${virtualExposesId}"))
4444
- .then((mod) => mod.default ?? mod)
4445
- .catch((e) => { exposesMapPromise = undefined; throw e; });
4446
- }
4447
- return exposesMapPromise
4668
+ return __mfExposesMap
4448
4669
  }
4449
4670
 
4450
4671
  async function init(shared = {}, initScope = [], remoteEntryInitOptions = {}) {
@@ -4560,29 +4781,33 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4560
4781
  const parts = pkg.split('/');
4561
4782
  return pkg.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
4562
4783
  };
4563
- const __mfGetPendingExternalSharedProvider = (pkg, share, versionMap) => {
4784
+ const __mfGetExternalSharedProvider = (pkg, share, versionMap, includePackage) => {
4564
4785
  if (typeof __mfSelectExternalSharedProvider !== 'function') return undefined;
4565
4786
  const packageName = __mfGetSharePackageName(pkg);
4566
- const candidates = packageName === pkg
4787
+ const candidates = !includePackage || packageName === pkg
4567
4788
  ? [[pkg, share]]
4568
4789
  : [[pkg, share], [packageName, usedShared[packageName]]];
4569
4790
  for (const [candidatePkg, candidateShare] of candidates) {
4570
4791
  if (!candidateShare) continue;
4571
4792
  const candidateVersionMap = versionMap
4572
4793
  ? (candidatePkg === pkg ? versionMap : initialShared[candidatePkg])
4573
- : ${hasMultipleShareScopes ? "getShareVersions(candidatePkg, candidateShare)" : "shared[candidatePkg]"};
4794
+ : (initialShared[candidatePkg] ?? ${hasMultipleShareScopes ? "getShareVersions(candidatePkg, candidateShare)" : "shared[candidatePkg]"});
4574
4795
  const provider = __mfSelectExternalSharedProvider(
4575
4796
  candidateVersionMap,
4576
4797
  candidatePkg,
4577
4798
  candidateShare,
4578
4799
  '${options.shareStrategy}'
4579
4800
  );
4580
- if (provider && isWebpackProvider(provider) && !provider.lib && !provider.loaded) {
4581
- return provider;
4582
- }
4801
+ if (provider) return provider;
4583
4802
  }
4584
4803
  return undefined;
4585
4804
  };
4805
+ const __mfGetPendingExternalSharedProvider = (pkg, share, versionMap) => {
4806
+ const provider = __mfGetExternalSharedProvider(pkg, share, versionMap, true);
4807
+ return provider && isWebpackProvider(provider) && !provider.lib && !provider.loaded
4808
+ ? provider
4809
+ : undefined;
4810
+ };
4586
4811
  // handling circular init calls before an external provider can re-enter this container
4587
4812
  ${hasMultipleShareScopes ? `const shareScopeNamesToInitialize = [];
4588
4813
  for (const shareScopeName of shareScopeNames) {
@@ -5320,7 +5545,28 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5320
5545
  const hostInitShareBatches = toSafeJsLiteral(getShareBatches(options, false));
5321
5546
  const cacheOwner = toSafeJsLiteral(resolvedOptions.name);
5322
5547
  const preferLocalVinextReact = hasPackageDependency("vinext") && (!exportConditions?.includes("browser") || exportConditions.includes("worker"));
5548
+ const hasConfiguredShared = hasShared(resolvedOptions);
5549
+ const hostInitSharedProviderHelperImport = shouldPreloadShares && hasConfiguredShared ? "import {share as runtimeShare} from \"@module-federation/runtime/helpers\";" : "";
5550
+ const hostInitSharedProviderHelperCode = shouldPreloadShares && hasConfiguredShared ? `
5551
+ ${sharedProviderSelectionHelperCode}
5552
+ const __mfHasUsableProvider = (versions, pkg, share, scopeName) => {
5553
+ // Keep runtime singleton negotiation unchanged. A singleton already
5554
+ // registered in this scope is authoritative, even when runtime-core
5555
+ // reports a version mismatch.
5556
+ if (share.shareConfig?.singleton) {
5557
+ return Object.values(versions || {}).some(
5558
+ (provider) => provider?.shareConfig?.import !== false
5559
+ );
5560
+ }
5561
+ return Boolean(__mfSelectSharedProvider(
5562
+ versions,
5563
+ pkg,
5564
+ { ...share, scope: [scopeName] },
5565
+ ${toSafeJsLiteral(resolvedOptions.shareStrategy)}
5566
+ ));
5567
+ };` : "";
5323
5568
  return `
5569
+ ${hostInitSharedProviderHelperImport}
5324
5570
  ${getRuntimeModuleCacheBootstrapCode(exportConditions)}
5325
5571
  let hostInitPromise;
5326
5572
  async function initHost() {
@@ -5334,12 +5580,13 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5334
5580
  ${normalizeRuntimeShareCode}
5335
5581
  ${shouldPreloadShares ? `
5336
5582
  const __mfHasAlternativeSharedVersion = (pkg, share) =>
5337
- (Array.isArray(share.scope) ? share.scope : [share.scope || 'default']).some(
5583
+ __mfGetShareScopeNames(share).some(
5338
5584
  (scopeName) => Object.keys(runtime.shareScopeMap?.[scopeName]?.[pkg] || {}).some(
5339
5585
  (version) => version !== share.version
5340
5586
  )
5341
5587
  );
5342
5588
  const __mfHostInitShareBatches = ${hostInitShareBatches};
5589
+ ${hostInitSharedProviderHelperCode}
5343
5590
  for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
5344
5591
  await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
5345
5592
  const share = usedShared[pkg];
@@ -5357,18 +5604,57 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5357
5604
  )`}
5358
5605
  ) return;
5359
5606
  // An import:false share has nothing to load until a foreign provider
5360
- // registers: its own stub getter throws by construction.
5361
- if (
5362
- share.shareConfig?.import === false &&
5363
- !(Array.isArray(share.scope) ? share.scope : [share.scope || 'default']).some((scopeName) =>
5364
- Object.values(runtime.shareScopeMap?.[scopeName]?.[pkg] || {}).some(
5365
- (provider) => provider?.shareConfig?.import !== false
5366
- )
5367
- )
5368
- ) return;
5607
+ // registers: its own stub getter throws by construction. A standalone
5608
+ // container initialized on the same page keeps its providers in its
5609
+ // own runtime scope (#1307), so adopt those before giving up.
5610
+ if (share.shareConfig?.import === false) {
5611
+ const __mfScopeNames = __mfGetShareScopeNames(share);
5612
+ const __mfNeedsSiblingProvider = (scopeName) =>
5613
+ !__mfHasUsableProvider(
5614
+ runtime.shareScopeMap?.[scopeName]?.[pkg],
5615
+ pkg,
5616
+ share,
5617
+ scopeName
5618
+ );
5619
+ if (__mfScopeNames.some(__mfNeedsSiblingProvider)) {
5620
+ // loadShare() re-runs initializeSharing(), which re-registers this
5621
+ // container's own stub and lets it displace an unloaded adopted
5622
+ // provider whenever this container's name sorts after the provider's
5623
+ // (#1311). Put the provider back: a stub never outranks a provider.
5624
+ if (!runtime.__mfKeepAdoptedProviders) {
5625
+ runtime.__mfKeepAdoptedProviders = true;
5626
+ runtime.sharedHandler?.hooks?.lifecycle?.afterRegisterShare?.on?.((args) => {
5627
+ const { shared, previousShared, registeredShared } = args || {};
5628
+ if (
5629
+ shared?.shareConfig?.import !== false ||
5630
+ registeredShared !== shared ||
5631
+ !previousShared ||
5632
+ previousShared.shareConfig?.import === false
5633
+ ) return;
5634
+ const versions = runtime.shareScopeMap?.[args.scope]?.[args.pkgName];
5635
+ if (versions && versions[shared.version] === shared) versions[shared.version] = previousShared;
5636
+ });
5637
+ }
5638
+ for (const instance of globalThis.__FEDERATION__?.__INSTANCES__ || []) {
5639
+ for (const scopeName of __mfScopeNames) {
5640
+ const versions = instance?.shareScopeMap?.[scopeName]?.[pkg];
5641
+ if (!__mfHasUsableProvider(versions, pkg, share, scopeName)) continue;
5642
+ if (!__mfNeedsSiblingProvider(scopeName)) continue;
5643
+ const target = (runtime.shareScopeMap[scopeName] ||= {})[pkg] ||= {};
5644
+ for (const [version, provider] of Object.entries(versions)) {
5645
+ if (provider?.shareConfig?.import === false) continue;
5646
+ if (target[version] && target[version].shareConfig?.import !== false) continue;
5647
+ target[version] = provider;
5648
+ }
5649
+ }
5650
+ }
5651
+ }
5652
+ if (__mfScopeNames.every(__mfNeedsSiblingProvider)) return;
5653
+ }
5369
5654
  await runtime.loadShare(pkg, {
5370
5655
  customShareInfo: { shareConfig: share.shareConfig }
5371
5656
  }).then(async (factory) => {
5657
+ if (factory === false) return;
5372
5658
  const mod = typeof factory === "function" ? factory() : factory;
5373
5659
  let resolved = __mfNormalizeRuntimeShare(await Promise.resolve(mod));
5374
5660
  ${preferLocalVinextReact ? `if (
@@ -5451,6 +5737,7 @@ function generatePendingSharesCode(command = "build", options) {
5451
5737
  const pendingShareImports = command === "build" ? getMaterializedShares(options).filter((pkg) => {
5452
5738
  const shareItem = getShareItemForPreload(pkg, resolvedOptions);
5453
5739
  if (!shareItem || pkg.endsWith("/")) return false;
5740
+ if (shareItem.shareConfig.eager) return false;
5454
5741
  return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
5455
5742
  }).map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`) : [];
5456
5743
  return `
@@ -5793,9 +6080,10 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
5793
6080
  const devRuntimeBootstrap = `${getRuntimeInitBootstrapCode(enableSsrInit, getRuntimeInitStatusImportId(options), ssrRemotes, hostAutoInitPath, exportConditions)}
5794
6081
  const { initPromise, initResolve, initReject, moduleCache: __mfModuleCache } = globalThis[globalKey];`;
5795
6082
  const importLine = command === "build" ? `${getRuntimeModuleCacheBootstrapCode(exportConditions)}
5796
- import { hostInitPromise as __mfHostInitPromise } from ${JSON.stringify(hostAutoInitPath)};` : `${devRuntimeBootstrap}
6083
+ const __mfHostInitPromise = () => import(${JSON.stringify(hostAutoInitPath)})
6084
+ .then((mod) => mod.hostInitPromise);` : `${devRuntimeBootstrap}
5797
6085
  ${command === "serve" && consumer !== "server" ? browserHostInitCode : ""}`;
5798
- const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise" : "initPromise";
6086
+ const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise()" : "initPromise";
5799
6087
  const remoteCacheKey = `${getRuntimeRemoteCachePrefix(options)}${id}`;
5800
6088
  const remoteLoadFailureHandler = command === "build" ? `.catch((error) => {
5801
6089
  delete __mfModuleCache.remote[pendingKey];
@@ -5859,24 +6147,19 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
5859
6147
  }
5860
6148
  //#endregion
5861
6149
  //#region src/plugins/pluginAddEntry.ts
5862
- const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !name.includes("__prebuild__") && !name.includes("__loadShare__");
6150
+ const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !name.includes("__prebuild__") && !name.includes("__loadShare__") && !name.includes("__loadRemote__");
5863
6151
  const HOST_INIT_PRELOAD_CHUNKS = [
5864
6152
  (name) => name === "hostInit",
5865
6153
  (name) => name === "remoteEntry",
5866
- (name) => name === "virtualExposes",
5867
6154
  isPreloadableVirtualMfChunk,
5868
6155
  (name) => name === "index"
5869
6156
  ];
5870
6157
  const isRemoteWarmupExcluded = (name) => name.includes("__prebuild__") || name.includes("__loadShare__");
5871
- const REMOTE_ENTRY_WARMUP_CHUNKS = [
5872
- (name) => name === "hostInit",
5873
- (name) => name === "virtualExposes",
5874
- (name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)
5875
- ];
6158
+ const REMOTE_ENTRY_WARMUP_CHUNKS = [(name) => name === "hostInit", (name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)];
5876
6159
  function getChunksByFileName(bundle) {
5877
6160
  return new Map(Object.values(bundle).filter((chunk) => chunk.type === "chunk").map((chunk) => [chunk.fileName, chunk]));
5878
6161
  }
5879
- function collectPreloadChunkFiles(chunksByFileName, seeds, excludeFromClosure = (name) => name.includes("__prebuild__")) {
6162
+ function collectPreloadChunkFiles(chunksByFileName, seeds, excludeFromClosure = (name) => name.includes(PREBUILD_TAG)) {
5880
6163
  const seenFiles = /* @__PURE__ */ new Set();
5881
6164
  const files = [];
5882
6165
  const queue = [...seeds];
@@ -5955,9 +6238,6 @@ if (typeof document !== 'undefined' && document.head) {
5955
6238
  function getFirstHtmlEntryFile(entryFiles) {
5956
6239
  return entryFiles.find((file) => file.endsWith(".html"));
5957
6240
  }
5958
- function stripQueryAndHash$1(file) {
5959
- return file.split(/[?#]/)[0];
5960
- }
5961
6241
  function isReactRouterClientRouteInput(file) {
5962
6242
  return /[?&]__react-router-build-client-route(?:[=&]|$)/.test(file);
5963
6243
  }
@@ -6008,6 +6288,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
6008
6288
  let emitFileId;
6009
6289
  let pendingSharesEmitId;
6010
6290
  let viteConfig;
6291
+ let devServer;
6011
6292
  let skipHtmlDevFallback = forceClientInjected ?? false;
6012
6293
  let clientInjected = false;
6013
6294
  let emittedFileName;
@@ -6081,9 +6362,31 @@ const __mfCurrentScript = document.currentScript;
6081
6362
  const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(federationOptions));
6082
6363
  return Array.from(new Set(remoteSources.flatMap((remote) => {
6083
6364
  const registration = getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions);
6084
- return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) ? [registration.entry] : [];
6365
+ return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) && !/\.json(?:[?#]|$)/i.test(registration.entry) ? [registration.entry] : [];
6085
6366
  })));
6086
6367
  }
6368
+ async function warmupDevEntryGraph(entryUrl) {
6369
+ const server = devServer;
6370
+ if (!server) return;
6371
+ const seen = /* @__PURE__ */ new Set();
6372
+ const cacheDir = normalizePathForImport(server.config?.cacheDir ?? "").replace(/\/$/, "") + "/";
6373
+ const visit = async (url) => {
6374
+ if (seen.has(url)) return;
6375
+ seen.add(url);
6376
+ try {
6377
+ await server.transformRequest(url);
6378
+ } catch {
6379
+ return;
6380
+ }
6381
+ const deps = [...(await server.moduleGraph.getModuleByUrl(url))?.importedModules ?? []].filter((dep) => {
6382
+ if (!dep.file || dep.type !== "js" || !path$1.isAbsolute(dep.file)) return false;
6383
+ const file = normalizePathForImport(dep.file);
6384
+ return !file.includes("/node_modules/") && !file.startsWith(cacheDir);
6385
+ });
6386
+ await Promise.all(deps.map((dep) => visit(dep.url)));
6387
+ };
6388
+ await visit(entryUrl).catch(() => {});
6389
+ }
6087
6390
  function getBootstrapSource(initSrc, entrySrc, useSystemImportFallback = false, options) {
6088
6391
  const importHelper = useSystemImportFallback ? `const __mfImport = (src) =>
6089
6392
  globalThis.System && typeof globalThis.System.import === 'function'
@@ -6109,7 +6412,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6109
6412
  import(/* @vite-ignore */ __mfRemoteEntryPrefetchUrl).catch(() => {});
6110
6413
  }
6111
6414
  ` : "";
6112
- const sharedPreloadSources = _command === "serve" && waitsForInit && Object.keys(normalizedOptions.exposes || {}).length > 0 && Object.keys(normalizedOptions.remotes || {}).length === 0 && federationOptions ? Array.from(getUsedShares(federationOptions)).filter((pkg) => !pkg.endsWith("/")).filter((pkg) => {
6415
+ const sharedPreloadSources = _command === "serve" && waitsForInit && isRemoteOnlyContainer(normalizedOptions) && federationOptions ? Array.from(getUsedShares(federationOptions)).filter((pkg) => !pkg.endsWith("/")).filter((pkg) => {
6113
6416
  const shareItem = federationOptions.shared[pkg] || Object.entries(federationOptions.shared).find(([key]) => key.endsWith("/") && pkg.startsWith(key))?.[1];
6114
6417
  const isExplicitShare = Object.hasOwn(federationOptions.shared, pkg);
6115
6418
  return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
@@ -6195,12 +6498,12 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6195
6498
  }
6196
6499
  function isFederationInternalVirtualId(id) {
6197
6500
  const normalized = decodeViteId(id).replace(/^\0+/, "");
6198
- return normalized.includes("virtual:mf:") || /__(?:loadShare|prebuild|loadRemote)__/.test(normalized);
6501
+ return normalized.includes("virtual:mf:") || normalized.startsWith("virtual:mf-") || /__(?:loadShare|prebuild|loadRemote)__/.test(normalized);
6199
6502
  }
6200
6503
  function isWorkspaceSourceId(id) {
6201
6504
  const normalized = normalizeModuleId(decodeViteId(id));
6202
6505
  if (normalized.startsWith("\0") || normalized.startsWith("virtual:")) return false;
6203
- const filePath = stripQueryAndHash$1(normalized);
6506
+ const filePath = stripQueryAndHash(normalized);
6204
6507
  if (filePath.startsWith("/@fs/")) return true;
6205
6508
  if (!path$1.isAbsolute(filePath)) return false;
6206
6509
  const root = normalizePathForImport(path$1.resolve(viteConfig.root));
@@ -6222,7 +6525,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6222
6525
  ignoredHtmlScriptSources.add(match[1]);
6223
6526
  continue;
6224
6527
  }
6225
- const scriptSrc = stripQueryAndHash$1(match[1]);
6528
+ const scriptSrc = stripQueryAndHash(match[1]);
6226
6529
  if (/^(?:[a-z]+:)?\/\//i.test(scriptSrc)) continue;
6227
6530
  addEntryFile(scriptSrc);
6228
6531
  addEntryFile(scriptSrc.startsWith("/") ? path$1.resolve(viteConfig.root, scriptSrc.slice(1)) : path$1.resolve(path$1.dirname(htmlPath), scriptSrc));
@@ -6230,7 +6533,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6230
6533
  }
6231
6534
  function addEntryRemoteImports(entrySrc) {
6232
6535
  if (!federationOptions || /^(?:[a-z]+:)?\/\//i.test(entrySrc)) return;
6233
- const file = path$1.resolve(viteConfig.root, stripQueryAndHash$1(entrySrc).replace(/^\//, ""));
6536
+ const file = path$1.resolve(viteConfig.root, stripQueryAndHash(entrySrc).replace(/^\//, ""));
6234
6537
  if (!fs$2.existsSync(file)) return;
6235
6538
  const code = fs$2.readFileSync(file, "utf-8");
6236
6539
  for (const source of findModuleImportSources(code)) {
@@ -6257,6 +6560,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6257
6560
  skipTransformIds = new Set(skipTransformFor.map(resolveProjectId));
6258
6561
  },
6259
6562
  configureServer(server) {
6563
+ devServer = server;
6260
6564
  server.middlewares.use((req, res, next) => {
6261
6565
  const rawUrl = req.url?.split("#")[0] ?? "";
6262
6566
  if (normalizeDevHtmlProxyId(rawUrl.split("?")[0]) === DEV_HTML_PROXY_PREFIX.slice(0, -1)) {
@@ -6266,9 +6570,12 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6266
6570
  const entrySrc = params.get("entry");
6267
6571
  if (initSrc && entrySrc) {
6268
6572
  const withBase = (src) => viteConfig.base + src.replace(/^\//, "");
6269
- res.statusCode = 200;
6270
- res.setHeader("Content-Type", "application/javascript");
6271
- res.end(getBootstrapSource(withBase(initSrc), withBase(entrySrc)));
6573
+ const source = getBootstrapSource(withBase(initSrc), withBase(entrySrc));
6574
+ warmupDevEntryGraph(entrySrc).finally(() => {
6575
+ res.statusCode = 200;
6576
+ res.setHeader("Content-Type", "application/javascript");
6577
+ res.end(source);
6578
+ });
6272
6579
  return;
6273
6580
  }
6274
6581
  }
@@ -6316,7 +6623,8 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6316
6623
  const initSrc = params.get("init");
6317
6624
  const entrySrc = params.get("entry");
6318
6625
  if (!initSrc || !entrySrc) return;
6319
- return getBootstrapSource(initSrc, entrySrc);
6626
+ const source = getBootstrapSource(initSrc, entrySrc);
6627
+ return warmupDevEntryGraph(entrySrc).then(() => source);
6320
6628
  },
6321
6629
  transform(code, id) {
6322
6630
  if (id.includes("node_modules") || inject !== "html" || htmlFilePath) return;
@@ -6334,15 +6642,24 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6334
6642
  configResolved(config) {
6335
6643
  viteConfig = config;
6336
6644
  skipTransformIds = new Set(skipTransformFor.map(resolveProjectId));
6337
- const ctx = this;
6338
- const envName = ctx != null && typeof ctx === "object" ? ctx["environment"] : void 0;
6339
- if (envName?.name && envName.name !== "client") return;
6340
- const inputOptions = getBuildInput(config);
6645
+ const clientEnvironmentInputs = [];
6646
+ for (const environment of Object.values(config.environments ?? {})) {
6647
+ if (environment.consumer !== "client") continue;
6648
+ const input = getBuildInput(environment);
6649
+ if (!input) {
6650
+ htmlFilePath ??= path$1.resolve(config.root, "index.html");
6651
+ continue;
6652
+ }
6653
+ if (typeof input === "string") clientEnvironmentInputs.push(input);
6654
+ else if (Array.isArray(input)) clientEnvironmentInputs.push(...input);
6655
+ else clientEnvironmentInputs.push(...Object.values(input));
6656
+ }
6657
+ const inputOptions = clientEnvironmentInputs.length > 0 ? clientEnvironmentInputs : getBuildInput(config);
6341
6658
  if (!inputOptions) htmlFilePath = path$1.resolve(config.root, "index.html");
6342
6659
  else if (typeof inputOptions === "string") entryFiles = [resolveProjectId(inputOptions)];
6343
6660
  else if (Array.isArray(inputOptions)) entryFiles = inputOptions.filter((input) => !isReactRouterClientRouteInput(String(input))).map(resolveProjectId);
6344
6661
  else if (typeof inputOptions === "object") entryFiles = Object.values(inputOptions).filter((input) => !isReactRouterClientRouteInput(String(input))).map((input) => resolveProjectId(String(input)));
6345
- if (entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles);
6662
+ if (entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles) ?? htmlFilePath;
6346
6663
  if (config.command === "serve" && !htmlFilePath) {
6347
6664
  const rootIndexHtml = path$1.resolve(config.root, "index.html");
6348
6665
  if (fs$2.existsSync(rootIndexHtml)) htmlFilePath = rootIndexHtml;
@@ -6457,14 +6774,13 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6457
6774
  },
6458
6775
  transform(code, id) {
6459
6776
  if (skipSvelteKitSsrBuild()) return;
6777
+ if (viteConfig?.command === "build" && !waitsForInit) return;
6460
6778
  if (isSvelteKitServerModule(id)) return;
6461
6779
  if (hasEntryBootstrapParam(id)) return;
6462
6780
  if (normalizeModuleId(id).endsWith(".html")) return;
6463
6781
  const projectId = resolveProjectId(id);
6464
6782
  if (skipTransformIds.has(projectId)) return;
6465
- const transformCtx = this;
6466
- const transformEnv = transformCtx != null && typeof transformCtx === "object" ? transformCtx["environment"] : void 0;
6467
- if (transformEnv?.name && transformEnv.name !== "client") return;
6783
+ if (!isClientEnvironment(this)) return;
6468
6784
  const isVinext = hasPackageDependency("vinext");
6469
6785
  if (isVinext && inject === "html" && id.includes("virtual:vite-rsc/remove-duplicate-server-css")) {
6470
6786
  const namespaceReactImport = `import * as React from 'react';`;
@@ -7252,7 +7568,7 @@ function pluginExternalRuntimeCore() {
7252
7568
  }
7253
7569
  //#endregion
7254
7570
  //#region package.json
7255
- var version$1 = "1.21.6";
7571
+ var version$1 = "1.22.1";
7256
7572
  //#endregion
7257
7573
  //#region src/virtualModules/index.ts
7258
7574
  function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
@@ -7341,16 +7657,31 @@ const collectStaticChunks = (bundle, roots) => {
7341
7657
  };
7342
7658
  /**
7343
7659
  * Analyzes assets associated with a chunk without mutating the output map.
7344
- * The static-import traversal is cycle-safe and ignores missing bundle entries.
7660
+ * Dynamic imports are collected transitively (a lazy route nested behind another
7661
+ * lazy route is still reachable), following both static and dynamic edges.
7662
+ * The traversal is cycle-safe and ignores missing bundle entries.
7345
7663
  */
7346
7664
  const analyzeChunkAssets = (bundle, fileName, chunk) => {
7347
7665
  const dynamicAssets = [];
7348
- for (const currentChunk of collectStaticChunks(bundle, [fileName])) for (const dynamicImport of currentChunk.dynamicImports ?? []) {
7349
- if (!bundle[dynamicImport]) continue;
7350
- dynamicAssets.push({
7351
- fileName: dynamicImport,
7352
- type: isCSSFile(dynamicImport) ? "css" : "js"
7353
- });
7666
+ const visited = /* @__PURE__ */ new Set([fileName]);
7667
+ const queue = [fileName];
7668
+ const enqueue = (imported) => {
7669
+ if (visited.has(imported)) return;
7670
+ visited.add(imported);
7671
+ queue.push(imported);
7672
+ };
7673
+ for (let queueIndex = 0; queueIndex < queue.length; queueIndex++) {
7674
+ const currentChunk = bundle[queue[queueIndex]];
7675
+ if (!currentChunk || currentChunk.type !== "chunk") continue;
7676
+ for (const imported of currentChunk.imports ?? []) enqueue(imported);
7677
+ for (const dynamicImport of currentChunk.dynamicImports ?? []) {
7678
+ if (!bundle[dynamicImport]) continue;
7679
+ dynamicAssets.push({
7680
+ fileName: dynamicImport,
7681
+ type: isCSSFile(dynamicImport) ? "css" : "js"
7682
+ });
7683
+ enqueue(dynamicImport);
7684
+ }
7354
7685
  }
7355
7686
  return {
7356
7687
  importedCss: Array.from(chunk.viteMetadata?.importedCss ?? []),
@@ -7699,8 +8030,38 @@ function collectImportedCss(chunks) {
7699
8030
  for (const chunk of chunks) for (const cssFile of chunk.viteMetadata?.importedCss ?? []) css.add(cssFile);
7700
8031
  return Array.from(css);
7701
8032
  }
7702
- function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options) {
8033
+ /**
8034
+ * Collects the virtual module ids of the `__loadShare__` wrappers belonging to shares
8035
+ * that are not eager.
8036
+ *
8037
+ * Such a wrapper resolves its share through the host at runtime, so it is a deferred
8038
+ * dependency even though the expose statically imports it. Advertising it as a sync
8039
+ * asset makes a preloader fetch a provider the host is going to supply anyway.
8040
+ */
8041
+ function collectDeferredShareModules(options, isRolldown) {
8042
+ const deferred = /* @__PURE__ */ new Set();
8043
+ for (const shareKey of getUsedShares(options)) {
8044
+ const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
8045
+ if (shareConfig?.eager === true) continue;
8046
+ if (shareConfig?.import === false) continue;
8047
+ deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)));
8048
+ }
8049
+ return deferred;
8050
+ }
8051
+ /**
8052
+ * True when the chunk exists to load a deferred share rather than expose code.
8053
+ *
8054
+ * `chunk.moduleIds` carry Rollup's `\0` virtual-module prefix while
8055
+ * `getLoadShareModulePath` returns the unprefixed id, so both sides are normalized —
8056
+ * the same comparison `isContainerBootstrapChunk` makes.
8057
+ */
8058
+ function isDeferredShareChunk(chunk, deferredShareModules) {
8059
+ if (!chunk || chunk.type !== "chunk" || deferredShareModules.size === 0) return false;
8060
+ return [chunk.facadeModuleId, ...chunk.moduleIds ?? []].some((id) => typeof id === "string" && deferredShareModules.has(normalizeVirtualModuleId(id)));
8061
+ }
8062
+ function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options, isRolldown) {
7703
8063
  if (exposeModules.length === 0) return;
8064
+ const deferredShareModules = collectDeferredShareModules(options, isRolldown);
7704
8065
  const containerChunks = remoteEntryFileName ? collectStaticChunks(bundle, [remoteEntryFileName]) : [];
7705
8066
  const bootstrapChunks = containerChunks.slice(1);
7706
8067
  const seen = new Set(containerChunks.map((chunk) => chunk.fileName));
@@ -7721,11 +8082,13 @@ function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName
7721
8082
  for (const exposeModule of exposeModules) {
7722
8083
  const assets = filesMap[exposeModule];
7723
8084
  if (!assets) continue;
7724
- const syncChunks = collectStaticChunks(bundle, assets.js.sync);
8085
+ const allSyncChunks = collectStaticChunks(bundle, assets.js.sync);
8086
+ const syncChunks = allSyncChunks.filter((chunk) => !isDeferredShareChunk(chunk, deferredShareModules));
8087
+ const deferredChunks = allSyncChunks.filter((chunk) => isDeferredShareChunk(chunk, deferredShareModules));
7725
8088
  const sync = Array.from(/* @__PURE__ */ new Set([...bootstrapAssets, ...syncChunks.map((chunk) => chunk.fileName)]));
7726
8089
  const syncSet = new Set(sync);
7727
- const asyncChunks = collectStaticChunks(bundle, assets.js.async);
7728
- const async = asyncChunks.map((chunk) => chunk.fileName).filter((fileName) => !syncSet.has(fileName));
8090
+ const asyncChunks = [...collectStaticChunks(bundle, assets.js.async), ...deferredChunks];
8091
+ const async = Array.from(new Set(asyncChunks.map((chunk) => chunk.fileName))).filter((fileName) => !syncSet.has(fileName));
7729
8092
  assets.js.sync = sync;
7730
8093
  assets.js.async = async;
7731
8094
  const syncCss = Array.from(/* @__PURE__ */ new Set([
@@ -7901,17 +8264,28 @@ const Manifest = (providedOptions) => {
7901
8264
  root,
7902
8265
  stripKnownJsExtensions: true
7903
8266
  });
7904
- expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions);
8267
+ expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions, getIsRolldown(this));
7905
8268
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(mfOptions), this.resolve.bind(this), mfOptions);
7906
8269
  processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
8270
+ const deferredSharedAssets = {
8271
+ js: /* @__PURE__ */ new Set(),
8272
+ css: /* @__PURE__ */ new Set()
8273
+ };
7907
8274
  for (const shareKey of getUsedShares(mfOptions)) {
7908
8275
  const shareItem = getNormalizeShareItem(shareKey, mfOptions);
7909
8276
  const assets = filesMap[shareKey];
7910
8277
  if (!assets || shareItem?.shareConfig.eager === true) continue;
7911
- assets.js.async.push(...assets.js.sync.splice(0));
7912
- assets.css.async.push(...assets.css.sync.splice(0));
8278
+ for (const type of ASSET_TYPES) {
8279
+ assets[type].async.push(...assets[type].sync.splice(0));
8280
+ for (const asset of assets[type].async) deferredSharedAssets[type].add(asset);
8281
+ }
7913
8282
  }
7914
8283
  if (mfOptions.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
8284
+ for (const exposeModule of exposesModules) {
8285
+ const assets = filesMap[exposeModule];
8286
+ if (!assets) continue;
8287
+ for (const type of ASSET_TYPES) for (const timing of LOAD_TIMINGS) assets[type][timing] = assets[type][timing].filter((asset) => !deferredSharedAssets[type].has(asset));
8288
+ }
7915
8289
  filesMap = deduplicateAssets(filesMap);
7916
8290
  }
7917
8291
  const manifest = await applyManifestAdditionalData(generateMFManifest(filesMap, disableAssetsAnalyze), void 0);
@@ -8438,21 +8812,6 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8438
8812
  };
8439
8813
  }
8440
8814
  //#endregion
8441
- //#region src/utils/remoteConsumerTarget.ts
8442
- function getPluginEnvironmentName(ctx) {
8443
- if (ctx == null || typeof ctx !== "object") return void 0;
8444
- const environment = ctx["environment"];
8445
- if (environment == null || typeof environment !== "object") return void 0;
8446
- const name = environment["name"];
8447
- return typeof name === "string" ? name : void 0;
8448
- }
8449
- function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
8450
- if (!hasMultiEnvironment) return "unified";
8451
- const envName = getPluginEnvironmentName(ctx);
8452
- if (!envName || envName === "client") return "client";
8453
- return "server";
8454
- }
8455
- //#endregion
8456
8815
  //#region src/plugins/pluginProxyRemotes.ts
8457
8816
  function isNodeModulesImporter(importer) {
8458
8817
  return importer?.includes("/node_modules/") || importer?.includes("\\node_modules\\");
@@ -8532,6 +8891,81 @@ function pluginProxyRemotes_default(options) {
8532
8891
  };
8533
8892
  }
8534
8893
  //#endregion
8894
+ //#region src/utils/sharedSource.ts
8895
+ /** Identify shared entries through Vite, with a cache scoped to this federation instance. */
8896
+ function createSharedSourceResolver(shared, getResolutionConfig) {
8897
+ const caches = /* @__PURE__ */ new Map();
8898
+ async function matchEntry(source, suffix, resolveEntry) {
8899
+ const packageName = getPackageNameFromNodeModulePath(source);
8900
+ if (!packageName) return;
8901
+ const candidates = /* @__PURE__ */ new Set();
8902
+ if (findSharedKey(packageName, shared)) candidates.add(packageName);
8903
+ if (findSharedKey(suffix, shared)) candidates.add(suffix);
8904
+ for (const key of Object.keys(shared)) {
8905
+ if (getPackageName(key) !== packageName) continue;
8906
+ if (!key.endsWith("/")) candidates.add(key);
8907
+ for (const subpath of getCommonSharedSubpaths(key)) if (findSharedKey(subpath, shared)) candidates.add(subpath);
8908
+ }
8909
+ if (candidates.size === 0) return;
8910
+ const resolvedSource = await resolveEntry(source);
8911
+ if (!resolvedSource) return;
8912
+ for (const candidate of candidates) {
8913
+ const entry = await resolveEntry(candidate);
8914
+ if (!entry) continue;
8915
+ if (normalizeNodeModulePath(entry) === normalizeNodeModulePath(resolvedSource) || getNodeModulesSuffix(entry) === suffix) return candidate;
8916
+ }
8917
+ }
8918
+ return {
8919
+ clear() {
8920
+ caches.clear();
8921
+ },
8922
+ async resolve(context, source, options = {}) {
8923
+ if (source.startsWith("\0") || source.includes("#")) return;
8924
+ const queryIndex = source.indexOf("?");
8925
+ const query = queryIndex === -1 ? "" : source.slice(queryIndex + 1);
8926
+ if (query && [...new URLSearchParams(query).keys()].some((key) => ![
8927
+ "v",
8928
+ "t",
8929
+ "import"
8930
+ ].includes(key))) return;
8931
+ if (findSharedKey(source, shared)) return source;
8932
+ const suffix = getNodeModulesSuffix(source);
8933
+ if (!suffix) return;
8934
+ const normalizedSource = stripViteFsPrefix(normalizeNodeModulePath(source));
8935
+ const environment = context.environment ?? !!options.ssr;
8936
+ const cacheable = !options.isEntry && !options.scan && (!options.kind || options.kind === "import-statement") && Object.keys(options.attributes ?? {}).length === 0 && Object.keys(options.custom ?? {}).length === 0;
8937
+ let cache = cacheable ? caches.get(environment) : void 0;
8938
+ if (cacheable && !cache) {
8939
+ cache = /* @__PURE__ */ new Map();
8940
+ caches.set(environment, cache);
8941
+ }
8942
+ if (cache?.has(normalizedSource)) return cache.get(normalizedSource);
8943
+ const { root, conditions } = getResolutionConfig(context, options);
8944
+ const result = await matchEntry(normalizedSource, suffix, async (request) => {
8945
+ if (!path$1.isAbsolute(request) && !isPackageExportAvailable(request, {
8946
+ cwd: root,
8947
+ conditions
8948
+ })) return void 0;
8949
+ try {
8950
+ const resolved = await context.resolve(request, path$1.join(root, "package.json"), {
8951
+ ...options,
8952
+ skipSelf: true,
8953
+ custom: {
8954
+ ...options.custom,
8955
+ __mfSharedEntryLookup: true
8956
+ }
8957
+ });
8958
+ return resolved && !resolved.external ? resolved.id : void 0;
8959
+ } catch {
8960
+ return;
8961
+ }
8962
+ });
8963
+ cache?.set(normalizedSource, result);
8964
+ return result;
8965
+ }
8966
+ };
8967
+ }
8968
+ //#endregion
8535
8969
  //#region src/utils/PromiseStore.ts
8536
8970
  /**
8537
8971
  * example:
@@ -8581,23 +9015,6 @@ function isBuildConfigImporter(importer) {
8581
9015
  if (!importer) return false;
8582
9016
  return /(^|\/)(?:nuxt|vite|vitest|webpack|rollup|rspack)\.config\.[cm]?[jt]sx?$/.test(importer.replace(/\\/g, "/"));
8583
9017
  }
8584
- function findSharedKeyForSource(source, shared) {
8585
- const key = findSharedKey(source, shared);
8586
- if (key) return key;
8587
- const explicitSharedSubpathKeys = Object.keys(shared || {}).filter((sharedKey) => getPackageName(sharedKey) !== sharedKey && !sharedKey.endsWith("/"));
8588
- if (isNodeModulePath(source)) {
8589
- const explicitSubpathKey = getMatchingNodeModuleSubpath(source, explicitSharedSubpathKeys);
8590
- if (explicitSubpathKey) return explicitSubpathKey;
8591
- const normalizedSource = normalizeNodeModulePath(source);
8592
- const explicitSubpathEntryKey = explicitSharedSubpathKeys.find((sharedKey) => {
8593
- const entry = getInstalledPackageEntry(sharedKey, { cwd: getPackageDetectionCwd() });
8594
- return entry ? normalizeNodeModulePath(entry) === normalizedSource : false;
8595
- });
8596
- if (explicitSubpathEntryKey) return explicitSubpathEntryKey;
8597
- }
8598
- const packageName = getPackageNameFromNodeModulePath(source);
8599
- return packageName ? findSharedKey(packageName, shared) : void 0;
8600
- }
8601
9018
  /**
8602
9019
  * Reads the dependencies of an installed package from its package.json.
8603
9020
  */
@@ -8755,6 +9172,21 @@ function isSharedPackageDependency(sharedKey, dependency) {
8755
9172
  }
8756
9173
  return reachable.has(dependency);
8757
9174
  }
9175
+ function isConfiguredSharedPackage(pkg, shared) {
9176
+ return Object.keys(shared).some((key) => getPackageName(key) === pkg);
9177
+ }
9178
+ function shouldKeepSharedImportLocal(source, importer, sharedKey, shared, importerPackage) {
9179
+ if (!importer || shared[sharedKey]?.shareConfig.import === false) return false;
9180
+ const prebuildImporter = importer.includes("__prebuild__") ? VirtualModule.findModule(PREBUILD_TAG, importer) : void 0;
9181
+ const fallbackPackage = prebuildImporter ? getPackageName(prebuildImporter.name) : importerPackage;
9182
+ if (!fallbackPackage || !isConfiguredSharedPackage(fallbackPackage, shared)) return false;
9183
+ const sourcePackage = getPackageName(sharedKey);
9184
+ if (fallbackPackage !== "react-dom" || sourcePackage !== "react") return false;
9185
+ if (prebuildImporter && matchesSharedSource(source, prebuildImporter.name)) return false;
9186
+ if (!isSharedPackageDependency(prebuildImporter?.name ?? fallbackPackage, sourcePackage)) return false;
9187
+ if (isSharedPackageDependency(sharedKey, fallbackPackage)) return false;
9188
+ return true;
9189
+ }
8758
9190
  const sharedRuntimeDependencyCache = /* @__PURE__ */ new Map();
8759
9191
  const SOURCE_FILE_RE = /\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/;
8760
9192
  const NON_RUNTIME_SOURCE_RE = /(?:\.d\.[cm]?ts|\.(?:test|spec|stories)\.[cm]?[jt]sx?)$/;
@@ -8956,6 +9388,10 @@ function proxySharedModule(options) {
8956
9388
  ssrTarget
8957
9389
  });
8958
9390
  };
9391
+ const sharedSourceResolver = createSharedSourceResolver(shared, (context, resolveOptions) => ({
9392
+ root: _config?.root || getPackageDetectionCwd(),
9393
+ conditions: getRuntimeDependencyConditions(context, resolveOptions)
9394
+ }));
8959
9395
  const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command, getIsRolldown(context), getEnvironmentConditions(context));
8960
9396
  const normalizeTreeShakingOutputPath = (value) => {
8961
9397
  const normalized = normalizePathForImport(value);
@@ -9005,7 +9441,7 @@ function proxySharedModule(options) {
9005
9441
  refreshTreeShakingForEnvironment(this);
9006
9442
  const providerPackages = /* @__PURE__ */ new Set([...Object.keys(shared).filter((pkg) => !pkg.endsWith("/")), ...getUsedShares(federationOptions)]);
9007
9443
  for (const pkg of providerPackages) {
9008
- const sharedKey = findSharedKeyForSource(pkg, shared);
9444
+ const sharedKey = findSharedKey(pkg, shared);
9009
9445
  const shareItem = shared[pkg] || (sharedKey ? shared[sharedKey] : void 0);
9010
9446
  if (shareItem) emitTreeShakingProvider(this, pkg, shareItem);
9011
9447
  }
@@ -9025,6 +9461,7 @@ function proxySharedModule(options) {
9025
9461
  setTreeShakingBuildMode(command === "build", federationOptions);
9026
9462
  resetTreeShakingExports(federationOptions);
9027
9463
  emittedTreeShakingProviders.clear();
9464
+ sharedSourceResolver.clear();
9028
9465
  sharedDependencyCache.clear();
9029
9466
  dependencyManifestCache.clear();
9030
9467
  sharedRuntimeDependencyCache.clear();
@@ -9059,7 +9496,11 @@ function proxySharedModule(options) {
9059
9496
  writeLocalSharedImportMap(federationOptions);
9060
9497
  refreshHostAutoInit(federationOptions);
9061
9498
  },
9499
+ watchChange() {
9500
+ sharedSourceResolver.clear();
9501
+ },
9062
9502
  buildStart() {
9503
+ sharedSourceResolver.clear();
9063
9504
  if (_command !== "build") return;
9064
9505
  resetTreeShakingExports(federationOptions);
9065
9506
  emittedTreeShakingProviders.clear();
@@ -9068,9 +9509,12 @@ function proxySharedModule(options) {
9068
9509
  shouldTransformCachedModule() {
9069
9510
  return _command === "build" && hasAnalyzableShares;
9070
9511
  },
9071
- transform(code, id) {
9512
+ async transform(code, id, transformOptions) {
9072
9513
  if (_command !== "build" || !hasAnalyzableShares) return;
9073
- collectTreeShakingImports(code, id, shared, findSharedKeyForSource, (sharedKey, exports, request) => recordTreeShakingExports(sharedKey, exports, request, federationOptions), (sharedKey, request) => markTreeShakingPackageUnsafe(sharedKey, request, federationOptions));
9514
+ await collectTreeShakingImports(code, id, shared, async (source, shares) => {
9515
+ const request = await sharedSourceResolver.resolve(this, source, transformOptions);
9516
+ return request ? findSharedKey(request, shares) : void 0;
9517
+ }, (sharedKey, exports, request) => recordTreeShakingExports(sharedKey, exports, request, federationOptions), (sharedKey, request) => markTreeShakingPackageUnsafe(sharedKey, request, federationOptions));
9074
9518
  refreshTreeShakingForEnvironment(this);
9075
9519
  }
9076
9520
  },
@@ -9079,6 +9523,7 @@ function proxySharedModule(options) {
9079
9523
  enforce: "pre",
9080
9524
  apply: "build",
9081
9525
  async resolveId(source, importer, resolveOptions) {
9526
+ if (resolveOptions.custom?.__mfSharedEntryLookup) return;
9082
9527
  const sourceToken = getTreeShakingGraphToken(source);
9083
9528
  const importerToken = getTreeShakingGraphToken(importer);
9084
9529
  const token = sourceToken || importerToken;
@@ -9086,7 +9531,8 @@ function proxySharedModule(options) {
9086
9531
  const cleanSource = normalizePathForImport(stripTreeShakingGraphQuery(source));
9087
9532
  const cleanImporter = importer ? normalizePathForImport(stripTreeShakingGraphQuery(importer)) : void 0;
9088
9533
  if (!sourceToken && importerToken) {
9089
- const nestedSharedKey = findSharedKeyForSource(cleanSource, shared);
9534
+ const request = await sharedSourceResolver.resolve(this, cleanSource, resolveOptions);
9535
+ const nestedSharedKey = request ? findSharedKey(request, shared) : void 0;
9090
9536
  if (nestedSharedKey && getPackageName(nestedSharedKey) !== getPackageName(importerToken)) return this.resolve(cleanSource, cleanImporter, {
9091
9537
  ...resolveOptions,
9092
9538
  skipSelf: true
@@ -9113,20 +9559,22 @@ function proxySharedModule(options) {
9113
9559
  name: "proxyPreBuildShared:resolve-shared-loadShare",
9114
9560
  enforce: "pre",
9115
9561
  async resolveId(source, importer, resolveOptions) {
9116
- if (resolveOptions.custom?.__mfTreeShakingGraph) return;
9117
- function shouldSkipTaggedImporterProxy(sharedKey, tag) {
9562
+ if (resolveOptions.custom?.__mfSharedEntryLookup || resolveOptions.custom?.__mfTreeShakingGraph) return;
9563
+ const sharedSource = await sharedSourceResolver.resolve(this, source, resolveOptions);
9564
+ if (!sharedSource) return;
9565
+ const key = findSharedKey(sharedSource, shared);
9566
+ if (!key) return;
9567
+ const shouldSkipTaggedImporterProxy = (sharedKey, tag) => {
9118
9568
  if (!importer?.includes(tag)) return false;
9119
9569
  const taggedModule = VirtualModule.findModule(tag, importer);
9120
9570
  if (!taggedModule) return true;
9121
- return taggedModule.name === sharedKey || matchesSharedSource(source, taggedModule.name);
9122
- }
9123
- const key = findSharedKeyForSource(source, shared);
9124
- if (!key) return;
9571
+ return taggedModule.name === sharedKey || matchesSharedSource(sharedSource, taggedModule.name);
9572
+ };
9125
9573
  const importerPackage = getSharedPackageFromFile(importer, shared);
9126
9574
  if (importerPackage === getPackageName(key)) return;
9127
- if (importerPackage) {
9575
+ if (importerPackage && shared[key].shareConfig.import !== false) {
9128
9576
  const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
9129
- const runtimeDependencyRequest = key.endsWith("/") && matchesSharedSource(source, key) ? source : key;
9577
+ const runtimeDependencyRequest = key.endsWith("/") && matchesSharedSource(sharedSource, key) ? sharedSource : key;
9130
9578
  if (importerIsUnsharedWorkspacePackage ? isSharedPackageRuntimeDependency(runtimeDependencyRequest, importerPackage, getRuntimeDependencyConditions(this, resolveOptions)) : isSharedPackageDependency(key, importerPackage)) return;
9131
9579
  }
9132
9580
  if (useDirectReactImport && key === "react") return;
@@ -9137,7 +9585,11 @@ function proxySharedModule(options) {
9137
9585
  if (importer && (importer.includes("hostAutoInit") || importer.includes("__H_A_I__"))) return;
9138
9586
  if (shouldSkipTaggedImporterProxy(key, "__loadShare__")) return;
9139
9587
  if (shouldSkipTaggedImporterProxy(key, "__prebuild__")) return;
9140
- const shareSource = key === "vue" && source.startsWith("vue/dist/") ? key : isNodeModulePath(source) ? getCommonSharedSubpathFromNodeModulePath(source, key) || key : source;
9588
+ const shareSource = key === "vue" && sharedSource.startsWith("vue/dist/") ? key : sharedSource;
9589
+ if (shouldKeepSharedImportLocal(sharedSource, importer, key, shared, importerPackage)) {
9590
+ const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
9591
+ return tryResolveFromProjectRoot(localSource) || localSource;
9592
+ }
9141
9593
  const loadSharePath = getLoadShareModulePath(shareSource, useRolldown, federationOptions);
9142
9594
  if (!materializedLoadShareSources.has(shareSource)) {
9143
9595
  materializedLoadShareSources.add(shareSource);
@@ -9460,7 +9912,6 @@ function pluginRemoteNamedExports(options) {
9460
9912
  const MAX_RUNNER_BODY_BYTES = 1024 * 1024;
9461
9913
  const MAX_RUNNER_START_OFFSET = 1024 * 1024;
9462
9914
  const ALLOWED_RUNNER_INVOKE_NAMES = /* @__PURE__ */ new Set(["fetchModule", "getBuiltins"]);
9463
- const VITE_FS_PREFIX = "/@fs/";
9464
9915
  function isPlainObject(value) {
9465
9916
  return !!value && typeof value === "object" && !Array.isArray(value);
9466
9917
  }
@@ -9479,12 +9930,6 @@ function isSafeRunnerFetchModuleOptions(value) {
9479
9930
  }
9480
9931
  return true;
9481
9932
  }
9482
- function stripQueryAndHash(id) {
9483
- const queryIndex = id.indexOf("?");
9484
- const hashIndex = id.indexOf("#");
9485
- const endIndex = queryIndex === -1 ? hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
9486
- return endIndex === -1 ? id : id.slice(0, endIndex);
9487
- }
9488
9933
  function decodeRunnerFilePath(filePath) {
9489
9934
  try {
9490
9935
  return decodeURIComponent(filePath);
@@ -9528,8 +9973,8 @@ function isSafeRunnerFetchModuleId(id, config) {
9528
9973
  const cleanId = decodeRunnerFilePath(stripQueryAndHash(decoded));
9529
9974
  if (!cleanId || hasRelativeTraversal(cleanId)) return false;
9530
9975
  const allowedDirectories = getRunnerAllowedDirectories(config);
9531
- if (cleanId.startsWith(VITE_FS_PREFIX)) {
9532
- const fsPath = `/${cleanId.slice(5)}`;
9976
+ if (cleanId.startsWith("/@fs/")) {
9977
+ const fsPath = stripViteFsPrefix(cleanId);
9533
9978
  return path$1.isAbsolute(fsPath) && isPathWithinAllowedDirectories(fsPath, allowedDirectories);
9534
9979
  }
9535
9980
  if (path$1.isAbsolute(cleanId)) {
@@ -9944,11 +10389,7 @@ var aliasToArrayPlugin_default = {
9944
10389
  };
9945
10390
  //#endregion
9946
10391
  //#region src/utils/controlChunkSanitizer.ts
9947
- const FEDERATION_CONTROL_CHUNK_HINTS = [
9948
- "hostInit",
9949
- "virtualExposes",
9950
- "localSharedImportMap"
9951
- ];
10392
+ const FEDERATION_CONTROL_CHUNK_HINTS = ["hostInit", "localSharedImportMap"];
9952
10393
  function stripEmptyPreloadCalls(code) {
9953
10394
  const helperImportRegex = /import\s*\{\s*_\s*as\s*([A-Za-z_$][\w$]*)\s*\}\s*from\s*["'][^"']+["']\s*;?/g;
9954
10395
  const helperAliases = [];
@@ -10068,7 +10509,7 @@ function applyRuntimeCapabilityDefines(define, options, { defaultDisableSnapshot
10068
10509
  function getRuntimeCapabilityConfigurationWarnings(options) {
10069
10510
  const warnings = [];
10070
10511
  if (options.disableRemote && Object.keys(options.remotes).length > 0) warnings.push("disableRemote is true, but remotes are configured. Remote loading will be unavailable at runtime.");
10071
- if (options.disableShared && Object.keys(options.shared).length > 0) warnings.push("disableShared is true, but shared dependencies are configured. Shared dependency loading will be unavailable at runtime.");
10512
+ if (options.disableShared && hasShared(options)) warnings.push("disableShared is true, but shared dependencies are configured. Shared dependency loading will be unavailable at runtime.");
10072
10513
  return warnings;
10073
10514
  }
10074
10515
  //#endregion
@@ -10159,7 +10600,7 @@ function escapeUnsafeJsSourceChars(str) {
10159
10600
  }
10160
10601
  function isFederationHtmlPreloadDependency(dep, includeSharedRuntime = false) {
10161
10602
  const file = path$1.basename(dep);
10162
- if (file.includes("__mfe_internal__") || file.includes("virtual_mf-") || file.includes("virtualExposes") || file.includes("localSharedImportMap") || file.includes("hostInit")) return true;
10603
+ if (file.includes("__mfe_internal__") || file.includes("virtual_mf-") || file.includes("localSharedImportMap") || file.includes("hostInit")) return true;
10163
10604
  return includeSharedRuntime && (file.includes("preload-helper") || file.includes("rolldown-runtime") || file.startsWith("dist-"));
10164
10605
  }
10165
10606
  function canResolveSharedSubpath(subpath, projectRoot) {
@@ -10379,6 +10820,7 @@ function createEarlyVirtualModulesPlugin(options) {
10379
10820
  const resolvedConfiguredEntryFiles = (typeof buildInput === "string" ? [buildInput] : Array.isArray(buildInput) ? buildInput : buildInput && typeof buildInput === "object" ? Object.values(buildInput) : []).map((entry) => String(entry)).filter((entry) => !isReactRouterBuildClientRouteInput(entry)).map((entry) => entry.split(/[?#]/)[0]).map((entry) => path$1.isAbsolute(entry) ? entry : path$1.resolve(root, entry));
10380
10821
  resetConcreteSharedImportSourceCache();
10381
10822
  setPackageDetectionCwd(root);
10823
+ resolveSharedVersions(shared, root);
10382
10824
  const isVinext = hasPackageDependency("vinext");
10383
10825
  initVirtualModules(_command, getRemoteEntryId(options), false, options);
10384
10826
  const isRolldown = getIsRolldown(this);
@@ -10391,11 +10833,11 @@ function createEarlyVirtualModulesPlugin(options) {
10391
10833
  config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
10392
10834
  }
10393
10835
  }
10394
- if (!config.build?.ssr && (Object.keys(shared ?? {}).length > 0 || Object.keys(remotes ?? {}).length > 0)) {
10836
+ if (!config.build?.ssr && (hasShared(options) || hasRemotes(options))) {
10395
10837
  const hasJsxSource = registerEntryImports(options, root, _command === "serve", resolvedConfiguredEntryFiles);
10396
10838
  if (_command === "serve") hasClientJsxSource = hasJsxSource;
10397
10839
  }
10398
- if (shared && Object.keys(shared).length > 0) {
10840
+ if (hasShared(options)) {
10399
10841
  if (_command === "serve") {
10400
10842
  excludeSharedSubDependencies(shared);
10401
10843
  config.optimizeDeps = config.optimizeDeps || {};
@@ -10568,9 +11010,7 @@ export default __mfShared.default ?? __mfShared;`
10568
11010
  const automaticJsxRuntime = getAutomaticJsxRuntime(config);
10569
11011
  if (automaticJsxRuntime && materializeAutomaticJsxRuntime(options, automaticJsxRuntime)) writeLocalSharedImportMap(options);
10570
11012
  }
10571
- const viteMajor = parseInt(version, 10);
10572
- const hasRemotes = Object.keys(options.remotes).length > 0;
10573
- if (!getSsrCapabilities(viteMajor, config.command, hasRemotes).injectSsrEntryLoader) return;
11013
+ if (!getSsrCapabilities(parseInt(version, 10), config.command, hasRemotes(options)).injectSsrEntryLoader) return;
10574
11014
  if (options.runtimePlugins.some((p) => {
10575
11015
  return (typeof p === "string" ? p : p[0]) === "@module-federation/vite/ssrEntryLoader";
10576
11016
  })) return;
@@ -10597,7 +11037,10 @@ export default __mfShared.default ?? __mfShared;`
10597
11037
  const ssrEntryLoaderSpecifier = SSR_ENTRY_LOADER_SPECIFIER;
10598
11038
  try {
10599
11039
  resolveImportPath(ssrEntryLoaderSpecifier);
10600
- options.runtimePlugins.push([ssrEntryLoaderSpecifier, { resolvedShared }]);
11040
+ options.runtimePlugins.push([ssrEntryLoaderSpecifier, {
11041
+ resolvedShared,
11042
+ ...options.ssrEntryLoader?.strategy ? { strategy: options.ssrEntryLoader.strategy } : {}
11043
+ }]);
10601
11044
  } catch {}
10602
11045
  }
10603
11046
  };
@@ -10613,7 +11056,7 @@ function applyBuildTimeRuntimeDefines(define, options, { target, isAstro, defaul
10613
11056
  }
10614
11057
  function loadPluginDts(options) {
10615
11058
  if (options.dts === false) return [];
10616
- return [import("./pluginDts-4sHIZPIi.js").then(({ default: pluginDts }) => pluginDts(options))];
11059
+ return [import("./pluginDts-CQ088qGF.js").then(({ default: pluginDts }) => pluginDts(options))];
10617
11060
  }
10618
11061
  const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
10619
11062
  function isInjectExternalRuntimeCorePlugin(specifier) {
@@ -10638,7 +11081,6 @@ function resolveInjectExternalRuntimeCorePlugin() {
10638
11081
  function applyExternalRuntimeExperiments(options) {
10639
11082
  const { experiments } = options;
10640
11083
  if (experiments.provideExternalRuntime) {
10641
- if (Object.keys(options.exposes).length > 0) throw createModuleFederationError("You can only set provideExternalRuntime: true in pure consumer which not expose modules.");
10642
11084
  if (!hasInjectExternalRuntimeCorePlugin(options.runtimePlugins)) options.runtimePlugins = options.runtimePlugins.concat(resolveInjectExternalRuntimeCorePlugin());
10643
11085
  }
10644
11086
  }
@@ -10654,7 +11096,7 @@ function federation(mfUserOptions) {
10654
11096
  const virtualExposesId = getVirtualExposesId(options);
10655
11097
  const moduleParseController = createModuleParseController();
10656
11098
  const moduleParsePlugins = pluginModuleParseEnd_default((id) => {
10657
- return id.includes(getHostAutoInitPath(options)) || id.includes(getPendingSharesPath(options)) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes("virtual:mf-localSharedImportMap") || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
11099
+ return id.includes(getHostAutoInitPath(options)) || id.includes(getPendingSharesPath(options)) || id.includes("virtual:mf-REMOTE_ENTRY_ID") || id.includes(virtualExposesId) || id.includes("virtual:mf-localSharedImportMap") || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
10658
11100
  }, {
10659
11101
  moduleParseTimeout: options.moduleParseTimeout,
10660
11102
  moduleParseIdleTimeout: options.moduleParseIdleTimeout,
@@ -10795,6 +11237,7 @@ function federation(mfUserOptions) {
10795
11237
  ssrTarget = config.ssr?.target ?? "node";
10796
11238
  isProduction = config.isProduction;
10797
11239
  const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, Object.keys(options.remotes).length > 0);
11240
+ resolveSharedVersions(shared, config.root);
10798
11241
  initVirtualModules(command, remoteEntryId, ssrCapabilities.enableSsrInitBootstrap, options);
10799
11242
  }
10800
11243
  },
@@ -10829,11 +11272,6 @@ function federation(mfUserOptions) {
10829
11272
  skipTransformFor: Object.values(options.exposes).map((expose) => expose.import),
10830
11273
  federationOptions: options
10831
11274
  }),
10832
- ...addEntry({
10833
- entryName: "virtualExposes",
10834
- entryPath: virtualExposesId,
10835
- federationOptions: options
10836
- }),
10837
11275
  pluginProxyRemoteEntry_default({
10838
11276
  options,
10839
11277
  remoteEntryId,
@@ -10857,6 +11295,10 @@ function federation(mfUserOptions) {
10857
11295
  const runtimeInitId = getRuntimeInitStatusImportId(options);
10858
11296
  config.build = config.build || {};
10859
11297
  if (config.build.modulePreload !== false) {
11298
+ const remoteEntryBasename = path$1.posix.basename(options.filename);
11299
+ const hashParts = remoteEntryBasename.split(/\[hash(?::\d+)?\]/);
11300
+ const remoteEntryFilePattern = new RegExp(`^${hashParts.map((part) => escapeRegExp(part)).join("[\\w-]+")}${hashParts.length > 1 && !/\.[^/.]+$/.test(remoteEntryBasename) ? "\\.js" : ""}$`);
11301
+ const isRemoteEntryFile = (file) => file === remoteEntryBasename || remoteEntryFilePattern.test(file);
10860
11302
  const currentModulePreload = config.build.modulePreload && typeof config.build.modulePreload === "object" ? config.build.modulePreload : {};
10861
11303
  const existingResolveDependencies = currentModulePreload.resolveDependencies;
10862
11304
  config.build.modulePreload = {
@@ -10864,7 +11306,7 @@ function federation(mfUserOptions) {
10864
11306
  resolveDependencies(filename, deps, context) {
10865
11307
  const resolvedDeps = existingResolveDependencies ? existingResolveDependencies(filename, deps, context) : deps;
10866
11308
  const hostFile = path$1.basename(context.hostId);
10867
- if (context.hostType === "js" && (hostFile === options.filename || hostFile.includes("hostInit") || hostFile.includes("virtualExposes") || hostFile.includes("localSharedImportMap"))) return [];
11309
+ if (context.hostType === "js" && (isRemoteEntryFile(hostFile) || hostFile.includes("hostInit") || hostFile.includes("localSharedImportMap"))) return [];
10868
11310
  const hasFederationHtmlDeps = context.hostType === "html" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
10869
11311
  const hasFederationJsDeps = context.hostType === "js" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
10870
11312
  const treeShakingFallbackDeps = hasTreeShakingShared ? (dep) => dep.includes("__prebuild__") : () => false;
@@ -10903,6 +11345,10 @@ function federation(mfUserOptions) {
10903
11345
  const mfChunkName = function(id) {
10904
11346
  if (id.includes(runtimeInitId) || id.includes("__mf_v__runtimeInit__mf_v__")) return "runtimeInit";
10905
11347
  if (id.includes("__loadShare__")) {
11348
+ const pkg = getCachedLoadSharePkg(id);
11349
+ const key = pkg && findSharedKey(pkg, shared);
11350
+ if (key && shared[key].shareConfig.eager === true) return "loadShare-eager";
11351
+ if (key && shared[key].shareConfig.import === false) return null;
10906
11352
  const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
10907
11353
  return match ? match[1] : "loadShare";
10908
11354
  }
@@ -11011,8 +11457,8 @@ function federation(mfUserOptions) {
11011
11457
  const virtualModule = VirtualModule.findById(id);
11012
11458
  if (!virtualModule?.code) return null;
11013
11459
  let code = virtualModule.code;
11014
- const environmentName = this.environment?.name;
11015
- if (environmentName && environmentName !== "client" || !environmentName && isSsrBuild) code = prependWorkspaceSingletonSsrImport(code);
11460
+ const consumerTarget = resolveEnvironmentConsumerTarget(this);
11461
+ if (consumerTarget === "server" || !consumerTarget && isSsrBuild) code = prependWorkspaceSingletonSsrImport(code);
11016
11462
  code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
11017
11463
  code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
11018
11464
  if (!(/\b(?:var|let|const)\s+__moduleExports\b/.test(code) || /\bexport\s+const\s+__moduleExports\b/.test(code) || /\bexport\s*\{[^}]*__moduleExports/.test(code))) {
@@ -11078,7 +11524,7 @@ function federation(mfUserOptions) {
11078
11524
  config(config, { command: _command }) {
11079
11525
  const isRolldown = getIsRolldown(this);
11080
11526
  isSsrBuild = _command === "build" && Boolean(config.build?.ssr);
11081
- const needsRuntimeHelpers = Object.keys(options.shared ?? {}).length > 0;
11527
+ const needsRuntimeHelpers = hasShared(options);
11082
11528
  if (needsRuntimeHelpers) appendResolveAlias(config, {
11083
11529
  find: /^@module-federation\/runtime\/helpers$/,
11084
11530
  replacement: getRuntimeHelpersImplementation(options.implementation)