@module-federation/vite 1.16.16 → 1.17.0

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-BcvLBYP3.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,257 @@ ${exportStatement}
928
939
  `);
929
940
  }
930
941
  //#endregion
942
+ //#region src/utils/treeShaking.ts
943
+ /**
944
+ * Analysis is scoped by both the configured share key and the concrete module
945
+ * request. A prefix share such as `lodash/` may materialize separate wrappers
946
+ * for `lodash/get` and `lodash/debounce`; combining those export sets would
947
+ * generate invalid wrappers and defeat per-subpath tree shaking.
948
+ */
949
+ const inferredTreeShakingUsage = /* @__PURE__ */ new Map();
950
+ let treeShakingBuildMode = false;
951
+ function setTreeShakingBuildMode(enabled) {
952
+ treeShakingBuildMode = enabled;
953
+ }
954
+ function resetTreeShakingExports() {
955
+ inferredTreeShakingUsage.clear();
956
+ }
957
+ function getOrCreateExportRecord(sharedKey, request) {
958
+ let byRequest = inferredTreeShakingUsage.get(sharedKey);
959
+ if (!byRequest) {
960
+ byRequest = /* @__PURE__ */ new Map();
961
+ inferredTreeShakingUsage.set(sharedKey, byRequest);
962
+ }
963
+ let record = byRequest.get(request);
964
+ if (!record) {
965
+ record = {
966
+ requiresFullBundle: false,
967
+ usedExports: /* @__PURE__ */ new Set()
968
+ };
969
+ byRequest.set(request, record);
970
+ }
971
+ return record;
972
+ }
973
+ function recordTreeShakingExports(sharedKey, exports, request = sharedKey) {
974
+ const record = getOrCreateExportRecord(sharedKey, request);
975
+ exports.forEach((name) => record.usedExports.add(name));
976
+ }
977
+ function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey) {
978
+ getOrCreateExportRecord(sharedKey, request).requiresFullBundle = true;
979
+ }
980
+ function getExportRecords(sharedKey, request) {
981
+ if (sharedKey) {
982
+ const records = inferredTreeShakingUsage.get(sharedKey);
983
+ const wildcard = records?.get("*");
984
+ const exact = records?.get(request);
985
+ return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
986
+ }
987
+ const records = [];
988
+ inferredTreeShakingUsage.forEach((byRequest, configuredKey) => {
989
+ const wildcard = byRequest.get("*");
990
+ const exact = byRequest.get(request);
991
+ const keyBase = configuredKey.endsWith("/") ? configuredKey.slice(0, -1) : configuredKey;
992
+ const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
993
+ if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
994
+ if (exact && exact !== wildcard) records.push(exact);
995
+ });
996
+ return records;
997
+ }
998
+ /**
999
+ * Return the analyzed requirement for one concrete shared request.
1000
+ *
1001
+ * Callers that know the configured share key should pass it explicitly. The
1002
+ * fallback lookup across keys keeps aliases/backwards-compatible callers
1003
+ * working, while still keeping each concrete request's exports isolated.
1004
+ */
1005
+ function getTreeShakingExportUsage(request, shareItem, sharedKey) {
1006
+ const treeShaking = shareItem?.shareConfig.treeShaking;
1007
+ if (!treeShaking || !treeShakingBuildMode) return void 0;
1008
+ const records = getExportRecords(sharedKey, request);
1009
+ if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
1010
+ const configured = treeShaking.usedExports ?? [];
1011
+ const result = new Set(configured);
1012
+ records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
1013
+ if (result.size > 0) return {
1014
+ kind: "exports",
1015
+ usedExports: [...result].sort()
1016
+ };
1017
+ return records.length > 0 ? {
1018
+ kind: "exports",
1019
+ usedExports: []
1020
+ } : { kind: "unknown" };
1021
+ }
1022
+ function getModuleSource(node) {
1023
+ if (!node || typeof node !== "object") return void 0;
1024
+ const source = node;
1025
+ if (source.type === "Literal" && typeof source.value === "string") return source.value;
1026
+ if (source.type === "StringLiteral" && typeof source.value === "string") return source.value;
1027
+ if (source.type !== "TemplateLiteral") return void 0;
1028
+ const expressions = Array.isArray(source.expressions) ? source.expressions : [];
1029
+ const quasis = Array.isArray(source.quasis) ? source.quasis : [];
1030
+ if (expressions.length > 0 || quasis.length !== 1) return void 0;
1031
+ const value = quasis[0]?.value;
1032
+ return typeof value?.cooked === "string" ? value.cooked : typeof value?.raw === "string" ? value.raw : void 0;
1033
+ }
1034
+ function getExportedName(node) {
1035
+ if (!node || typeof node !== "object") return void 0;
1036
+ const exported = node;
1037
+ if (exported.type === "Identifier" && typeof exported.name === "string") return exported.name;
1038
+ if ((exported.type === "Literal" || exported.type === "StringLiteral") && typeof exported.value === "string") return exported.value;
1039
+ }
1040
+ function isTypeOnly(node) {
1041
+ return node.importKind === "type" || node.exportKind === "type";
1042
+ }
1043
+ function forEachAstNode(root, visit) {
1044
+ const stack = [root];
1045
+ const seen = /* @__PURE__ */ new Set();
1046
+ while (stack.length > 0) {
1047
+ const value = stack.pop();
1048
+ if (!value || typeof value !== "object") continue;
1049
+ if (seen.has(value)) continue;
1050
+ seen.add(value);
1051
+ if (Array.isArray(value)) {
1052
+ for (let index = value.length - 1; index >= 0; index--) stack.push(value[index]);
1053
+ continue;
1054
+ }
1055
+ const node = value;
1056
+ if (typeof node.type === "string") visit(node);
1057
+ Object.entries(node).forEach(([key, child]) => {
1058
+ if (key !== "parent" && key !== "loc") stack.push(child);
1059
+ });
1060
+ }
1061
+ }
1062
+ function collectImportDeclaration(node, source, record, markUnsafe) {
1063
+ if (isTypeOnly(node)) return;
1064
+ const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1065
+ if (specifiers.length === 0) {
1066
+ markUnsafe(source);
1067
+ return;
1068
+ }
1069
+ const names = [];
1070
+ for (const specifier of specifiers) {
1071
+ if (isTypeOnly(specifier)) continue;
1072
+ if (specifier.type === "ImportNamespaceSpecifier") {
1073
+ markUnsafe(source);
1074
+ return;
1075
+ }
1076
+ if (specifier.type === "ImportDefaultSpecifier") {
1077
+ names.push("default");
1078
+ continue;
1079
+ }
1080
+ if (specifier.type === "ImportSpecifier") {
1081
+ const imported = specifier.imported;
1082
+ if (imported?.type === "Literal" || imported?.type === "StringLiteral") {
1083
+ markUnsafe(source);
1084
+ return;
1085
+ }
1086
+ const name = getExportedName(specifier.imported);
1087
+ if (!name) {
1088
+ markUnsafe(source);
1089
+ return;
1090
+ }
1091
+ names.push(name);
1092
+ continue;
1093
+ }
1094
+ markUnsafe(source);
1095
+ return;
1096
+ }
1097
+ record(names, source);
1098
+ }
1099
+ function collectReExport(node, source, record, markUnsafe) {
1100
+ if (isTypeOnly(node)) return;
1101
+ if (node.type === "ExportAllDeclaration") {
1102
+ markUnsafe(source);
1103
+ return;
1104
+ }
1105
+ const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1106
+ if (specifiers.length === 0) {
1107
+ markUnsafe(source);
1108
+ return;
1109
+ }
1110
+ const names = [];
1111
+ for (const specifier of specifiers) {
1112
+ if (isTypeOnly(specifier)) continue;
1113
+ if (specifier.type !== "ExportSpecifier") {
1114
+ markUnsafe(source);
1115
+ return;
1116
+ }
1117
+ const local = specifier.local;
1118
+ if (local?.type === "Literal" || local?.type === "StringLiteral") {
1119
+ markUnsafe(source);
1120
+ return;
1121
+ }
1122
+ const name = getExportedName(specifier.local);
1123
+ if (!name) {
1124
+ markUnsafe(source);
1125
+ return;
1126
+ }
1127
+ names.push(name);
1128
+ }
1129
+ record(names, source);
1130
+ }
1131
+ /**
1132
+ * Collect the exports required by a consumer's ESM graph.
1133
+ *
1134
+ * Parsing the module avoids treating import-looking text in comments, strings,
1135
+ * templates, or regular expressions as real dependencies. If parsing fails,
1136
+ * every configured tree-shaken share is conservatively marked as requiring its
1137
+ * full bundle instead of guessing from source text.
1138
+ *
1139
+ * Generated federation wrappers are excluded because their imports describe
1140
+ * the wrapper implementation, not the consumer's requirements.
1141
+ */
1142
+ function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe) {
1143
+ const normalizedId = normalizePathForImport(id);
1144
+ if (normalizedId.includes("__prebuild__") || normalizedId.includes("__loadShare__") || normalizedId.includes("__mf_tree_shaking_graph__")) return;
1145
+ let ast;
1146
+ try {
1147
+ ast = parseAst(code);
1148
+ } catch {
1149
+ Object.entries(shared).forEach(([sharedKey, shareItem]) => {
1150
+ if (shareItem.shareConfig.treeShaking) markUnsafe(sharedKey, "*");
1151
+ });
1152
+ return;
1153
+ }
1154
+ const matchShared = (source) => {
1155
+ const sharedKey = findSharedKey(source, shared);
1156
+ return sharedKey && shared[sharedKey]?.shareConfig.treeShaking ? sharedKey : void 0;
1157
+ };
1158
+ const recordSource = (names, source) => {
1159
+ const sharedKey = matchShared(source);
1160
+ if (sharedKey) record(sharedKey, names, source);
1161
+ };
1162
+ const markSourceUnsafe = (source) => {
1163
+ const sharedKey = matchShared(source);
1164
+ if (sharedKey) markUnsafe(sharedKey, source);
1165
+ };
1166
+ forEachAstNode(ast, (node) => {
1167
+ if (node.type === "ImportDeclaration") {
1168
+ const source = getModuleSource(node.source);
1169
+ if (source) collectImportDeclaration(node, source, recordSource, markSourceUnsafe);
1170
+ return;
1171
+ }
1172
+ if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
1173
+ const source = getModuleSource(node.source);
1174
+ if (source) collectReExport(node, source, recordSource, markSourceUnsafe);
1175
+ return;
1176
+ }
1177
+ if (node.type === "ImportExpression") {
1178
+ const source = getModuleSource(node.source);
1179
+ if (source) markSourceUnsafe(source);
1180
+ return;
1181
+ }
1182
+ if (node.type === "CallExpression") {
1183
+ const callee = node.callee;
1184
+ const args = Array.isArray(node.arguments) ? node.arguments : [];
1185
+ if (callee?.type === "Identifier" && callee.name === "require" && args.length > 0) {
1186
+ const source = getModuleSource(args[0]);
1187
+ if (source) markSourceUnsafe(source);
1188
+ }
1189
+ }
1190
+ });
1191
+ }
1192
+ //#endregion
931
1193
  //#region src/virtualModules/virtualShared_preBuild.ts
932
1194
  /**
933
1195
  * Even the resolveId hook cannot interfere with vite pre-build,
@@ -1173,7 +1435,7 @@ function isWorkspaceFilePath(resolved) {
1173
1435
  try {
1174
1436
  realResolved = realpathSync.native(resolved);
1175
1437
  } catch {}
1176
- return !realResolved.includes("/node_modules/") && !realResolved.includes("\\node_modules\\");
1438
+ return !normalizeNodeModulePath(realResolved).includes("/node_modules/");
1177
1439
  }
1178
1440
  /**
1179
1441
  * When createRequire resolves a workspace package to a CJS entry (e.g. dist/index.cjs),
@@ -1285,10 +1547,104 @@ function getConcreteSharedImportSource(pkg, shareItem) {
1285
1547
  const preBuildCacheMap = {};
1286
1548
  const preBuildShareItemMap = {};
1287
1549
  const PREBUILD_TAG = "__prebuild__";
1550
+ const treeShakingProviderCacheMap = {};
1551
+ const materializedTreeShakingProviders = /* @__PURE__ */ new Set();
1552
+ const TREE_SHAKING_PROVIDER_TAG = "__treeShakingProvider__";
1553
+ const TREE_SHAKING_GRAPH_QUERY = "__mf_tree_shaking_graph__";
1554
+ function getTreeShakingGraphToken(id) {
1555
+ if (!id) return void 0;
1556
+ const queryStart = id.indexOf("?");
1557
+ if (queryStart === -1) return void 0;
1558
+ const hashStart = id.indexOf("#", queryStart);
1559
+ const entry = id.slice(queryStart + 1, hashStart === -1 ? void 0 : hashStart).split("&").find((part) => part.split("=", 1)[0] === TREE_SHAKING_GRAPH_QUERY);
1560
+ if (!entry) return void 0;
1561
+ const value = entry.slice(26);
1562
+ try {
1563
+ return decodeURIComponent(value);
1564
+ } catch {
1565
+ return value;
1566
+ }
1567
+ }
1568
+ function stripTreeShakingGraphQuery(id) {
1569
+ const queryStart = id.indexOf("?");
1570
+ if (queryStart === -1) return id;
1571
+ const hashStart = id.indexOf("#", queryStart);
1572
+ const pathname = id.slice(0, queryStart);
1573
+ const hash = hashStart === -1 ? "" : id.slice(hashStart);
1574
+ const remaining = id.slice(queryStart + 1, hashStart === -1 ? void 0 : hashStart).split("&").filter(Boolean).filter((part) => part.split("=", 1)[0] !== TREE_SHAKING_GRAPH_QUERY);
1575
+ return `${pathname}${remaining.length ? `?${remaining.join("&")}` : ""}${hash}`;
1576
+ }
1577
+ function addTreeShakingGraphQuery(id, token) {
1578
+ const cleanId = stripTreeShakingGraphQuery(id);
1579
+ const hashStart = cleanId.indexOf("#");
1580
+ const base = hashStart === -1 ? cleanId : cleanId.slice(0, hashStart);
1581
+ const hash = hashStart === -1 ? "" : cleanId.slice(hashStart);
1582
+ return `${base}${base.includes("?") ? "&" : "?"}${TREE_SHAKING_GRAPH_QUERY}=${encodeURIComponent(token)}${hash}`;
1583
+ }
1584
+ function getConcreteTreeShakingExportUsage(pkg, shareItem) {
1585
+ return getTreeShakingExportUsage(pkg, shareItem, shareItem?.name);
1586
+ }
1587
+ function getTreeShakingSharedProviderName(pkg) {
1588
+ const { internalName, name } = getNormalizeModuleFederationOptions();
1589
+ return `${internalName || name}__tree_shaking__${packageNameEncode(pkg)}`;
1590
+ }
1591
+ function getTreeShakingSharedProviderImportId(pkg) {
1592
+ if (!treeShakingProviderCacheMap[pkg]) treeShakingProviderCacheMap[pkg] = new VirtualModule(pkg, TREE_SHAKING_PROVIDER_TAG, ".js");
1593
+ return treeShakingProviderCacheMap[pkg].getImportId();
1594
+ }
1595
+ function hasTreeShakingSharedProvider(pkg, shareItem) {
1596
+ const usage = getConcreteTreeShakingExportUsage(pkg, shareItem);
1597
+ return materializedTreeShakingProviders.has(pkg) && usage?.kind === "exports";
1598
+ }
1599
+ /**
1600
+ * Materialize the locally optimized provider as a small ESM container.
1601
+ *
1602
+ * The normal prebuild module remains the complete fallback. This container only
1603
+ * retains the selected exports and is installed as `treeShaking.get` by the
1604
+ * generated runtime record. Keeping the two getters distinct lets the Runtime
1605
+ * perform its normal usedExports compatibility check and safely choose the full
1606
+ * provider when the optimized one is insufficient.
1607
+ */
1608
+ function writeTreeShakingSharedProvider(pkg, shareItem) {
1609
+ const usage = getConcreteTreeShakingExportUsage(pkg, shareItem);
1610
+ if (usage?.kind !== "exports" || !usage.usedExports.length || shareItem?.shareConfig.import === false) {
1611
+ materializedTreeShakingProviders.delete(pkg);
1612
+ return;
1613
+ }
1614
+ const usedExports = usage.usedExports;
1615
+ const unsupportedExport = usedExports.find((name) => name !== "default" && !isValidEsmExportName(name));
1616
+ if (unsupportedExport) {
1617
+ materializedTreeShakingProviders.delete(pkg);
1618
+ mfWarn(`Tree-shaking shared dependency "${pkg}" was disabled because export "${unsupportedExport}" cannot be represented by the generated ESM provider.`);
1619
+ return;
1620
+ }
1621
+ const provider = treeShakingProviderCacheMap[pkg] || (treeShakingProviderCacheMap[pkg] = new VirtualModule(pkg, "__treeShakingProvider__", ".js"));
1622
+ const optimizedImportSource = addTreeShakingGraphQuery(getConcreteSharedImportSource(pkg, shareItem) || pkg, pkg);
1623
+ const namedExports = usedExports.filter((name) => name !== "default");
1624
+ const namedImports = namedExports.map((name, index) => `${name} as __mfTreeShaken_${index}`).join(", ");
1625
+ const importLines = [namedImports ? `import { ${namedImports} } from ${escapeGeneratedStringLiteral(optimizedImportSource)};` : "", usedExports.includes("default") ? `import __mfTreeShakenDefault from ${escapeGeneratedStringLiteral(optimizedImportSource)};` : ""].filter(Boolean).join("\n");
1626
+ 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(", ")} }`]];
1627
+ provider.writeSync(`${importLines}
1628
+ const __mfTreeShakenModule = { ${namespaceEntries.join(", ")} };
1629
+ Object.defineProperty(__mfTreeShakenModule, "__esModule", {
1630
+ value: true,
1631
+ enumerable: false,
1632
+ });
1633
+ async function init() {}
1634
+ function get() {
1635
+ return () => __mfTreeShakenModule;
1636
+ }
1637
+ const usedExports = ${JSON.stringify([...usedExports].sort())};
1638
+ export { get, init, usedExports };
1639
+ export default { get, init };
1640
+ `, true);
1641
+ materializedTreeShakingProviders.add(pkg);
1642
+ }
1288
1643
  function writePreBuildLibPath(pkg, shareItem) {
1289
1644
  if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG, ".js");
1290
1645
  preBuildShareItemMap[pkg] = shareItem;
1291
1646
  const importSource = getConcreteSharedImportSource(pkg, shareItem) || pkg;
1647
+ writeTreeShakingSharedProvider(pkg, shareItem);
1292
1648
  if (pkg === "react/compiler-runtime") {
1293
1649
  const reactCacheDescriptor = getSharedCacheDescriptorLiteral("react", shareItem ?? {
1294
1650
  name: "react",
@@ -1343,16 +1699,27 @@ function writePreBuildLibPath(pkg, shareItem) {
1343
1699
  const __mfPrebuildExports = __mfPrebuildNamespace;
1344
1700
  ${declarations}
1345
1701
  ${namedExportLine}
1346
- export default __mfPrebuildNamespace.default ?? __mfPrebuildNamespace;
1702
+ export default Reflect.get(__mfPrebuildNamespace, "default") ?? __mfPrebuildNamespace;
1347
1703
  `, true);
1348
1704
  return;
1349
1705
  }
1350
1706
  preBuildCacheMap[pkg].writeSync(`
1351
1707
  import * as __mfPrebuildExports from ${escapeGeneratedStringLiteral(importSource)};
1352
1708
  export * from ${escapeGeneratedStringLiteral(importSource)};
1353
- export default __mfPrebuildExports.default ?? __mfPrebuildExports;
1709
+ // Reflect access avoids bundler warnings for ESM packages without a
1710
+ // default export (for example antd/es/index.js), while preserving the
1711
+ // namespace fallback for packages that do provide one.
1712
+ export default Reflect.get(__mfPrebuildExports, "default") ?? __mfPrebuildExports;
1354
1713
  `, true);
1355
1714
  }
1715
+ /** Re-render already materialized wrappers after import analysis discovers exports. */
1716
+ function refreshTreeShakingModules() {
1717
+ for (const [pkg, shareItem] of Object.entries(preBuildShareItemMap)) {
1718
+ if (!shareItem?.shareConfig.treeShaking) continue;
1719
+ writePreBuildLibPath(pkg, shareItem);
1720
+ writeLoadShareModule(pkg, shareItem, "build", false);
1721
+ }
1722
+ }
1356
1723
  function getPreBuildLibImportId(pkg) {
1357
1724
  if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG, ".js");
1358
1725
  return preBuildCacheMap[pkg].getImportId();
@@ -1398,12 +1765,15 @@ function materializeCachedLoadShareModule(options) {
1398
1765
  options.addUsedShares(pkg);
1399
1766
  options.writeLocalSharedImportMap();
1400
1767
  }
1401
- function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor) {
1768
+ function getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer) {
1769
+ return treeShakingConsumer ? `__mfReadTreeShakingSharedSelection(__mfModuleCache.share, ${cacheDescriptor}, ${JSON.stringify(treeShakingConsumer)})` : `__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor})`;
1770
+ }
1771
+ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, treeShakingConsumer) {
1402
1772
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1403
1773
  const namedExportAssignments = namedExports.length > 0 ? `\n ${namedExports.map((name, i) => `const ${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`).join("\n ")}` : "";
1404
1774
  const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1405
1775
  return `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(importSource)};
1406
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1776
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1407
1777
  if (exportModule === undefined) {
1408
1778
  Promise.resolve().then(() => {
1409
1779
  if (__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor}) === undefined) {
@@ -1415,24 +1785,25 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
1415
1785
  const __mf_default = exportModule.default ?? exportModule;${namedExportAssignments}
1416
1786
  export { __mf_default as default };${namedExportLine}`;
1417
1787
  }
1418
- function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor) {
1788
+ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, treeShakingConsumer) {
1419
1789
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1420
1790
  const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
1421
1791
  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
1792
  const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1793
+ const applyLocalFallback = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1794
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1795
+ __mfApplyLazyShareExports(exportModule);`;
1423
1796
  return `${declarations}
1424
1797
  const __mfApplyLazyShareExports = (mod) => {
1425
1798
  ${assignments}
1426
1799
  };
1427
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1800
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1428
1801
  if (exportModule === undefined) {
1429
1802
  if (import.meta.env.SSR) {
1430
- ${`exportModule = __mfNormalizeShareModule(__mfLocalShare);
1431
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1432
- __mfApplyLazyShareExports(exportModule);`}
1803
+ ${applyLocalFallback}
1433
1804
  } else {
1434
1805
  (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
1435
- exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1806
+ exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1436
1807
  if (exportModule !== undefined) {
1437
1808
  __mfApplyLazyShareExports(exportModule);
1438
1809
  return;
@@ -1459,16 +1830,19 @@ function prependWorkspaceSingletonSsrImport(code) {
1459
1830
  const quote = importMatch[1];
1460
1831
  return `import * as __mfLocalShare from ${quote}${importMatch[2]}${quote};\n${code}`;
1461
1832
  }
1462
- function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor) {
1833
+ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer) {
1463
1834
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1464
- return `${["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ")}
1835
+ const declarations = ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ");
1836
+ const assignments = [...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ");
1837
+ const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1838
+ return `${declarations}
1465
1839
  const __mfApplyHostProvidedExports = (exportModule) => {
1466
- ${[...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ")}
1840
+ ${assignments}
1467
1841
  };
1468
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1842
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1469
1843
  if (exportModule === undefined) {
1470
1844
  (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
1471
- exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1845
+ exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1472
1846
  if (exportModule === undefined) {
1473
1847
  throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
1474
1848
  }
@@ -1477,7 +1851,7 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor)
1477
1851
  } else {
1478
1852
  __mfApplyHostProvidedExports(exportModule);
1479
1853
  }
1480
- export { __mf_default as default };${namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : ""}`;
1854
+ export { __mf_default as default };${namedExportLine}`;
1481
1855
  }
1482
1856
  function generateShareModuleUnwrapCode({ source, preserveNamedExports, stopWithReturn }) {
1483
1857
  return `let current = ${source};
@@ -1500,13 +1874,14 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1500
1874
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".js");
1501
1875
  let importLine = getRuntimeModuleCacheBootstrapCode();
1502
1876
  const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
1877
+ const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ? getNormalizeModuleFederationOptions().name : void 0;
1503
1878
  if (shareItem.shareConfig.import === false) {
1504
1879
  const namedExports = getPackageNamedExports(pkg);
1505
1880
  let exportLine;
1506
- if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor);
1881
+ if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer);
1507
1882
  else {
1508
1883
  mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
1509
- exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor);
1884
+ exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor, treeShakingConsumer);
1510
1885
  }
1511
1886
  loadShareCacheMap[pkg].writeSync(`
1512
1887
  ${getRuntimeInitPromiseBootstrapCode()}
@@ -1529,13 +1904,17 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1529
1904
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg);
1530
1905
  const usesEntryInjectedRemoteFallback = command !== "build" && !isWorkspaceSingleton && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && getNormalizeModuleFederationOptions().hostInitInjectLocation === "entry" && isConsumedByPeerSingleton;
1531
1906
  const usesEagerWorkspaceFallback = isWorkspaceSingleton && isConsumedByPeerSingleton;
1907
+ const usesDeferredTreeShakingFallback = Boolean(treeShakingConsumer);
1532
1908
  const namedExports = getSharedNamedExports(pkg, shareItem);
1533
1909
  let exportLine;
1534
1910
  let initBlock = "";
1535
- if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor);
1911
+ if (usesDeferredTreeShakingFallback) {
1912
+ importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
1913
+ exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, treeShakingConsumer);
1914
+ } else if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, treeShakingConsumer);
1536
1915
  else if (usesDeferredSingletonFallback) {
1537
1916
  importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
1538
- exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor);
1917
+ exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, treeShakingConsumer);
1539
1918
  } else if (namedExports.length > 0) {
1540
1919
  const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1541
1920
  const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
@@ -1556,9 +1935,9 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1556
1935
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1557
1936
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);`;
1558
1937
  }
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 ? `
1938
+ const prebuildImportLine = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
1939
+ const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
1940
+ const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? `
1562
1941
  ${prebuildImportLine}
1563
1942
  ${devDynamicImportLine}
1564
1943
  ${importLine}
@@ -1571,7 +1950,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1571
1950
  ${importLine}
1572
1951
  ${sharedCacheHelperCode}
1573
1952
  ${normalizeLocalShareModuleCode}
1574
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor})
1953
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)}
1575
1954
  if (exportModule === undefined) {
1576
1955
  ${initBlock}
1577
1956
  }
@@ -1618,14 +1997,21 @@ function getDirectSharedCacheSeedImportPath(pkg, shareItem) {
1618
1997
  function generateLocalSharedImportMap() {
1619
1998
  const useDirectReactImport = shouldUseDirectReactImport();
1620
1999
  const options = getNormalizeModuleFederationOptions();
2000
+ const orderedShares = getOrderedUsedShares();
1621
2001
  return `
1622
2002
  import {loadShare} from "@module-federation/runtime";
2003
+ ${orderedShares.map((pkg, index) => {
2004
+ const shareItem = getNormalizeShareItem(pkg);
2005
+ if (!shareItem?.shareConfig.eager || shareItem.shareConfig.import === false) return "";
2006
+ return `import * as __mfEagerShare_${index} from ${JSON.stringify(getLocalSharedPackagePath(pkg, shareItem))};`;
2007
+ }).filter(Boolean).join("\n")}
1623
2008
  const importMap = {
1624
- ${getOrderedUsedShares().map((pkg) => {
2009
+ ${orderedShares.map((pkg, index) => {
1625
2010
  const shareItem = getNormalizeShareItem(pkg);
1626
2011
  return `
1627
2012
  ${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))});
2013
+ ${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};
2014
+ return pkg;` : `let pkg = await import(${JSON.stringify(getLocalSharedPackagePath(pkg, shareItem))});
1629
2015
  return pkg;`}
1630
2016
  }
1631
2017
  `;
@@ -1635,12 +2021,19 @@ function generateLocalSharedImportMap() {
1635
2021
  ${getOrderedUsedShares().map((key) => {
1636
2022
  const shareItem = getNormalizeShareItem(key);
1637
2023
  if (!shareItem) return null;
2024
+ const treeShakingUsage = getTreeShakingExportUsage(key, shareItem, shareItem.name);
2025
+ const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
2026
+ const treeShakingUsedExports = options.injectTreeShakingUsedExports === false ? shareItem.shareConfig.treeShaking?.usedExports || [] : treeShakingProviderExports;
2027
+ const disableRuntimeInference = shareItem.shareConfig.treeShaking?.mode === "runtime-infer" && options.injectTreeShakingUsedExports === false;
2028
+ const treeShakingProviderImportId = !disableRuntimeInference && hasTreeShakingSharedProvider(key, shareItem) ? getTreeShakingSharedProviderImportId(key) : void 0;
2029
+ const treeShakingStatus = treeShakingUsage?.kind === "full" || disableRuntimeInference || shareItem.shareConfig.treeShaking?.mode === "runtime-infer" && !treeShakingProviderImportId && shareItem.shareConfig.import !== false ? 0 : 1;
1638
2030
  return `
1639
2031
  ${JSON.stringify(key)}: {
1640
2032
  name: ${JSON.stringify(key)},
1641
2033
  version: ${JSON.stringify(shareItem.version)},
1642
2034
  scope: [${JSON.stringify(shareItem.scope)}],
1643
2035
  loaded: false,
2036
+ eager: ${Boolean(shareItem.shareConfig.eager)},
1644
2037
  from: ${JSON.stringify(options.name)},
1645
2038
  async get () {
1646
2039
  if (${shareItem.shareConfig.import === false}) {
@@ -1665,8 +2058,20 @@ function generateLocalSharedImportMap() {
1665
2058
  singleton: ${shareItem.shareConfig.singleton},
1666
2059
  requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
1667
2060
  strictVersion: ${shareItem.shareConfig.strictVersion},
2061
+ eager: ${Boolean(shareItem.shareConfig.eager)},
1668
2062
  ${shareItem.shareConfig.import === false ? "import: false," : ""}
1669
- }
2063
+ },
2064
+ ${shareItem.shareConfig.treeShaking ? `treeShaking: {
2065
+ mode: ${JSON.stringify(shareItem.shareConfig.treeShaking.mode)},
2066
+ usedExports: ${JSON.stringify(treeShakingUsedExports)},
2067
+ providedExports: ${JSON.stringify(treeShakingProviderExports)},
2068
+ status: ${treeShakingStatus},
2069
+ ${treeShakingProviderImportId ? `async get() {
2070
+ const container = await import(${JSON.stringify(treeShakingProviderImportId)});
2071
+ if (typeof container.init === "function") await container.init();
2072
+ return container.get();
2073
+ },` : ""}
2074
+ }` : ""}
1670
2075
  }
1671
2076
  `;
1672
2077
  }).filter((x) => x !== null).join(",")}
@@ -1676,6 +2081,7 @@ function generateLocalSharedImportMap() {
1676
2081
  if (!remote) return null;
1677
2082
  return `
1678
2083
  {
2084
+ alias: ${JSON.stringify(key)},
1679
2085
  entryGlobalName: ${JSON.stringify(remote.entryGlobalName)},
1680
2086
  name: ${JSON.stringify(remote.name)},
1681
2087
  type: ${JSON.stringify(remote.type)},
@@ -1838,7 +2244,11 @@ function generateRuntimeSharedCacheSeedCode() {
1838
2244
  for (const pkg of __mfSeedKeys) {
1839
2245
  const share = usedShared[pkg];
1840
2246
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
1841
- if (share.shareConfig?.import === false || __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) {
2247
+ if (
2248
+ share.shareConfig?.import === false ||
2249
+ Boolean(share.treeShaking) ||
2250
+ __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined
2251
+ ) {
1842
2252
  continue;
1843
2253
  }
1844
2254
  const singletonCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, true, share.version, share.scope);
@@ -1889,8 +2299,176 @@ function getRemoteEntryId(options) {
1889
2299
  const SSR_ONLY_PLUGIN_SPECIFIERS = new Set(["@module-federation/vite/ssrEntryLoader"]);
1890
2300
  const isSsrOnlyPlugin = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].some((s) => importStatement.includes(s));
1891
2301
  const getSsrOnlyPluginSpecifier = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].find((s) => importStatement.includes(s));
2302
+ function generateTreeShakingSharedResolutionCode(enabled) {
2303
+ if (!enabled) return "";
2304
+ return `
2305
+ // Resolve tree-enabled shares through the Runtime after all providers have
2306
+ // registered. Partial providers are stored with their export coverage and
2307
+ // never occupy generic/legacy cache keys, which are reserved for complete
2308
+ // modules only.
2309
+ for (const [pkg, share] of Object.entries(usedShared)) {
2310
+ const treeShaking = share.treeShaking;
2311
+ if (!treeShaking) continue;
2312
+ try {
2313
+ const factory = await initRes.loadShare(pkg, {
2314
+ customShareInfo: {
2315
+ shareConfig: share.shareConfig,
2316
+ treeShaking: {
2317
+ mode: treeShaking.mode,
2318
+ status: treeShaking.status,
2319
+ usedExports: treeShaking.usedExports,
2320
+ },
2321
+ },
2322
+ });
2323
+ if (factory === false) continue;
2324
+ const mod = typeof factory === "function" ? factory() : factory;
2325
+ const resolved = await Promise.resolve(mod);
2326
+ ${normalizeRuntimeShareCode}
2327
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2328
+ const normalizedShared = __mfNormalizeRuntimeShare(resolved);
2329
+ const hasPartialProvider =
2330
+ Array.isArray(treeShaking.providedExports) &&
2331
+ treeShaking.providedExports.length > 0 &&
2332
+ ((treeShaking.mode === "runtime-infer" && treeShaking.status !== 0) ||
2333
+ treeShaking.status === 2);
2334
+ if (hasPartialProvider) {
2335
+ __mfWriteTreeShakingSharedCache(
2336
+ __mfModuleCache.share,
2337
+ cacheDescriptor,
2338
+ treeShaking.providedExports,
2339
+ normalizedShared
2340
+ );
2341
+ __mfWriteTreeShakingSharedSelection(
2342
+ __mfModuleCache.share,
2343
+ cacheDescriptor,
2344
+ mfName,
2345
+ normalizedShared
2346
+ );
2347
+ } else {
2348
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, normalizedShared);
2349
+ }
2350
+ } catch (e) {
2351
+ console.warn('[Module Federation] Failed to load tree-shaken shared module', pkg, e);
2352
+ }
2353
+ }`;
2354
+ }
2355
+ const treeShakingResolveShareBodyCode = `const originalResolver = args.resolver;
2356
+ args.resolver = () => {
2357
+ const resolved = originalResolver();
2358
+ if (!resolved?.useTreesShaking) return resolved;
2359
+
2360
+ const consumerTreeShaking = args.shareInfo?.treeShaking;
2361
+ if (consumerTreeShaking?.mode !== "runtime-infer") return resolved;
2362
+ const requiredExports = consumerTreeShaking.usedExports;
2363
+ if (!Array.isArray(requiredExports)) return resolved;
2364
+
2365
+ const selectedExports = resolved.shared?.treeShaking?.usedExports;
2366
+ const selectedMatches = Array.isArray(selectedExports) &&
2367
+ requiredExports.every((name) => selectedExports.includes(name));
2368
+ if (selectedMatches) return resolved;
2369
+
2370
+ // Runtime 2.7 prefers a tree provider by version before checking export
2371
+ // coverage. Prefer this consumer's own compatible provider when one is
2372
+ // available; otherwise retain the selected version but use its complete
2373
+ // top-level getter.
2374
+ const localExports = consumerTreeShaking.providedExports;
2375
+ const localMatches = typeof consumerTreeShaking.get === "function" &&
2376
+ Array.isArray(localExports) &&
2377
+ requiredExports.every((name) => localExports.includes(name));
2378
+ if (localMatches) {
2379
+ return { shared: args.shareInfo, useTreesShaking: true };
2380
+ }
2381
+ return { shared: resolved.shared, useTreesShaking: false };
2382
+ };
2383
+ return args;`;
2384
+ function generateTreeShakingSnapshotPluginCode(enabled) {
2385
+ if (!enabled) return "";
2386
+ return `
2387
+ const __mfTreeShakingSnapshotPlugin = () => ({
2388
+ name: "vite-tree-shaking-snapshot-plugin",
2389
+ resolveShare(args) {
2390
+ ${treeShakingResolveShareBodyCode}
2391
+ },
2392
+ beforeInit(args) {
2393
+ const { userOptions, origin, options: registeredOptions } = args;
2394
+ const version = userOptions.version || registeredOptions.version;
2395
+ const hostSnapshot = runtimeGlobal.getGlobalSnapshotInfoByModuleInfo({
2396
+ name: origin.name,
2397
+ version,
2398
+ });
2399
+ if (!hostSnapshot || !("shared" in hostSnapshot)) return args;
2400
+
2401
+ const candidates = [];
2402
+ const appendShared = (records) => {
2403
+ for (const [pkgName, value] of Object.entries(records || {})) {
2404
+ const values = Array.isArray(value) ? value : [value];
2405
+ for (const shared of values) candidates.push([pkgName, shared]);
2406
+ }
2407
+ };
2408
+ appendShared(userOptions.shared);
2409
+ appendShared(registeredOptions.shared);
2410
+
2411
+ for (const [pkgName, shared] of candidates) {
2412
+ const treeShaking = shared?.treeShaking;
2413
+ if (!treeShaking || treeShaking.mode !== "server-calc") continue;
2414
+ const shareSnapshot = hostSnapshot.shared.find((item) => item.sharedName === pkgName);
2415
+ if (!shareSnapshot || typeof shareSnapshot.treeShakingStatus !== "number") continue;
2416
+ const {
2417
+ secondarySharedTreeShakingEntry: entry,
2418
+ secondarySharedTreeShakingName: name,
2419
+ treeShakingStatus: status,
2420
+ usedExports,
2421
+ fallbackType,
2422
+ } = shareSnapshot;
2423
+
2424
+ // A CALCULATED snapshot without a loadable secondary entry is not safe:
2425
+ // retain UNKNOWN so the Runtime chooses the complete top-level getter.
2426
+ if (status === 2 && (!entry || !name)) continue;
2427
+ if (Array.isArray(usedExports)) {
2428
+ treeShaking.usedExports = usedExports;
2429
+ treeShaking.providedExports = usedExports;
2430
+ }
2431
+ if (entry && name) {
2432
+ const fullFallbackGet = shared.get;
2433
+ treeShaking.get = async () => {
2434
+ try {
2435
+ const shareEntry = await getRemoteEntry({
2436
+ origin,
2437
+ remoteInfo: {
2438
+ name,
2439
+ entry,
2440
+ type: fallbackType || "global",
2441
+ entryGlobalName: name,
2442
+ shareScope: "default",
2443
+ },
2444
+ });
2445
+ if (!shareEntry) throw new Error("Tree-shaken shared entry did not load");
2446
+ if (typeof shareEntry.init === "function") {
2447
+ await shareEntry.init(origin);
2448
+ }
2449
+ return shareEntry.get();
2450
+ } catch (error) {
2451
+ if (typeof fullFallbackGet === "function") return fullFallbackGet();
2452
+ throw error;
2453
+ }
2454
+ };
2455
+ }
2456
+ treeShaking.status = status;
2457
+ }
2458
+ return args;
2459
+ },
2460
+ });`;
2461
+ }
1892
2462
  function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
1893
2463
  const needsSharedProviderSelectionHelper = hasImportFalseShared$1(options);
2464
+ const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
2465
+ const hasEagerShared = Object.values(options.shared ?? {}).some((share) => share?.shareConfig.eager === true && share.shareConfig.import !== false);
2466
+ const runtimeImports = [
2467
+ "init as runtimeInit",
2468
+ "loadRemote",
2469
+ ...hasTreeShakingShared ? ["getRemoteEntry"] : []
2470
+ ].join(", ");
2471
+ const runtimeHelperImports = [...hasTreeShakingShared ? ["global as runtimeGlobal"] : [], ...needsSharedProviderSelectionHelper ? ["share as runtimeShare"] : []];
1894
2472
  const pluginImportNames = options.runtimePlugins.map((p, i) => {
1895
2473
  if (typeof p === "string") return [
1896
2474
  `$runtimePlugin_${i}`,
@@ -1912,8 +2490,9 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1912
2490
  if (typeof __VUE_HMR_RUNTIME__ === 'undefined') {
1913
2491
  globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
1914
2492
  }
1915
- import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
1916
- ${needsSharedProviderSelectionHelper ? "import {share as runtimeShare} from \"@module-federation/runtime/helpers\";" : ""}
2493
+ import {${runtimeImports}} from "@module-federation/runtime";
2494
+ ${hasEagerShared ? `import * as __mfLocalSharedImportMap from "${getLocalSharedImportMapPath()}";` : ""}
2495
+ ${runtimeHelperImports.length ? `import {${runtimeHelperImports.join(", ")}} from "@module-federation/runtime/helpers";` : ""}
1917
2496
  ${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
1918
2497
  ${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
1919
2498
  ${getRuntimeModuleCacheBootstrapCode()}
@@ -1941,14 +2520,16 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1941
2520
  }
1942
2521
  }
1943
2522
  }
2523
+ ${generateTreeShakingSnapshotPluginCode(hasTreeShakingShared)}
1944
2524
  ${needsSharedProviderSelectionHelper ? sharedProviderSelectionHelperCode : ""}
1945
2525
 
1946
2526
  async function getLocalSharedImportMap() {
1947
- if (!localSharedImportMapPromise) {
2527
+ ${hasEagerShared ? "return __mfLocalSharedImportMap;" : ""}
2528
+ ${hasEagerShared ? "" : `if (!localSharedImportMapPromise) {
1948
2529
  localSharedImportMapPromise = retrySharedInit(() => import("${getLocalSharedImportMapPath()}"))
1949
2530
  .catch((e) => { localSharedImportMapPromise = undefined; throw e; });
1950
2531
  }
1951
- return localSharedImportMapPromise
2532
+ return localSharedImportMapPromise`}
1952
2533
  }
1953
2534
 
1954
2535
  async function getExposesMap() {
@@ -2021,7 +2602,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
2021
2602
  name: mfName,
2022
2603
  remotes: ${options.shareStrategy === "loaded-first" ? "[]" : "usedRemotes"},
2023
2604
  shared: usedShared,
2024
- plugins: [...__browserPlugins, ...__ssrPlugins],
2605
+ plugins: [${hasTreeShakingShared ? "__mfTreeShakingSnapshotPlugin()," : ""} ...__browserPlugins, ...__ssrPlugins],
2025
2606
  ${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
2026
2607
  });
2027
2608
  // handling circular init calls
@@ -2042,9 +2623,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
2042
2623
  } catch (e) {
2043
2624
  console.error('[Module Federation]', e)
2044
2625
  }
2626
+ ${generateTreeShakingSharedResolutionCode(hasTreeShakingShared)}
2045
2627
  for (const [pkg, share] of Object.entries(usedShared)) {
2046
2628
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2047
- if (share.shareConfig?.import !== false || __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) continue;
2629
+ const cachedShare = share.treeShaking
2630
+ ? __mfReadTreeShakingSharedSelection(__mfModuleCache.share, cacheDescriptor, mfName)
2631
+ : __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor);
2632
+ if (share.shareConfig?.import !== false || cachedShare !== undefined) continue;
2048
2633
  ${normalizeRuntimeShareCode}
2049
2634
  const versions = shared?.[pkg];
2050
2635
  const provider = __mfSelectSharedProvider(versions, pkg, share, '${options.shareStrategy}');
@@ -2096,6 +2681,10 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
2096
2681
  for (const pkg of __mfHostInitShareOrder) {
2097
2682
  const share = usedShared[pkg];
2098
2683
  if (!share) continue;
2684
+ // remoteEntry.init resolves tree-enabled shares into the
2685
+ // coverage-aware cache. Never republish that selected partial under
2686
+ // a generic full-module key here.
2687
+ if (share.treeShaking) continue;
2099
2688
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2100
2689
  if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) {
2101
2690
  continue;
@@ -2158,9 +2747,8 @@ function addUsedRemote(remoteKey, remoteModule) {
2158
2747
  function getUsedRemotesMap() {
2159
2748
  return usedRemotesMap;
2160
2749
  }
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;
2750
+ function getRemoteAliasFromId(id, remotes) {
2751
+ return Object.keys(remotes).filter((name) => id === name || id.startsWith(name + "/")).sort((a, b) => b.length - a.length)[0];
2164
2752
  }
2165
2753
  function resolveRemoteInitMode(shareStrategy, consumer) {
2166
2754
  if (shareStrategy !== "loaded-first") return "eager";
@@ -2316,10 +2904,12 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
2316
2904
  const isLoadedFirst = options.shareStrategy === "loaded-first";
2317
2905
  const initMode = resolveRemoteInitMode(options.shareStrategy, consumer);
2318
2906
  const deferRemoteLoad = shouldDeferRemoteLoad(initMode);
2319
- const remote = getRemoteFromId(id, options.remotes);
2907
+ const remoteAlias = getRemoteAliasFromId(id, options.remotes);
2908
+ const remote = remoteAlias ? options.remotes[remoteAlias] : void 0;
2320
2909
  const registerRemoteCode = isLoadedFirst && remote ? `runtime.registerRemotes([${JSON.stringify({
2321
2910
  entryGlobalName: remote.entryGlobalName,
2322
2911
  name: remote.name,
2912
+ alias: remoteAlias,
2323
2913
  type: remote.type,
2324
2914
  entry: remote.entry,
2325
2915
  shareScope: remote.shareScope ?? "default"
@@ -2391,7 +2981,7 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
2391
2981
  const HOST_INIT_PRELOAD_CHUNKS = [
2392
2982
  (name) => name === "hostInit",
2393
2983
  (name) => name === "remoteEntry",
2394
- (name) => name.startsWith("_virtual_mf"),
2984
+ (name) => name.startsWith("_virtual_mf") && !name.includes("__prebuild__"),
2395
2985
  (name) => name === "index"
2396
2986
  ];
2397
2987
  function escapeHtmlAttr(value) {
@@ -2593,7 +3183,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2593
3183
  return decodeViteId(id).replace(/^\0/, "");
2594
3184
  }
2595
3185
  function normalizeModuleId(id) {
2596
- return id.split("?")[0].replace(/\\/g, "/");
3186
+ return normalizePathForImport(id.split("?")[0]);
2597
3187
  }
2598
3188
  function resolveProjectId(id) {
2599
3189
  if (id.startsWith("\0") || id.startsWith("virtual:")) return normalizeModuleId(id);
@@ -2630,8 +3220,8 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2630
3220
  const resolvedEntryPath = getEntryPath();
2631
3221
  if (resolvedEntryPath.startsWith("virtual:mf")) devEntryPath = config.base + VITE_ID_PREFIX.slice(1) + resolvedEntryPath;
2632
3222
  else {
2633
- const normalized = resolvedEntryPath.replace(/\\\\?/g, "/");
2634
- const root = config.root.replace(/\\\\?/g, "/").replace(/\/$/, "");
3223
+ const normalized = normalizePathForImport(resolvedEntryPath);
3224
+ const root = normalizePathForImport(config.root).replace(/\/$/, "");
2635
3225
  const relativePath = normalized.startsWith(root + "/") ? normalized.slice(root.length) : "/" + normalized.replace(/^[A-Za-z]:[\\/]/, "");
2636
3226
  devEntryPath = config.base + relativePath.replace(/^\//, "");
2637
3227
  }
@@ -3382,7 +3972,7 @@ function initVirtualModules(command, remoteEntryId, enableSsrInit = false) {
3382
3972
  function isOutputChunk$1(chunk) {
3383
3973
  return chunk.type === "chunk";
3384
3974
  }
3385
- function escapeRegExp(value) {
3975
+ function escapeRegExp$1(value) {
3386
3976
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3387
3977
  }
3388
3978
  function getProxyBaseName(fileName) {
@@ -3474,7 +4064,7 @@ function rewriteEsmProxyConsumers(code, proxyChunks) {
3474
4064
  const claimedLocals = /* @__PURE__ */ new Set();
3475
4065
  for (const [proxyFileName, proxyInfo] of Array.from(proxyChunks.entries())) {
3476
4066
  const proxyBaseName = getProxyBaseName(proxyFileName);
3477
- const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${escapeRegExp(proxyBaseName)}[^"']*)["']\\s*;?`).exec(nextCode);
4067
+ const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${escapeRegExp$1(proxyBaseName)}[^"']*)["']\\s*;?`).exec(nextCode);
3478
4068
  if (!importMatch) continue;
3479
4069
  const fullImport = importMatch[0];
3480
4070
  const bindings = importMatch[1].split(",").map((s) => {
@@ -3531,7 +4121,7 @@ function rewriteSystemProxyConsumers(code, systemProxyInfo) {
3531
4121
  let nextCode = code;
3532
4122
  for (const [proxyFileName, proxyInfo] of Array.from(systemProxyInfo.entries())) {
3533
4123
  const proxyBaseName = getProxyBaseName(proxyFileName);
3534
- const depMatch = new RegExp(`["']([^"']*${escapeRegExp(proxyBaseName)}[^"']*)["']`).exec(nextCode);
4124
+ const depMatch = new RegExp(`["']([^"']*${escapeRegExp$1(proxyBaseName)}[^"']*)["']`).exec(nextCode);
3535
4125
  if (!depMatch) continue;
3536
4126
  let setterIndex = 0;
3537
4127
  const depListMatch = nextCode.match(/System\.register\(\[([\s\S]*?)\]/);
@@ -3890,10 +4480,28 @@ function createRemoteEntryAssetMap(fileName) {
3890
4480
  }
3891
4481
  };
3892
4482
  }
4483
+ function isTreeShakingProviderChunk(file) {
4484
+ if (file.type !== "chunk") return false;
4485
+ if (file.facadeModuleId?.includes("__treeShakingProvider__")) return true;
4486
+ return Object.keys(file.modules || {}).some((id) => id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__"));
4487
+ }
4488
+ function getTreeShakingBuildInfo(options) {
4489
+ if (!(Object.values(options.shared || {}).some((share) => !!share.shareConfig.treeShaking) || !!options.treeShakingSharedPlugins?.length || !!options.treeShakingSharedExcludePlugins?.length)) return {};
4490
+ return {
4491
+ target: [options.target || "web"],
4492
+ ...options.treeShakingSharedPlugins?.length ? { plugins: [...options.treeShakingSharedPlugins] } : {},
4493
+ ...options.treeShakingSharedExcludePlugins?.length ? { excludePlugins: [...options.treeShakingSharedExcludePlugins] } : {}
4494
+ };
4495
+ }
4496
+ function getRemoteContainerName(remoteKey, remote) {
4497
+ const entryGlobalName = remote.entryGlobalName;
4498
+ if (entryGlobalName && entryGlobalName !== remoteKey && entryGlobalName !== remote.entry) return entryGlobalName;
4499
+ return remote.name;
4500
+ }
3893
4501
  const Manifest = () => {
3894
4502
  const mfOptions = getNormalizeModuleFederationOptions();
3895
4503
  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;
4504
+ let mfManifestName = manifestOptions === true ? "mf-manifest.json" : typeof manifestOptions === "object" ? normalizePathForImport(path$1.join(manifestOptions?.filePath || "", manifestOptions?.fileName || "mf-manifest.json")) : void 0;
3897
4505
  let mfManifestStatsName = mfManifestName ? getStatsFileName(mfManifestName) : void 0;
3898
4506
  const isConsumerProject = Object.keys(mfOptions.exposes).length === 0;
3899
4507
  let disableAssetsAnalyze = false;
@@ -3942,7 +4550,8 @@ const Manifest = () => {
3942
4550
  type: "app",
3943
4551
  buildInfo: {
3944
4552
  buildVersion: getBuildVersion(),
3945
- buildName: name
4553
+ buildName: name,
4554
+ ...getTreeShakingBuildInfo(mfOptions)
3946
4555
  },
3947
4556
  remoteEntry: {
3948
4557
  name: devRemoteEntryFile,
@@ -3997,6 +4606,16 @@ const Manifest = () => {
3997
4606
  if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
3998
4607
  ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(resolveDevRemoteEntryFileName(mfOptions.filename)) : expectedSsrRemoteEntryFile);
3999
4608
  const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
4609
+ if (allCssAssets.size > 0) {
4610
+ const secondaryCss = /* @__PURE__ */ new Set();
4611
+ const primaryCss = /* @__PURE__ */ new Set();
4612
+ for (const file of Object.values(bundle)) {
4613
+ if (file.type !== "chunk") continue;
4614
+ const target = isTreeShakingProviderChunk(file) ? secondaryCss : primaryCss;
4615
+ for (const css of file.viteMetadata?.importedCss || []) target.add(css);
4616
+ }
4617
+ for (const css of secondaryCss) if (!primaryCss.has(css)) allCssAssets.delete(css);
4618
+ }
4000
4619
  if (!disableAssetsAnalyze) {
4001
4620
  const exposesModules = Object.keys(mfOptions.exposes).map((item) => mfOptions.exposes[item].import);
4002
4621
  processModuleAssets(bundle, filesMap, (modulePath) => {
@@ -4008,7 +4627,7 @@ const Manifest = () => {
4008
4627
  stripKnownJsExtensions: true
4009
4628
  });
4010
4629
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(), this.resolve.bind(this));
4011
- processModuleAssets(bundle, filesMap, (modulePath) => fileToShareKey.get(modulePath));
4630
+ processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
4012
4631
  if (mfOptions.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
4013
4632
  filesMap = deduplicateAssets(filesMap);
4014
4633
  }
@@ -4052,22 +4671,37 @@ const Manifest = () => {
4052
4671
  path: "",
4053
4672
  type: "var"
4054
4673
  } : 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
- })));
4674
+ const remotes = Array.from(Object.entries(getUsedRemotesMap())).flatMap(([remoteKey, modules]) => {
4675
+ const remote = options.remotes[remoteKey];
4676
+ return Array.from(modules).map((moduleKey) => ({
4677
+ federationContainerName: getRemoteContainerName(remoteKey, remote),
4678
+ moduleName: moduleKey.replace(remoteKey, "").replace("/", ""),
4679
+ alias: remoteKey,
4680
+ entry: "*"
4681
+ }));
4682
+ });
4061
4683
  const shared = Array.from(getUsedShares()).flatMap((shareKey) => {
4062
4684
  const shareItem = getNormalizeShareItem(shareKey);
4063
4685
  if (!shareItem) return [];
4064
4686
  const assets = preloadMap[shareKey] || (_command === "serve" && resolvedRemoteEntryFile ? createRemoteEntryAssetMap(resolvedRemoteEntryFile) : createEmptyAssetMap());
4687
+ const treeShakingUsage = getTreeShakingExportUsage(shareKey, shareItem, shareItem.name);
4688
+ const treeShakingUsedExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
4689
+ const treeShakingStatus = treeShakingUsage?.kind === "full" ? 0 : 1;
4065
4690
  return [{
4066
4691
  id: `${name}:${shareKey}`,
4067
4692
  name: shareKey,
4068
4693
  version: shareItem.version,
4069
4694
  singleton: shareItem.shareConfig.singleton,
4070
4695
  requiredVersion: shareItem.shareConfig.requiredVersion,
4696
+ ...shareItem.shareConfig.treeShaking ? {
4697
+ usedExports: treeShakingUsedExports,
4698
+ referenceExports: treeShakingUsedExports,
4699
+ treeShaking: {
4700
+ mode: shareItem.shareConfig.treeShaking.mode,
4701
+ ...treeShakingUsage?.kind === "exports" ? { usedExports: treeShakingUsedExports } : {},
4702
+ status: treeShakingStatus
4703
+ }
4704
+ } : {},
4071
4705
  assets: {
4072
4706
  js: {
4073
4707
  async: assets.js.async,
@@ -4107,7 +4741,8 @@ const Manifest = () => {
4107
4741
  type: "app",
4108
4742
  buildInfo: {
4109
4743
  buildVersion: getBuildVersion(),
4110
- buildName: name
4744
+ buildName: name,
4745
+ ...getTreeShakingBuildInfo(options)
4111
4746
  },
4112
4747
  remoteEntry,
4113
4748
  ssrRemoteEntry,
@@ -4152,32 +4787,41 @@ function getStatsFileName(manifestFileName) {
4152
4787
  const fileExt = parsed.ext || ".json";
4153
4788
  const baseName = parsed.ext ? parsed.name : parsed.base;
4154
4789
  const fileName = `${baseName === "mf-manifest" ? "mf" : baseName}-stats${fileExt}`;
4155
- return parsed.dir ? path$1.join(parsed.dir, fileName) : fileName;
4790
+ return parsed.dir ? normalizePathForImport(path$1.join(parsed.dir, fileName)) : fileName;
4156
4791
  }
4157
4792
  //#endregion
4158
4793
  //#region src/plugins/pluginModuleParseEnd.ts
4159
4794
  let _resolve = null;
4160
4795
  let _parseTimeout = null;
4796
+ let _settleTimeout = null;
4161
4797
  let parsePromise = Promise.resolve(1);
4162
- let exposesParseEnd = false;
4163
- let expectsExposesParseEnd = false;
4164
4798
  let parseStartSet = /* @__PURE__ */ new Set();
4165
4799
  let parseEndSet = /* @__PURE__ */ new Set();
4800
+ let lastLoadedModule = "";
4801
+ let lastParsedModule = "";
4166
4802
  function clearParseTimeout() {
4167
4803
  if (_parseTimeout) {
4168
4804
  clearTimeout(_parseTimeout);
4169
4805
  _parseTimeout = null;
4170
4806
  }
4171
4807
  }
4808
+ function clearSettleTimeout() {
4809
+ if (_settleTimeout) {
4810
+ clearTimeout(_settleTimeout);
4811
+ _settleTimeout = null;
4812
+ }
4813
+ }
4172
4814
  function resetParseState() {
4173
4815
  clearParseTimeout();
4174
- exposesParseEnd = false;
4175
- expectsExposesParseEnd = false;
4816
+ clearSettleTimeout();
4176
4817
  parseStartSet = /* @__PURE__ */ new Set();
4177
4818
  parseEndSet = /* @__PURE__ */ new Set();
4819
+ lastLoadedModule = "";
4820
+ lastParsedModule = "";
4178
4821
  parsePromise = new Promise((resolve) => {
4179
4822
  _resolve = (v) => {
4180
4823
  clearParseTimeout();
4824
+ clearSettleTimeout();
4181
4825
  resolve(v);
4182
4826
  };
4183
4827
  });
@@ -4191,10 +4835,18 @@ function setParseTimeout(timeout) {
4191
4835
  function resetIdleTimeout(timeout) {
4192
4836
  clearParseTimeout();
4193
4837
  _parseTimeout = setTimeout(() => {
4194
- mfWarn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout.`);
4838
+ const pendingModules = Array.from(parseStartSet).filter((moduleId) => !parseEndSet.has(moduleId));
4839
+ 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
4840
  _resolve?.(1);
4196
4841
  }, timeout * 1e3);
4197
4842
  }
4843
+ function scheduleParseCompletionCheck() {
4844
+ clearSettleTimeout();
4845
+ _settleTimeout = setTimeout(() => {
4846
+ _settleTimeout = null;
4847
+ if (parseStartSet.size > 0 && Array.from(parseStartSet).every((moduleId) => parseEndSet.has(moduleId))) _resolve?.(1);
4848
+ }, 10);
4849
+ }
4198
4850
  function pluginModuleParseEnd_default(excludeFn, options) {
4199
4851
  const idleTimeout = options.moduleParseIdleTimeout ?? options.moduleParseTimeout;
4200
4852
  return [
@@ -4209,14 +4861,20 @@ function pluginModuleParseEnd_default(excludeFn, options) {
4209
4861
  enforce: "pre",
4210
4862
  name: "parseStart",
4211
4863
  apply: "build",
4212
- buildStart() {
4864
+ async buildStart() {
4213
4865
  resetParseState();
4214
4866
  if (idleTimeout) resetIdleTimeout(idleTimeout);
4215
- else setParseTimeout(options.moduleParseTimeout);
4867
+ else if (options.moduleParseTimeout) setParseTimeout(options.moduleParseTimeout);
4868
+ for (const importSource of options.exposedModuleImports || []) {
4869
+ const resolved = await this.resolve(importSource);
4870
+ if (resolved && !resolved.external && !excludeFn(resolved.id)) parseStartSet.add(resolved.id);
4871
+ }
4216
4872
  },
4217
4873
  load(id) {
4874
+ lastLoadedModule = id;
4218
4875
  if (excludeFn(id)) return;
4219
- if (id === options.virtualExposesId) expectsExposesParseEnd = true;
4876
+ clearSettleTimeout();
4877
+ if (idleTimeout) resetIdleTimeout(idleTimeout);
4220
4878
  parseStartSet.add(id);
4221
4879
  }
4222
4880
  },
@@ -4225,12 +4883,18 @@ function pluginModuleParseEnd_default(excludeFn, options) {
4225
4883
  name: "parseEnd",
4226
4884
  apply: "build",
4227
4885
  moduleParsed(module) {
4886
+ clearSettleTimeout();
4228
4887
  const id = module.id;
4229
- if (id === options.virtualExposesId) exposesParseEnd = true;
4888
+ lastParsedModule = id;
4230
4889
  if (idleTimeout) resetIdleTimeout(idleTimeout);
4231
- if (excludeFn(id)) return;
4232
- parseEndSet.add(id);
4233
- if (parseStartSet.size === parseEndSet.size && (!expectsExposesParseEnd || exposesParseEnd)) _resolve?.(1);
4890
+ const parsedModule = module;
4891
+ const addPendingResolutions = (resolutions) => {
4892
+ for (const resolution of resolutions || []) if (!resolution.external && !excludeFn(resolution.id)) parseStartSet.add(resolution.id);
4893
+ };
4894
+ addPendingResolutions(parsedModule.importedIdResolutions);
4895
+ addPendingResolutions(parsedModule.dynamicallyImportedIdResolutions);
4896
+ if (!excludeFn(id)) parseEndSet.add(id);
4897
+ scheduleParseCompletionCheck();
4234
4898
  },
4235
4899
  buildEnd() {
4236
4900
  _resolve?.(1);
@@ -4249,6 +4913,9 @@ function resolveDevHashEntryFileName(fileName) {
4249
4913
  function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
4250
4914
  let viteConfig, _command, root;
4251
4915
  let exposeRemoteDependencies = {};
4916
+ let exposeRemoteDependenciesDirty = true;
4917
+ let refreshPromise;
4918
+ let dependencyInvalidationVersion = 0;
4252
4919
  function isRemoteImport(source) {
4253
4920
  return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
4254
4921
  }
@@ -4287,12 +4954,26 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4287
4954
  return Array.from(dependencies).sort();
4288
4955
  }
4289
4956
  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) : [];
4957
+ if (!exposeRemoteDependenciesDirty) return;
4958
+ if (!refreshPromise) {
4959
+ const refreshVersion = dependencyInvalidationVersion;
4960
+ refreshPromise = (async () => {
4961
+ const next = {};
4962
+ for (const [exposeKey, expose] of Object.entries(options.exposes)) {
4963
+ const resolved = await ctx.resolve(expose.import);
4964
+ next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id) : [];
4965
+ }
4966
+ exposeRemoteDependencies = next;
4967
+ if (refreshVersion === dependencyInvalidationVersion) exposeRemoteDependenciesDirty = false;
4968
+ })().finally(() => {
4969
+ refreshPromise = void 0;
4970
+ });
4294
4971
  }
4295
- exposeRemoteDependencies = next;
4972
+ await refreshPromise;
4973
+ }
4974
+ function invalidateExposeRemoteDependencies() {
4975
+ exposeRemoteDependenciesDirty = true;
4976
+ dependencyInvalidationVersion += 1;
4296
4977
  }
4297
4978
  return {
4298
4979
  name: "proxyRemoteEntry",
@@ -4315,6 +4996,12 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4315
4996
  });
4316
4997
  }
4317
4998
  },
4999
+ watchChange() {
5000
+ invalidateExposeRemoteDependencies();
5001
+ },
5002
+ handleHotUpdate() {
5003
+ invalidateExposeRemoteDependencies();
5004
+ },
4318
5005
  async resolveId(id, importer) {
4319
5006
  if (id === remoteEntryId) return remoteEntryId;
4320
5007
  if (id === virtualExposesId) return virtualExposesId;
@@ -4325,16 +5012,22 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4325
5012
  if (resolved) return resolved;
4326
5013
  }
4327
5014
  },
4328
- load(id) {
5015
+ async load(id) {
4329
5016
  if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
4330
- if (id === virtualExposesId) return generateExposes(options, exposeRemoteDependencies, _command);
5017
+ if (id === virtualExposesId) {
5018
+ await refreshExposeRemoteDependencies(this);
5019
+ return generateExposes(options, exposeRemoteDependencies, _command);
5020
+ }
4331
5021
  if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
4332
5022
  },
4333
- transform(code, id) {
4334
- return mapCodeToCodeWithSourcemap((() => {
5023
+ async transform(code, id) {
5024
+ return mapCodeToCodeWithSourcemap(await (async () => {
4335
5025
  if (!filterId(id)) return;
4336
5026
  if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
4337
- if (id === virtualExposesId) return generateExposes(options, exposeRemoteDependencies, _command);
5027
+ if (id === virtualExposesId) {
5028
+ await refreshExposeRemoteDependencies(this);
5029
+ return generateExposes(options, exposeRemoteDependencies, _command);
5030
+ }
4338
5031
  if (id.includes(getHostAutoInitPath())) {
4339
5032
  if (_command === "serve") {
4340
5033
  const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
@@ -4409,6 +5102,9 @@ function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
4409
5102
  function isNodeModulesImporter(importer) {
4410
5103
  return importer?.includes("/node_modules/") || importer?.includes("\\node_modules\\");
4411
5104
  }
5105
+ function escapeRegExp(value) {
5106
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5107
+ }
4412
5108
  function appendAlias(config, alias) {
4413
5109
  config.resolve ??= {};
4414
5110
  const existingAlias = config.resolve.alias;
@@ -4451,10 +5147,9 @@ function pluginProxyRemotes_default(options) {
4451
5147
  config(config, { command: _command }) {
4452
5148
  command = _command;
4453
5149
  root = config.root || process.cwd();
4454
- Object.keys(remotes).forEach((key) => {
4455
- const remote = remotes[key];
5150
+ Object.keys(remotes).forEach((remoteAlias) => {
4456
5151
  appendAlias(config, {
4457
- find: new RegExp(`^(${remote.name}(\/.*|$))`),
5152
+ find: new RegExp(`^(${escapeRegExp(remoteAlias)}(\/.*|$))`),
4458
5153
  replacement: "$1"
4459
5154
  });
4460
5155
  });
@@ -4465,9 +5160,9 @@ function pluginProxyRemotes_default(options) {
4465
5160
  },
4466
5161
  resolveId(source, importer) {
4467
5162
  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);
5163
+ for (const remoteAlias of Object.keys(remotes)) {
5164
+ if (source !== remoteAlias && !source.startsWith(`${remoteAlias}/`)) continue;
5165
+ return resolveRemoteId(this, source, importer, remoteAlias);
4471
5166
  }
4472
5167
  }
4473
5168
  };
@@ -4625,6 +5320,36 @@ function proxySharedModule(options) {
4625
5320
  const savePrebuild = new PromiseStore();
4626
5321
  let devServer;
4627
5322
  const materializedLoadShareSources = /* @__PURE__ */ new Set();
5323
+ const emittedTreeShakingProviders = /* @__PURE__ */ new Set();
5324
+ const normalizeTreeShakingOutputPath = (value) => {
5325
+ const normalized = normalizePathForImport(value);
5326
+ 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.`);
5327
+ let start = normalized.startsWith("./") ? 2 : 0;
5328
+ let end = normalized.length;
5329
+ while (start < end && normalized.charCodeAt(start) === 47) start++;
5330
+ while (end > start && normalized.charCodeAt(end - 1) === 47) end--;
5331
+ return normalized.slice(start, end);
5332
+ };
5333
+ const getTreeShakingProviderFileName = (pkg, shareItem) => {
5334
+ if (!shareItem.shareConfig.treeShaking) return void 0;
5335
+ const normalizedOptions = getNormalizeModuleFederationOptions();
5336
+ const outputDir = normalizedOptions.treeShakingDir ? normalizeTreeShakingOutputPath(normalizedOptions.treeShakingDir) : void 0;
5337
+ const fileName = outputDir ? path$1.posix.join(outputDir, `${getTreeShakingSharedProviderName(pkg)}.js`) : void 0;
5338
+ if (!fileName) return void 0;
5339
+ return fileName;
5340
+ };
5341
+ const emitTreeShakingProvider = (context, pkg, shareItem) => {
5342
+ if (_command !== "build" || emittedTreeShakingProviders.has(pkg)) return;
5343
+ if (!hasTreeShakingSharedProvider(pkg, shareItem)) return;
5344
+ const fileName = getTreeShakingProviderFileName(pkg, shareItem);
5345
+ context.emitFile({
5346
+ type: "chunk",
5347
+ id: getTreeShakingSharedProviderImportId(pkg),
5348
+ name: getTreeShakingSharedProviderName(pkg),
5349
+ ...fileName ? { fileName } : {}
5350
+ });
5351
+ emittedTreeShakingProviders.add(pkg);
5352
+ };
4628
5353
  return [
4629
5354
  {
4630
5355
  name: "generateLocalSharedImportMap",
@@ -4640,7 +5365,16 @@ function proxySharedModule(options) {
4640
5365
  if (source === getLocalSharedImportMapPath()) return getResolvedLocalSharedImportMapId();
4641
5366
  },
4642
5367
  load(id) {
4643
- if (id === getResolvedLocalSharedImportMapId()) return parsePromise.then((_) => generateLocalSharedImportMap());
5368
+ if (id === getResolvedLocalSharedImportMapId()) return parsePromise.then((_) => {
5369
+ refreshTreeShakingModules();
5370
+ const providerPackages = new Set([...Object.keys(shared).filter((pkg) => !pkg.endsWith("/")), ...getUsedShares()]);
5371
+ for (const pkg of providerPackages) {
5372
+ const sharedKey = findSharedKeyForSource(pkg, shared);
5373
+ const shareItem = shared[pkg] || (sharedKey ? shared[sharedKey] : void 0);
5374
+ if (shareItem) emitTreeShakingProvider(this, pkg, shareItem);
5375
+ }
5376
+ return generateLocalSharedImportMap();
5377
+ });
4644
5378
  },
4645
5379
  closeBundle() {
4646
5380
  if (devServer) return;
@@ -4652,6 +5386,9 @@ function proxySharedModule(options) {
4652
5386
  enforce: "post",
4653
5387
  config(config, { command }) {
4654
5388
  setPackageDetectionCwd(config.root || process.cwd());
5389
+ setTreeShakingBuildMode(command === "build");
5390
+ resetTreeShakingExports();
5391
+ emittedTreeShakingProviders.clear();
4655
5392
  const isVinext = hasPackageDependency("vinext");
4656
5393
  const isAstro = hasPackageDependency("astro");
4657
5394
  const isRolldown = getIsRolldown(this);
@@ -4675,12 +5412,62 @@ function proxySharedModule(options) {
4675
5412
  });
4676
5413
  writeLocalSharedImportMap();
4677
5414
  refreshHostAutoInit();
5415
+ },
5416
+ buildStart() {
5417
+ if (_command !== "build") return;
5418
+ resetTreeShakingExports();
5419
+ emittedTreeShakingProviders.clear();
5420
+ refreshTreeShakingModules();
5421
+ },
5422
+ shouldTransformCachedModule() {
5423
+ return _command === "build" && Object.values(shared).some((share) => !!share.shareConfig.treeShaking);
5424
+ },
5425
+ transform(code, id) {
5426
+ if (_command !== "build" || !Object.keys(shared).some((key) => shared[key].shareConfig.treeShaking)) return;
5427
+ collectTreeShakingImports(code, id, shared, findSharedKeyForSource, recordTreeShakingExports, markTreeShakingPackageUnsafe);
5428
+ refreshTreeShakingModules();
5429
+ }
5430
+ },
5431
+ {
5432
+ name: "proxyPreBuildShared:tree-shaking-graph",
5433
+ enforce: "pre",
5434
+ apply: "build",
5435
+ async resolveId(source, importer, resolveOptions) {
5436
+ const sourceToken = getTreeShakingGraphToken(source);
5437
+ const importerToken = getTreeShakingGraphToken(importer);
5438
+ const token = sourceToken || importerToken;
5439
+ if (!token) return;
5440
+ const cleanSource = normalizePathForImport(stripTreeShakingGraphQuery(source));
5441
+ const cleanImporter = importer ? normalizePathForImport(stripTreeShakingGraphQuery(importer)) : void 0;
5442
+ if (!sourceToken && importerToken) {
5443
+ const nestedSharedKey = findSharedKeyForSource(cleanSource, shared);
5444
+ if (nestedSharedKey && getPackageName(nestedSharedKey) !== getPackageName(importerToken)) return this.resolve(cleanSource, cleanImporter, {
5445
+ ...resolveOptions,
5446
+ skipSelf: true
5447
+ });
5448
+ }
5449
+ const projectResolvedSource = sourceToken ? tryResolveFromProjectRoot(cleanSource) || cleanSource : cleanSource;
5450
+ const resolved = await this.resolve(projectResolvedSource, cleanImporter, {
5451
+ ...resolveOptions,
5452
+ custom: {
5453
+ ...resolveOptions.custom,
5454
+ __mfTreeShakingGraph: true
5455
+ },
5456
+ skipSelf: true
5457
+ });
5458
+ if (!resolved || resolved.external) return resolved;
5459
+ if (resolved.id.startsWith("\0")) return resolved;
5460
+ return {
5461
+ ...resolved,
5462
+ id: addTreeShakingGraphQuery(normalizePathForImport(resolved.id), token)
5463
+ };
4678
5464
  }
4679
5465
  },
4680
5466
  {
4681
5467
  name: "proxyPreBuildShared:resolve-shared-loadShare",
4682
5468
  enforce: "pre",
4683
- async resolveId(source, importer) {
5469
+ async resolveId(source, importer, resolveOptions) {
5470
+ if (resolveOptions.custom?.__mfTreeShakingGraph) return;
4684
5471
  function shouldSkipTaggedImporterProxy(sharedKey, tag) {
4685
5472
  if (!importer?.includes(tag)) return false;
4686
5473
  const taggedModule = VirtualModule.findModule(tag, importer);
@@ -5642,10 +6429,10 @@ function hasImportFalseShared(options) {
5642
6429
  }
5643
6430
  function getRuntimeHelpersImplementation(runtimeImplementation) {
5644
6431
  const indexEntryMatch = runtimeImplementation.match(/^(.*[\\/])index(\.[cm]?js)$/);
5645
- if (indexEntryMatch) return `${indexEntryMatch[1]}helpers${indexEntryMatch[2]}`;
6432
+ if (indexEntryMatch) return normalizePathForImport(`${indexEntryMatch[1]}helpers${indexEntryMatch[2]}`);
5646
6433
  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");
6434
+ if (extension) return normalizePathForImport(path$1.join(path$1.dirname(runtimeImplementation), `helpers${extension}`));
6435
+ if (path$1.isAbsolute(runtimeImplementation) || runtimeImplementation.startsWith(".")) return normalizePathForImport(path$1.join(runtimeImplementation, "helpers"));
5649
6436
  return `${runtimeImplementation.replace(/\/$/, "")}/helpers`;
5650
6437
  }
5651
6438
  const UNSAFE_JS_SOURCE_CHAR_MAP = {
@@ -5828,7 +6615,7 @@ export default __mfShared.default ?? __mfShared;`
5828
6615
  const optimizeDeps = config.optimizeDeps ??= {};
5829
6616
  optimizeDeps.include ??= [];
5830
6617
  optimizeDeps.exclude ??= [];
5831
- const shouldBypassOptimizeDep = isLitShare(key) || key === "react" && shareItem.shareConfig?.singleton === true;
6618
+ const shouldBypassOptimizeDep = isLitShare(key);
5832
6619
  if (optimizeDeps.include.includes(key)) optimizeDeps.exclude = optimizeDeps.exclude.filter((dep) => dep !== key);
5833
6620
  else if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
5834
6621
  else optimizeDeps.include.push(key);
@@ -5883,13 +6670,14 @@ export default __mfShared.default ?? __mfShared;`
5883
6670
  const SSR_ONLY_PLUGINS = new Set(["@module-federation/vite/ssrEntryLoader"]);
5884
6671
  function loadPluginDts(options) {
5885
6672
  if (options.dts === false) return [];
5886
- return [import("./pluginDts-Bo95ELmX.js").then((n) => n.n).then(({ default: pluginDts }) => pluginDts(options))];
6673
+ return [import("./pluginDts-BcvLBYP3.js").then((n) => n.n).then(({ default: pluginDts }) => pluginDts(options))];
5887
6674
  }
5888
6675
  function federation(mfUserOptions) {
5889
6676
  if (isTestEnv()) return [];
5890
6677
  const options = normalizeModuleFederationOptions(mfUserOptions);
5891
6678
  const isVinext = hasPackageDependency("vinext");
5892
6679
  const { name, shared, filename, hostInitInjectLocation } = options;
6680
+ const hasTreeShakingShared = Object.values(shared).some((share) => !!share.shareConfig.treeShaking);
5893
6681
  if (!name) throw createModuleFederationError("name is required");
5894
6682
  const remoteEntryId = getRemoteEntryId(options);
5895
6683
  const virtualExposesId = getVirtualExposesId(options);
@@ -5995,11 +6783,11 @@ function federation(mfUserOptions) {
5995
6783
  pluginProxyRemotes_default(options),
5996
6784
  pluginRemoteNamedExports(options),
5997
6785
  ...pluginModuleParseEnd_default((id) => {
5998
- return id.includes(getHostAutoInitImportId()) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath()) || id.includes("__loadShare__") || id.includes("__prebuild__");
6786
+ 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
6787
  }, {
6000
6788
  moduleParseTimeout: options.moduleParseTimeout,
6001
6789
  moduleParseIdleTimeout: options.moduleParseIdleTimeout,
6002
- virtualExposesId
6790
+ exposedModuleImports: Object.values(options.exposes).map((expose) => expose.import)
6003
6791
  }),
6004
6792
  ...proxySharedModule({ shared }),
6005
6793
  {
@@ -6021,7 +6809,8 @@ function federation(mfUserOptions) {
6021
6809
  if (context.hostType === "js" && (hostFile === options.filename || hostFile.includes("hostInit") || hostFile.includes("virtualExposes") || hostFile.includes("localSharedImportMap"))) return [];
6022
6810
  const hasFederationHtmlDeps = context.hostType === "html" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
6023
6811
  const hasFederationJsDeps = context.hostType === "js" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
6024
- return hasFederationHtmlDeps || hasFederationJsDeps ? resolvedDeps.filter((dep) => !isFederationHtmlPreloadDependency(dep, true)) : resolvedDeps;
6812
+ const treeShakingFallbackDeps = hasTreeShakingShared ? (dep) => dep.includes("__prebuild__") : () => false;
6813
+ return hasFederationHtmlDeps || hasFederationJsDeps ? resolvedDeps.filter((dep) => !isFederationHtmlPreloadDependency(dep, true) && !treeShakingFallbackDeps(dep)) : resolvedDeps.filter((dep) => !treeShakingFallbackDeps(dep));
6025
6814
  }
6026
6815
  };
6027
6816
  }
@@ -6195,8 +6984,8 @@ function federation(mfUserOptions) {
6195
6984
  config(config, { command: _command }) {
6196
6985
  const isRolldown = getIsRolldown(this);
6197
6986
  isSsrBuild = _command === "build" && config.build?.ssr === true;
6198
- const needsSharedProviderSelectionHelper = hasImportFalseShared(options);
6199
- if (needsSharedProviderSelectionHelper) appendResolveAlias(config, {
6987
+ const needsRuntimeHelpers = hasImportFalseShared(options) || Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
6988
+ if (needsRuntimeHelpers) appendResolveAlias(config, {
6200
6989
  find: /^@module-federation\/runtime\/helpers$/,
6201
6990
  replacement: getRuntimeHelpersImplementation(options.implementation)
6202
6991
  });
@@ -6210,7 +6999,7 @@ function federation(mfUserOptions) {
6210
6999
  config.optimizeDeps ||= {};
6211
7000
  config.optimizeDeps.include ||= [];
6212
7001
  config.optimizeDeps.include.push("@module-federation/runtime");
6213
- if (needsSharedProviderSelectionHelper) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
7002
+ if (needsRuntimeHelpers) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
6214
7003
  options.runtimePlugins.forEach((p) => {
6215
7004
  const pluginPath = typeof p === "string" ? p : p[0];
6216
7005
  if (SSR_ONLY_PLUGINS.has(pluginPath)) return;