@module-federation/vite 1.17.0 → 1.17.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,4 +1,4 @@
1
- import { _ as createModuleFederationError, a as getIsRolldown, b as rebaseImport, c as getPackageNameFromNodeModulePath, d as isNuxtProjectRoot, f as packageNameDecode, g as sharedCacheHelperCode, h as setPackageDetectionCwd, i as getInstalledPackageJson, l as getSharedCacheDescriptor, m as resolveImportPath, o as getPackageDetectionCwd, p as packageNameEncode, r as getInstalledPackageEntry, s as getPackageName, u as hasPackageDependency, v as mfWarn, y as normalizePathForImport } from "./pluginDts-BcvLBYP3.js";
1
+ import { _ as createModuleFederationError, a as getIsRolldown, b as rebaseImport, c as getPackageNameFromNodeModulePath, d as isNuxtProjectRoot, f as packageNameDecode, g as sharedCacheHelperCode, h as setPackageDetectionCwd, i as getInstalledPackageJson, l as getSharedCacheDescriptor, m as resolveImportPath, o as getPackageDetectionCwd, p as packageNameEncode, r as getInstalledPackageEntry, s as getPackageName, u as hasPackageDependency, v as mfWarn, y as normalizePathForImport } from "./pluginDts-CGDIZCsD.js";
2
2
  import { createRequire } from "node:module";
3
3
  import * as fs$2 from "fs";
4
4
  import { existsSync, readFileSync, realpathSync, statSync, writeFileSync } from "fs";
@@ -939,6 +939,145 @@ ${exportStatement}
939
939
  `);
940
940
  }
941
941
  //#endregion
942
+ //#region src/utils/codePositionMap.ts
943
+ const REGEX_PREFIX_KEYWORDS = new Set([
944
+ "await",
945
+ "case",
946
+ "delete",
947
+ "in",
948
+ "instanceof",
949
+ "new",
950
+ "return",
951
+ "throw",
952
+ "typeof",
953
+ "void",
954
+ "yield"
955
+ ]);
956
+ function isJsxClosingTagSlash(code, slashIndex) {
957
+ if (code[slashIndex - 1] !== "<") return false;
958
+ let cursor = slashIndex + 1;
959
+ while (/\s/.test(code[cursor] || "")) cursor++;
960
+ if (code[cursor] === ">") return true;
961
+ const tagStart = cursor;
962
+ while (/[-:.$_\u200C\u200D\p{ID_Continue}]/u.test(code[cursor] || "")) cursor++;
963
+ if (cursor === tagStart) return false;
964
+ while (/\s/.test(code[cursor] || "")) cursor++;
965
+ return code[cursor] === ">";
966
+ }
967
+ /** Mark comments, string/template literals, and regular expressions as non-code. */
968
+ function createCodePositionMap(code) {
969
+ const positions = Array(code.length).fill(true);
970
+ const mask = (start, end) => {
971
+ for (let index = start; index < end; index++) positions[index] = false;
972
+ };
973
+ let canStartRegex = true;
974
+ for (let index = 0; index < code.length;) {
975
+ const char = code[index];
976
+ const next = code[index + 1];
977
+ if (/\s/.test(char)) {
978
+ index++;
979
+ continue;
980
+ }
981
+ if (char === "/" && next === "/") {
982
+ const start = index;
983
+ index += 2;
984
+ while (index < code.length && code[index] !== "\n" && code[index] !== "\r") index++;
985
+ mask(start, index);
986
+ continue;
987
+ }
988
+ if (char === "/" && next === "*") {
989
+ const start = index;
990
+ index += 2;
991
+ while (index < code.length && !(code[index] === "*" && code[index + 1] === "/")) index++;
992
+ index = Math.min(code.length, index + 2);
993
+ mask(start, index);
994
+ continue;
995
+ }
996
+ if (char === "\"" || char === "'" || char === "`") {
997
+ const quote = char;
998
+ const start = index++;
999
+ while (index < code.length) {
1000
+ if (code[index] === "\\") {
1001
+ index += 2;
1002
+ continue;
1003
+ }
1004
+ if (code[index] === quote) {
1005
+ index++;
1006
+ break;
1007
+ }
1008
+ index++;
1009
+ }
1010
+ mask(start, index);
1011
+ canStartRegex = false;
1012
+ continue;
1013
+ }
1014
+ const closesJsxTag = isJsxClosingTagSlash(code, index);
1015
+ if (char === "/" && canStartRegex && !closesJsxTag) {
1016
+ const start = index;
1017
+ let cursor = index + 1;
1018
+ let escaped = false;
1019
+ let inCharacterClass = false;
1020
+ let closed = false;
1021
+ for (; cursor < code.length; cursor++) {
1022
+ const regexChar = code[cursor];
1023
+ if (regexChar === "\n" || regexChar === "\r") break;
1024
+ if (escaped) {
1025
+ escaped = false;
1026
+ continue;
1027
+ }
1028
+ if (regexChar === "\\") {
1029
+ escaped = true;
1030
+ continue;
1031
+ }
1032
+ if (regexChar === "[") {
1033
+ inCharacterClass = true;
1034
+ continue;
1035
+ }
1036
+ if (regexChar === "]" && inCharacterClass) {
1037
+ inCharacterClass = false;
1038
+ continue;
1039
+ }
1040
+ if (regexChar === "/" && !inCharacterClass) {
1041
+ cursor++;
1042
+ while (/[$_\p{ID_Continue}]/u.test(code[cursor] || "")) cursor++;
1043
+ closed = true;
1044
+ break;
1045
+ }
1046
+ }
1047
+ if (closed) {
1048
+ mask(start, cursor);
1049
+ index = cursor;
1050
+ canStartRegex = false;
1051
+ continue;
1052
+ }
1053
+ }
1054
+ if (/[$_\p{ID_Start}]/u.test(char)) {
1055
+ const start = index++;
1056
+ while (/[$_\u200C\u200D\p{ID_Continue}]/u.test(code[index] || "")) index++;
1057
+ canStartRegex = REGEX_PREFIX_KEYWORDS.has(code.slice(start, index));
1058
+ continue;
1059
+ }
1060
+ if (/\d/.test(char)) {
1061
+ index++;
1062
+ while (/[\w.]/.test(code[index] || "")) index++;
1063
+ canStartRegex = false;
1064
+ continue;
1065
+ }
1066
+ if ((char === "+" || char === "-") && next === char) {
1067
+ index += 2;
1068
+ continue;
1069
+ }
1070
+ if (char === "!" && next !== "=") {
1071
+ index++;
1072
+ continue;
1073
+ }
1074
+ if (char === ")" || char === "]" || char === "}") canStartRegex = false;
1075
+ else if (char !== ".") canStartRegex = true;
1076
+ index++;
1077
+ }
1078
+ return positions;
1079
+ }
1080
+ //#endregion
942
1081
  //#region src/utils/treeShaking.ts
943
1082
  /**
944
1083
  * Analysis is scoped by both the configured share key and the concrete module
@@ -1241,17 +1380,30 @@ function getPackageEsmEntryPath(pkg) {
1241
1380
  resolveSubpathWithRequire: false
1242
1381
  }) || resolvePackageEntryFromProjectRoot(pkg);
1243
1382
  }
1244
- function getEsmNamedExportsFromFile(entryPath) {
1383
+ function hasCodeMatch(source, regex, codePositions) {
1384
+ regex.lastIndex = 0;
1385
+ let match;
1386
+ while ((match = regex.exec(source)) !== null) if (codePositions[match.index]) return true;
1387
+ return false;
1388
+ }
1389
+ function hasCommonJsExports(source) {
1390
+ return hasCodeMatch(source, /\bmodule\s*(?:\.exports|\[\s*['"]exports['"]\s*\])|\bexports\s*(?:\.|\[|[,)]|=(?!=|>))/g, createCodePositionMap(source));
1391
+ }
1392
+ function inspectSharedExportsFromFile(entryPath) {
1245
1393
  try {
1246
- if (!entryPath) return [];
1247
- return getNamedExportsViaRegex(readFileSync(entryPath, "utf-8"), entryPath);
1394
+ if (!entryPath) return void 0;
1395
+ const source = readFileSync(entryPath, "utf-8");
1396
+ const scanState = { complete: true };
1397
+ const namedExports = getNamedExportsViaRegex(source, entryPath, void 0, scanState);
1398
+ const commonJs = hasCommonJsExports(source);
1399
+ return {
1400
+ namedExports: scanState.complete && !commonJs ? namedExports : void 0,
1401
+ commonJs
1402
+ };
1248
1403
  } catch {
1249
- return [];
1404
+ return;
1250
1405
  }
1251
1406
  }
1252
- function getEsmNamedExports(pkg) {
1253
- return getEsmNamedExportsFromFile(getPackageEsmEntryPath(pkg));
1254
- }
1255
1407
  function resolveConfiguredImportPath(importSource) {
1256
1408
  if (path$1.isAbsolute(importSource)) return resolveFileLikeModule(importSource);
1257
1409
  const projectRoot = getPackageDetectionCwd();
@@ -1332,19 +1484,156 @@ function resolveReExportModule(filePath, specifier) {
1332
1484
  return;
1333
1485
  }
1334
1486
  }
1335
- function getNamedExportsViaRegex(source, filePath, visited) {
1487
+ function hasTopLevelDeclaratorComma(source, start) {
1488
+ let depth = 0;
1489
+ let quote;
1490
+ let escaped = false;
1491
+ let canStartRegex = true;
1492
+ for (let index = start; index < source.length; index++) {
1493
+ const char = source[index];
1494
+ if (quote) {
1495
+ if (escaped) escaped = false;
1496
+ else if (char === "\\") escaped = true;
1497
+ else if (char === quote) quote = void 0;
1498
+ continue;
1499
+ }
1500
+ if (char === "\"" || char === "'" || char === "`") {
1501
+ quote = char;
1502
+ canStartRegex = false;
1503
+ continue;
1504
+ }
1505
+ if (char === "/" && source[index + 1] === "/") {
1506
+ index = source.indexOf("\n", index + 2);
1507
+ if (index === -1) return false;
1508
+ continue;
1509
+ }
1510
+ if (char === "/" && source[index + 1] === "*") {
1511
+ const commentEnd = source.indexOf("*/", index + 2);
1512
+ if (commentEnd === -1) return true;
1513
+ index = commentEnd + 1;
1514
+ continue;
1515
+ }
1516
+ if (char === "/" && canStartRegex) {
1517
+ let regexEscaped = false;
1518
+ let inCharacterClass = false;
1519
+ let closed = false;
1520
+ for (index++; index < source.length; index++) {
1521
+ const regexChar = source[index];
1522
+ if (regexEscaped) {
1523
+ regexEscaped = false;
1524
+ continue;
1525
+ }
1526
+ if (regexChar === "\\") {
1527
+ regexEscaped = true;
1528
+ continue;
1529
+ }
1530
+ if (regexChar === "[") {
1531
+ inCharacterClass = true;
1532
+ continue;
1533
+ }
1534
+ if (regexChar === "]" && inCharacterClass) {
1535
+ inCharacterClass = false;
1536
+ continue;
1537
+ }
1538
+ if (regexChar === "/" && !inCharacterClass) {
1539
+ closed = true;
1540
+ while (/[$_\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
1541
+ break;
1542
+ }
1543
+ if (regexChar === "\n" || regexChar === "\r") return true;
1544
+ }
1545
+ if (!closed) return true;
1546
+ canStartRegex = false;
1547
+ continue;
1548
+ }
1549
+ if (char === "/") {
1550
+ canStartRegex = true;
1551
+ continue;
1552
+ }
1553
+ if (/[$_\p{ID_Start}]/u.test(char)) {
1554
+ const tokenStart = index;
1555
+ while (/[$_\u200C\u200D\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
1556
+ const token = source.slice(tokenStart, index + 1);
1557
+ canStartRegex = /^(?:await|case|delete|in|instanceof|new|return|throw|typeof|void|yield)$/.test(token);
1558
+ continue;
1559
+ }
1560
+ if (/\d/.test(char)) {
1561
+ while (/[\w.]/.test(source[index + 1] || "")) index++;
1562
+ canStartRegex = false;
1563
+ continue;
1564
+ }
1565
+ if ((char === "+" || char === "-") && source[index + 1] === char) {
1566
+ index++;
1567
+ continue;
1568
+ }
1569
+ if (char === "!" && source[index + 1] !== "=") continue;
1570
+ if (char === "(" || char === "[" || char === "{") {
1571
+ depth++;
1572
+ canStartRegex = true;
1573
+ continue;
1574
+ }
1575
+ if (char === ")" || char === "]" || char === "}") {
1576
+ depth = Math.max(0, depth - 1);
1577
+ canStartRegex = false;
1578
+ continue;
1579
+ }
1580
+ if (depth === 0 && char === ",") return true;
1581
+ if (depth === 0 && char === ";") return false;
1582
+ if (!/\s/.test(char)) canStartRegex = char !== ".";
1583
+ }
1584
+ return false;
1585
+ }
1586
+ function hasUnsupportedBindingPattern(source, start) {
1587
+ const opening = source[start];
1588
+ if (opening !== "{" && opening !== "[") return false;
1589
+ let depth = 0;
1590
+ for (let index = start; index < source.length; index++) {
1591
+ const char = source[index];
1592
+ if (char === "\"" || char === "'" || char === "`") return true;
1593
+ if (char === "(" || char === "/" || char === ":" && opening === "[") return true;
1594
+ if (char === "{" || char === "[") {
1595
+ depth++;
1596
+ if (depth > 1) return true;
1597
+ continue;
1598
+ }
1599
+ if (char === "}" || char === "]") {
1600
+ depth--;
1601
+ if (depth === 0) {
1602
+ let next = index + 1;
1603
+ while (/\s/.test(source[next] || "")) next++;
1604
+ return source[next] !== "=";
1605
+ }
1606
+ }
1607
+ }
1608
+ return true;
1609
+ }
1610
+ function getNamedExportsViaRegex(source, filePath, visited, scanState = { complete: true }) {
1336
1611
  const names = /* @__PURE__ */ new Set();
1612
+ const codePositions = createCodePositionMap(source);
1613
+ const recognizedExportStarts = /* @__PURE__ */ new Set();
1337
1614
  visited = visited || /* @__PURE__ */ new Set();
1338
1615
  if (filePath) visited.add(filePath);
1339
- const declRegex = new RegExp(`export\\s+(?:async\\s+)?(?:function(?:\\*\\s*|\\s+\\*?\\s*)|const\\s+|let\\s+|var\\s+|class\\s+|enum\\s+|namespace\\s+)(${JS_IDENTIFIER_PATTERN})`, "gu");
1616
+ const declRegex = new RegExp(`export\\s+(?:async\\s+)?(?:function(?:\\*\\s*|\\s+\\*?\\s*)|const\\s+enum\\s+|const\\s+|let\\s+|var\\s+|class\\s+|abstract\\s+class\\s+|enum\\s+|namespace\\s+|module\\s+)(${JS_IDENTIFIER_PATTERN})`, "gu");
1340
1617
  let match;
1341
1618
  while ((match = declRegex.exec(source)) !== null) {
1619
+ if (!codePositions[match.index]) continue;
1620
+ recognizedExportStarts.add(match.index);
1342
1621
  const name = match[1];
1343
1622
  if (isValidEsmExportName(name)) names.add(name);
1344
1623
  }
1624
+ const exportedVariableDeclarationRegex = /export\s+(?:const|let|var)\s+/g;
1625
+ while ((match = exportedVariableDeclarationRegex.exec(source)) !== null) {
1626
+ if (!codePositions[match.index]) continue;
1627
+ if (hasTopLevelDeclaratorComma(source, exportedVariableDeclarationRegex.lastIndex)) scanState.complete = false;
1628
+ if (hasUnsupportedBindingPattern(source, exportedVariableDeclarationRegex.lastIndex)) scanState.complete = false;
1629
+ }
1630
+ if (hasCodeMatch(source, /export\s+import\s+/g, codePositions) || hasCodeMatch(source, /export\s*=/g, codePositions)) scanState.complete = false;
1631
+ if (hasCodeMatch(source, /export\s+@/g, codePositions)) scanState.complete = false;
1345
1632
  const destructureRegex = /export\s+(?:const|let|var)\s+(\{[^}]*\}|\[[^\]]*\])\s*=/g;
1346
1633
  const bindingNameRegex = new RegExp(`^(${JS_IDENTIFIER_PATTERN})`, "u");
1347
1634
  while ((match = destructureRegex.exec(source)) !== null) {
1635
+ if (!codePositions[match.index]) continue;
1636
+ recognizedExportStarts.add(match.index);
1348
1637
  const inner = match[1].slice(1, -1);
1349
1638
  for (const part of inner.split(",")) {
1350
1639
  let token = part.split("=")[0].trim();
@@ -1359,45 +1648,109 @@ function getNamedExportsViaRegex(source, filePath, visited) {
1359
1648
  const typeOnlySpecifierRegex = new RegExp(`^type\\s+${JS_IDENTIFIER_PATTERN}(?:\\s+as\\s+${JS_IDENTIFIER_PATTERN})?$`, "u");
1360
1649
  const exportSpecifierRegex = new RegExp(`(?:\\S+\\s+as\\s+)?(${JS_IDENTIFIER_PATTERN})$`, "u");
1361
1650
  while ((match = listRegex.exec(source)) !== null) {
1651
+ if (!codePositions[match.index]) continue;
1652
+ recognizedExportStarts.add(match.index);
1362
1653
  const specifiers = match[1].split(",");
1363
1654
  for (const specifier of specifiers) {
1364
1655
  const trimmed = specifier.trim();
1365
1656
  if (typeOnlySpecifierRegex.test(trimmed)) continue;
1366
1657
  const asMatch = trimmed.match(exportSpecifierRegex);
1367
- if (!asMatch) continue;
1658
+ if (!asMatch) {
1659
+ scanState.complete = false;
1660
+ continue;
1661
+ }
1368
1662
  const name = asMatch[1];
1369
1663
  if (isValidEsmExportName(name)) names.add(name);
1664
+ else scanState.complete = false;
1370
1665
  }
1371
1666
  }
1372
1667
  const namespaceReExportRegex = new RegExp(`export\\s+\\*\\s+as\\s+(${JS_IDENTIFIER_PATTERN})\\s+from\\s+['"][^'"]+['"]`, "gu");
1373
- while ((match = namespaceReExportRegex.exec(source)) !== null) if (isValidEsmExportName(match[1])) names.add(match[1]);
1668
+ while ((match = namespaceReExportRegex.exec(source)) !== null) {
1669
+ if (!codePositions[match.index]) continue;
1670
+ recognizedExportStarts.add(match.index);
1671
+ if (isValidEsmExportName(match[1])) names.add(match[1]);
1672
+ }
1673
+ if (hasCodeMatch(source, /export\s+\*\s+as\s+['"]/g, codePositions)) scanState.complete = false;
1374
1674
  if (filePath) {
1375
1675
  const starExportRegex = /export\s+\*\s+from\s+['"]([^'"]+)['"]/g;
1376
1676
  while ((match = starExportRegex.exec(source)) !== null) {
1677
+ if (!codePositions[match.index]) continue;
1678
+ recognizedExportStarts.add(match.index);
1377
1679
  const specifier = match[1];
1378
1680
  const resolvedPath = resolveReExportModule(filePath, specifier);
1379
- if (!resolvedPath || visited.has(resolvedPath)) continue;
1681
+ if (!resolvedPath) {
1682
+ scanState.complete = false;
1683
+ continue;
1684
+ }
1685
+ if (visited.has(resolvedPath)) continue;
1686
+ if (path$1.extname(resolvedPath) === ".cjs") {
1687
+ scanState.complete = false;
1688
+ continue;
1689
+ }
1380
1690
  try {
1381
- const reExportNames = getNamedExportsViaRegex(readFileSync(resolvedPath, "utf-8"), resolvedPath, visited);
1691
+ const reExportSource = readFileSync(resolvedPath, "utf-8");
1692
+ if (hasCommonJsExports(reExportSource)) {
1693
+ scanState.complete = false;
1694
+ continue;
1695
+ }
1696
+ const reExportNames = getNamedExportsViaRegex(reExportSource, resolvedPath, visited, scanState);
1382
1697
  for (const name of reExportNames) names.add(name);
1383
- } catch {}
1698
+ } catch {
1699
+ scanState.complete = false;
1700
+ }
1701
+ }
1702
+ }
1703
+ const noNamedExportRegex = /export(?:\s+default\b|\s*\{\s*\}|\s+(?:type|interface|declare)\b)/g;
1704
+ while ((match = noNamedExportRegex.exec(source)) !== null) {
1705
+ if (!codePositions[match.index]) continue;
1706
+ recognizedExportStarts.add(match.index);
1707
+ }
1708
+ const exportKeywordRegex = /\bexport\b/g;
1709
+ while ((match = exportKeywordRegex.exec(source)) !== null) {
1710
+ if (!codePositions[match.index]) continue;
1711
+ if (!recognizedExportStarts.has(match.index)) {
1712
+ scanState.complete = false;
1713
+ break;
1384
1714
  }
1385
1715
  }
1386
1716
  return Array.from(names);
1387
1717
  }
1388
- function getPackageNamedExports(pkg) {
1718
+ function getRequiredNamedExports(specifier) {
1389
1719
  try {
1390
- const mod = createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json")))(pkg);
1391
- return Object.keys(mod).filter((k) => isValidEsmExportName(k));
1720
+ const mod = createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json")))(specifier);
1721
+ const runtimeNamedKeys = Object.keys(mod).filter((key) => key !== "default" && key !== "__esModule");
1722
+ if (runtimeNamedKeys.some((key) => !isValidEsmExportName(key))) return void 0;
1723
+ return runtimeNamedKeys;
1392
1724
  } catch {
1393
- return getEsmNamedExports(pkg);
1725
+ return;
1394
1726
  }
1395
1727
  }
1728
+ function getPackageNamedExports(pkg) {
1729
+ const esmEntryPath = getInstalledPackageEntry(pkg, {
1730
+ conditions: [
1731
+ "browser",
1732
+ "import",
1733
+ "module",
1734
+ "default"
1735
+ ],
1736
+ resolveSubpathWithRequire: false
1737
+ });
1738
+ if (esmEntryPath) {
1739
+ const inspection = inspectSharedExportsFromFile(esmEntryPath);
1740
+ if (!inspection || inspection.commonJs || path$1.extname(esmEntryPath) === ".cjs") return getRequiredNamedExports(esmEntryPath);
1741
+ if (inspection.namedExports !== void 0) return inspection.namedExports;
1742
+ return;
1743
+ }
1744
+ return getRequiredNamedExports(pkg);
1745
+ }
1396
1746
  function getSharedNamedExports(pkg, shareItem) {
1397
1747
  const configuredImport = shareItem?.shareConfig.import;
1398
1748
  if (typeof configuredImport === "string") {
1399
- const configuredNamedExports = getEsmNamedExportsFromFile(resolveConfiguredImportPath(configuredImport));
1400
- if (configuredNamedExports.length > 0) return configuredNamedExports;
1749
+ const configuredImportPath = resolveConfiguredImportPath(configuredImport);
1750
+ const inspection = inspectSharedExportsFromFile(configuredImportPath);
1751
+ if (configuredImportPath && (inspection?.commonJs || path$1.extname(configuredImportPath) === ".cjs")) return getRequiredNamedExports(configuredImportPath);
1752
+ if (inspection?.namedExports !== void 0) return inspection.namedExports;
1753
+ return;
1401
1754
  }
1402
1755
  return getPackageNamedExports(pkg);
1403
1756
  }
@@ -1689,7 +2042,7 @@ function writePreBuildLibPath(pkg, shareItem) {
1689
2042
  `, true);
1690
2043
  return;
1691
2044
  }
1692
- const namedExports = getSharedNamedExports(pkg, shareItem);
2045
+ const namedExports = getSharedNamedExports(pkg, shareItem) ?? [];
1693
2046
  if (namedExports.length > 0) {
1694
2047
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1695
2048
  const declarations = namedExports.map((name, i) => `const ${namedExportVars[i]} = __mfPrebuildExports[${escapeGeneratedStringLiteral(name)}];`).join("\n ");
@@ -1768,35 +2121,41 @@ function materializeCachedLoadShareModule(options) {
1768
2121
  function getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer) {
1769
2122
  return treeShakingConsumer ? `__mfReadTreeShakingSharedSelection(__mfModuleCache.share, ${cacheDescriptor}, ${JSON.stringify(treeShakingConsumer)})` : `__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor})`;
1770
2123
  }
1771
- function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, treeShakingConsumer) {
2124
+ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer) {
1772
2125
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1773
- const namedExportAssignments = namedExports.length > 0 ? `\n ${namedExports.map((name, i) => `const ${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`).join("\n ")}` : "";
2126
+ const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
2127
+ const assignments = [...namedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = mod.default ?? mod;"].join("\n ");
1774
2128
  const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1775
2129
  return `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(importSource)};
1776
2130
  let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1777
2131
  if (exportModule === undefined) {
1778
2132
  Promise.resolve().then(() => {
1779
2133
  if (__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor}) === undefined) {
1780
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfNormalizeShareModule(__mfLocalShare));
2134
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfNormalizeShareModule(__mfLocalShare), ${cacheOwner});
1781
2135
  }
1782
2136
  });
1783
2137
  exportModule = __mfLocalShare;
1784
2138
  }
1785
- const __mf_default = exportModule.default ?? exportModule;${namedExportAssignments}
2139
+ ${declarations}
2140
+ const __mfApplyEagerShareExports = (mod) => {
2141
+ ${assignments}
2142
+ };
2143
+ __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyEagerShareExports);
2144
+ __mfApplyEagerShareExports(exportModule);
1786
2145
  export { __mf_default as default };${namedExportLine}`;
1787
2146
  }
1788
- function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, treeShakingConsumer) {
2147
+ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer) {
1789
2148
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1790
2149
  const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
1791
2150
  const assignments = namedExports.length > 0 ? [...namedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = mod.default ?? mod;"].join("\n ") : "__mf_default = mod.default ?? mod;";
1792
2151
  const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1793
2152
  const applyLocalFallback = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1794
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1795
- __mfApplyLazyShareExports(exportModule);`;
2153
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
1796
2154
  return `${declarations}
1797
2155
  const __mfApplyLazyShareExports = (mod) => {
1798
2156
  ${assignments}
1799
2157
  };
2158
+ __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyLazyShareExports);
1800
2159
  let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1801
2160
  if (exportModule === undefined) {
1802
2161
  if (import.meta.env.SSR) {
@@ -1810,8 +2169,7 @@ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cache
1810
2169
  }
1811
2170
  return import(${escapeGeneratedStringLiteral(importSource)}).then((mod) => {
1812
2171
  exportModule = __mfNormalizeShareModule(mod);
1813
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1814
- __mfApplyLazyShareExports(exportModule);
2172
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
1815
2173
  });
1816
2174
  }));
1817
2175
  }
@@ -1874,13 +2232,15 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1874
2232
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".js");
1875
2233
  let importLine = getRuntimeModuleCacheBootstrapCode();
1876
2234
  const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
2235
+ const cacheOwner = JSON.stringify(getNormalizeModuleFederationOptions().name);
1877
2236
  const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ? getNormalizeModuleFederationOptions().name : void 0;
1878
2237
  if (shareItem.shareConfig.import === false) {
1879
- const namedExports = getPackageNamedExports(pkg);
2238
+ const detectedNamedExports = getPackageNamedExports(pkg);
2239
+ const namedExports = detectedNamedExports ?? [];
1880
2240
  let exportLine;
1881
2241
  if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer);
1882
2242
  else {
1883
- mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
2243
+ if (detectedNamedExports === void 0) mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
1884
2244
  exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor, treeShakingConsumer);
1885
2245
  }
1886
2246
  loadShareCacheMap[pkg].writeSync(`
@@ -1895,26 +2255,59 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1895
2255
  const sharedImportSource = concreteSharedImportSource || getPreBuildLibImportId(pkg);
1896
2256
  const devImportSource = concreteSharedImportSource || pkg;
1897
2257
  const localProviderPath = getLocalProviderImportPath(pkg);
2258
+ const coherentLocalSource = concreteSharedImportSource || localProviderPath || devImportSource;
1898
2259
  const isWorkspacePackage = isWorkspacePackageEntry(pkg, localProviderPath) || isWorkspacePackageEntry(pkg, concreteSharedImportSource);
1899
2260
  const lazyLocalFallbackSource = command !== "build" ? concreteSharedImportSource || localProviderPath || devImportSource : concreteSharedImportSource || localProviderPath || sharedImportSource;
1900
2261
  const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
2262
+ const detectedNamedExports = getSharedNamedExports(pkg, shareItem);
2263
+ const namedExports = detectedNamedExports ?? [];
2264
+ const hasCompleteExportCoverage = detectedNamedExports !== void 0;
1901
2265
  const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
1902
2266
  const isDefaultShareScope = shareItem.scope === void 0 || shareItem.scope === "default" || Array.isArray(shareItem.scope) && shareItem.scope[0] === "default";
1903
- const usesDeferredSingletonFallback = isWorkspaceSingleton || command !== "build" && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && !isDefaultShareScope;
2267
+ const usesDeferredSingletonFallback = hasCompleteExportCoverage && (isWorkspaceSingleton || command !== "build" && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && !isDefaultShareScope);
1904
2268
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg);
1905
- const usesEntryInjectedRemoteFallback = command !== "build" && !isWorkspaceSingleton && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && getNormalizeModuleFederationOptions().hostInitInjectLocation === "entry" && isConsumedByPeerSingleton;
1906
- const usesEagerWorkspaceFallback = isWorkspaceSingleton && isConsumedByPeerSingleton;
1907
- const usesDeferredTreeShakingFallback = Boolean(treeShakingConsumer);
1908
- const namedExports = getSharedNamedExports(pkg, shareItem);
2269
+ const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && command !== "build" && !isWorkspaceSingleton && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && getNormalizeModuleFederationOptions().hostInitInjectLocation === "entry" && isConsumedByPeerSingleton;
2270
+ const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && isConsumedByPeerSingleton;
2271
+ const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
1909
2272
  let exportLine;
1910
2273
  let initBlock = "";
1911
2274
  if (usesDeferredTreeShakingFallback) {
1912
2275
  importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
1913
- exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, treeShakingConsumer);
1914
- } else if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, treeShakingConsumer);
2276
+ exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer);
2277
+ } else if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer);
1915
2278
  else if (usesDeferredSingletonFallback) {
1916
2279
  importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
1917
- exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, treeShakingConsumer);
2280
+ exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer);
2281
+ } else if (detectedNamedExports === void 0) {
2282
+ exportLine = `const __mfDefaultExport = (() => {
2283
+ ${generateShareModuleUnwrapCode({
2284
+ source: "__mfLocalShare",
2285
+ preserveNamedExports: false,
2286
+ stopWithReturn: "defaultExport ?? current"
2287
+ })}
2288
+ })();
2289
+ export default __mfDefaultExport;
2290
+ export * from ${escapeGeneratedStringLiteral(coherentLocalSource)}`;
2291
+ initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
2292
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
2293
+ } else if (namedExports.length > 0 && shareItem.shareConfig.singleton === true) {
2294
+ const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
2295
+ exportLine = `${["let __mfDefaultExport;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ")}
2296
+ const __mfApplySharedExports = (mod) => {
2297
+ ${[...namedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), `__mfDefaultExport = (() => {
2298
+ ${generateShareModuleUnwrapCode({
2299
+ source: "mod",
2300
+ preserveNamedExports: false,
2301
+ stopWithReturn: "defaultExport ?? current"
2302
+ })}
2303
+ })();`].join("\n ")}
2304
+ };
2305
+ __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplySharedExports);
2306
+ __mfApplySharedExports(exportModule);
2307
+ export { __mfDefaultExport as default };
2308
+ ${`export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`}`;
2309
+ initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
2310
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
1918
2311
  } else if (namedExports.length > 0) {
1919
2312
  const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1920
2313
  const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
@@ -1929,13 +2322,24 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1929
2322
  ${destructure}
1930
2323
  ${namedExportLine}`;
1931
2324
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1932
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);`;
2325
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
2326
+ } else if (shareItem.shareConfig.singleton === true) {
2327
+ exportLine = `let __mfDefaultExport;
2328
+ const __mfApplySharedDefaultExport = (mod) => {
2329
+ __mfDefaultExport = mod.default ?? mod;
2330
+ };
2331
+ __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplySharedDefaultExport);
2332
+ __mfApplySharedDefaultExport(exportModule);
2333
+ export { __mfDefaultExport as default };
2334
+ export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
2335
+ initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
2336
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
1933
2337
  } else {
1934
2338
  exportLine = `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
1935
2339
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1936
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);`;
2340
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
1937
2341
  }
1938
- const prebuildImportLine = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
2342
+ const prebuildImportLine = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
1939
2343
  const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
1940
2344
  const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? `
1941
2345
  ${prebuildImportLine}
@@ -2021,12 +2425,15 @@ function generateLocalSharedImportMap() {
2021
2425
  ${getOrderedUsedShares().map((key) => {
2022
2426
  const shareItem = getNormalizeShareItem(key);
2023
2427
  if (!shareItem) return null;
2024
- const treeShakingUsage = getTreeShakingExportUsage(key, shareItem, shareItem.name);
2428
+ const detectedNamedExports = getSharedNamedExports(key, shareItem);
2429
+ const canLiveRebind = shareItem.shareConfig.import === false || detectedNamedExports !== void 0;
2430
+ const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
2431
+ const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name) : void 0;
2025
2432
  const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
2026
- const treeShakingUsedExports = options.injectTreeShakingUsedExports === false ? shareItem.shareConfig.treeShaking?.usedExports || [] : treeShakingProviderExports;
2027
- const disableRuntimeInference = shareItem.shareConfig.treeShaking?.mode === "runtime-infer" && options.injectTreeShakingUsedExports === false;
2028
- const treeShakingProviderImportId = !disableRuntimeInference && hasTreeShakingSharedProvider(key, shareItem) ? getTreeShakingSharedProviderImportId(key) : void 0;
2029
- const treeShakingStatus = treeShakingUsage?.kind === "full" || disableRuntimeInference || shareItem.shareConfig.treeShaking?.mode === "runtime-infer" && !treeShakingProviderImportId && shareItem.shareConfig.import !== false ? 0 : 1;
2433
+ const treeShakingUsedExports = options.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
2434
+ const disableRuntimeInference = treeShakingConfig?.mode === "runtime-infer" && options.injectTreeShakingUsedExports === false;
2435
+ const treeShakingProviderImportId = treeShakingConfig && !disableRuntimeInference && hasTreeShakingSharedProvider(key, shareItem) ? getTreeShakingSharedProviderImportId(key) : void 0;
2436
+ const treeShakingStatus = treeShakingUsage?.kind === "full" || disableRuntimeInference || treeShakingConfig?.mode === "runtime-infer" && !treeShakingProviderImportId && shareItem.shareConfig.import !== false ? 0 : 1;
2030
2437
  return `
2031
2438
  ${JSON.stringify(key)}: {
2032
2439
  name: ${JSON.stringify(key)},
@@ -2035,6 +2442,7 @@ function generateLocalSharedImportMap() {
2035
2442
  loaded: false,
2036
2443
  eager: ${Boolean(shareItem.shareConfig.eager)},
2037
2444
  from: ${JSON.stringify(options.name)},
2445
+ canLiveRebind: ${canLiveRebind},
2038
2446
  async get () {
2039
2447
  if (${shareItem.shareConfig.import === false}) {
2040
2448
  throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
@@ -2061,8 +2469,8 @@ function generateLocalSharedImportMap() {
2061
2469
  eager: ${Boolean(shareItem.shareConfig.eager)},
2062
2470
  ${shareItem.shareConfig.import === false ? "import: false," : ""}
2063
2471
  },
2064
- ${shareItem.shareConfig.treeShaking ? `treeShaking: {
2065
- mode: ${JSON.stringify(shareItem.shareConfig.treeShaking.mode)},
2472
+ ${treeShakingConfig ? `treeShaking: {
2473
+ mode: ${JSON.stringify(treeShakingConfig.mode)},
2066
2474
  usedExports: ${JSON.stringify(treeShakingUsedExports)},
2067
2475
  providedExports: ${JSON.stringify(treeShakingProviderExports)},
2068
2476
  status: ${treeShakingStatus},
@@ -2158,6 +2566,7 @@ function getShareItemForPreload(pkg) {
2158
2566
  }
2159
2567
  function generateSharedCacheSeedItem(pkg, shareItem, importPath) {
2160
2568
  const cacheDescriptor = getSharedCacheDescriptor(pkg, shareItem);
2569
+ const cacheOwner = getNormalizeModuleFederationOptions().name;
2161
2570
  return `if (__mfReadSharedCache(__mfModuleCache.share, ${JSON.stringify(cacheDescriptor)}) === undefined) {
2162
2571
  const mod = await import(${JSON.stringify(importPath)});
2163
2572
  ${normalizeRuntimeShareCode}
@@ -2167,7 +2576,7 @@ function generateSharedCacheSeedItem(pkg, shareItem, importPath) {
2167
2576
  value: true,
2168
2577
  enumerable: false
2169
2578
  });
2170
- __mfWriteSharedCache(__mfModuleCache.share, ${JSON.stringify(cacheDescriptor)}, exportModule);
2579
+ __mfWriteSharedCache(__mfModuleCache.share, ${JSON.stringify(cacheDescriptor)}, exportModule, ${JSON.stringify(cacheOwner)});
2171
2580
  }`;
2172
2581
  }
2173
2582
  const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
@@ -2188,15 +2597,33 @@ const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbo
2188
2597
  const selectionVersions = {};
2189
2598
  for (const [version, provider] of Object.entries(versions)) {
2190
2599
  selectionVersions[version] = Object.assign({}, provider, {
2191
- loaded: false,
2192
- loading: undefined,
2193
- lib: undefined,
2194
2600
  [__mfOriginalProviderKey]: provider
2195
2601
  });
2196
2602
  }
2197
2603
  return selectionVersions;
2198
2604
  };
2199
- const __mfSelectSharedProvider = (versions, pkg, share, strategy) => {
2605
+ const __mfFindSharedProviderEntry = (versions, provider) => {
2606
+ if (!provider) return undefined;
2607
+ const entries = Object.entries(versions || {});
2608
+ const registeredEntry = entries.find(([, candidate]) => candidate === provider);
2609
+ if (registeredEntry) {
2610
+ return { version: registeredEntry[0], provider, registered: true };
2611
+ }
2612
+ if (typeof provider.version === "string" && provider.version) {
2613
+ return { version: provider.version, provider, registered: false };
2614
+ }
2615
+ const provenanceEntries = entries.filter(([, candidate]) =>
2616
+ candidate === provider || Boolean(provider.from && candidate?.from === provider.from)
2617
+ );
2618
+ if (provenanceEntries.length !== 1) return undefined;
2619
+ return { version: provenanceEntries[0][0], provider, registered: false };
2620
+ };
2621
+ const __mfSelectSharedProvider = (
2622
+ versions,
2623
+ pkg,
2624
+ share,
2625
+ strategy
2626
+ ) => {
2200
2627
  if (!versions || !share) return undefined;
2201
2628
  const scopes = Array.isArray(share.scope) ? share.scope : [share.scope || "default"];
2202
2629
  const selectionVersions = __mfCreateProviderSelectionVersions(versions, strategy);
@@ -2212,10 +2639,103 @@ const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbo
2212
2639
  )?.shared;
2213
2640
  return selected?.[__mfOriginalProviderKey] || selected;
2214
2641
  };`;
2215
- function hasImportFalseShared$1(options) {
2216
- return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
2217
- }
2218
- function generateRuntimeSharedCacheSeedCode() {
2642
+ const externalSharedProviderSelectionHelperCode = `const __mfSelectExternalSharedProvider = (
2643
+ versions,
2644
+ pkg,
2645
+ localShare,
2646
+ strategy
2647
+ ) => {
2648
+ const isLocalProvider = (provider) => __mfMatchesSharedProvider(provider, localShare);
2649
+ const candidates = Object.fromEntries(
2650
+ Object.entries(versions || {}).filter(([, provider]) => !isLocalProvider(provider))
2651
+ );
2652
+ if (localShare?.version) {
2653
+ const sameVersionProvider = candidates[localShare.version];
2654
+ // Runtime registration keeps an existing same-version record,
2655
+ // even when it has only a getter and is not loaded yet. Model
2656
+ // that retained provider here so pre-init seeding cannot choose
2657
+ // the local module while loadShare() later chooses the parent.
2658
+ if (!sameVersionProvider) {
2659
+ candidates[localShare.version] = localShare;
2660
+ }
2661
+ }
2662
+ const provider = __mfSelectSharedProvider(
2663
+ candidates,
2664
+ pkg,
2665
+ localShare,
2666
+ strategy
2667
+ );
2668
+ return isLocalProvider(provider) ? undefined : provider;
2669
+ };
2670
+ const __mfMatchesSharedProvider = (provider, expected) => provider === expected || Boolean(
2671
+ expected?.from && provider?.from === expected.from
2672
+ );
2673
+ const __mfGetScopeRootProvider = (
2674
+ instances,
2675
+ scopeRoot,
2676
+ shared,
2677
+ scopeName,
2678
+ pkg,
2679
+ version,
2680
+ provider,
2681
+ passedProvider,
2682
+ strategy
2683
+ ) => {
2684
+ if (strategy !== "version-first" || !passedProvider) return undefined;
2685
+ const scopeRootProviders = scopeRoot?.options?.shared?.[pkg];
2686
+ const configuredScopeRootProvider = Array.isArray(scopeRootProviders)
2687
+ ? scopeRootProviders.find((candidate) => candidate?.version === version)
2688
+ : undefined;
2689
+ const registeredScopeRootProvider = passedProvider?.from === scopeRoot?.options?.name
2690
+ ? passedProvider
2691
+ : undefined;
2692
+ const scopeRootProvider = registeredScopeRootProvider || (
2693
+ __mfMatchesSharedProvider(configuredScopeRootProvider, passedProvider)
2694
+ ? configuredScopeRootProvider
2695
+ // A plain Webpack/Rspack host has no enhanced-runtime instance.
2696
+ // Its pre-init snapshot is still authoritative when this remote's
2697
+ // registration rewrites the same-version provider in-place.
2698
+ : scopeRoot ? undefined : passedProvider
2699
+ );
2700
+ if (!scopeRootProvider) return undefined;
2701
+ const selectedFromLaterInstance = instances.some((instance) =>
2702
+ instance !== scopeRoot &&
2703
+ instance?.options?.name === provider?.from &&
2704
+ instance?.shareScopeMap?.[scopeName] === shared
2705
+ );
2706
+ return selectedFromLaterInstance ? scopeRootProvider : undefined;
2707
+ };
2708
+ const __mfResolveExternalSharedProvider = (
2709
+ instances,
2710
+ scopeRoot,
2711
+ shared,
2712
+ scopeName,
2713
+ pkg,
2714
+ providerEntry,
2715
+ selectedExternalProvider,
2716
+ passedProvider,
2717
+ strategy
2718
+ ) => {
2719
+ const scopeRootProvider = providerEntry.registered ? __mfGetScopeRootProvider(
2720
+ instances,
2721
+ scopeRoot,
2722
+ shared,
2723
+ scopeName,
2724
+ pkg,
2725
+ providerEntry.version,
2726
+ providerEntry.provider,
2727
+ passedProvider,
2728
+ strategy
2729
+ ) : undefined;
2730
+ const provider = scopeRootProvider || selectedExternalProvider;
2731
+ if (!provider) return undefined;
2732
+ if (
2733
+ providerEntry.registered &&
2734
+ !__mfMatchesSharedProvider(provider, passedProvider)
2735
+ ) return undefined;
2736
+ return { provider, scopeRootProvider };
2737
+ };`;
2738
+ function generateRuntimeSharedCacheSeedCode(shareStrategy) {
2219
2739
  const seedOrder = getOrderedUsedShares();
2220
2740
  return `
2221
2741
  const __mfSeedOrder = ${JSON.stringify(seedOrder)};
@@ -2241,34 +2761,99 @@ function generateRuntimeSharedCacheSeedCode() {
2241
2761
  }
2242
2762
  __mfSeedKeys.splice(insertIndex, 0, pkg);
2243
2763
  }
2244
- for (const pkg of __mfSeedKeys) {
2245
- const share = usedShared[pkg];
2246
- const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2247
- if (
2248
- share.shareConfig?.import === false ||
2249
- Boolean(share.treeShaking) ||
2250
- __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined
2251
- ) {
2252
- continue;
2253
- }
2254
- const singletonCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, true, share.version, share.scope);
2255
- const singletonModule = __mfReadSharedCache(__mfModuleCache.share, singletonCacheDescriptor);
2256
- if (singletonModule !== undefined) {
2257
- __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, singletonModule);
2258
- continue;
2764
+ var __mfSeedLocalShared = async (seedKeys) => {
2765
+ for (const pkg of seedKeys) {
2766
+ const share = usedShared[pkg];
2767
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2768
+ if (
2769
+ share.shareConfig?.import === false ||
2770
+ Boolean(share.treeShaking) ||
2771
+ __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined
2772
+ ) {
2773
+ continue;
2774
+ }
2775
+ const singletonCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, true, share.version, share.scope);
2776
+ const singletonModule = __mfReadSharedCache(__mfModuleCache.share, singletonCacheDescriptor);
2777
+ if (singletonModule !== undefined) {
2778
+ __mfWriteSharedCache(
2779
+ __mfModuleCache.share,
2780
+ cacheDescriptor,
2781
+ singletonModule,
2782
+ __mfReadSharedCacheOwner(__mfModuleCache.share, singletonCacheDescriptor)
2783
+ );
2784
+ continue;
2785
+ }
2786
+ const factory = await share.get();
2787
+ const mod = typeof factory === "function" ? factory() : factory;
2788
+ const resolved = await Promise.resolve(mod);
2789
+ ${normalizeRuntimeShareCode}
2790
+ const normalizedModule = __mfNormalizeRuntimeShare(resolved);
2791
+ const exportModule = normalizedModule === resolved ? {...resolved} : normalizedModule;
2792
+ Object.defineProperty(exportModule, "__esModule", {
2793
+ value: true,
2794
+ enumerable: false
2795
+ });
2796
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, exportModule, mfName);
2259
2797
  }
2260
- const factory = await share.get();
2261
- const mod = typeof factory === "function" ? factory() : factory;
2262
- const resolved = await Promise.resolve(mod);
2263
- ${normalizeRuntimeShareCode}
2264
- const normalizedModule = __mfNormalizeRuntimeShare(resolved);
2265
- const exportModule = normalizedModule === resolved ? {...resolved} : normalizedModule;
2266
- Object.defineProperty(exportModule, "__esModule", {
2267
- value: true,
2268
- enumerable: false
2269
- });
2270
- __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, exportModule);
2271
- }`;
2798
+ };
2799
+ const __mfIsRuntimeOnlySharePending = (pkg) => {
2800
+ const share = usedShared[pkg];
2801
+ if (!share.treeShaking && share.shareConfig?.import !== false) return false;
2802
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(
2803
+ pkg,
2804
+ share.shareConfig?.singleton,
2805
+ share.version,
2806
+ share.scope
2807
+ );
2808
+ return share.treeShaking
2809
+ ? (
2810
+ __mfReadTreeShakingSharedSelection(
2811
+ __mfModuleCache.share,
2812
+ cacheDescriptor,
2813
+ mfName
2814
+ ) === undefined &&
2815
+ __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) === undefined
2816
+ )
2817
+ : __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) === undefined;
2818
+ };
2819
+ const __mfNeedsPreInitSeedBarrier = (pkg) => {
2820
+ const share = usedShared[pkg];
2821
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(
2822
+ pkg,
2823
+ share.shareConfig?.singleton,
2824
+ share.version,
2825
+ share.scope
2826
+ );
2827
+ const cachedShare = share.treeShaking
2828
+ ? (
2829
+ __mfReadTreeShakingSharedSelection(
2830
+ __mfModuleCache.share,
2831
+ cacheDescriptor,
2832
+ mfName
2833
+ ) ?? __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor)
2834
+ )
2835
+ : __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor);
2836
+ if (cachedShare !== undefined) return false;
2837
+ if (share.treeShaking || share.shareConfig?.import === false) return true;
2838
+ if (!share.shareConfig?.singleton) return false;
2839
+ if (typeof __mfSelectExternalSharedProvider !== 'function') return false;
2840
+ return Boolean(__mfSelectExternalSharedProvider(
2841
+ initialShared[pkg],
2842
+ pkg,
2843
+ share,
2844
+ ${JSON.stringify(shareStrategy)}
2845
+ ));
2846
+ };
2847
+ const __mfFirstRuntimeSeedBarrierIndex = __mfSeedKeys.findIndex(
2848
+ __mfNeedsPreInitSeedBarrier
2849
+ );
2850
+ const __mfImmediateSeedKeys = __mfFirstRuntimeSeedBarrierIndex === -1
2851
+ ? __mfSeedKeys
2852
+ : __mfSeedKeys.slice(0, __mfFirstRuntimeSeedBarrierIndex);
2853
+ var __mfDeferredSeedKeys = __mfFirstRuntimeSeedBarrierIndex === -1
2854
+ ? []
2855
+ : __mfSeedKeys.slice(__mfFirstRuntimeSeedBarrierIndex);
2856
+ await __mfSeedLocalShared(__mfImmediateSeedKeys);`;
2272
2857
  }
2273
2858
  function getBrowserImportPath(importPath) {
2274
2859
  if (/^(?:[a-zA-Z]:[\\/]|\/)/.test(importPath) && !importPath.startsWith("/@")) return `/@fs/${importPath}`;
@@ -2300,15 +2885,15 @@ const SSR_ONLY_PLUGIN_SPECIFIERS = new Set(["@module-federation/vite/ssrEntryLoa
2300
2885
  const isSsrOnlyPlugin = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].some((s) => importStatement.includes(s));
2301
2886
  const getSsrOnlyPluginSpecifier = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].find((s) => importStatement.includes(s));
2302
2887
  function generateTreeShakingSharedResolutionCode(enabled) {
2303
- if (!enabled) return "";
2888
+ if (!enabled) return "const __mfResolveTreeShakingShared = async () => {};";
2304
2889
  return `
2305
2890
  // Resolve tree-enabled shares through the Runtime after all providers have
2306
2891
  // registered. Partial providers are stored with their export coverage and
2307
2892
  // never occupy generic/legacy cache keys, which are reserved for complete
2308
2893
  // modules only.
2309
- for (const [pkg, share] of Object.entries(usedShared)) {
2894
+ const __mfResolveTreeShakingShared = async (pkg, share) => {
2310
2895
  const treeShaking = share.treeShaking;
2311
- if (!treeShaking) continue;
2896
+ if (!treeShaking) return;
2312
2897
  try {
2313
2898
  const factory = await initRes.loadShare(pkg, {
2314
2899
  customShareInfo: {
@@ -2320,22 +2905,21 @@ function generateTreeShakingSharedResolutionCode(enabled) {
2320
2905
  },
2321
2906
  },
2322
2907
  });
2323
- if (factory === false) continue;
2908
+ if (factory === false) return;
2324
2909
  const mod = typeof factory === "function" ? factory() : factory;
2325
2910
  const resolved = await Promise.resolve(mod);
2326
2911
  ${normalizeRuntimeShareCode}
2327
2912
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2328
2913
  const normalizedShared = __mfNormalizeRuntimeShare(resolved);
2914
+ const providedExports = treeShaking.providedExports ?? treeShaking.usedExports ?? [];
2329
2915
  const hasPartialProvider =
2330
- Array.isArray(treeShaking.providedExports) &&
2331
- treeShaking.providedExports.length > 0 &&
2332
2916
  ((treeShaking.mode === "runtime-infer" && treeShaking.status !== 0) ||
2333
2917
  treeShaking.status === 2);
2334
2918
  if (hasPartialProvider) {
2335
2919
  __mfWriteTreeShakingSharedCache(
2336
2920
  __mfModuleCache.share,
2337
2921
  cacheDescriptor,
2338
- treeShaking.providedExports,
2922
+ providedExports,
2339
2923
  normalizedShared
2340
2924
  );
2341
2925
  __mfWriteTreeShakingSharedSelection(
@@ -2350,18 +2934,18 @@ function generateTreeShakingSharedResolutionCode(enabled) {
2350
2934
  } catch (e) {
2351
2935
  console.warn('[Module Federation] Failed to load tree-shaken shared module', pkg, e);
2352
2936
  }
2353
- }`;
2937
+ };`;
2354
2938
  }
2355
- const treeShakingResolveShareBodyCode = `const originalResolver = args.resolver;
2939
+ const treeShakingResolveShareBodyCode = `const consumerTreeShaking = args.shareInfo?.treeShaking;
2940
+ if (consumerTreeShaking?.mode !== "runtime-infer") return args;
2941
+ const requiredExports = consumerTreeShaking.usedExports;
2942
+ if (!Array.isArray(requiredExports)) return args;
2943
+
2944
+ const originalResolver = args.resolver;
2356
2945
  args.resolver = () => {
2357
2946
  const resolved = originalResolver();
2358
2947
  if (!resolved?.useTreesShaking) return resolved;
2359
2948
 
2360
- const consumerTreeShaking = args.shareInfo?.treeShaking;
2361
- if (consumerTreeShaking?.mode !== "runtime-infer") return resolved;
2362
- const requiredExports = consumerTreeShaking.usedExports;
2363
- if (!Array.isArray(requiredExports)) return resolved;
2364
-
2365
2949
  const selectedExports = resolved.shared?.treeShaking?.usedExports;
2366
2950
  const selectedMatches = Array.isArray(selectedExports) &&
2367
2951
  requiredExports.every((name) => selectedExports.includes(name));
@@ -2460,7 +3044,7 @@ function generateTreeShakingSnapshotPluginCode(enabled) {
2460
3044
  });`;
2461
3045
  }
2462
3046
  function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
2463
- const needsSharedProviderSelectionHelper = hasImportFalseShared$1(options);
3047
+ const needsSharedProviderSelectionHelper = Object.keys(options.shared ?? {}).length > 0;
2464
3048
  const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
2465
3049
  const hasEagerShared = Object.values(options.shared ?? {}).some((share) => share?.shareConfig.eager === true && share.shareConfig.import !== false);
2466
3050
  const runtimeImports = [
@@ -2481,6 +3065,17 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
2481
3065
  serializeRuntimeOptions(p[1])
2482
3066
  ];
2483
3067
  });
3068
+ const initializeSharingCode = `try {
3069
+ await retrySharedInit(async () => {
3070
+ await Promise.all(await initRes.initializeSharing('${options.shareScope}', {
3071
+ strategy: '${options.shareStrategy}',
3072
+ from: "build",
3073
+ initScope
3074
+ }));
3075
+ });
3076
+ } catch (e) {
3077
+ console.error('[Module Federation]', e)
3078
+ }`;
2484
3079
  return `
2485
3080
  // Shim Vue HMR runtime for dev-compiled components loaded by a non-Vite host.
2486
3081
  // When a remote is served by a Vite dev server, Vue's SFC compiler injects HMR
@@ -2522,6 +3117,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
2522
3117
  }
2523
3118
  ${generateTreeShakingSnapshotPluginCode(hasTreeShakingShared)}
2524
3119
  ${needsSharedProviderSelectionHelper ? sharedProviderSelectionHelperCode : ""}
3120
+ ${needsSharedProviderSelectionHelper ? externalSharedProviderSelectionHelperCode : ""}
2525
3121
 
2526
3122
  async function getLocalSharedImportMap() {
2527
3123
  ${hasEagerShared ? "return __mfLocalSharedImportMap;" : ""}
@@ -2543,53 +3139,32 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
2543
3139
 
2544
3140
  async function init(shared = {}, initScope = []) {
2545
3141
  ${sharedCacheHelperCode}
2546
- const {usedShared, usedRemotes} = await getLocalSharedImportMap()
2547
- try {
2548
- const allInstances = globalThis.__FEDERATION__?.__SHARE__;
2549
- if (allInstances) {
2550
- ${normalizeRuntimeShareCode}
2551
- for (const [, scopes] of Object.entries(allInstances)) {
2552
- const scopeShare = scopes?.['${options.shareScope}'];
2553
- if (!scopeShare) continue;
2554
- for (const [pkg, versionMap] of Object.entries(scopeShare)) {
2555
- const usedShare = usedShared?.[pkg];
2556
- const selectedProvider = usedShare?.shareConfig?.import === false
2557
- ? __mfSelectSharedProvider(versionMap, pkg, usedShare, '${options.shareStrategy}')
2558
- : undefined;
2559
- const providerEntries = usedShare?.shareConfig?.import === false
2560
- ? Object.entries(versionMap).filter(([, provider]) => provider === selectedProvider)
2561
- : Object.entries(versionMap);
2562
- for (const [version, provider] of providerEntries) {
2563
- if (!provider.lib) continue;
2564
- const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, provider.shareConfig?.singleton, version, ${JSON.stringify(options.shareScope)});
2565
- if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) continue;
2566
- const mod = typeof provider.lib === "function" ? provider.lib() : provider.lib;
2567
- const resolved = await Promise.resolve(mod);
2568
- const normalized = __mfNormalizeRuntimeShare(resolved);
2569
- __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, normalized);
2570
- if (provider.shareConfig?.singleton && usedShare) {
2571
- const usedCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, usedShare.shareConfig?.singleton, usedShare.version, usedShare.scope);
2572
- if (__mfReadSharedCache(__mfModuleCache.share, usedCacheDescriptor) === undefined) {
2573
- __mfWriteSharedCache(__mfModuleCache.share, usedCacheDescriptor, normalized);
2574
- }
2575
- }
2576
- }
2577
- }
2578
- }
2579
- }
2580
- } catch (e) {
2581
- console.error('[Module Federation] Failed to bridge external shared modules', e)
2582
- }
2583
- for (const [pkg, share] of Object.entries(usedShared)) {
2584
- const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2585
- if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) continue;
2586
- const singletonCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, true, share.version, share.scope);
2587
- const singletonModule = __mfReadSharedCache(__mfModuleCache.share, singletonCacheDescriptor);
2588
- if (singletonModule !== undefined) {
2589
- __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, singletonModule);
3142
+ const federationInstances = globalThis.__FEDERATION__?.__INSTANCES__ || [];
3143
+ const initRootName = initScope.find((token) => token?.from)?.from;
3144
+ const scopeRoot = federationInstances.find((instance) =>
3145
+ instance?.options?.name === initRootName &&
3146
+ instance?.shareScopeMap?.['${options.shareScope}'] === shared
3147
+ ) || federationInstances.find((instance) =>
3148
+ instance?.options?.name !== mfName &&
3149
+ instance?.shareScopeMap?.['${options.shareScope}'] === shared
3150
+ );
3151
+ const initialShared = Object.create(null);
3152
+ for (const [pkg, versions] of Object.entries(shared)) {
3153
+ const initialVersions = initialShared[pkg] = Object.create(null);
3154
+ for (const [version, provider] of Object.entries(versions)) {
3155
+ // Runtime registration mutates provider records in-place, notably their origin.
3156
+ // Preserve the parent-visible provider and its original provenance.
3157
+ initialVersions[version] = Object.assign({}, provider);
2590
3158
  }
2591
3159
  }
2592
- ${generateRuntimeSharedCacheSeedCode()}
3160
+ const {usedShared, usedRemotes} = await getLocalSharedImportMap()
3161
+ // handling circular init calls before an external provider can re-enter this container
3162
+ var initToken = initTokens[shareScopeName];
3163
+ if (!initToken)
3164
+ initToken = initTokens[shareScopeName] = { from: mfName };
3165
+ if (initScope.indexOf(initToken) >= 0) return;
3166
+ initScope.push(initToken);
3167
+ ${normalizeRuntimeShareCode}
2593
3168
  const __browserPlugins = [${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => `${item[0]}(${item[2]})`).join(", ")}];
2594
3169
  const __ssrPlugins = typeof globalThis.window === 'undefined'
2595
3170
  ? await Promise.all([${pluginImportNames.filter((item) => isSsrOnlyPlugin(item[1])).map((item) => {
@@ -2598,46 +3173,592 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
2598
3173
  return `import(${JSON.stringify(specifier)}).then(m => (m.default ?? m)(${opts}))`;
2599
3174
  }).join(", ")}])
2600
3175
  : [];
3176
+ const __mfRuntimeShareLoadIdKey = "__mf_vite_runtime_share_load_id__";
3177
+ let __mfRuntimeShareLoadId = 0;
3178
+ const __mfRuntimeShareSelections = new Map();
3179
+ const __mfRuntimeShareLifecycles = new Map();
2601
3180
  const initRes = runtimeInit({
2602
3181
  name: mfName,
2603
3182
  remotes: ${options.shareStrategy === "loaded-first" ? "[]" : "usedRemotes"},
2604
3183
  shared: usedShared,
2605
- plugins: [${hasTreeShakingShared ? "__mfTreeShakingSnapshotPlugin()," : ""} ...__browserPlugins, ...__ssrPlugins],
3184
+ plugins: [__mfSharePinLifecyclePlugin(), ${hasTreeShakingShared ? "__mfTreeShakingSnapshotPlugin()," : ""} ...__browserPlugins, ...__ssrPlugins],
2606
3185
  ${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
2607
3186
  });
2608
- // handling circular init calls
2609
- var initToken = initTokens[shareScopeName];
2610
- if (!initToken)
2611
- initToken = initTokens[shareScopeName] = { from: mfName };
2612
- if (initScope.indexOf(initToken) >= 0) return;
2613
- initScope.push(initToken);
2614
3187
  initRes.initShareScopeMap('${options.shareScope}', shared);
2615
- try {
2616
- await retrySharedInit(async () => {
2617
- await Promise.all(await initRes.initializeSharing('${options.shareScope}', {
2618
- strategy: '${options.shareStrategy}',
2619
- from: "build",
2620
- initScope
2621
- }));
3188
+ function __mfSharePinLifecyclePlugin() {
3189
+ return {
3190
+ name: "vite-share-pin-lifecycle-plugin",
3191
+ resolveShare(args) {
3192
+ const loadId = args.shareInfo?.[__mfRuntimeShareLoadIdKey];
3193
+ const lifecycle = loadId === undefined
3194
+ ? undefined
3195
+ : __mfRuntimeShareLifecycles.get(loadId);
3196
+ if (!lifecycle) return args;
3197
+ const defaultResolver = args.resolver;
3198
+ args.resolver = (...resolverArgs) => {
3199
+ lifecycle.pinned.reapply();
3200
+ return defaultResolver(...resolverArgs);
3201
+ };
3202
+ lifecycle.pinned.reveal();
3203
+ return args;
3204
+ }
3205
+ };
3206
+ }
3207
+ const runtimeResolveShareHook = initRes.sharedHandler.hooks.lifecycle.resolveShare;
3208
+ const __mfRuntimeProviderOrigins = new WeakMap();
3209
+ runtimeResolveShareHook.on((args) => {
3210
+ const loadId = args.shareInfo?.[__mfRuntimeShareLoadIdKey];
3211
+ const resolver = args.resolver;
3212
+ if (typeof resolver !== "function") return args;
3213
+ const instrumentedResolver = (...resolverArgs) => {
3214
+ const resolved = resolver(...resolverArgs);
3215
+ const selectedProvider = resolved?.shared;
3216
+ if (
3217
+ selectedProvider &&
3218
+ (typeof selectedProvider === "object" || typeof selectedProvider === "function") &&
3219
+ !__mfRuntimeProviderOrigins.has(selectedProvider)
3220
+ ) {
3221
+ __mfRuntimeProviderOrigins.set(selectedProvider, { from: selectedProvider.from });
3222
+ }
3223
+ if (loadId !== undefined && selectedProvider) {
3224
+ __mfRuntimeShareSelections.set(loadId, selectedProvider);
3225
+ }
3226
+ return resolved;
3227
+ };
3228
+ args.resolver = instrumentedResolver;
3229
+ return args;
3230
+ });
3231
+ const __mfPinSharedProvider = (versionMap, version, currentProvider, provider) => {
3232
+ if (!versionMap || versionMap[version] !== currentProvider) return undefined;
3233
+ const pinnedProvider = Object.assign({}, provider, {
3234
+ version: provider.version ?? version,
3235
+ scope: provider.scope ?? currentProvider?.scope ?? ['${options.shareScope}'],
3236
+ strategy: 'loaded-first'
2622
3237
  });
3238
+ const providerFrom = provider.from;
3239
+ versionMap[version] = pinnedProvider;
3240
+ const isCurrentProviderActive = () => currentProvider === undefined
3241
+ ? versionMap[version] === undefined
3242
+ : versionMap[version] === currentProvider;
3243
+ return {
3244
+ provider: pinnedProvider,
3245
+ reveal() {
3246
+ if (versionMap[version] !== pinnedProvider) return false;
3247
+ if (currentProvider === undefined) delete versionMap[version];
3248
+ else versionMap[version] = currentProvider;
3249
+ return true;
3250
+ },
3251
+ reapply() {
3252
+ if (!isCurrentProviderActive()) return false;
3253
+ versionMap[version] = pinnedProvider;
3254
+ return true;
3255
+ },
3256
+ release(loaded, selected = true) {
3257
+ provider.from = providerFrom;
3258
+ if (versionMap[version] !== pinnedProvider) {
3259
+ return !selected && isCurrentProviderActive();
3260
+ }
3261
+ if (!selected) {
3262
+ if (currentProvider === undefined) delete versionMap[version];
3263
+ else versionMap[version] = currentProvider;
3264
+ return true;
3265
+ }
3266
+ if (!loaded) {
3267
+ if (currentProvider === undefined) delete versionMap[version];
3268
+ else versionMap[version] = currentProvider;
3269
+ return false;
3270
+ }
3271
+ pinnedProvider.from = providerFrom;
3272
+ if (loaded && pinnedProvider.lib) pinnedProvider.loaded = true;
3273
+ if (provider.strategy === undefined) delete pinnedProvider.strategy;
3274
+ else pinnedProvider.strategy = provider.strategy;
3275
+ return true;
3276
+ }
3277
+ };
3278
+ };
3279
+ const __mfSnapshotSharedProviders = (versionMap) => (
3280
+ Object.entries(versionMap || {}).map(([version, provider]) => ({
3281
+ provider,
3282
+ version,
3283
+ from: provider.from,
3284
+ registered: true
3285
+ }))
3286
+ );
3287
+ const __mfMatchLoadedSharedProvider = (providerSelections, factory) => {
3288
+ if (factory === undefined) return undefined;
3289
+ let match;
3290
+ for (const selection of providerSelections) {
3291
+ const provider = selection.provider;
3292
+ const directProvider = provider.treeShaking || provider;
3293
+ if (
3294
+ selection.loadedFactory !== factory &&
3295
+ provider.lib !== factory &&
3296
+ directProvider.lib !== factory
3297
+ ) continue;
3298
+ if (match) return undefined;
3299
+ match = selection;
3300
+ }
3301
+ return match;
3302
+ };
3303
+ const __mfLoadRuntimeShare = async (pkg, shareConfig, pinned) => {
3304
+ const loadId = ++__mfRuntimeShareLoadId;
3305
+ __mfRuntimeShareLifecycles.set(loadId, {
3306
+ pinned
3307
+ });
3308
+ try {
3309
+ const factory = await initRes.loadShare(pkg, {
3310
+ customShareInfo: {
3311
+ shareConfig,
3312
+ [__mfRuntimeShareLoadIdKey]: loadId
3313
+ }
3314
+ });
3315
+ return {
3316
+ factory: factory === false ? undefined : factory,
3317
+ selectedProvider: __mfRuntimeShareSelections.get(loadId)
3318
+ };
3319
+ } finally {
3320
+ __mfRuntimeShareSelections.delete(loadId);
3321
+ __mfRuntimeShareLifecycles.delete(loadId);
3322
+ }
3323
+ };
3324
+ const __mfLoadPinnedRuntimeShare = async (
3325
+ pkg,
3326
+ shareConfig,
3327
+ versionMap,
3328
+ version,
3329
+ currentProvider,
3330
+ provider,
3331
+ providerRegistered = true
3332
+ ) => {
3333
+ const providerFrom = provider.from;
3334
+ const pinned = __mfPinSharedProvider(
3335
+ versionMap,
3336
+ version,
3337
+ currentProvider,
3338
+ provider
3339
+ );
3340
+ if (!pinned) return undefined;
3341
+ let runtimeLoad;
3342
+ try {
3343
+ runtimeLoad = await __mfLoadRuntimeShare(pkg, shareConfig, pinned);
3344
+ } catch (error) {
3345
+ pinned.release(false);
3346
+ throw error;
3347
+ }
3348
+ const factory = runtimeLoad?.factory;
3349
+ if (factory === undefined) {
3350
+ pinned.release(false);
3351
+ return undefined;
3352
+ }
3353
+ const providerSelections = __mfSnapshotSharedProviders(versionMap);
3354
+ const directPinnedProvider = pinned.provider.treeShaking || pinned.provider;
3355
+ const pinnedMatchesFactory =
3356
+ pinned.provider.lib === factory || directPinnedProvider.lib === factory;
3357
+ if (!providerRegistered && pinnedMatchesFactory) {
3358
+ const pinnedSelectionIndex = providerSelections.findIndex(
3359
+ (selection) => selection.provider === pinned.provider
3360
+ );
3361
+ if (pinnedSelectionIndex !== -1) providerSelections.splice(pinnedSelectionIndex, 1);
3362
+ }
3363
+ if (!providerRegistered && !providerSelections.some((selection) => selection.provider === provider)) {
3364
+ providerSelections.push({
3365
+ provider,
3366
+ version,
3367
+ from: providerFrom,
3368
+ registered: false,
3369
+ loadedFactory: pinnedMatchesFactory ? factory : undefined
3370
+ });
3371
+ }
3372
+ const runtimeSelectedProvider =
3373
+ !providerRegistered &&
3374
+ runtimeLoad.selectedProvider === pinned.provider &&
3375
+ pinnedMatchesFactory
3376
+ ? provider
3377
+ : runtimeLoad.selectedProvider;
3378
+ if (
3379
+ runtimeSelectedProvider &&
3380
+ !providerSelections.some((selection) => selection.provider === runtimeSelectedProvider)
3381
+ ) {
3382
+ const runtimeProviderOrigin = __mfRuntimeProviderOrigins.get(runtimeSelectedProvider);
3383
+ const selectedVersion = typeof runtimeSelectedProvider.version === "string" && runtimeSelectedProvider.version
3384
+ ? runtimeSelectedProvider.version
3385
+ : version;
3386
+ providerSelections.push({
3387
+ provider: runtimeSelectedProvider,
3388
+ version: selectedVersion,
3389
+ from: runtimeProviderOrigin ? runtimeProviderOrigin.from : runtimeSelectedProvider.from,
3390
+ registered: versionMap?.[selectedVersion] === runtimeSelectedProvider,
3391
+ loadedFactory: factory
3392
+ });
3393
+ }
3394
+ const selection = providerSelections.find(
3395
+ (candidate) => candidate.provider === runtimeSelectedProvider
3396
+ ) ?? __mfMatchLoadedSharedProvider(providerSelections, factory);
3397
+ const providerStayedActive = pinned.release(
3398
+ true,
3399
+ selection?.provider === pinned.provider
3400
+ );
3401
+ if (!providerStayedActive || !selection) return undefined;
3402
+ const runtimeProviderOrigin = __mfRuntimeProviderOrigins.get(selection.provider);
3403
+ selection.from = selection.provider === provider
3404
+ ? providerFrom
3405
+ : runtimeProviderOrigin
3406
+ ? runtimeProviderOrigin.from
3407
+ : selection.provider.from;
3408
+ if (runtimeProviderOrigin) selection.provider.from = runtimeProviderOrigin.from;
3409
+ const mod = typeof factory === "function" ? factory() : factory;
3410
+ const resolved = await Promise.resolve(mod);
3411
+ if (selection.registered && versionMap?.[selection.version] !== selection.provider) return undefined;
3412
+ return { provider: selection.provider, selection, resolved };
3413
+ };
3414
+ const bridgedProviders = new Set();
3415
+ const bridgeSelections = new Map();
3416
+ const __mfBridgeMaterializedProvider = async (pkg, usedShare, versionMap) => {
3417
+ const singleton = Boolean(usedShare.shareConfig?.singleton);
3418
+ if (singleton && '${options.shareStrategy}' !== 'loaded-first') return;
3419
+ if (usedShare.canLiveRebind === false) return;
3420
+ try {
3421
+ const provider = __mfSelectExternalSharedProvider(
3422
+ versionMap,
3423
+ pkg,
3424
+ usedShare,
3425
+ '${options.shareStrategy}'
3426
+ );
3427
+ const providerEntry = __mfFindSharedProviderEntry(versionMap, provider);
3428
+ if (!providerEntry) return;
3429
+ const { version } = providerEntry;
3430
+ if (!singleton && version !== usedShare.version) return;
3431
+ if (
3432
+ !provider.lib &&
3433
+ !provider.loading &&
3434
+ !(provider.loaded && typeof provider.get === 'function')
3435
+ ) return;
3436
+ const usedCacheDescriptor = __mfGetSharedCacheDescriptor(
3437
+ pkg,
3438
+ singleton,
3439
+ usedShare.version,
3440
+ usedShare.scope
3441
+ );
3442
+ if (__mfReadSharedCache(__mfModuleCache.share, usedCacheDescriptor) !== undefined) return;
3443
+ const liveVersionMap = shared[pkg];
3444
+ const liveProvider = liveVersionMap?.[version];
3445
+ if (providerEntry.registered && !__mfMatchesSharedProvider(liveProvider, provider)) return;
3446
+ let loadedShare;
3447
+ ${options.shareStrategy === "loaded-first" ? `loadedShare = await __mfLoadPinnedRuntimeShare(
3448
+ pkg,
3449
+ usedShare.shareConfig,
3450
+ liveVersionMap,
3451
+ version,
3452
+ liveProvider,
3453
+ provider,
3454
+ providerEntry.registered
3455
+ );` : `// Runtime loadShare() implicitly initializes version-first remotes without
3456
+ // this container's outer initScope. Materialized providers are already active,
3457
+ // so resolve them directly and keep remote initialization on the guarded path.
3458
+ let directFactory = provider.lib;
3459
+ if (!directFactory && provider.loading) directFactory = await provider.loading;
3460
+ if (!directFactory && provider.loaded && typeof provider.get === 'function') {
3461
+ directFactory = await provider.get();
3462
+ }
3463
+ if (!directFactory) return;
3464
+ const directModule = typeof directFactory === "function" ? directFactory() : directFactory;
3465
+ const directResolved = await Promise.resolve(directModule);
3466
+ const directProvider = providerEntry.registered ? liveProvider : provider;
3467
+ loadedShare = {
3468
+ provider: directProvider,
3469
+ selection: {
3470
+ provider: directProvider,
3471
+ version,
3472
+ from: provider.from,
3473
+ registered: providerEntry.registered
3474
+ },
3475
+ resolved: directResolved
3476
+ };`}
3477
+ const actualProvider = loadedShare?.provider;
3478
+ const actualSelection = loadedShare?.selection;
3479
+ if (!actualSelection) return;
3480
+ const resolved = loadedShare?.resolved;
3481
+ if (resolved === undefined) return;
3482
+ if (__mfReadSharedCache(__mfModuleCache.share, usedCacheDescriptor) !== undefined) return;
3483
+ ${options.shareStrategy === "loaded-first" ? `if (
3484
+ actualSelection.registered &&
3485
+ liveVersionMap?.[actualSelection.version] !== actualProvider
3486
+ ) return;` : `if (
3487
+ actualSelection.registered &&
3488
+ liveVersionMap?.[actualSelection.version] !== actualProvider
3489
+ ) return;`}
3490
+ __mfWriteSharedCache(
3491
+ __mfModuleCache.share,
3492
+ usedCacheDescriptor,
3493
+ __mfNormalizeRuntimeShare(resolved),
3494
+ actualSelection.from
3495
+ );
3496
+ bridgedProviders.add(actualProvider);
3497
+ } catch (e) {
3498
+ console.error('[Module Federation] Failed to bridge materialized shared module "' + pkg + '"', e)
3499
+ }
3500
+ };
3501
+ const __mfBridgeExternalSharedProvider = async (
3502
+ pkg,
3503
+ usedShare,
3504
+ versionMap,
3505
+ passedVersionMap,
3506
+ expectedSelection
3507
+ ) => {
3508
+ try {
3509
+ const usedCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, usedShare.shareConfig?.singleton, usedShare.version, usedShare.scope);
3510
+ const cachedShare = __mfReadSharedCache(__mfModuleCache.share, usedCacheDescriptor);
3511
+ const cachedShareOwner = __mfReadSharedCacheOwner(__mfModuleCache.share, usedCacheDescriptor);
3512
+ const selectedExternalProvider = __mfSelectExternalSharedProvider(
3513
+ versionMap,
3514
+ pkg,
3515
+ usedShare,
3516
+ '${options.shareStrategy}'
3517
+ );
3518
+ const selectedRuntimeProvider = selectedExternalProvider ||
3519
+ __mfSelectSharedProvider(versionMap, pkg, usedShare, '${options.shareStrategy}') ||
3520
+ usedShare;
3521
+ const providerEntry = __mfFindSharedProviderEntry(versionMap, selectedRuntimeProvider);
3522
+ if (!providerEntry) return;
3523
+ const selectedLocalProvider = __mfMatchesSharedProvider(selectedRuntimeProvider, usedShare);
3524
+ const { version } = providerEntry;
3525
+ const passedProvider = passedVersionMap?.[version];
3526
+ const resolvedExternalProvider = __mfResolveExternalSharedProvider(
3527
+ federationInstances,
3528
+ scopeRoot,
3529
+ shared,
3530
+ '${options.shareScope}',
3531
+ pkg,
3532
+ providerEntry,
3533
+ selectedExternalProvider,
3534
+ passedProvider,
3535
+ '${options.shareStrategy}'
3536
+ );
3537
+ if (!resolvedExternalProvider && !selectedLocalProvider) return;
3538
+ const { provider, scopeRootProvider } = resolvedExternalProvider || {
3539
+ provider: selectedRuntimeProvider,
3540
+ scopeRootProvider: undefined
3541
+ };
3542
+ // Non-singleton proxies may have already snapshotted their local exports while
3543
+ // seeding shared dependencies. Late cache replacement is safe only for the
3544
+ // live-bound singleton proxies.
3545
+ if (!usedShare.shareConfig?.singleton) return;
3546
+ if (usedShare.canLiveRebind === false) return;
3547
+ // Preserve a singleton already selected by another container. The bridge may
3548
+ // only replace the provisional local fallback seeded by this container.
3549
+ if (cachedShare !== undefined && cachedShareOwner !== mfName) return;
3550
+ // Registration can replace an unloaded same-version root provider in-place.
3551
+ // Pin the chosen provider while loadShare() runs its implicit registration.
3552
+ const liveVersionMap = shared[pkg];
3553
+ const liveProvider = liveVersionMap?.[version];
3554
+ if (
3555
+ providerEntry.registered &&
3556
+ !scopeRootProvider &&
3557
+ !__mfMatchesSharedProvider(liveProvider, provider)
3558
+ ) return;
3559
+ const loadedShare = await __mfLoadPinnedRuntimeShare(
3560
+ pkg,
3561
+ usedShare.shareConfig,
3562
+ liveVersionMap,
3563
+ version,
3564
+ liveProvider,
3565
+ provider,
3566
+ providerEntry.registered && !selectedLocalProvider
3567
+ );
3568
+ const actualProvider = loadedShare?.provider;
3569
+ const actualSelection = loadedShare?.selection;
3570
+ if (!actualSelection) return;
3571
+ if (__mfMatchesSharedProvider(actualProvider, usedShare)) return;
3572
+ if (expectedSelection) {
3573
+ if (
3574
+ expectedSelection.version !== actualSelection.version ||
3575
+ !__mfMatchesSharedProvider({ from: actualSelection.from }, expectedSelection.provider)
3576
+ ) return;
3577
+ }
3578
+ if (bridgedProviders.has(actualProvider)) return;
3579
+ const resolved = loadedShare?.resolved;
3580
+ if (resolved === undefined) return;
3581
+ const latestCachedShare = __mfReadSharedCache(__mfModuleCache.share, usedCacheDescriptor);
3582
+ const latestCachedShareOwner = __mfReadSharedCacheOwner(__mfModuleCache.share, usedCacheDescriptor);
3583
+ if (latestCachedShare !== undefined && latestCachedShareOwner !== mfName) return;
3584
+ if (
3585
+ actualSelection.registered &&
3586
+ liveVersionMap?.[actualSelection.version] !== actualProvider
3587
+ ) return;
3588
+ if (!expectedSelection) {
3589
+ bridgeSelections.set(pkg, {
3590
+ version: actualSelection.version,
3591
+ provider: { from: actualSelection.from }
3592
+ });
3593
+ }
3594
+ bridgedProviders.add(actualProvider);
3595
+ const normalized = __mfNormalizeRuntimeShare(resolved);
3596
+ __mfWriteSharedCache(
3597
+ __mfModuleCache.share,
3598
+ usedCacheDescriptor,
3599
+ normalized,
3600
+ actualSelection.from
3601
+ );
3602
+ } catch (e) {
3603
+ console.error('[Module Federation] Failed to bridge external shared module "' + pkg + '"', e)
3604
+ }
3605
+ };
3606
+ for (const [pkg, usedShare] of Object.entries(usedShared)) {
3607
+ if (usedShare.treeShaking) continue;
3608
+ await __mfBridgeMaterializedProvider(pkg, usedShare, initialShared[pkg]);
3609
+ }
3610
+ for (const [pkg, share] of Object.entries(usedShared)) {
3611
+ if (share.treeShaking) continue;
3612
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
3613
+ if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) continue;
3614
+ const singletonCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, true, share.version, share.scope);
3615
+ const singletonModule = __mfReadSharedCache(__mfModuleCache.share, singletonCacheDescriptor);
3616
+ if (singletonModule !== undefined) {
3617
+ __mfWriteSharedCache(
3618
+ __mfModuleCache.share,
3619
+ cacheDescriptor,
3620
+ singletonModule,
3621
+ __mfReadSharedCacheOwner(__mfModuleCache.share, singletonCacheDescriptor)
3622
+ );
3623
+ }
3624
+ }
3625
+ ${generateRuntimeSharedCacheSeedCode(options.shareStrategy)}
3626
+ ${initializeSharingCode}
3627
+ // Calling provider.get() marks a provider as loaded. Wait until the Runtime has
3628
+ // finalized normal same-version precedence before materializing an external share.
3629
+ for (const [pkg, usedShare] of Object.entries(usedShared)) {
3630
+ if (usedShare.treeShaking) continue;
3631
+ await __mfBridgeExternalSharedProvider(
3632
+ pkg,
3633
+ usedShare,
3634
+ shared[pkg],
3635
+ initialShared[pkg],
3636
+ undefined
3637
+ );
3638
+ }
3639
+ try {
3640
+ const allInstances = globalThis.__FEDERATION__?.__SHARE__;
3641
+ const globalVersionsByPackage = Object.create(null);
3642
+ if (allInstances) {
3643
+ for (const [, scopes] of Object.entries(allInstances)) {
3644
+ const scopeShare = scopes?.['${options.shareScope}'];
3645
+ if (!scopeShare) continue;
3646
+ for (const [pkg, versionMap] of Object.entries(scopeShare)) {
3647
+ const usedShare = usedShared?.[pkg];
3648
+ const passedVersions = initialShared[pkg];
3649
+ const bridgeSelection = bridgeSelections.get(pkg);
3650
+ if (!usedShare) continue;
3651
+ if (!passedVersions) continue;
3652
+ if (!bridgeSelection) continue;
3653
+ if (usedShare.treeShaking) continue;
3654
+ const globalVersions = globalVersionsByPackage[pkg] || (globalVersionsByPackage[pkg] = Object.create(null));
3655
+ for (const [version, provider] of Object.entries(versionMap)) {
3656
+ if (!provider.lib) continue;
3657
+ if (bridgeSelection.version !== version) continue;
3658
+ if (!__mfMatchesSharedProvider(provider, bridgeSelection.provider)) continue;
3659
+ const passedProvider = passedVersions[version];
3660
+ const matchesPassedProvider = provider === passedProvider || (
3661
+ passedProvider?.from && provider.from === passedProvider.from
3662
+ );
3663
+ if (!matchesPassedProvider) continue;
3664
+ if (provider === usedShare || (usedShare.from && provider.from === usedShare.from)) continue;
3665
+ if (globalVersions[version] === undefined) globalVersions[version] = provider;
3666
+ }
3667
+ }
3668
+ }
3669
+ }
3670
+ for (const [pkg, versionMap] of Object.entries(globalVersionsByPackage)) {
3671
+ await __mfBridgeExternalSharedProvider(
3672
+ pkg,
3673
+ usedShared[pkg],
3674
+ versionMap,
3675
+ initialShared[pkg],
3676
+ bridgeSelections.get(pkg)
3677
+ );
3678
+ }
2623
3679
  } catch (e) {
2624
- console.error('[Module Federation]', e)
3680
+ console.error('[Module Federation] Failed to bridge external shared modules', e)
2625
3681
  }
2626
3682
  ${generateTreeShakingSharedResolutionCode(hasTreeShakingShared)}
2627
- for (const [pkg, share] of Object.entries(usedShared)) {
3683
+ const __mfResolveImportFalseShared = async (pkg, share) => {
2628
3684
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2629
3685
  const cachedShare = share.treeShaking
2630
3686
  ? __mfReadTreeShakingSharedSelection(__mfModuleCache.share, cacheDescriptor, mfName)
2631
3687
  : __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor);
2632
- if (share.shareConfig?.import !== false || cachedShare !== undefined) continue;
3688
+ if (share.shareConfig?.import !== false || cachedShare !== undefined) return;
2633
3689
  ${normalizeRuntimeShareCode}
2634
- const versions = shared?.[pkg];
2635
- const provider = __mfSelectSharedProvider(versions, pkg, share, '${options.shareStrategy}');
2636
- if (!provider) continue;
2637
- const factory = provider.lib || (provider.loading ? await provider.loading : await provider.get?.());
2638
- const mod = typeof factory === "function" ? factory() : factory;
2639
- const resolved = await Promise.resolve(mod);
2640
- __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, __mfNormalizeRuntimeShare(resolved));
3690
+ const versionMap = shared?.[pkg];
3691
+ const provider = __mfSelectSharedProvider(
3692
+ versionMap,
3693
+ pkg,
3694
+ share,
3695
+ '${options.shareStrategy}'
3696
+ ) || share;
3697
+ const providerEntry = __mfFindSharedProviderEntry(versionMap, provider);
3698
+ if (!providerEntry) return;
3699
+ const { version } = providerEntry;
3700
+ const currentProvider = versionMap?.[version];
3701
+ const loadedShare = await __mfLoadPinnedRuntimeShare(
3702
+ pkg,
3703
+ share.shareConfig,
3704
+ versionMap,
3705
+ version,
3706
+ currentProvider,
3707
+ provider,
3708
+ providerEntry.registered && !__mfMatchesSharedProvider(provider, share)
3709
+ );
3710
+ const providerSelection = loadedShare?.selection;
3711
+ const actualProvider = loadedShare?.provider;
3712
+ const resolved = loadedShare?.resolved;
3713
+ if (!providerSelection) return;
3714
+ if (__mfMatchesSharedProvider(actualProvider, share)) return;
3715
+ if (resolved === undefined) return;
3716
+ const latestCachedShare = share.treeShaking
3717
+ ? __mfReadTreeShakingSharedSelection(__mfModuleCache.share, cacheDescriptor, mfName)
3718
+ : __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor);
3719
+ if (latestCachedShare !== undefined) return;
3720
+ if (
3721
+ providerSelection.registered &&
3722
+ versionMap?.[providerSelection.version] !== actualProvider
3723
+ ) return;
3724
+ const normalizedShared = __mfNormalizeRuntimeShare(resolved);
3725
+ if (share.treeShaking) {
3726
+ const providedExports = share.treeShaking.providedExports ?? share.treeShaking.usedExports ?? [];
3727
+ __mfWriteTreeShakingSharedCache(
3728
+ __mfModuleCache.share,
3729
+ cacheDescriptor,
3730
+ providedExports,
3731
+ normalizedShared
3732
+ );
3733
+ __mfWriteTreeShakingSharedSelection(
3734
+ __mfModuleCache.share,
3735
+ cacheDescriptor,
3736
+ mfName,
3737
+ normalizedShared
3738
+ );
3739
+ } else {
3740
+ __mfWriteSharedCache(
3741
+ __mfModuleCache.share,
3742
+ cacheDescriptor,
3743
+ normalizedShared,
3744
+ providerSelection.from
3745
+ );
3746
+ }
3747
+ };
3748
+ // Resolve runtime-only dependencies and seed local fallbacks in dependency
3749
+ // order. Stop at an unresolved provider so its consumers cannot capture an
3750
+ // undefined or provisional singleton.
3751
+ for (const pkg of __mfDeferredSeedKeys) {
3752
+ const share = usedShared[pkg];
3753
+ if (__mfIsRuntimeOnlySharePending(pkg)) {
3754
+ if (share.treeShaking) {
3755
+ await __mfResolveTreeShakingShared(pkg, share);
3756
+ } else if (share.shareConfig?.import === false) {
3757
+ await __mfResolveImportFalseShared(pkg, share);
3758
+ }
3759
+ }
3760
+ if (__mfIsRuntimeOnlySharePending(pkg)) break;
3761
+ await __mfSeedLocalShared([pkg]);
2641
3762
  }
2642
3763
  initResolve(initRes)
2643
3764
  return initRes
@@ -2663,6 +3784,7 @@ let currentHostAutoInitCommand = "build";
2663
3784
  function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
2664
3785
  const shouldPreloadShares = getNormalizeModuleFederationOptions().shareStrategy !== "loaded-first";
2665
3786
  const hostInitShareOrder = JSON.stringify(getOrderedUsedShares());
3787
+ const cacheOwner = JSON.stringify(getNormalizeModuleFederationOptions().name);
2666
3788
  return `
2667
3789
  ${getRuntimeModuleCacheBootstrapCode()}
2668
3790
  let hostInitPromise;
@@ -2694,7 +3816,12 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
2694
3816
  }).then((factory) => {
2695
3817
  const mod = typeof factory === "function" ? factory() : factory;
2696
3818
  return Promise.resolve(mod).then((resolved) => {
2697
- __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, __mfNormalizeRuntimeShare(resolved));
3819
+ __mfWriteSharedCache(
3820
+ __mfModuleCache.share,
3821
+ cacheDescriptor,
3822
+ __mfNormalizeRuntimeShare(resolved),
3823
+ ${cacheOwner}
3824
+ );
2698
3825
  });
2699
3826
  });
2700
3827
  }
@@ -5764,50 +6891,6 @@ function collectFromRegex(code, isRemoteImport) {
5764
6891
  }
5765
6892
  return result.length > 0 ? result : void 0;
5766
6893
  }
5767
- function createCodePositionMap(code) {
5768
- const positions = Array(code.length).fill(true);
5769
- function mask(start, end) {
5770
- for (let i = start; i < end; i++) positions[i] = false;
5771
- }
5772
- for (let i = 0; i < code.length;) {
5773
- const char = code[i];
5774
- const next = code[i + 1];
5775
- if (char === "/" && next === "/") {
5776
- const start = i;
5777
- i += 2;
5778
- while (i < code.length && code[i] !== "\n" && code[i] !== "\r") i++;
5779
- mask(start, i);
5780
- continue;
5781
- }
5782
- if (char === "/" && next === "*") {
5783
- const start = i;
5784
- i += 2;
5785
- while (i < code.length && !(code[i] === "*" && code[i + 1] === "/")) i++;
5786
- i = Math.min(code.length, i + 2);
5787
- mask(start, i);
5788
- continue;
5789
- }
5790
- if (char === "\"" || char === "'" || char === "`") {
5791
- const quote = char;
5792
- const start = i++;
5793
- while (i < code.length) {
5794
- if (code[i] === "\\") {
5795
- i += 2;
5796
- continue;
5797
- }
5798
- if (code[i] === quote) {
5799
- i++;
5800
- break;
5801
- }
5802
- i++;
5803
- }
5804
- mask(start, i);
5805
- continue;
5806
- }
5807
- i++;
5808
- }
5809
- return positions;
5810
- }
5811
6894
  function pluginRemoteNamedExports(options) {
5812
6895
  const remoteNames = Object.keys(options.remotes);
5813
6896
  const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
@@ -6424,9 +7507,6 @@ function appendResolveAlias(config, alias) {
6424
7507
  replacement
6425
7508
  })), alias];
6426
7509
  }
6427
- function hasImportFalseShared(options) {
6428
- return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
6429
- }
6430
7510
  function getRuntimeHelpersImplementation(runtimeImplementation) {
6431
7511
  const indexEntryMatch = runtimeImplementation.match(/^(.*[\\/])index(\.[cm]?js)$/);
6432
7512
  if (indexEntryMatch) return normalizePathForImport(`${indexEntryMatch[1]}helpers${indexEntryMatch[2]}`);
@@ -6670,7 +7750,7 @@ export default __mfShared.default ?? __mfShared;`
6670
7750
  const SSR_ONLY_PLUGINS = new Set(["@module-federation/vite/ssrEntryLoader"]);
6671
7751
  function loadPluginDts(options) {
6672
7752
  if (options.dts === false) return [];
6673
- return [import("./pluginDts-BcvLBYP3.js").then((n) => n.n).then(({ default: pluginDts }) => pluginDts(options))];
7753
+ return [import("./pluginDts-CGDIZCsD.js").then((n) => n.n).then(({ default: pluginDts }) => pluginDts(options))];
6674
7754
  }
6675
7755
  function federation(mfUserOptions) {
6676
7756
  if (isTestEnv()) return [];
@@ -6984,7 +8064,7 @@ function federation(mfUserOptions) {
6984
8064
  config(config, { command: _command }) {
6985
8065
  const isRolldown = getIsRolldown(this);
6986
8066
  isSsrBuild = _command === "build" && config.build?.ssr === true;
6987
- const needsRuntimeHelpers = hasImportFalseShared(options) || Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
8067
+ const needsRuntimeHelpers = Object.keys(options.shared ?? {}).length > 0;
6988
8068
  if (needsRuntimeHelpers) appendResolveAlias(config, {
6989
8069
  find: /^@module-federation\/runtime\/helpers$/,
6990
8070
  replacement: getRuntimeHelpersImplementation(options.implementation)