@module-federation/vite 1.16.16 → 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-Bo95ELmX.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";
@@ -6,7 +6,7 @@ import { createRequire as createRequire$1 } from "module";
6
6
  import * as path$1 from "node:path";
7
7
  import path, { basename } from "node:path";
8
8
  import { fileURLToPath, pathToFileURL } from "url";
9
- import { version } from "vite";
9
+ import { parseAst, version } from "vite";
10
10
  import { createHash } from "node:crypto";
11
11
  import * as fs$1 from "node:fs";
12
12
  import { existsSync as existsSync$1, readFileSync as readFileSync$1 } from "node:fs";
@@ -373,6 +373,10 @@ function normalizeShareItem(key, shareItem) {
373
373
  const isImportFalse = typeof shareItem === "object" && shareItem.import === false;
374
374
  const explicitVersion = typeof shareItem === "object" ? shareItem.version : void 0;
375
375
  const inferredVersion = typeof shareItem === "object" ? inferVersionFromRequiredVersion(shareItem.requiredVersion) : void 0;
376
+ const treeShaking = typeof shareItem === "object" ? shareItem.treeShaking : void 0;
377
+ if (treeShaking && treeShaking.mode !== "server-calc" && treeShaking.mode !== "runtime-infer") throw createModuleFederationError(`Invalid shared config for "${key}": treeShaking.mode must be either "server-calc" or "runtime-infer".`);
378
+ if (treeShaking && typeof shareItem === "object" && shareItem.eager) throw createModuleFederationError(`Invalid shared config for "${key}": cannot use both "eager: true" and "treeShaking.mode" simultaneously. Choose one strategy.`);
379
+ if (treeShaking?.mode === "runtime-infer" && typeof shareItem === "object" && shareItem.singleton) mfWarn(`Shared singleton "${key}" uses runtime-infer tree shaking, which may load both a tree-shaken bundle and a full bundle when consumers require different exports. Prefer server-calc for singleton dependencies. If runtime-infer is required, expand usedExports to reduce this risk.`);
376
380
  const version = explicitVersion || searchPackageVersion(key) || inferredVersion;
377
381
  if (typeof shareItem === "string") return {
378
382
  name: shareItem,
@@ -382,6 +386,7 @@ function normalizeShareItem(key, shareItem) {
382
386
  shareConfig: {
383
387
  import: void 0,
384
388
  singleton: false,
389
+ eager: false,
385
390
  requiredVersion: version ? `^${version}` : "*"
386
391
  }
387
392
  };
@@ -393,8 +398,10 @@ function normalizeShareItem(key, shareItem) {
393
398
  shareConfig: {
394
399
  import: shareItem.import,
395
400
  singleton: shareItem.singleton || false,
401
+ eager: shareItem.eager || false,
396
402
  requiredVersion: shareItem.requiredVersion !== void 0 ? shareItem.requiredVersion : isImportFalse || shareItem.version ? "*" : version ? `^${version}` : "*",
397
- strictVersion: !!shareItem.strictVersion
403
+ strictVersion: !!shareItem.strictVersion,
404
+ ...treeShaking ? { treeShaking: { ...treeShaking } } : {}
398
405
  }
399
406
  };
400
407
  }
@@ -519,7 +526,7 @@ function normalizeModuleFederationOptions(options) {
519
526
  shareScope: options.shareScope || "default",
520
527
  shared: normalizeShared(options.shared),
521
528
  runtimePlugins: options.runtimePlugins || [],
522
- implementation: options.implementation || resolveRuntimeImplementation(),
529
+ implementation: normalizePathForImport(options.implementation || resolveRuntimeImplementation()),
523
530
  manifest: normalizeManifest(options.manifest),
524
531
  dev: options.dev,
525
532
  dts: options.dts,
@@ -530,6 +537,10 @@ function normalizeModuleFederationOptions(options) {
530
537
  virtualModuleDir: options.virtualModuleDir || "__mf__virtual",
531
538
  hostInitInjectLocation: options.hostInitInjectLocation || "html",
532
539
  bundleAllCSS: options.bundleAllCSS || false,
540
+ treeShakingDir: options.treeShakingDir,
541
+ injectTreeShakingUsedExports: options.injectTreeShakingUsedExports,
542
+ treeShakingSharedPlugins: options.treeShakingSharedPlugins,
543
+ treeShakingSharedExcludePlugins: options.treeShakingSharedExcludePlugins,
533
544
  moduleParseTimeout: options.moduleParseTimeout || 10,
534
545
  moduleParseIdleTimeout: options.moduleParseIdleTimeout,
535
546
  varFilename: options.varFilename,
@@ -549,11 +560,11 @@ const cacheMap = {};
549
560
  const idCacheMap = {};
550
561
  const VITE_ID_PREFIX = "/@id/";
551
562
  const VITE_ENCODED_NULL_BYTE_PREFIX = `${VITE_ID_PREFIX}__x00__`;
552
- function escapeRegExp$1(value) {
563
+ function escapeRegExp$2(value) {
553
564
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
554
565
  }
555
566
  function createViteEncodedIdPrefixRegExp(sourcePrefix = "") {
556
- return new RegExp(`^(?:${escapeRegExp$1(VITE_ENCODED_NULL_BYTE_PREFIX)})?${sourcePrefix}`);
567
+ return new RegExp(`^(?:${escapeRegExp$2(VITE_ENCODED_NULL_BYTE_PREFIX)})?${sourcePrefix}`);
557
568
  }
558
569
  function toViteEncodedId(id) {
559
570
  return `${VITE_ENCODED_NULL_BYTE_PREFIX}${id}`;
@@ -928,6 +939,396 @@ ${exportStatement}
928
939
  `);
929
940
  }
930
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
1081
+ //#region src/utils/treeShaking.ts
1082
+ /**
1083
+ * Analysis is scoped by both the configured share key and the concrete module
1084
+ * request. A prefix share such as `lodash/` may materialize separate wrappers
1085
+ * for `lodash/get` and `lodash/debounce`; combining those export sets would
1086
+ * generate invalid wrappers and defeat per-subpath tree shaking.
1087
+ */
1088
+ const inferredTreeShakingUsage = /* @__PURE__ */ new Map();
1089
+ let treeShakingBuildMode = false;
1090
+ function setTreeShakingBuildMode(enabled) {
1091
+ treeShakingBuildMode = enabled;
1092
+ }
1093
+ function resetTreeShakingExports() {
1094
+ inferredTreeShakingUsage.clear();
1095
+ }
1096
+ function getOrCreateExportRecord(sharedKey, request) {
1097
+ let byRequest = inferredTreeShakingUsage.get(sharedKey);
1098
+ if (!byRequest) {
1099
+ byRequest = /* @__PURE__ */ new Map();
1100
+ inferredTreeShakingUsage.set(sharedKey, byRequest);
1101
+ }
1102
+ let record = byRequest.get(request);
1103
+ if (!record) {
1104
+ record = {
1105
+ requiresFullBundle: false,
1106
+ usedExports: /* @__PURE__ */ new Set()
1107
+ };
1108
+ byRequest.set(request, record);
1109
+ }
1110
+ return record;
1111
+ }
1112
+ function recordTreeShakingExports(sharedKey, exports, request = sharedKey) {
1113
+ const record = getOrCreateExportRecord(sharedKey, request);
1114
+ exports.forEach((name) => record.usedExports.add(name));
1115
+ }
1116
+ function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey) {
1117
+ getOrCreateExportRecord(sharedKey, request).requiresFullBundle = true;
1118
+ }
1119
+ function getExportRecords(sharedKey, request) {
1120
+ if (sharedKey) {
1121
+ const records = inferredTreeShakingUsage.get(sharedKey);
1122
+ const wildcard = records?.get("*");
1123
+ const exact = records?.get(request);
1124
+ return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
1125
+ }
1126
+ const records = [];
1127
+ inferredTreeShakingUsage.forEach((byRequest, configuredKey) => {
1128
+ const wildcard = byRequest.get("*");
1129
+ const exact = byRequest.get(request);
1130
+ const keyBase = configuredKey.endsWith("/") ? configuredKey.slice(0, -1) : configuredKey;
1131
+ const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
1132
+ if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
1133
+ if (exact && exact !== wildcard) records.push(exact);
1134
+ });
1135
+ return records;
1136
+ }
1137
+ /**
1138
+ * Return the analyzed requirement for one concrete shared request.
1139
+ *
1140
+ * Callers that know the configured share key should pass it explicitly. The
1141
+ * fallback lookup across keys keeps aliases/backwards-compatible callers
1142
+ * working, while still keeping each concrete request's exports isolated.
1143
+ */
1144
+ function getTreeShakingExportUsage(request, shareItem, sharedKey) {
1145
+ const treeShaking = shareItem?.shareConfig.treeShaking;
1146
+ if (!treeShaking || !treeShakingBuildMode) return void 0;
1147
+ const records = getExportRecords(sharedKey, request);
1148
+ if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
1149
+ const configured = treeShaking.usedExports ?? [];
1150
+ const result = new Set(configured);
1151
+ records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
1152
+ if (result.size > 0) return {
1153
+ kind: "exports",
1154
+ usedExports: [...result].sort()
1155
+ };
1156
+ return records.length > 0 ? {
1157
+ kind: "exports",
1158
+ usedExports: []
1159
+ } : { kind: "unknown" };
1160
+ }
1161
+ function getModuleSource(node) {
1162
+ if (!node || typeof node !== "object") return void 0;
1163
+ const source = node;
1164
+ if (source.type === "Literal" && typeof source.value === "string") return source.value;
1165
+ if (source.type === "StringLiteral" && typeof source.value === "string") return source.value;
1166
+ if (source.type !== "TemplateLiteral") return void 0;
1167
+ const expressions = Array.isArray(source.expressions) ? source.expressions : [];
1168
+ const quasis = Array.isArray(source.quasis) ? source.quasis : [];
1169
+ if (expressions.length > 0 || quasis.length !== 1) return void 0;
1170
+ const value = quasis[0]?.value;
1171
+ return typeof value?.cooked === "string" ? value.cooked : typeof value?.raw === "string" ? value.raw : void 0;
1172
+ }
1173
+ function getExportedName(node) {
1174
+ if (!node || typeof node !== "object") return void 0;
1175
+ const exported = node;
1176
+ if (exported.type === "Identifier" && typeof exported.name === "string") return exported.name;
1177
+ if ((exported.type === "Literal" || exported.type === "StringLiteral") && typeof exported.value === "string") return exported.value;
1178
+ }
1179
+ function isTypeOnly(node) {
1180
+ return node.importKind === "type" || node.exportKind === "type";
1181
+ }
1182
+ function forEachAstNode(root, visit) {
1183
+ const stack = [root];
1184
+ const seen = /* @__PURE__ */ new Set();
1185
+ while (stack.length > 0) {
1186
+ const value = stack.pop();
1187
+ if (!value || typeof value !== "object") continue;
1188
+ if (seen.has(value)) continue;
1189
+ seen.add(value);
1190
+ if (Array.isArray(value)) {
1191
+ for (let index = value.length - 1; index >= 0; index--) stack.push(value[index]);
1192
+ continue;
1193
+ }
1194
+ const node = value;
1195
+ if (typeof node.type === "string") visit(node);
1196
+ Object.entries(node).forEach(([key, child]) => {
1197
+ if (key !== "parent" && key !== "loc") stack.push(child);
1198
+ });
1199
+ }
1200
+ }
1201
+ function collectImportDeclaration(node, source, record, markUnsafe) {
1202
+ if (isTypeOnly(node)) return;
1203
+ const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1204
+ if (specifiers.length === 0) {
1205
+ markUnsafe(source);
1206
+ return;
1207
+ }
1208
+ const names = [];
1209
+ for (const specifier of specifiers) {
1210
+ if (isTypeOnly(specifier)) continue;
1211
+ if (specifier.type === "ImportNamespaceSpecifier") {
1212
+ markUnsafe(source);
1213
+ return;
1214
+ }
1215
+ if (specifier.type === "ImportDefaultSpecifier") {
1216
+ names.push("default");
1217
+ continue;
1218
+ }
1219
+ if (specifier.type === "ImportSpecifier") {
1220
+ const imported = specifier.imported;
1221
+ if (imported?.type === "Literal" || imported?.type === "StringLiteral") {
1222
+ markUnsafe(source);
1223
+ return;
1224
+ }
1225
+ const name = getExportedName(specifier.imported);
1226
+ if (!name) {
1227
+ markUnsafe(source);
1228
+ return;
1229
+ }
1230
+ names.push(name);
1231
+ continue;
1232
+ }
1233
+ markUnsafe(source);
1234
+ return;
1235
+ }
1236
+ record(names, source);
1237
+ }
1238
+ function collectReExport(node, source, record, markUnsafe) {
1239
+ if (isTypeOnly(node)) return;
1240
+ if (node.type === "ExportAllDeclaration") {
1241
+ markUnsafe(source);
1242
+ return;
1243
+ }
1244
+ const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1245
+ if (specifiers.length === 0) {
1246
+ markUnsafe(source);
1247
+ return;
1248
+ }
1249
+ const names = [];
1250
+ for (const specifier of specifiers) {
1251
+ if (isTypeOnly(specifier)) continue;
1252
+ if (specifier.type !== "ExportSpecifier") {
1253
+ markUnsafe(source);
1254
+ return;
1255
+ }
1256
+ const local = specifier.local;
1257
+ if (local?.type === "Literal" || local?.type === "StringLiteral") {
1258
+ markUnsafe(source);
1259
+ return;
1260
+ }
1261
+ const name = getExportedName(specifier.local);
1262
+ if (!name) {
1263
+ markUnsafe(source);
1264
+ return;
1265
+ }
1266
+ names.push(name);
1267
+ }
1268
+ record(names, source);
1269
+ }
1270
+ /**
1271
+ * Collect the exports required by a consumer's ESM graph.
1272
+ *
1273
+ * Parsing the module avoids treating import-looking text in comments, strings,
1274
+ * templates, or regular expressions as real dependencies. If parsing fails,
1275
+ * every configured tree-shaken share is conservatively marked as requiring its
1276
+ * full bundle instead of guessing from source text.
1277
+ *
1278
+ * Generated federation wrappers are excluded because their imports describe
1279
+ * the wrapper implementation, not the consumer's requirements.
1280
+ */
1281
+ function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe) {
1282
+ const normalizedId = normalizePathForImport(id);
1283
+ if (normalizedId.includes("__prebuild__") || normalizedId.includes("__loadShare__") || normalizedId.includes("__mf_tree_shaking_graph__")) return;
1284
+ let ast;
1285
+ try {
1286
+ ast = parseAst(code);
1287
+ } catch {
1288
+ Object.entries(shared).forEach(([sharedKey, shareItem]) => {
1289
+ if (shareItem.shareConfig.treeShaking) markUnsafe(sharedKey, "*");
1290
+ });
1291
+ return;
1292
+ }
1293
+ const matchShared = (source) => {
1294
+ const sharedKey = findSharedKey(source, shared);
1295
+ return sharedKey && shared[sharedKey]?.shareConfig.treeShaking ? sharedKey : void 0;
1296
+ };
1297
+ const recordSource = (names, source) => {
1298
+ const sharedKey = matchShared(source);
1299
+ if (sharedKey) record(sharedKey, names, source);
1300
+ };
1301
+ const markSourceUnsafe = (source) => {
1302
+ const sharedKey = matchShared(source);
1303
+ if (sharedKey) markUnsafe(sharedKey, source);
1304
+ };
1305
+ forEachAstNode(ast, (node) => {
1306
+ if (node.type === "ImportDeclaration") {
1307
+ const source = getModuleSource(node.source);
1308
+ if (source) collectImportDeclaration(node, source, recordSource, markSourceUnsafe);
1309
+ return;
1310
+ }
1311
+ if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
1312
+ const source = getModuleSource(node.source);
1313
+ if (source) collectReExport(node, source, recordSource, markSourceUnsafe);
1314
+ return;
1315
+ }
1316
+ if (node.type === "ImportExpression") {
1317
+ const source = getModuleSource(node.source);
1318
+ if (source) markSourceUnsafe(source);
1319
+ return;
1320
+ }
1321
+ if (node.type === "CallExpression") {
1322
+ const callee = node.callee;
1323
+ const args = Array.isArray(node.arguments) ? node.arguments : [];
1324
+ if (callee?.type === "Identifier" && callee.name === "require" && args.length > 0) {
1325
+ const source = getModuleSource(args[0]);
1326
+ if (source) markSourceUnsafe(source);
1327
+ }
1328
+ }
1329
+ });
1330
+ }
1331
+ //#endregion
931
1332
  //#region src/virtualModules/virtualShared_preBuild.ts
932
1333
  /**
933
1334
  * Even the resolveId hook cannot interfere with vite pre-build,
@@ -979,17 +1380,30 @@ function getPackageEsmEntryPath(pkg) {
979
1380
  resolveSubpathWithRequire: false
980
1381
  }) || resolvePackageEntryFromProjectRoot(pkg);
981
1382
  }
982
- 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) {
983
1393
  try {
984
- if (!entryPath) return [];
985
- 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
+ };
986
1403
  } catch {
987
- return [];
1404
+ return;
988
1405
  }
989
1406
  }
990
- function getEsmNamedExports(pkg) {
991
- return getEsmNamedExportsFromFile(getPackageEsmEntryPath(pkg));
992
- }
993
1407
  function resolveConfiguredImportPath(importSource) {
994
1408
  if (path$1.isAbsolute(importSource)) return resolveFileLikeModule(importSource);
995
1409
  const projectRoot = getPackageDetectionCwd();
@@ -1070,19 +1484,156 @@ function resolveReExportModule(filePath, specifier) {
1070
1484
  return;
1071
1485
  }
1072
1486
  }
1073
- 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 }) {
1074
1611
  const names = /* @__PURE__ */ new Set();
1612
+ const codePositions = createCodePositionMap(source);
1613
+ const recognizedExportStarts = /* @__PURE__ */ new Set();
1075
1614
  visited = visited || /* @__PURE__ */ new Set();
1076
1615
  if (filePath) visited.add(filePath);
1077
- 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");
1078
1617
  let match;
1079
1618
  while ((match = declRegex.exec(source)) !== null) {
1619
+ if (!codePositions[match.index]) continue;
1620
+ recognizedExportStarts.add(match.index);
1080
1621
  const name = match[1];
1081
1622
  if (isValidEsmExportName(name)) names.add(name);
1082
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;
1083
1632
  const destructureRegex = /export\s+(?:const|let|var)\s+(\{[^}]*\}|\[[^\]]*\])\s*=/g;
1084
1633
  const bindingNameRegex = new RegExp(`^(${JS_IDENTIFIER_PATTERN})`, "u");
1085
1634
  while ((match = destructureRegex.exec(source)) !== null) {
1635
+ if (!codePositions[match.index]) continue;
1636
+ recognizedExportStarts.add(match.index);
1086
1637
  const inner = match[1].slice(1, -1);
1087
1638
  for (const part of inner.split(",")) {
1088
1639
  let token = part.split("=")[0].trim();
@@ -1097,45 +1648,109 @@ function getNamedExportsViaRegex(source, filePath, visited) {
1097
1648
  const typeOnlySpecifierRegex = new RegExp(`^type\\s+${JS_IDENTIFIER_PATTERN}(?:\\s+as\\s+${JS_IDENTIFIER_PATTERN})?$`, "u");
1098
1649
  const exportSpecifierRegex = new RegExp(`(?:\\S+\\s+as\\s+)?(${JS_IDENTIFIER_PATTERN})$`, "u");
1099
1650
  while ((match = listRegex.exec(source)) !== null) {
1651
+ if (!codePositions[match.index]) continue;
1652
+ recognizedExportStarts.add(match.index);
1100
1653
  const specifiers = match[1].split(",");
1101
1654
  for (const specifier of specifiers) {
1102
1655
  const trimmed = specifier.trim();
1103
1656
  if (typeOnlySpecifierRegex.test(trimmed)) continue;
1104
1657
  const asMatch = trimmed.match(exportSpecifierRegex);
1105
- if (!asMatch) continue;
1658
+ if (!asMatch) {
1659
+ scanState.complete = false;
1660
+ continue;
1661
+ }
1106
1662
  const name = asMatch[1];
1107
1663
  if (isValidEsmExportName(name)) names.add(name);
1664
+ else scanState.complete = false;
1108
1665
  }
1109
1666
  }
1110
1667
  const namespaceReExportRegex = new RegExp(`export\\s+\\*\\s+as\\s+(${JS_IDENTIFIER_PATTERN})\\s+from\\s+['"][^'"]+['"]`, "gu");
1111
- 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;
1112
1674
  if (filePath) {
1113
1675
  const starExportRegex = /export\s+\*\s+from\s+['"]([^'"]+)['"]/g;
1114
1676
  while ((match = starExportRegex.exec(source)) !== null) {
1677
+ if (!codePositions[match.index]) continue;
1678
+ recognizedExportStarts.add(match.index);
1115
1679
  const specifier = match[1];
1116
1680
  const resolvedPath = resolveReExportModule(filePath, specifier);
1117
- 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
+ }
1118
1690
  try {
1119
- 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);
1120
1697
  for (const name of reExportNames) names.add(name);
1121
- } 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;
1122
1714
  }
1123
1715
  }
1124
1716
  return Array.from(names);
1125
1717
  }
1126
- function getPackageNamedExports(pkg) {
1718
+ function getRequiredNamedExports(specifier) {
1127
1719
  try {
1128
- const mod = createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json")))(pkg);
1129
- 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;
1130
1724
  } catch {
1131
- return getEsmNamedExports(pkg);
1725
+ return;
1132
1726
  }
1133
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
+ }
1134
1746
  function getSharedNamedExports(pkg, shareItem) {
1135
1747
  const configuredImport = shareItem?.shareConfig.import;
1136
1748
  if (typeof configuredImport === "string") {
1137
- const configuredNamedExports = getEsmNamedExportsFromFile(resolveConfiguredImportPath(configuredImport));
1138
- 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;
1139
1754
  }
1140
1755
  return getPackageNamedExports(pkg);
1141
1756
  }
@@ -1173,7 +1788,7 @@ function isWorkspaceFilePath(resolved) {
1173
1788
  try {
1174
1789
  realResolved = realpathSync.native(resolved);
1175
1790
  } catch {}
1176
- return !realResolved.includes("/node_modules/") && !realResolved.includes("\\node_modules\\");
1791
+ return !normalizeNodeModulePath(realResolved).includes("/node_modules/");
1177
1792
  }
1178
1793
  /**
1179
1794
  * When createRequire resolves a workspace package to a CJS entry (e.g. dist/index.cjs),
@@ -1285,10 +1900,104 @@ function getConcreteSharedImportSource(pkg, shareItem) {
1285
1900
  const preBuildCacheMap = {};
1286
1901
  const preBuildShareItemMap = {};
1287
1902
  const PREBUILD_TAG = "__prebuild__";
1903
+ const treeShakingProviderCacheMap = {};
1904
+ const materializedTreeShakingProviders = /* @__PURE__ */ new Set();
1905
+ const TREE_SHAKING_PROVIDER_TAG = "__treeShakingProvider__";
1906
+ const TREE_SHAKING_GRAPH_QUERY = "__mf_tree_shaking_graph__";
1907
+ function getTreeShakingGraphToken(id) {
1908
+ if (!id) return void 0;
1909
+ const queryStart = id.indexOf("?");
1910
+ if (queryStart === -1) return void 0;
1911
+ const hashStart = id.indexOf("#", queryStart);
1912
+ const entry = id.slice(queryStart + 1, hashStart === -1 ? void 0 : hashStart).split("&").find((part) => part.split("=", 1)[0] === TREE_SHAKING_GRAPH_QUERY);
1913
+ if (!entry) return void 0;
1914
+ const value = entry.slice(26);
1915
+ try {
1916
+ return decodeURIComponent(value);
1917
+ } catch {
1918
+ return value;
1919
+ }
1920
+ }
1921
+ function stripTreeShakingGraphQuery(id) {
1922
+ const queryStart = id.indexOf("?");
1923
+ if (queryStart === -1) return id;
1924
+ const hashStart = id.indexOf("#", queryStart);
1925
+ const pathname = id.slice(0, queryStart);
1926
+ const hash = hashStart === -1 ? "" : id.slice(hashStart);
1927
+ const remaining = id.slice(queryStart + 1, hashStart === -1 ? void 0 : hashStart).split("&").filter(Boolean).filter((part) => part.split("=", 1)[0] !== TREE_SHAKING_GRAPH_QUERY);
1928
+ return `${pathname}${remaining.length ? `?${remaining.join("&")}` : ""}${hash}`;
1929
+ }
1930
+ function addTreeShakingGraphQuery(id, token) {
1931
+ const cleanId = stripTreeShakingGraphQuery(id);
1932
+ const hashStart = cleanId.indexOf("#");
1933
+ const base = hashStart === -1 ? cleanId : cleanId.slice(0, hashStart);
1934
+ const hash = hashStart === -1 ? "" : cleanId.slice(hashStart);
1935
+ return `${base}${base.includes("?") ? "&" : "?"}${TREE_SHAKING_GRAPH_QUERY}=${encodeURIComponent(token)}${hash}`;
1936
+ }
1937
+ function getConcreteTreeShakingExportUsage(pkg, shareItem) {
1938
+ return getTreeShakingExportUsage(pkg, shareItem, shareItem?.name);
1939
+ }
1940
+ function getTreeShakingSharedProviderName(pkg) {
1941
+ const { internalName, name } = getNormalizeModuleFederationOptions();
1942
+ return `${internalName || name}__tree_shaking__${packageNameEncode(pkg)}`;
1943
+ }
1944
+ function getTreeShakingSharedProviderImportId(pkg) {
1945
+ if (!treeShakingProviderCacheMap[pkg]) treeShakingProviderCacheMap[pkg] = new VirtualModule(pkg, TREE_SHAKING_PROVIDER_TAG, ".js");
1946
+ return treeShakingProviderCacheMap[pkg].getImportId();
1947
+ }
1948
+ function hasTreeShakingSharedProvider(pkg, shareItem) {
1949
+ const usage = getConcreteTreeShakingExportUsage(pkg, shareItem);
1950
+ return materializedTreeShakingProviders.has(pkg) && usage?.kind === "exports";
1951
+ }
1952
+ /**
1953
+ * Materialize the locally optimized provider as a small ESM container.
1954
+ *
1955
+ * The normal prebuild module remains the complete fallback. This container only
1956
+ * retains the selected exports and is installed as `treeShaking.get` by the
1957
+ * generated runtime record. Keeping the two getters distinct lets the Runtime
1958
+ * perform its normal usedExports compatibility check and safely choose the full
1959
+ * provider when the optimized one is insufficient.
1960
+ */
1961
+ function writeTreeShakingSharedProvider(pkg, shareItem) {
1962
+ const usage = getConcreteTreeShakingExportUsage(pkg, shareItem);
1963
+ if (usage?.kind !== "exports" || !usage.usedExports.length || shareItem?.shareConfig.import === false) {
1964
+ materializedTreeShakingProviders.delete(pkg);
1965
+ return;
1966
+ }
1967
+ const usedExports = usage.usedExports;
1968
+ const unsupportedExport = usedExports.find((name) => name !== "default" && !isValidEsmExportName(name));
1969
+ if (unsupportedExport) {
1970
+ materializedTreeShakingProviders.delete(pkg);
1971
+ mfWarn(`Tree-shaking shared dependency "${pkg}" was disabled because export "${unsupportedExport}" cannot be represented by the generated ESM provider.`);
1972
+ return;
1973
+ }
1974
+ const provider = treeShakingProviderCacheMap[pkg] || (treeShakingProviderCacheMap[pkg] = new VirtualModule(pkg, "__treeShakingProvider__", ".js"));
1975
+ const optimizedImportSource = addTreeShakingGraphQuery(getConcreteSharedImportSource(pkg, shareItem) || pkg, pkg);
1976
+ const namedExports = usedExports.filter((name) => name !== "default");
1977
+ const namedImports = namedExports.map((name, index) => `${name} as __mfTreeShaken_${index}`).join(", ");
1978
+ const importLines = [namedImports ? `import { ${namedImports} } from ${escapeGeneratedStringLiteral(optimizedImportSource)};` : "", usedExports.includes("default") ? `import __mfTreeShakenDefault from ${escapeGeneratedStringLiteral(optimizedImportSource)};` : ""].filter(Boolean).join("\n");
1979
+ const namespaceEntries = [...namedExports.map((name, index) => `[${JSON.stringify(name)}]: __mfTreeShaken_${index}`), ...usedExports.includes("default") ? ["default: __mfTreeShakenDefault"] : [`default: { ${namedExports.map((name, index) => `[${JSON.stringify(name)}]: __mfTreeShaken_${index}`).join(", ")} }`]];
1980
+ provider.writeSync(`${importLines}
1981
+ const __mfTreeShakenModule = { ${namespaceEntries.join(", ")} };
1982
+ Object.defineProperty(__mfTreeShakenModule, "__esModule", {
1983
+ value: true,
1984
+ enumerable: false,
1985
+ });
1986
+ async function init() {}
1987
+ function get() {
1988
+ return () => __mfTreeShakenModule;
1989
+ }
1990
+ const usedExports = ${JSON.stringify([...usedExports].sort())};
1991
+ export { get, init, usedExports };
1992
+ export default { get, init };
1993
+ `, true);
1994
+ materializedTreeShakingProviders.add(pkg);
1995
+ }
1288
1996
  function writePreBuildLibPath(pkg, shareItem) {
1289
1997
  if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG, ".js");
1290
1998
  preBuildShareItemMap[pkg] = shareItem;
1291
1999
  const importSource = getConcreteSharedImportSource(pkg, shareItem) || pkg;
2000
+ writeTreeShakingSharedProvider(pkg, shareItem);
1292
2001
  if (pkg === "react/compiler-runtime") {
1293
2002
  const reactCacheDescriptor = getSharedCacheDescriptorLiteral("react", shareItem ?? {
1294
2003
  name: "react",
@@ -1333,7 +2042,7 @@ function writePreBuildLibPath(pkg, shareItem) {
1333
2042
  `, true);
1334
2043
  return;
1335
2044
  }
1336
- const namedExports = getSharedNamedExports(pkg, shareItem);
2045
+ const namedExports = getSharedNamedExports(pkg, shareItem) ?? [];
1337
2046
  if (namedExports.length > 0) {
1338
2047
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1339
2048
  const declarations = namedExports.map((name, i) => `const ${namedExportVars[i]} = __mfPrebuildExports[${escapeGeneratedStringLiteral(name)}];`).join("\n ");
@@ -1343,16 +2052,27 @@ function writePreBuildLibPath(pkg, shareItem) {
1343
2052
  const __mfPrebuildExports = __mfPrebuildNamespace;
1344
2053
  ${declarations}
1345
2054
  ${namedExportLine}
1346
- export default __mfPrebuildNamespace.default ?? __mfPrebuildNamespace;
2055
+ export default Reflect.get(__mfPrebuildNamespace, "default") ?? __mfPrebuildNamespace;
1347
2056
  `, true);
1348
2057
  return;
1349
2058
  }
1350
2059
  preBuildCacheMap[pkg].writeSync(`
1351
2060
  import * as __mfPrebuildExports from ${escapeGeneratedStringLiteral(importSource)};
1352
2061
  export * from ${escapeGeneratedStringLiteral(importSource)};
1353
- export default __mfPrebuildExports.default ?? __mfPrebuildExports;
2062
+ // Reflect access avoids bundler warnings for ESM packages without a
2063
+ // default export (for example antd/es/index.js), while preserving the
2064
+ // namespace fallback for packages that do provide one.
2065
+ export default Reflect.get(__mfPrebuildExports, "default") ?? __mfPrebuildExports;
1354
2066
  `, true);
1355
2067
  }
2068
+ /** Re-render already materialized wrappers after import analysis discovers exports. */
2069
+ function refreshTreeShakingModules() {
2070
+ for (const [pkg, shareItem] of Object.entries(preBuildShareItemMap)) {
2071
+ if (!shareItem?.shareConfig.treeShaking) continue;
2072
+ writePreBuildLibPath(pkg, shareItem);
2073
+ writeLoadShareModule(pkg, shareItem, "build", false);
2074
+ }
2075
+ }
1356
2076
  function getPreBuildLibImportId(pkg) {
1357
2077
  if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG, ".js");
1358
2078
  return preBuildCacheMap[pkg].getImportId();
@@ -1398,49 +2118,58 @@ function materializeCachedLoadShareModule(options) {
1398
2118
  options.addUsedShares(pkg);
1399
2119
  options.writeLocalSharedImportMap();
1400
2120
  }
1401
- function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor) {
2121
+ function getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer) {
2122
+ return treeShakingConsumer ? `__mfReadTreeShakingSharedSelection(__mfModuleCache.share, ${cacheDescriptor}, ${JSON.stringify(treeShakingConsumer)})` : `__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor})`;
2123
+ }
2124
+ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer) {
1402
2125
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1403
- 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 ");
1404
2128
  const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1405
2129
  return `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(importSource)};
1406
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
2130
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1407
2131
  if (exportModule === undefined) {
1408
2132
  Promise.resolve().then(() => {
1409
2133
  if (__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor}) === undefined) {
1410
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfNormalizeShareModule(__mfLocalShare));
2134
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfNormalizeShareModule(__mfLocalShare), ${cacheOwner});
1411
2135
  }
1412
2136
  });
1413
2137
  exportModule = __mfLocalShare;
1414
2138
  }
1415
- 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);
1416
2145
  export { __mf_default as default };${namedExportLine}`;
1417
2146
  }
1418
- function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor) {
2147
+ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer) {
1419
2148
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1420
2149
  const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
1421
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;";
1422
2151
  const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
2152
+ const applyLocalFallback = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
2153
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
1423
2154
  return `${declarations}
1424
2155
  const __mfApplyLazyShareExports = (mod) => {
1425
2156
  ${assignments}
1426
2157
  };
1427
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
2158
+ __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyLazyShareExports);
2159
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1428
2160
  if (exportModule === undefined) {
1429
2161
  if (import.meta.env.SSR) {
1430
- ${`exportModule = __mfNormalizeShareModule(__mfLocalShare);
1431
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1432
- __mfApplyLazyShareExports(exportModule);`}
2162
+ ${applyLocalFallback}
1433
2163
  } else {
1434
2164
  (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
1435
- exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
2165
+ exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1436
2166
  if (exportModule !== undefined) {
1437
2167
  __mfApplyLazyShareExports(exportModule);
1438
2168
  return;
1439
2169
  }
1440
2170
  return import(${escapeGeneratedStringLiteral(importSource)}).then((mod) => {
1441
2171
  exportModule = __mfNormalizeShareModule(mod);
1442
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1443
- __mfApplyLazyShareExports(exportModule);
2172
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
1444
2173
  });
1445
2174
  }));
1446
2175
  }
@@ -1459,16 +2188,19 @@ function prependWorkspaceSingletonSsrImport(code) {
1459
2188
  const quote = importMatch[1];
1460
2189
  return `import * as __mfLocalShare from ${quote}${importMatch[2]}${quote};\n${code}`;
1461
2190
  }
1462
- function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor) {
2191
+ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer) {
1463
2192
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1464
- return `${["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ")}
2193
+ const declarations = ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ");
2194
+ const assignments = [...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ");
2195
+ const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
2196
+ return `${declarations}
1465
2197
  const __mfApplyHostProvidedExports = (exportModule) => {
1466
- ${[...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ")}
2198
+ ${assignments}
1467
2199
  };
1468
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
2200
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1469
2201
  if (exportModule === undefined) {
1470
2202
  (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
1471
- exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
2203
+ exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1472
2204
  if (exportModule === undefined) {
1473
2205
  throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
1474
2206
  }
@@ -1477,7 +2209,7 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor)
1477
2209
  } else {
1478
2210
  __mfApplyHostProvidedExports(exportModule);
1479
2211
  }
1480
- export { __mf_default as default };${namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : ""}`;
2212
+ export { __mf_default as default };${namedExportLine}`;
1481
2213
  }
1482
2214
  function generateShareModuleUnwrapCode({ source, preserveNamedExports, stopWithReturn }) {
1483
2215
  return `let current = ${source};
@@ -1500,13 +2232,16 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1500
2232
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".js");
1501
2233
  let importLine = getRuntimeModuleCacheBootstrapCode();
1502
2234
  const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
2235
+ const cacheOwner = JSON.stringify(getNormalizeModuleFederationOptions().name);
2236
+ const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ? getNormalizeModuleFederationOptions().name : void 0;
1503
2237
  if (shareItem.shareConfig.import === false) {
1504
- const namedExports = getPackageNamedExports(pkg);
2238
+ const detectedNamedExports = getPackageNamedExports(pkg);
2239
+ const namedExports = detectedNamedExports ?? [];
1505
2240
  let exportLine;
1506
- if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor);
2241
+ if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer);
1507
2242
  else {
1508
- 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.`);
1509
- exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor);
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.`);
2244
+ exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor, treeShakingConsumer);
1510
2245
  }
1511
2246
  loadShareCacheMap[pkg].writeSync(`
1512
2247
  ${getRuntimeInitPromiseBootstrapCode()}
@@ -1520,22 +2255,59 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1520
2255
  const sharedImportSource = concreteSharedImportSource || getPreBuildLibImportId(pkg);
1521
2256
  const devImportSource = concreteSharedImportSource || pkg;
1522
2257
  const localProviderPath = getLocalProviderImportPath(pkg);
2258
+ const coherentLocalSource = concreteSharedImportSource || localProviderPath || devImportSource;
1523
2259
  const isWorkspacePackage = isWorkspacePackageEntry(pkg, localProviderPath) || isWorkspacePackageEntry(pkg, concreteSharedImportSource);
1524
2260
  const lazyLocalFallbackSource = command !== "build" ? concreteSharedImportSource || localProviderPath || devImportSource : concreteSharedImportSource || localProviderPath || sharedImportSource;
1525
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;
1526
2265
  const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
1527
2266
  const isDefaultShareScope = shareItem.scope === void 0 || shareItem.scope === "default" || Array.isArray(shareItem.scope) && shareItem.scope[0] === "default";
1528
- 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);
1529
2268
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg);
1530
- const usesEntryInjectedRemoteFallback = command !== "build" && !isWorkspaceSingleton && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && getNormalizeModuleFederationOptions().hostInitInjectLocation === "entry" && isConsumedByPeerSingleton;
1531
- const usesEagerWorkspaceFallback = isWorkspaceSingleton && isConsumedByPeerSingleton;
1532
- 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);
1533
2272
  let exportLine;
1534
2273
  let initBlock = "";
1535
- if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor);
2274
+ if (usesDeferredTreeShakingFallback) {
2275
+ importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
2276
+ exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer);
2277
+ } else if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer);
1536
2278
  else if (usesDeferredSingletonFallback) {
1537
2279
  importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
1538
- exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor);
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});`;
1539
2311
  } else if (namedExports.length > 0) {
1540
2312
  const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1541
2313
  const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
@@ -1550,15 +2322,26 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1550
2322
  ${destructure}
1551
2323
  ${namedExportLine}`;
1552
2324
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1553
- __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});`;
1554
2337
  } else {
1555
2338
  exportLine = `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
1556
2339
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1557
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);`;
2340
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
1558
2341
  }
1559
- const prebuildImportLine = usesDeferredSingletonFallback || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
1560
- const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
1561
- const moduleBody = usesDeferredSingletonFallback ? `
2342
+ const prebuildImportLine = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
2343
+ const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
2344
+ const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? `
1562
2345
  ${prebuildImportLine}
1563
2346
  ${devDynamicImportLine}
1564
2347
  ${importLine}
@@ -1571,7 +2354,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1571
2354
  ${importLine}
1572
2355
  ${sharedCacheHelperCode}
1573
2356
  ${normalizeLocalShareModuleCode}
1574
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor})
2357
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)}
1575
2358
  if (exportModule === undefined) {
1576
2359
  ${initBlock}
1577
2360
  }
@@ -1618,14 +2401,21 @@ function getDirectSharedCacheSeedImportPath(pkg, shareItem) {
1618
2401
  function generateLocalSharedImportMap() {
1619
2402
  const useDirectReactImport = shouldUseDirectReactImport();
1620
2403
  const options = getNormalizeModuleFederationOptions();
2404
+ const orderedShares = getOrderedUsedShares();
1621
2405
  return `
1622
2406
  import {loadShare} from "@module-federation/runtime";
2407
+ ${orderedShares.map((pkg, index) => {
2408
+ const shareItem = getNormalizeShareItem(pkg);
2409
+ if (!shareItem?.shareConfig.eager || shareItem.shareConfig.import === false) return "";
2410
+ return `import * as __mfEagerShare_${index} from ${JSON.stringify(getLocalSharedPackagePath(pkg, shareItem))};`;
2411
+ }).filter(Boolean).join("\n")}
1623
2412
  const importMap = {
1624
- ${getOrderedUsedShares().map((pkg) => {
2413
+ ${orderedShares.map((pkg, index) => {
1625
2414
  const shareItem = getNormalizeShareItem(pkg);
1626
2415
  return `
1627
2416
  ${JSON.stringify(pkg)}: async () => {
1628
- ${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(pkg)}}' must be provided by host\`);` : `let pkg = await import(${JSON.stringify(getLocalSharedPackagePath(pkg, shareItem))});
2417
+ ${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(pkg)}}' must be provided by host\`);` : shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
2418
+ return pkg;` : `let pkg = await import(${JSON.stringify(getLocalSharedPackagePath(pkg, shareItem))});
1629
2419
  return pkg;`}
1630
2420
  }
1631
2421
  `;
@@ -1635,13 +2425,24 @@ function generateLocalSharedImportMap() {
1635
2425
  ${getOrderedUsedShares().map((key) => {
1636
2426
  const shareItem = getNormalizeShareItem(key);
1637
2427
  if (!shareItem) return null;
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;
2432
+ const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
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;
1638
2437
  return `
1639
2438
  ${JSON.stringify(key)}: {
1640
2439
  name: ${JSON.stringify(key)},
1641
2440
  version: ${JSON.stringify(shareItem.version)},
1642
2441
  scope: [${JSON.stringify(shareItem.scope)}],
1643
2442
  loaded: false,
2443
+ eager: ${Boolean(shareItem.shareConfig.eager)},
1644
2444
  from: ${JSON.stringify(options.name)},
2445
+ canLiveRebind: ${canLiveRebind},
1645
2446
  async get () {
1646
2447
  if (${shareItem.shareConfig.import === false}) {
1647
2448
  throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
@@ -1665,8 +2466,20 @@ function generateLocalSharedImportMap() {
1665
2466
  singleton: ${shareItem.shareConfig.singleton},
1666
2467
  requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
1667
2468
  strictVersion: ${shareItem.shareConfig.strictVersion},
2469
+ eager: ${Boolean(shareItem.shareConfig.eager)},
1668
2470
  ${shareItem.shareConfig.import === false ? "import: false," : ""}
1669
- }
2471
+ },
2472
+ ${treeShakingConfig ? `treeShaking: {
2473
+ mode: ${JSON.stringify(treeShakingConfig.mode)},
2474
+ usedExports: ${JSON.stringify(treeShakingUsedExports)},
2475
+ providedExports: ${JSON.stringify(treeShakingProviderExports)},
2476
+ status: ${treeShakingStatus},
2477
+ ${treeShakingProviderImportId ? `async get() {
2478
+ const container = await import(${JSON.stringify(treeShakingProviderImportId)});
2479
+ if (typeof container.init === "function") await container.init();
2480
+ return container.get();
2481
+ },` : ""}
2482
+ }` : ""}
1670
2483
  }
1671
2484
  `;
1672
2485
  }).filter((x) => x !== null).join(",")}
@@ -1676,6 +2489,7 @@ function generateLocalSharedImportMap() {
1676
2489
  if (!remote) return null;
1677
2490
  return `
1678
2491
  {
2492
+ alias: ${JSON.stringify(key)},
1679
2493
  entryGlobalName: ${JSON.stringify(remote.entryGlobalName)},
1680
2494
  name: ${JSON.stringify(remote.name)},
1681
2495
  type: ${JSON.stringify(remote.type)},
@@ -1752,6 +2566,7 @@ function getShareItemForPreload(pkg) {
1752
2566
  }
1753
2567
  function generateSharedCacheSeedItem(pkg, shareItem, importPath) {
1754
2568
  const cacheDescriptor = getSharedCacheDescriptor(pkg, shareItem);
2569
+ const cacheOwner = getNormalizeModuleFederationOptions().name;
1755
2570
  return `if (__mfReadSharedCache(__mfModuleCache.share, ${JSON.stringify(cacheDescriptor)}) === undefined) {
1756
2571
  const mod = await import(${JSON.stringify(importPath)});
1757
2572
  ${normalizeRuntimeShareCode}
@@ -1761,7 +2576,7 @@ function generateSharedCacheSeedItem(pkg, shareItem, importPath) {
1761
2576
  value: true,
1762
2577
  enumerable: false
1763
2578
  });
1764
- __mfWriteSharedCache(__mfModuleCache.share, ${JSON.stringify(cacheDescriptor)}, exportModule);
2579
+ __mfWriteSharedCache(__mfModuleCache.share, ${JSON.stringify(cacheDescriptor)}, exportModule, ${JSON.stringify(cacheOwner)});
1765
2580
  }`;
1766
2581
  }
1767
2582
  const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
@@ -1782,15 +2597,33 @@ const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbo
1782
2597
  const selectionVersions = {};
1783
2598
  for (const [version, provider] of Object.entries(versions)) {
1784
2599
  selectionVersions[version] = Object.assign({}, provider, {
1785
- loaded: false,
1786
- loading: undefined,
1787
- lib: undefined,
1788
2600
  [__mfOriginalProviderKey]: provider
1789
2601
  });
1790
2602
  }
1791
2603
  return selectionVersions;
1792
2604
  };
1793
- 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
+ ) => {
1794
2627
  if (!versions || !share) return undefined;
1795
2628
  const scopes = Array.isArray(share.scope) ? share.scope : [share.scope || "default"];
1796
2629
  const selectionVersions = __mfCreateProviderSelectionVersions(versions, strategy);
@@ -1806,10 +2639,103 @@ const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbo
1806
2639
  )?.shared;
1807
2640
  return selected?.[__mfOriginalProviderKey] || selected;
1808
2641
  };`;
1809
- function hasImportFalseShared$1(options) {
1810
- return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
1811
- }
1812
- 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) {
1813
2739
  const seedOrder = getOrderedUsedShares();
1814
2740
  return `
1815
2741
  const __mfSeedOrder = ${JSON.stringify(seedOrder)};
@@ -1835,30 +2761,99 @@ function generateRuntimeSharedCacheSeedCode() {
1835
2761
  }
1836
2762
  __mfSeedKeys.splice(insertIndex, 0, pkg);
1837
2763
  }
1838
- for (const pkg of __mfSeedKeys) {
1839
- const share = usedShared[pkg];
1840
- const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
1841
- if (share.shareConfig?.import === false || __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) {
1842
- continue;
1843
- }
1844
- const singletonCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, true, share.version, share.scope);
1845
- const singletonModule = __mfReadSharedCache(__mfModuleCache.share, singletonCacheDescriptor);
1846
- if (singletonModule !== undefined) {
1847
- __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, singletonModule);
1848
- 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);
1849
2797
  }
1850
- const factory = await share.get();
1851
- const mod = typeof factory === "function" ? factory() : factory;
1852
- const resolved = await Promise.resolve(mod);
1853
- ${normalizeRuntimeShareCode}
1854
- const normalizedModule = __mfNormalizeRuntimeShare(resolved);
1855
- const exportModule = normalizedModule === resolved ? {...resolved} : normalizedModule;
1856
- Object.defineProperty(exportModule, "__esModule", {
1857
- value: true,
1858
- enumerable: false
1859
- });
1860
- __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, exportModule);
1861
- }`;
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);`;
1862
2857
  }
1863
2858
  function getBrowserImportPath(importPath) {
1864
2859
  if (/^(?:[a-zA-Z]:[\\/]|\/)/.test(importPath) && !importPath.startsWith("/@")) return `/@fs/${importPath}`;
@@ -1886,11 +2881,178 @@ const REMOTE_ENTRY_ID = "virtual:mf-REMOTE_ENTRY_ID";
1886
2881
  function getRemoteEntryId(options) {
1887
2882
  return `${REMOTE_ENTRY_ID}:${`${options.internalName}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
1888
2883
  }
1889
- const SSR_ONLY_PLUGIN_SPECIFIERS = new Set(["@module-federation/vite/ssrEntryLoader"]);
1890
- const isSsrOnlyPlugin = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].some((s) => importStatement.includes(s));
1891
- const getSsrOnlyPluginSpecifier = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].find((s) => importStatement.includes(s));
2884
+ const SSR_ONLY_PLUGIN_SPECIFIERS = new Set(["@module-federation/vite/ssrEntryLoader"]);
2885
+ const isSsrOnlyPlugin = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].some((s) => importStatement.includes(s));
2886
+ const getSsrOnlyPluginSpecifier = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].find((s) => importStatement.includes(s));
2887
+ function generateTreeShakingSharedResolutionCode(enabled) {
2888
+ if (!enabled) return "const __mfResolveTreeShakingShared = async () => {};";
2889
+ return `
2890
+ // Resolve tree-enabled shares through the Runtime after all providers have
2891
+ // registered. Partial providers are stored with their export coverage and
2892
+ // never occupy generic/legacy cache keys, which are reserved for complete
2893
+ // modules only.
2894
+ const __mfResolveTreeShakingShared = async (pkg, share) => {
2895
+ const treeShaking = share.treeShaking;
2896
+ if (!treeShaking) return;
2897
+ try {
2898
+ const factory = await initRes.loadShare(pkg, {
2899
+ customShareInfo: {
2900
+ shareConfig: share.shareConfig,
2901
+ treeShaking: {
2902
+ mode: treeShaking.mode,
2903
+ status: treeShaking.status,
2904
+ usedExports: treeShaking.usedExports,
2905
+ },
2906
+ },
2907
+ });
2908
+ if (factory === false) return;
2909
+ const mod = typeof factory === "function" ? factory() : factory;
2910
+ const resolved = await Promise.resolve(mod);
2911
+ ${normalizeRuntimeShareCode}
2912
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2913
+ const normalizedShared = __mfNormalizeRuntimeShare(resolved);
2914
+ const providedExports = treeShaking.providedExports ?? treeShaking.usedExports ?? [];
2915
+ const hasPartialProvider =
2916
+ ((treeShaking.mode === "runtime-infer" && treeShaking.status !== 0) ||
2917
+ treeShaking.status === 2);
2918
+ if (hasPartialProvider) {
2919
+ __mfWriteTreeShakingSharedCache(
2920
+ __mfModuleCache.share,
2921
+ cacheDescriptor,
2922
+ providedExports,
2923
+ normalizedShared
2924
+ );
2925
+ __mfWriteTreeShakingSharedSelection(
2926
+ __mfModuleCache.share,
2927
+ cacheDescriptor,
2928
+ mfName,
2929
+ normalizedShared
2930
+ );
2931
+ } else {
2932
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, normalizedShared);
2933
+ }
2934
+ } catch (e) {
2935
+ console.warn('[Module Federation] Failed to load tree-shaken shared module', pkg, e);
2936
+ }
2937
+ };`;
2938
+ }
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;
2945
+ args.resolver = () => {
2946
+ const resolved = originalResolver();
2947
+ if (!resolved?.useTreesShaking) return resolved;
2948
+
2949
+ const selectedExports = resolved.shared?.treeShaking?.usedExports;
2950
+ const selectedMatches = Array.isArray(selectedExports) &&
2951
+ requiredExports.every((name) => selectedExports.includes(name));
2952
+ if (selectedMatches) return resolved;
2953
+
2954
+ // Runtime 2.7 prefers a tree provider by version before checking export
2955
+ // coverage. Prefer this consumer's own compatible provider when one is
2956
+ // available; otherwise retain the selected version but use its complete
2957
+ // top-level getter.
2958
+ const localExports = consumerTreeShaking.providedExports;
2959
+ const localMatches = typeof consumerTreeShaking.get === "function" &&
2960
+ Array.isArray(localExports) &&
2961
+ requiredExports.every((name) => localExports.includes(name));
2962
+ if (localMatches) {
2963
+ return { shared: args.shareInfo, useTreesShaking: true };
2964
+ }
2965
+ return { shared: resolved.shared, useTreesShaking: false };
2966
+ };
2967
+ return args;`;
2968
+ function generateTreeShakingSnapshotPluginCode(enabled) {
2969
+ if (!enabled) return "";
2970
+ return `
2971
+ const __mfTreeShakingSnapshotPlugin = () => ({
2972
+ name: "vite-tree-shaking-snapshot-plugin",
2973
+ resolveShare(args) {
2974
+ ${treeShakingResolveShareBodyCode}
2975
+ },
2976
+ beforeInit(args) {
2977
+ const { userOptions, origin, options: registeredOptions } = args;
2978
+ const version = userOptions.version || registeredOptions.version;
2979
+ const hostSnapshot = runtimeGlobal.getGlobalSnapshotInfoByModuleInfo({
2980
+ name: origin.name,
2981
+ version,
2982
+ });
2983
+ if (!hostSnapshot || !("shared" in hostSnapshot)) return args;
2984
+
2985
+ const candidates = [];
2986
+ const appendShared = (records) => {
2987
+ for (const [pkgName, value] of Object.entries(records || {})) {
2988
+ const values = Array.isArray(value) ? value : [value];
2989
+ for (const shared of values) candidates.push([pkgName, shared]);
2990
+ }
2991
+ };
2992
+ appendShared(userOptions.shared);
2993
+ appendShared(registeredOptions.shared);
2994
+
2995
+ for (const [pkgName, shared] of candidates) {
2996
+ const treeShaking = shared?.treeShaking;
2997
+ if (!treeShaking || treeShaking.mode !== "server-calc") continue;
2998
+ const shareSnapshot = hostSnapshot.shared.find((item) => item.sharedName === pkgName);
2999
+ if (!shareSnapshot || typeof shareSnapshot.treeShakingStatus !== "number") continue;
3000
+ const {
3001
+ secondarySharedTreeShakingEntry: entry,
3002
+ secondarySharedTreeShakingName: name,
3003
+ treeShakingStatus: status,
3004
+ usedExports,
3005
+ fallbackType,
3006
+ } = shareSnapshot;
3007
+
3008
+ // A CALCULATED snapshot without a loadable secondary entry is not safe:
3009
+ // retain UNKNOWN so the Runtime chooses the complete top-level getter.
3010
+ if (status === 2 && (!entry || !name)) continue;
3011
+ if (Array.isArray(usedExports)) {
3012
+ treeShaking.usedExports = usedExports;
3013
+ treeShaking.providedExports = usedExports;
3014
+ }
3015
+ if (entry && name) {
3016
+ const fullFallbackGet = shared.get;
3017
+ treeShaking.get = async () => {
3018
+ try {
3019
+ const shareEntry = await getRemoteEntry({
3020
+ origin,
3021
+ remoteInfo: {
3022
+ name,
3023
+ entry,
3024
+ type: fallbackType || "global",
3025
+ entryGlobalName: name,
3026
+ shareScope: "default",
3027
+ },
3028
+ });
3029
+ if (!shareEntry) throw new Error("Tree-shaken shared entry did not load");
3030
+ if (typeof shareEntry.init === "function") {
3031
+ await shareEntry.init(origin);
3032
+ }
3033
+ return shareEntry.get();
3034
+ } catch (error) {
3035
+ if (typeof fullFallbackGet === "function") return fullFallbackGet();
3036
+ throw error;
3037
+ }
3038
+ };
3039
+ }
3040
+ treeShaking.status = status;
3041
+ }
3042
+ return args;
3043
+ },
3044
+ });`;
3045
+ }
1892
3046
  function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
1893
- const needsSharedProviderSelectionHelper = hasImportFalseShared$1(options);
3047
+ const needsSharedProviderSelectionHelper = Object.keys(options.shared ?? {}).length > 0;
3048
+ const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
3049
+ const hasEagerShared = Object.values(options.shared ?? {}).some((share) => share?.shareConfig.eager === true && share.shareConfig.import !== false);
3050
+ const runtimeImports = [
3051
+ "init as runtimeInit",
3052
+ "loadRemote",
3053
+ ...hasTreeShakingShared ? ["getRemoteEntry"] : []
3054
+ ].join(", ");
3055
+ const runtimeHelperImports = [...hasTreeShakingShared ? ["global as runtimeGlobal"] : [], ...needsSharedProviderSelectionHelper ? ["share as runtimeShare"] : []];
1894
3056
  const pluginImportNames = options.runtimePlugins.map((p, i) => {
1895
3057
  if (typeof p === "string") return [
1896
3058
  `$runtimePlugin_${i}`,
@@ -1903,6 +3065,17 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1903
3065
  serializeRuntimeOptions(p[1])
1904
3066
  ];
1905
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
+ }`;
1906
3079
  return `
1907
3080
  // Shim Vue HMR runtime for dev-compiled components loaded by a non-Vite host.
1908
3081
  // When a remote is served by a Vite dev server, Vue's SFC compiler injects HMR
@@ -1912,8 +3085,9 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1912
3085
  if (typeof __VUE_HMR_RUNTIME__ === 'undefined') {
1913
3086
  globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
1914
3087
  }
1915
- import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
1916
- ${needsSharedProviderSelectionHelper ? "import {share as runtimeShare} from \"@module-federation/runtime/helpers\";" : ""}
3088
+ import {${runtimeImports}} from "@module-federation/runtime";
3089
+ ${hasEagerShared ? `import * as __mfLocalSharedImportMap from "${getLocalSharedImportMapPath()}";` : ""}
3090
+ ${runtimeHelperImports.length ? `import {${runtimeHelperImports.join(", ")}} from "@module-federation/runtime/helpers";` : ""}
1917
3091
  ${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
1918
3092
  ${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
1919
3093
  ${getRuntimeModuleCacheBootstrapCode()}
@@ -1941,14 +3115,17 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1941
3115
  }
1942
3116
  }
1943
3117
  }
3118
+ ${generateTreeShakingSnapshotPluginCode(hasTreeShakingShared)}
1944
3119
  ${needsSharedProviderSelectionHelper ? sharedProviderSelectionHelperCode : ""}
3120
+ ${needsSharedProviderSelectionHelper ? externalSharedProviderSelectionHelperCode : ""}
1945
3121
 
1946
3122
  async function getLocalSharedImportMap() {
1947
- if (!localSharedImportMapPromise) {
3123
+ ${hasEagerShared ? "return __mfLocalSharedImportMap;" : ""}
3124
+ ${hasEagerShared ? "" : `if (!localSharedImportMapPromise) {
1948
3125
  localSharedImportMapPromise = retrySharedInit(() => import("${getLocalSharedImportMapPath()}"))
1949
3126
  .catch((e) => { localSharedImportMapPromise = undefined; throw e; });
1950
3127
  }
1951
- return localSharedImportMapPromise
3128
+ return localSharedImportMapPromise`}
1952
3129
  }
1953
3130
 
1954
3131
  async function getExposesMap() {
@@ -1962,53 +3139,32 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1962
3139
 
1963
3140
  async function init(shared = {}, initScope = []) {
1964
3141
  ${sharedCacheHelperCode}
1965
- const {usedShared, usedRemotes} = await getLocalSharedImportMap()
1966
- try {
1967
- const allInstances = globalThis.__FEDERATION__?.__SHARE__;
1968
- if (allInstances) {
1969
- ${normalizeRuntimeShareCode}
1970
- for (const [, scopes] of Object.entries(allInstances)) {
1971
- const scopeShare = scopes?.['${options.shareScope}'];
1972
- if (!scopeShare) continue;
1973
- for (const [pkg, versionMap] of Object.entries(scopeShare)) {
1974
- const usedShare = usedShared?.[pkg];
1975
- const selectedProvider = usedShare?.shareConfig?.import === false
1976
- ? __mfSelectSharedProvider(versionMap, pkg, usedShare, '${options.shareStrategy}')
1977
- : undefined;
1978
- const providerEntries = usedShare?.shareConfig?.import === false
1979
- ? Object.entries(versionMap).filter(([, provider]) => provider === selectedProvider)
1980
- : Object.entries(versionMap);
1981
- for (const [version, provider] of providerEntries) {
1982
- if (!provider.lib) continue;
1983
- const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, provider.shareConfig?.singleton, version, ${JSON.stringify(options.shareScope)});
1984
- if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) continue;
1985
- const mod = typeof provider.lib === "function" ? provider.lib() : provider.lib;
1986
- const resolved = await Promise.resolve(mod);
1987
- const normalized = __mfNormalizeRuntimeShare(resolved);
1988
- __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, normalized);
1989
- if (provider.shareConfig?.singleton && usedShare) {
1990
- const usedCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, usedShare.shareConfig?.singleton, usedShare.version, usedShare.scope);
1991
- if (__mfReadSharedCache(__mfModuleCache.share, usedCacheDescriptor) === undefined) {
1992
- __mfWriteSharedCache(__mfModuleCache.share, usedCacheDescriptor, normalized);
1993
- }
1994
- }
1995
- }
1996
- }
1997
- }
1998
- }
1999
- } catch (e) {
2000
- console.error('[Module Federation] Failed to bridge external shared modules', e)
2001
- }
2002
- for (const [pkg, share] of Object.entries(usedShared)) {
2003
- const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2004
- if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) continue;
2005
- const singletonCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, true, share.version, share.scope);
2006
- const singletonModule = __mfReadSharedCache(__mfModuleCache.share, singletonCacheDescriptor);
2007
- if (singletonModule !== undefined) {
2008
- __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);
2009
3158
  }
2010
3159
  }
2011
- ${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}
2012
3168
  const __browserPlugins = [${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => `${item[0]}(${item[2]})`).join(", ")}];
2013
3169
  const __ssrPlugins = typeof globalThis.window === 'undefined'
2014
3170
  ? await Promise.all([${pluginImportNames.filter((item) => isSsrOnlyPlugin(item[1])).map((item) => {
@@ -2017,42 +3173,592 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
2017
3173
  return `import(${JSON.stringify(specifier)}).then(m => (m.default ?? m)(${opts}))`;
2018
3174
  }).join(", ")}])
2019
3175
  : [];
3176
+ const __mfRuntimeShareLoadIdKey = "__mf_vite_runtime_share_load_id__";
3177
+ let __mfRuntimeShareLoadId = 0;
3178
+ const __mfRuntimeShareSelections = new Map();
3179
+ const __mfRuntimeShareLifecycles = new Map();
2020
3180
  const initRes = runtimeInit({
2021
3181
  name: mfName,
2022
3182
  remotes: ${options.shareStrategy === "loaded-first" ? "[]" : "usedRemotes"},
2023
3183
  shared: usedShared,
2024
- plugins: [...__browserPlugins, ...__ssrPlugins],
3184
+ plugins: [__mfSharePinLifecyclePlugin(), ${hasTreeShakingShared ? "__mfTreeShakingSnapshotPlugin()," : ""} ...__browserPlugins, ...__ssrPlugins],
2025
3185
  ${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
2026
3186
  });
2027
- // handling circular init calls
2028
- var initToken = initTokens[shareScopeName];
2029
- if (!initToken)
2030
- initToken = initTokens[shareScopeName] = { from: mfName };
2031
- if (initScope.indexOf(initToken) >= 0) return;
2032
- initScope.push(initToken);
2033
3187
  initRes.initShareScopeMap('${options.shareScope}', shared);
2034
- try {
2035
- await retrySharedInit(async () => {
2036
- await Promise.all(await initRes.initializeSharing('${options.shareScope}', {
2037
- strategy: '${options.shareStrategy}',
2038
- from: "build",
2039
- initScope
2040
- }));
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'
2041
3237
  });
2042
- } catch (e) {
2043
- console.error('[Module Federation]', e)
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]);
2044
3609
  }
2045
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
+ }
3679
+ } catch (e) {
3680
+ console.error('[Module Federation] Failed to bridge external shared modules', e)
3681
+ }
3682
+ ${generateTreeShakingSharedResolutionCode(hasTreeShakingShared)}
3683
+ const __mfResolveImportFalseShared = async (pkg, share) => {
2046
3684
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2047
- if (share.shareConfig?.import !== false || __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) continue;
3685
+ const cachedShare = share.treeShaking
3686
+ ? __mfReadTreeShakingSharedSelection(__mfModuleCache.share, cacheDescriptor, mfName)
3687
+ : __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor);
3688
+ if (share.shareConfig?.import !== false || cachedShare !== undefined) return;
2048
3689
  ${normalizeRuntimeShareCode}
2049
- const versions = shared?.[pkg];
2050
- const provider = __mfSelectSharedProvider(versions, pkg, share, '${options.shareStrategy}');
2051
- if (!provider) continue;
2052
- const factory = provider.lib || (provider.loading ? await provider.loading : await provider.get?.());
2053
- const mod = typeof factory === "function" ? factory() : factory;
2054
- const resolved = await Promise.resolve(mod);
2055
- __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]);
2056
3762
  }
2057
3763
  initResolve(initRes)
2058
3764
  return initRes
@@ -2078,6 +3784,7 @@ let currentHostAutoInitCommand = "build";
2078
3784
  function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
2079
3785
  const shouldPreloadShares = getNormalizeModuleFederationOptions().shareStrategy !== "loaded-first";
2080
3786
  const hostInitShareOrder = JSON.stringify(getOrderedUsedShares());
3787
+ const cacheOwner = JSON.stringify(getNormalizeModuleFederationOptions().name);
2081
3788
  return `
2082
3789
  ${getRuntimeModuleCacheBootstrapCode()}
2083
3790
  let hostInitPromise;
@@ -2096,6 +3803,10 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
2096
3803
  for (const pkg of __mfHostInitShareOrder) {
2097
3804
  const share = usedShared[pkg];
2098
3805
  if (!share) continue;
3806
+ // remoteEntry.init resolves tree-enabled shares into the
3807
+ // coverage-aware cache. Never republish that selected partial under
3808
+ // a generic full-module key here.
3809
+ if (share.treeShaking) continue;
2099
3810
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2100
3811
  if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) {
2101
3812
  continue;
@@ -2105,7 +3816,12 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
2105
3816
  }).then((factory) => {
2106
3817
  const mod = typeof factory === "function" ? factory() : factory;
2107
3818
  return Promise.resolve(mod).then((resolved) => {
2108
- __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, __mfNormalizeRuntimeShare(resolved));
3819
+ __mfWriteSharedCache(
3820
+ __mfModuleCache.share,
3821
+ cacheDescriptor,
3822
+ __mfNormalizeRuntimeShare(resolved),
3823
+ ${cacheOwner}
3824
+ );
2109
3825
  });
2110
3826
  });
2111
3827
  }
@@ -2158,9 +3874,8 @@ function addUsedRemote(remoteKey, remoteModule) {
2158
3874
  function getUsedRemotesMap() {
2159
3875
  return usedRemotesMap;
2160
3876
  }
2161
- function getRemoteFromId(id, remotes) {
2162
- const remoteName = Object.keys(remotes).filter((name) => id === name || id.startsWith(name + "/")).sort((a, b) => b.length - a.length)[0];
2163
- return remoteName ? remotes[remoteName] : void 0;
3877
+ function getRemoteAliasFromId(id, remotes) {
3878
+ return Object.keys(remotes).filter((name) => id === name || id.startsWith(name + "/")).sort((a, b) => b.length - a.length)[0];
2164
3879
  }
2165
3880
  function resolveRemoteInitMode(shareStrategy, consumer) {
2166
3881
  if (shareStrategy !== "loaded-first") return "eager";
@@ -2316,10 +4031,12 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
2316
4031
  const isLoadedFirst = options.shareStrategy === "loaded-first";
2317
4032
  const initMode = resolveRemoteInitMode(options.shareStrategy, consumer);
2318
4033
  const deferRemoteLoad = shouldDeferRemoteLoad(initMode);
2319
- const remote = getRemoteFromId(id, options.remotes);
4034
+ const remoteAlias = getRemoteAliasFromId(id, options.remotes);
4035
+ const remote = remoteAlias ? options.remotes[remoteAlias] : void 0;
2320
4036
  const registerRemoteCode = isLoadedFirst && remote ? `runtime.registerRemotes([${JSON.stringify({
2321
4037
  entryGlobalName: remote.entryGlobalName,
2322
4038
  name: remote.name,
4039
+ alias: remoteAlias,
2323
4040
  type: remote.type,
2324
4041
  entry: remote.entry,
2325
4042
  shareScope: remote.shareScope ?? "default"
@@ -2391,7 +4108,7 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
2391
4108
  const HOST_INIT_PRELOAD_CHUNKS = [
2392
4109
  (name) => name === "hostInit",
2393
4110
  (name) => name === "remoteEntry",
2394
- (name) => name.startsWith("_virtual_mf"),
4111
+ (name) => name.startsWith("_virtual_mf") && !name.includes("__prebuild__"),
2395
4112
  (name) => name === "index"
2396
4113
  ];
2397
4114
  function escapeHtmlAttr(value) {
@@ -2593,7 +4310,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2593
4310
  return decodeViteId(id).replace(/^\0/, "");
2594
4311
  }
2595
4312
  function normalizeModuleId(id) {
2596
- return id.split("?")[0].replace(/\\/g, "/");
4313
+ return normalizePathForImport(id.split("?")[0]);
2597
4314
  }
2598
4315
  function resolveProjectId(id) {
2599
4316
  if (id.startsWith("\0") || id.startsWith("virtual:")) return normalizeModuleId(id);
@@ -2630,8 +4347,8 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2630
4347
  const resolvedEntryPath = getEntryPath();
2631
4348
  if (resolvedEntryPath.startsWith("virtual:mf")) devEntryPath = config.base + VITE_ID_PREFIX.slice(1) + resolvedEntryPath;
2632
4349
  else {
2633
- const normalized = resolvedEntryPath.replace(/\\\\?/g, "/");
2634
- const root = config.root.replace(/\\\\?/g, "/").replace(/\/$/, "");
4350
+ const normalized = normalizePathForImport(resolvedEntryPath);
4351
+ const root = normalizePathForImport(config.root).replace(/\/$/, "");
2635
4352
  const relativePath = normalized.startsWith(root + "/") ? normalized.slice(root.length) : "/" + normalized.replace(/^[A-Za-z]:[\\/]/, "");
2636
4353
  devEntryPath = config.base + relativePath.replace(/^\//, "");
2637
4354
  }
@@ -3382,7 +5099,7 @@ function initVirtualModules(command, remoteEntryId, enableSsrInit = false) {
3382
5099
  function isOutputChunk$1(chunk) {
3383
5100
  return chunk.type === "chunk";
3384
5101
  }
3385
- function escapeRegExp(value) {
5102
+ function escapeRegExp$1(value) {
3386
5103
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3387
5104
  }
3388
5105
  function getProxyBaseName(fileName) {
@@ -3474,7 +5191,7 @@ function rewriteEsmProxyConsumers(code, proxyChunks) {
3474
5191
  const claimedLocals = /* @__PURE__ */ new Set();
3475
5192
  for (const [proxyFileName, proxyInfo] of Array.from(proxyChunks.entries())) {
3476
5193
  const proxyBaseName = getProxyBaseName(proxyFileName);
3477
- const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${escapeRegExp(proxyBaseName)}[^"']*)["']\\s*;?`).exec(nextCode);
5194
+ const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${escapeRegExp$1(proxyBaseName)}[^"']*)["']\\s*;?`).exec(nextCode);
3478
5195
  if (!importMatch) continue;
3479
5196
  const fullImport = importMatch[0];
3480
5197
  const bindings = importMatch[1].split(",").map((s) => {
@@ -3531,7 +5248,7 @@ function rewriteSystemProxyConsumers(code, systemProxyInfo) {
3531
5248
  let nextCode = code;
3532
5249
  for (const [proxyFileName, proxyInfo] of Array.from(systemProxyInfo.entries())) {
3533
5250
  const proxyBaseName = getProxyBaseName(proxyFileName);
3534
- const depMatch = new RegExp(`["']([^"']*${escapeRegExp(proxyBaseName)}[^"']*)["']`).exec(nextCode);
5251
+ const depMatch = new RegExp(`["']([^"']*${escapeRegExp$1(proxyBaseName)}[^"']*)["']`).exec(nextCode);
3535
5252
  if (!depMatch) continue;
3536
5253
  let setterIndex = 0;
3537
5254
  const depListMatch = nextCode.match(/System\.register\(\[([\s\S]*?)\]/);
@@ -3890,10 +5607,28 @@ function createRemoteEntryAssetMap(fileName) {
3890
5607
  }
3891
5608
  };
3892
5609
  }
5610
+ function isTreeShakingProviderChunk(file) {
5611
+ if (file.type !== "chunk") return false;
5612
+ if (file.facadeModuleId?.includes("__treeShakingProvider__")) return true;
5613
+ return Object.keys(file.modules || {}).some((id) => id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__"));
5614
+ }
5615
+ function getTreeShakingBuildInfo(options) {
5616
+ if (!(Object.values(options.shared || {}).some((share) => !!share.shareConfig.treeShaking) || !!options.treeShakingSharedPlugins?.length || !!options.treeShakingSharedExcludePlugins?.length)) return {};
5617
+ return {
5618
+ target: [options.target || "web"],
5619
+ ...options.treeShakingSharedPlugins?.length ? { plugins: [...options.treeShakingSharedPlugins] } : {},
5620
+ ...options.treeShakingSharedExcludePlugins?.length ? { excludePlugins: [...options.treeShakingSharedExcludePlugins] } : {}
5621
+ };
5622
+ }
5623
+ function getRemoteContainerName(remoteKey, remote) {
5624
+ const entryGlobalName = remote.entryGlobalName;
5625
+ if (entryGlobalName && entryGlobalName !== remoteKey && entryGlobalName !== remote.entry) return entryGlobalName;
5626
+ return remote.name;
5627
+ }
3893
5628
  const Manifest = () => {
3894
5629
  const mfOptions = getNormalizeModuleFederationOptions();
3895
5630
  const { name, filename, getPublicPath, manifest: manifestOptions, varFilename } = mfOptions;
3896
- let mfManifestName = manifestOptions === true ? "mf-manifest.json" : typeof manifestOptions === "object" ? path$1.join(manifestOptions?.filePath || "", manifestOptions?.fileName || "mf-manifest.json") : void 0;
5631
+ let mfManifestName = manifestOptions === true ? "mf-manifest.json" : typeof manifestOptions === "object" ? normalizePathForImport(path$1.join(manifestOptions?.filePath || "", manifestOptions?.fileName || "mf-manifest.json")) : void 0;
3897
5632
  let mfManifestStatsName = mfManifestName ? getStatsFileName(mfManifestName) : void 0;
3898
5633
  const isConsumerProject = Object.keys(mfOptions.exposes).length === 0;
3899
5634
  let disableAssetsAnalyze = false;
@@ -3942,7 +5677,8 @@ const Manifest = () => {
3942
5677
  type: "app",
3943
5678
  buildInfo: {
3944
5679
  buildVersion: getBuildVersion(),
3945
- buildName: name
5680
+ buildName: name,
5681
+ ...getTreeShakingBuildInfo(mfOptions)
3946
5682
  },
3947
5683
  remoteEntry: {
3948
5684
  name: devRemoteEntryFile,
@@ -3997,6 +5733,16 @@ const Manifest = () => {
3997
5733
  if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
3998
5734
  ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(resolveDevRemoteEntryFileName(mfOptions.filename)) : expectedSsrRemoteEntryFile);
3999
5735
  const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
5736
+ if (allCssAssets.size > 0) {
5737
+ const secondaryCss = /* @__PURE__ */ new Set();
5738
+ const primaryCss = /* @__PURE__ */ new Set();
5739
+ for (const file of Object.values(bundle)) {
5740
+ if (file.type !== "chunk") continue;
5741
+ const target = isTreeShakingProviderChunk(file) ? secondaryCss : primaryCss;
5742
+ for (const css of file.viteMetadata?.importedCss || []) target.add(css);
5743
+ }
5744
+ for (const css of secondaryCss) if (!primaryCss.has(css)) allCssAssets.delete(css);
5745
+ }
4000
5746
  if (!disableAssetsAnalyze) {
4001
5747
  const exposesModules = Object.keys(mfOptions.exposes).map((item) => mfOptions.exposes[item].import);
4002
5748
  processModuleAssets(bundle, filesMap, (modulePath) => {
@@ -4008,7 +5754,7 @@ const Manifest = () => {
4008
5754
  stripKnownJsExtensions: true
4009
5755
  });
4010
5756
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(), this.resolve.bind(this));
4011
- processModuleAssets(bundle, filesMap, (modulePath) => fileToShareKey.get(modulePath));
5757
+ processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
4012
5758
  if (mfOptions.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
4013
5759
  filesMap = deduplicateAssets(filesMap);
4014
5760
  }
@@ -4052,22 +5798,37 @@ const Manifest = () => {
4052
5798
  path: "",
4053
5799
  type: "var"
4054
5800
  } : void 0;
4055
- const remotes = Array.from(Object.entries(getUsedRemotesMap())).flatMap(([remoteKey, modules]) => Array.from(modules).map((moduleKey) => ({
4056
- federationContainerName: options.remotes[remoteKey].entry,
4057
- moduleName: moduleKey.replace(remoteKey, "").replace("/", ""),
4058
- alias: remoteKey,
4059
- entry: "*"
4060
- })));
5801
+ const remotes = Array.from(Object.entries(getUsedRemotesMap())).flatMap(([remoteKey, modules]) => {
5802
+ const remote = options.remotes[remoteKey];
5803
+ return Array.from(modules).map((moduleKey) => ({
5804
+ federationContainerName: getRemoteContainerName(remoteKey, remote),
5805
+ moduleName: moduleKey.replace(remoteKey, "").replace("/", ""),
5806
+ alias: remoteKey,
5807
+ entry: "*"
5808
+ }));
5809
+ });
4061
5810
  const shared = Array.from(getUsedShares()).flatMap((shareKey) => {
4062
5811
  const shareItem = getNormalizeShareItem(shareKey);
4063
5812
  if (!shareItem) return [];
4064
5813
  const assets = preloadMap[shareKey] || (_command === "serve" && resolvedRemoteEntryFile ? createRemoteEntryAssetMap(resolvedRemoteEntryFile) : createEmptyAssetMap());
5814
+ const treeShakingUsage = getTreeShakingExportUsage(shareKey, shareItem, shareItem.name);
5815
+ const treeShakingUsedExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
5816
+ const treeShakingStatus = treeShakingUsage?.kind === "full" ? 0 : 1;
4065
5817
  return [{
4066
5818
  id: `${name}:${shareKey}`,
4067
5819
  name: shareKey,
4068
5820
  version: shareItem.version,
4069
5821
  singleton: shareItem.shareConfig.singleton,
4070
5822
  requiredVersion: shareItem.shareConfig.requiredVersion,
5823
+ ...shareItem.shareConfig.treeShaking ? {
5824
+ usedExports: treeShakingUsedExports,
5825
+ referenceExports: treeShakingUsedExports,
5826
+ treeShaking: {
5827
+ mode: shareItem.shareConfig.treeShaking.mode,
5828
+ ...treeShakingUsage?.kind === "exports" ? { usedExports: treeShakingUsedExports } : {},
5829
+ status: treeShakingStatus
5830
+ }
5831
+ } : {},
4071
5832
  assets: {
4072
5833
  js: {
4073
5834
  async: assets.js.async,
@@ -4107,7 +5868,8 @@ const Manifest = () => {
4107
5868
  type: "app",
4108
5869
  buildInfo: {
4109
5870
  buildVersion: getBuildVersion(),
4110
- buildName: name
5871
+ buildName: name,
5872
+ ...getTreeShakingBuildInfo(options)
4111
5873
  },
4112
5874
  remoteEntry,
4113
5875
  ssrRemoteEntry,
@@ -4152,32 +5914,41 @@ function getStatsFileName(manifestFileName) {
4152
5914
  const fileExt = parsed.ext || ".json";
4153
5915
  const baseName = parsed.ext ? parsed.name : parsed.base;
4154
5916
  const fileName = `${baseName === "mf-manifest" ? "mf" : baseName}-stats${fileExt}`;
4155
- return parsed.dir ? path$1.join(parsed.dir, fileName) : fileName;
5917
+ return parsed.dir ? normalizePathForImport(path$1.join(parsed.dir, fileName)) : fileName;
4156
5918
  }
4157
5919
  //#endregion
4158
5920
  //#region src/plugins/pluginModuleParseEnd.ts
4159
5921
  let _resolve = null;
4160
5922
  let _parseTimeout = null;
5923
+ let _settleTimeout = null;
4161
5924
  let parsePromise = Promise.resolve(1);
4162
- let exposesParseEnd = false;
4163
- let expectsExposesParseEnd = false;
4164
5925
  let parseStartSet = /* @__PURE__ */ new Set();
4165
5926
  let parseEndSet = /* @__PURE__ */ new Set();
5927
+ let lastLoadedModule = "";
5928
+ let lastParsedModule = "";
4166
5929
  function clearParseTimeout() {
4167
5930
  if (_parseTimeout) {
4168
5931
  clearTimeout(_parseTimeout);
4169
5932
  _parseTimeout = null;
4170
5933
  }
4171
5934
  }
5935
+ function clearSettleTimeout() {
5936
+ if (_settleTimeout) {
5937
+ clearTimeout(_settleTimeout);
5938
+ _settleTimeout = null;
5939
+ }
5940
+ }
4172
5941
  function resetParseState() {
4173
5942
  clearParseTimeout();
4174
- exposesParseEnd = false;
4175
- expectsExposesParseEnd = false;
5943
+ clearSettleTimeout();
4176
5944
  parseStartSet = /* @__PURE__ */ new Set();
4177
5945
  parseEndSet = /* @__PURE__ */ new Set();
5946
+ lastLoadedModule = "";
5947
+ lastParsedModule = "";
4178
5948
  parsePromise = new Promise((resolve) => {
4179
5949
  _resolve = (v) => {
4180
5950
  clearParseTimeout();
5951
+ clearSettleTimeout();
4181
5952
  resolve(v);
4182
5953
  };
4183
5954
  });
@@ -4191,10 +5962,18 @@ function setParseTimeout(timeout) {
4191
5962
  function resetIdleTimeout(timeout) {
4192
5963
  clearParseTimeout();
4193
5964
  _parseTimeout = setTimeout(() => {
4194
- mfWarn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout.`);
5965
+ const pendingModules = Array.from(parseStartSet).filter((moduleId) => !parseEndSet.has(moduleId));
5966
+ mfWarn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout. Tracked modules: ${parseEndSet.size}/${parseStartSet.size}.` + (lastLoadedModule ? ` Last loaded: ${lastLoadedModule}.` : "") + (lastParsedModule ? ` Last parsed: ${lastParsedModule}.` : "") + (pendingModules.length ? ` Pending modules: ${pendingModules.slice(0, 10).join(", ")}` : ""));
4195
5967
  _resolve?.(1);
4196
5968
  }, timeout * 1e3);
4197
5969
  }
5970
+ function scheduleParseCompletionCheck() {
5971
+ clearSettleTimeout();
5972
+ _settleTimeout = setTimeout(() => {
5973
+ _settleTimeout = null;
5974
+ if (parseStartSet.size > 0 && Array.from(parseStartSet).every((moduleId) => parseEndSet.has(moduleId))) _resolve?.(1);
5975
+ }, 10);
5976
+ }
4198
5977
  function pluginModuleParseEnd_default(excludeFn, options) {
4199
5978
  const idleTimeout = options.moduleParseIdleTimeout ?? options.moduleParseTimeout;
4200
5979
  return [
@@ -4209,14 +5988,20 @@ function pluginModuleParseEnd_default(excludeFn, options) {
4209
5988
  enforce: "pre",
4210
5989
  name: "parseStart",
4211
5990
  apply: "build",
4212
- buildStart() {
5991
+ async buildStart() {
4213
5992
  resetParseState();
4214
5993
  if (idleTimeout) resetIdleTimeout(idleTimeout);
4215
- else setParseTimeout(options.moduleParseTimeout);
5994
+ else if (options.moduleParseTimeout) setParseTimeout(options.moduleParseTimeout);
5995
+ for (const importSource of options.exposedModuleImports || []) {
5996
+ const resolved = await this.resolve(importSource);
5997
+ if (resolved && !resolved.external && !excludeFn(resolved.id)) parseStartSet.add(resolved.id);
5998
+ }
4216
5999
  },
4217
6000
  load(id) {
6001
+ lastLoadedModule = id;
4218
6002
  if (excludeFn(id)) return;
4219
- if (id === options.virtualExposesId) expectsExposesParseEnd = true;
6003
+ clearSettleTimeout();
6004
+ if (idleTimeout) resetIdleTimeout(idleTimeout);
4220
6005
  parseStartSet.add(id);
4221
6006
  }
4222
6007
  },
@@ -4225,12 +6010,18 @@ function pluginModuleParseEnd_default(excludeFn, options) {
4225
6010
  name: "parseEnd",
4226
6011
  apply: "build",
4227
6012
  moduleParsed(module) {
6013
+ clearSettleTimeout();
4228
6014
  const id = module.id;
4229
- if (id === options.virtualExposesId) exposesParseEnd = true;
6015
+ lastParsedModule = id;
4230
6016
  if (idleTimeout) resetIdleTimeout(idleTimeout);
4231
- if (excludeFn(id)) return;
4232
- parseEndSet.add(id);
4233
- if (parseStartSet.size === parseEndSet.size && (!expectsExposesParseEnd || exposesParseEnd)) _resolve?.(1);
6017
+ const parsedModule = module;
6018
+ const addPendingResolutions = (resolutions) => {
6019
+ for (const resolution of resolutions || []) if (!resolution.external && !excludeFn(resolution.id)) parseStartSet.add(resolution.id);
6020
+ };
6021
+ addPendingResolutions(parsedModule.importedIdResolutions);
6022
+ addPendingResolutions(parsedModule.dynamicallyImportedIdResolutions);
6023
+ if (!excludeFn(id)) parseEndSet.add(id);
6024
+ scheduleParseCompletionCheck();
4234
6025
  },
4235
6026
  buildEnd() {
4236
6027
  _resolve?.(1);
@@ -4249,6 +6040,9 @@ function resolveDevHashEntryFileName(fileName) {
4249
6040
  function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
4250
6041
  let viteConfig, _command, root;
4251
6042
  let exposeRemoteDependencies = {};
6043
+ let exposeRemoteDependenciesDirty = true;
6044
+ let refreshPromise;
6045
+ let dependencyInvalidationVersion = 0;
4252
6046
  function isRemoteImport(source) {
4253
6047
  return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
4254
6048
  }
@@ -4287,12 +6081,26 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4287
6081
  return Array.from(dependencies).sort();
4288
6082
  }
4289
6083
  async function refreshExposeRemoteDependencies(ctx) {
4290
- const next = {};
4291
- for (const [exposeKey, expose] of Object.entries(options.exposes)) {
4292
- const resolved = await ctx.resolve(expose.import);
4293
- next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id) : [];
6084
+ if (!exposeRemoteDependenciesDirty) return;
6085
+ if (!refreshPromise) {
6086
+ const refreshVersion = dependencyInvalidationVersion;
6087
+ refreshPromise = (async () => {
6088
+ const next = {};
6089
+ for (const [exposeKey, expose] of Object.entries(options.exposes)) {
6090
+ const resolved = await ctx.resolve(expose.import);
6091
+ next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id) : [];
6092
+ }
6093
+ exposeRemoteDependencies = next;
6094
+ if (refreshVersion === dependencyInvalidationVersion) exposeRemoteDependenciesDirty = false;
6095
+ })().finally(() => {
6096
+ refreshPromise = void 0;
6097
+ });
4294
6098
  }
4295
- exposeRemoteDependencies = next;
6099
+ await refreshPromise;
6100
+ }
6101
+ function invalidateExposeRemoteDependencies() {
6102
+ exposeRemoteDependenciesDirty = true;
6103
+ dependencyInvalidationVersion += 1;
4296
6104
  }
4297
6105
  return {
4298
6106
  name: "proxyRemoteEntry",
@@ -4315,6 +6123,12 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4315
6123
  });
4316
6124
  }
4317
6125
  },
6126
+ watchChange() {
6127
+ invalidateExposeRemoteDependencies();
6128
+ },
6129
+ handleHotUpdate() {
6130
+ invalidateExposeRemoteDependencies();
6131
+ },
4318
6132
  async resolveId(id, importer) {
4319
6133
  if (id === remoteEntryId) return remoteEntryId;
4320
6134
  if (id === virtualExposesId) return virtualExposesId;
@@ -4325,16 +6139,22 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4325
6139
  if (resolved) return resolved;
4326
6140
  }
4327
6141
  },
4328
- load(id) {
6142
+ async load(id) {
4329
6143
  if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
4330
- if (id === virtualExposesId) return generateExposes(options, exposeRemoteDependencies, _command);
6144
+ if (id === virtualExposesId) {
6145
+ await refreshExposeRemoteDependencies(this);
6146
+ return generateExposes(options, exposeRemoteDependencies, _command);
6147
+ }
4331
6148
  if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
4332
6149
  },
4333
- transform(code, id) {
4334
- return mapCodeToCodeWithSourcemap((() => {
6150
+ async transform(code, id) {
6151
+ return mapCodeToCodeWithSourcemap(await (async () => {
4335
6152
  if (!filterId(id)) return;
4336
6153
  if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
4337
- if (id === virtualExposesId) return generateExposes(options, exposeRemoteDependencies, _command);
6154
+ if (id === virtualExposesId) {
6155
+ await refreshExposeRemoteDependencies(this);
6156
+ return generateExposes(options, exposeRemoteDependencies, _command);
6157
+ }
4338
6158
  if (id.includes(getHostAutoInitPath())) {
4339
6159
  if (_command === "serve") {
4340
6160
  const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
@@ -4409,6 +6229,9 @@ function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
4409
6229
  function isNodeModulesImporter(importer) {
4410
6230
  return importer?.includes("/node_modules/") || importer?.includes("\\node_modules\\");
4411
6231
  }
6232
+ function escapeRegExp(value) {
6233
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6234
+ }
4412
6235
  function appendAlias(config, alias) {
4413
6236
  config.resolve ??= {};
4414
6237
  const existingAlias = config.resolve.alias;
@@ -4451,10 +6274,9 @@ function pluginProxyRemotes_default(options) {
4451
6274
  config(config, { command: _command }) {
4452
6275
  command = _command;
4453
6276
  root = config.root || process.cwd();
4454
- Object.keys(remotes).forEach((key) => {
4455
- const remote = remotes[key];
6277
+ Object.keys(remotes).forEach((remoteAlias) => {
4456
6278
  appendAlias(config, {
4457
- find: new RegExp(`^(${remote.name}(\/.*|$))`),
6279
+ find: new RegExp(`^(${escapeRegExp(remoteAlias)}(\/.*|$))`),
4458
6280
  replacement: "$1"
4459
6281
  });
4460
6282
  });
@@ -4465,9 +6287,9 @@ function pluginProxyRemotes_default(options) {
4465
6287
  },
4466
6288
  resolveId(source, importer) {
4467
6289
  if (!filterId(source)) return;
4468
- for (const remote of Object.values(remotes)) {
4469
- if (source !== remote.name && !source.startsWith(`${remote.name}/`)) continue;
4470
- return resolveRemoteId(this, source, importer, remote.name);
6290
+ for (const remoteAlias of Object.keys(remotes)) {
6291
+ if (source !== remoteAlias && !source.startsWith(`${remoteAlias}/`)) continue;
6292
+ return resolveRemoteId(this, source, importer, remoteAlias);
4471
6293
  }
4472
6294
  }
4473
6295
  };
@@ -4625,6 +6447,36 @@ function proxySharedModule(options) {
4625
6447
  const savePrebuild = new PromiseStore();
4626
6448
  let devServer;
4627
6449
  const materializedLoadShareSources = /* @__PURE__ */ new Set();
6450
+ const emittedTreeShakingProviders = /* @__PURE__ */ new Set();
6451
+ const normalizeTreeShakingOutputPath = (value) => {
6452
+ const normalized = normalizePathForImport(value);
6453
+ if (path$1.posix.isAbsolute(normalized) || /^[A-Za-z]:\//.test(normalized) || normalized.split("/").includes("..")) throw new Error(`Invalid treeShakingDir "${value}": absolute paths and parent segments are not allowed.`);
6454
+ let start = normalized.startsWith("./") ? 2 : 0;
6455
+ let end = normalized.length;
6456
+ while (start < end && normalized.charCodeAt(start) === 47) start++;
6457
+ while (end > start && normalized.charCodeAt(end - 1) === 47) end--;
6458
+ return normalized.slice(start, end);
6459
+ };
6460
+ const getTreeShakingProviderFileName = (pkg, shareItem) => {
6461
+ if (!shareItem.shareConfig.treeShaking) return void 0;
6462
+ const normalizedOptions = getNormalizeModuleFederationOptions();
6463
+ const outputDir = normalizedOptions.treeShakingDir ? normalizeTreeShakingOutputPath(normalizedOptions.treeShakingDir) : void 0;
6464
+ const fileName = outputDir ? path$1.posix.join(outputDir, `${getTreeShakingSharedProviderName(pkg)}.js`) : void 0;
6465
+ if (!fileName) return void 0;
6466
+ return fileName;
6467
+ };
6468
+ const emitTreeShakingProvider = (context, pkg, shareItem) => {
6469
+ if (_command !== "build" || emittedTreeShakingProviders.has(pkg)) return;
6470
+ if (!hasTreeShakingSharedProvider(pkg, shareItem)) return;
6471
+ const fileName = getTreeShakingProviderFileName(pkg, shareItem);
6472
+ context.emitFile({
6473
+ type: "chunk",
6474
+ id: getTreeShakingSharedProviderImportId(pkg),
6475
+ name: getTreeShakingSharedProviderName(pkg),
6476
+ ...fileName ? { fileName } : {}
6477
+ });
6478
+ emittedTreeShakingProviders.add(pkg);
6479
+ };
4628
6480
  return [
4629
6481
  {
4630
6482
  name: "generateLocalSharedImportMap",
@@ -4640,7 +6492,16 @@ function proxySharedModule(options) {
4640
6492
  if (source === getLocalSharedImportMapPath()) return getResolvedLocalSharedImportMapId();
4641
6493
  },
4642
6494
  load(id) {
4643
- if (id === getResolvedLocalSharedImportMapId()) return parsePromise.then((_) => generateLocalSharedImportMap());
6495
+ if (id === getResolvedLocalSharedImportMapId()) return parsePromise.then((_) => {
6496
+ refreshTreeShakingModules();
6497
+ const providerPackages = new Set([...Object.keys(shared).filter((pkg) => !pkg.endsWith("/")), ...getUsedShares()]);
6498
+ for (const pkg of providerPackages) {
6499
+ const sharedKey = findSharedKeyForSource(pkg, shared);
6500
+ const shareItem = shared[pkg] || (sharedKey ? shared[sharedKey] : void 0);
6501
+ if (shareItem) emitTreeShakingProvider(this, pkg, shareItem);
6502
+ }
6503
+ return generateLocalSharedImportMap();
6504
+ });
4644
6505
  },
4645
6506
  closeBundle() {
4646
6507
  if (devServer) return;
@@ -4652,6 +6513,9 @@ function proxySharedModule(options) {
4652
6513
  enforce: "post",
4653
6514
  config(config, { command }) {
4654
6515
  setPackageDetectionCwd(config.root || process.cwd());
6516
+ setTreeShakingBuildMode(command === "build");
6517
+ resetTreeShakingExports();
6518
+ emittedTreeShakingProviders.clear();
4655
6519
  const isVinext = hasPackageDependency("vinext");
4656
6520
  const isAstro = hasPackageDependency("astro");
4657
6521
  const isRolldown = getIsRolldown(this);
@@ -4675,12 +6539,62 @@ function proxySharedModule(options) {
4675
6539
  });
4676
6540
  writeLocalSharedImportMap();
4677
6541
  refreshHostAutoInit();
6542
+ },
6543
+ buildStart() {
6544
+ if (_command !== "build") return;
6545
+ resetTreeShakingExports();
6546
+ emittedTreeShakingProviders.clear();
6547
+ refreshTreeShakingModules();
6548
+ },
6549
+ shouldTransformCachedModule() {
6550
+ return _command === "build" && Object.values(shared).some((share) => !!share.shareConfig.treeShaking);
6551
+ },
6552
+ transform(code, id) {
6553
+ if (_command !== "build" || !Object.keys(shared).some((key) => shared[key].shareConfig.treeShaking)) return;
6554
+ collectTreeShakingImports(code, id, shared, findSharedKeyForSource, recordTreeShakingExports, markTreeShakingPackageUnsafe);
6555
+ refreshTreeShakingModules();
6556
+ }
6557
+ },
6558
+ {
6559
+ name: "proxyPreBuildShared:tree-shaking-graph",
6560
+ enforce: "pre",
6561
+ apply: "build",
6562
+ async resolveId(source, importer, resolveOptions) {
6563
+ const sourceToken = getTreeShakingGraphToken(source);
6564
+ const importerToken = getTreeShakingGraphToken(importer);
6565
+ const token = sourceToken || importerToken;
6566
+ if (!token) return;
6567
+ const cleanSource = normalizePathForImport(stripTreeShakingGraphQuery(source));
6568
+ const cleanImporter = importer ? normalizePathForImport(stripTreeShakingGraphQuery(importer)) : void 0;
6569
+ if (!sourceToken && importerToken) {
6570
+ const nestedSharedKey = findSharedKeyForSource(cleanSource, shared);
6571
+ if (nestedSharedKey && getPackageName(nestedSharedKey) !== getPackageName(importerToken)) return this.resolve(cleanSource, cleanImporter, {
6572
+ ...resolveOptions,
6573
+ skipSelf: true
6574
+ });
6575
+ }
6576
+ const projectResolvedSource = sourceToken ? tryResolveFromProjectRoot(cleanSource) || cleanSource : cleanSource;
6577
+ const resolved = await this.resolve(projectResolvedSource, cleanImporter, {
6578
+ ...resolveOptions,
6579
+ custom: {
6580
+ ...resolveOptions.custom,
6581
+ __mfTreeShakingGraph: true
6582
+ },
6583
+ skipSelf: true
6584
+ });
6585
+ if (!resolved || resolved.external) return resolved;
6586
+ if (resolved.id.startsWith("\0")) return resolved;
6587
+ return {
6588
+ ...resolved,
6589
+ id: addTreeShakingGraphQuery(normalizePathForImport(resolved.id), token)
6590
+ };
4678
6591
  }
4679
6592
  },
4680
6593
  {
4681
6594
  name: "proxyPreBuildShared:resolve-shared-loadShare",
4682
6595
  enforce: "pre",
4683
- async resolveId(source, importer) {
6596
+ async resolveId(source, importer, resolveOptions) {
6597
+ if (resolveOptions.custom?.__mfTreeShakingGraph) return;
4684
6598
  function shouldSkipTaggedImporterProxy(sharedKey, tag) {
4685
6599
  if (!importer?.includes(tag)) return false;
4686
6600
  const taggedModule = VirtualModule.findModule(tag, importer);
@@ -4977,50 +6891,6 @@ function collectFromRegex(code, isRemoteImport) {
4977
6891
  }
4978
6892
  return result.length > 0 ? result : void 0;
4979
6893
  }
4980
- function createCodePositionMap(code) {
4981
- const positions = Array(code.length).fill(true);
4982
- function mask(start, end) {
4983
- for (let i = start; i < end; i++) positions[i] = false;
4984
- }
4985
- for (let i = 0; i < code.length;) {
4986
- const char = code[i];
4987
- const next = code[i + 1];
4988
- if (char === "/" && next === "/") {
4989
- const start = i;
4990
- i += 2;
4991
- while (i < code.length && code[i] !== "\n" && code[i] !== "\r") i++;
4992
- mask(start, i);
4993
- continue;
4994
- }
4995
- if (char === "/" && next === "*") {
4996
- const start = i;
4997
- i += 2;
4998
- while (i < code.length && !(code[i] === "*" && code[i + 1] === "/")) i++;
4999
- i = Math.min(code.length, i + 2);
5000
- mask(start, i);
5001
- continue;
5002
- }
5003
- if (char === "\"" || char === "'" || char === "`") {
5004
- const quote = char;
5005
- const start = i++;
5006
- while (i < code.length) {
5007
- if (code[i] === "\\") {
5008
- i += 2;
5009
- continue;
5010
- }
5011
- if (code[i] === quote) {
5012
- i++;
5013
- break;
5014
- }
5015
- i++;
5016
- }
5017
- mask(start, i);
5018
- continue;
5019
- }
5020
- i++;
5021
- }
5022
- return positions;
5023
- }
5024
6894
  function pluginRemoteNamedExports(options) {
5025
6895
  const remoteNames = Object.keys(options.remotes);
5026
6896
  const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
@@ -5637,15 +7507,12 @@ function appendResolveAlias(config, alias) {
5637
7507
  replacement
5638
7508
  })), alias];
5639
7509
  }
5640
- function hasImportFalseShared(options) {
5641
- return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
5642
- }
5643
7510
  function getRuntimeHelpersImplementation(runtimeImplementation) {
5644
7511
  const indexEntryMatch = runtimeImplementation.match(/^(.*[\\/])index(\.[cm]?js)$/);
5645
- if (indexEntryMatch) return `${indexEntryMatch[1]}helpers${indexEntryMatch[2]}`;
7512
+ if (indexEntryMatch) return normalizePathForImport(`${indexEntryMatch[1]}helpers${indexEntryMatch[2]}`);
5646
7513
  const extension = path$1.extname(runtimeImplementation);
5647
- if (extension) return path$1.join(path$1.dirname(runtimeImplementation), `helpers${extension}`);
5648
- if (path$1.isAbsolute(runtimeImplementation) || runtimeImplementation.startsWith(".")) return path$1.join(runtimeImplementation, "helpers");
7514
+ if (extension) return normalizePathForImport(path$1.join(path$1.dirname(runtimeImplementation), `helpers${extension}`));
7515
+ if (path$1.isAbsolute(runtimeImplementation) || runtimeImplementation.startsWith(".")) return normalizePathForImport(path$1.join(runtimeImplementation, "helpers"));
5649
7516
  return `${runtimeImplementation.replace(/\/$/, "")}/helpers`;
5650
7517
  }
5651
7518
  const UNSAFE_JS_SOURCE_CHAR_MAP = {
@@ -5828,7 +7695,7 @@ export default __mfShared.default ?? __mfShared;`
5828
7695
  const optimizeDeps = config.optimizeDeps ??= {};
5829
7696
  optimizeDeps.include ??= [];
5830
7697
  optimizeDeps.exclude ??= [];
5831
- const shouldBypassOptimizeDep = isLitShare(key) || key === "react" && shareItem.shareConfig?.singleton === true;
7698
+ const shouldBypassOptimizeDep = isLitShare(key);
5832
7699
  if (optimizeDeps.include.includes(key)) optimizeDeps.exclude = optimizeDeps.exclude.filter((dep) => dep !== key);
5833
7700
  else if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
5834
7701
  else optimizeDeps.include.push(key);
@@ -5883,13 +7750,14 @@ export default __mfShared.default ?? __mfShared;`
5883
7750
  const SSR_ONLY_PLUGINS = new Set(["@module-federation/vite/ssrEntryLoader"]);
5884
7751
  function loadPluginDts(options) {
5885
7752
  if (options.dts === false) return [];
5886
- return [import("./pluginDts-Bo95ELmX.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))];
5887
7754
  }
5888
7755
  function federation(mfUserOptions) {
5889
7756
  if (isTestEnv()) return [];
5890
7757
  const options = normalizeModuleFederationOptions(mfUserOptions);
5891
7758
  const isVinext = hasPackageDependency("vinext");
5892
7759
  const { name, shared, filename, hostInitInjectLocation } = options;
7760
+ const hasTreeShakingShared = Object.values(shared).some((share) => !!share.shareConfig.treeShaking);
5893
7761
  if (!name) throw createModuleFederationError("name is required");
5894
7762
  const remoteEntryId = getRemoteEntryId(options);
5895
7763
  const virtualExposesId = getVirtualExposesId(options);
@@ -5995,11 +7863,11 @@ function federation(mfUserOptions) {
5995
7863
  pluginProxyRemotes_default(options),
5996
7864
  pluginRemoteNamedExports(options),
5997
7865
  ...pluginModuleParseEnd_default((id) => {
5998
- return id.includes(getHostAutoInitImportId()) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath()) || id.includes("__loadShare__") || id.includes("__prebuild__");
7866
+ return id.includes(getHostAutoInitImportId()) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath()) || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
5999
7867
  }, {
6000
7868
  moduleParseTimeout: options.moduleParseTimeout,
6001
7869
  moduleParseIdleTimeout: options.moduleParseIdleTimeout,
6002
- virtualExposesId
7870
+ exposedModuleImports: Object.values(options.exposes).map((expose) => expose.import)
6003
7871
  }),
6004
7872
  ...proxySharedModule({ shared }),
6005
7873
  {
@@ -6021,7 +7889,8 @@ function federation(mfUserOptions) {
6021
7889
  if (context.hostType === "js" && (hostFile === options.filename || hostFile.includes("hostInit") || hostFile.includes("virtualExposes") || hostFile.includes("localSharedImportMap"))) return [];
6022
7890
  const hasFederationHtmlDeps = context.hostType === "html" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
6023
7891
  const hasFederationJsDeps = context.hostType === "js" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
6024
- return hasFederationHtmlDeps || hasFederationJsDeps ? resolvedDeps.filter((dep) => !isFederationHtmlPreloadDependency(dep, true)) : resolvedDeps;
7892
+ const treeShakingFallbackDeps = hasTreeShakingShared ? (dep) => dep.includes("__prebuild__") : () => false;
7893
+ return hasFederationHtmlDeps || hasFederationJsDeps ? resolvedDeps.filter((dep) => !isFederationHtmlPreloadDependency(dep, true) && !treeShakingFallbackDeps(dep)) : resolvedDeps.filter((dep) => !treeShakingFallbackDeps(dep));
6025
7894
  }
6026
7895
  };
6027
7896
  }
@@ -6195,8 +8064,8 @@ function federation(mfUserOptions) {
6195
8064
  config(config, { command: _command }) {
6196
8065
  const isRolldown = getIsRolldown(this);
6197
8066
  isSsrBuild = _command === "build" && config.build?.ssr === true;
6198
- const needsSharedProviderSelectionHelper = hasImportFalseShared(options);
6199
- if (needsSharedProviderSelectionHelper) appendResolveAlias(config, {
8067
+ const needsRuntimeHelpers = Object.keys(options.shared ?? {}).length > 0;
8068
+ if (needsRuntimeHelpers) appendResolveAlias(config, {
6200
8069
  find: /^@module-federation\/runtime\/helpers$/,
6201
8070
  replacement: getRuntimeHelpersImplementation(options.implementation)
6202
8071
  });
@@ -6210,7 +8079,7 @@ function federation(mfUserOptions) {
6210
8079
  config.optimizeDeps ||= {};
6211
8080
  config.optimizeDeps.include ||= [];
6212
8081
  config.optimizeDeps.include.push("@module-federation/runtime");
6213
- if (needsSharedProviderSelectionHelper) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
8082
+ if (needsRuntimeHelpers) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
6214
8083
  options.runtimePlugins.forEach((p) => {
6215
8084
  const pluginPath = typeof p === "string" ? p : p[0];
6216
8085
  if (SSR_ONLY_PLUGINS.has(pluginPath)) return;