@module-federation/vite 1.16.15 → 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";
@@ -360,7 +360,7 @@ function searchPackageVersion(sharedName) {
360
360
  return typeof version === "string" ? version : void 0;
361
361
  }
362
362
  function inferVersionFromRequiredVersion(requiredVersion) {
363
- if (!requiredVersion) return void 0;
363
+ if (typeof requiredVersion !== "string") return void 0;
364
364
  return requiredVersion.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0];
365
365
  }
366
366
  function getLitExportSubpathShares(sharedName) {
@@ -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,
396
- requiredVersion: shareItem.requiredVersion || (isImportFalse || shareItem.version ? "*" : version ? `^${version}` : "*"),
397
- strictVersion: !!shareItem.strictVersion
401
+ eager: shareItem.eager || false,
402
+ requiredVersion: shareItem.requiredVersion !== void 0 ? shareItem.requiredVersion : isImportFalse || shareItem.version ? "*" : version ? `^${version}` : "*",
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}`;
@@ -658,7 +669,7 @@ function getSsrCapabilities(viteMajor, command, hasRemotes) {
658
669
  * @returns {string} The resulting JavaScript source code string.
659
670
  */
660
671
  function serializeRuntimeOptions(options) {
661
- const seenObjects = /* @__PURE__ */ new WeakSet();
672
+ const ancestors = /* @__PURE__ */ new WeakSet();
662
673
  /**
663
674
  * Recursive inner function to serialize any value into a source code string.
664
675
  */
@@ -676,16 +687,18 @@ function serializeRuntimeOptions(options) {
676
687
  if (val instanceof Date) return `new Date(${JSON.stringify(val.toISOString())})`;
677
688
  if (val instanceof RegExp) return `new RegExp(${JSON.stringify(val.source)}, ${JSON.stringify(val.flags)})`;
678
689
  if (type === "object") {
679
- if (seenObjects.has(val)) return `"__circular__"`;
680
- seenObjects.add(val);
681
- }
682
- if (Array.isArray(val)) return `[${val.map(valueToCode).join(", ")}]`;
683
- if (val instanceof Map) return `new Map([${Array.from(val.entries()).map(([k, v]) => `[${valueToCode(k)}, ${valueToCode(v)}]`).join(", ")}])`;
684
- if (val instanceof Set) return `new Set([${Array.from(val.values()).map(valueToCode).join(", ")}])`;
685
- if (type === "object") {
686
- const properties = [];
687
- for (const key in val) if (Object.prototype.hasOwnProperty.call(val, key)) properties.push(`${JSON.stringify(key)}: ${valueToCode(val[key])}`);
688
- return `{${properties.join(", ")}}`;
690
+ if (ancestors.has(val)) return `"__circular__"`;
691
+ ancestors.add(val);
692
+ try {
693
+ if (Array.isArray(val)) return `[${val.map(valueToCode).join(", ")}]`;
694
+ if (val instanceof Map) return `new Map([${Array.from(val.entries()).map(([k, v]) => `[${valueToCode(k)}, ${valueToCode(v)}]`).join(", ")}])`;
695
+ if (val instanceof Set) return `new Set([${Array.from(val.values()).map(valueToCode).join(", ")}])`;
696
+ const properties = [];
697
+ for (const key in val) if (Object.prototype.hasOwnProperty.call(val, key)) properties.push(`${JSON.stringify(key)}: ${valueToCode(val[key])}`);
698
+ return `{${properties.join(", ")}}`;
699
+ } finally {
700
+ ancestors.delete(val);
701
+ }
689
702
  }
690
703
  return JSON.stringify(String(val));
691
704
  }
@@ -926,6 +939,257 @@ ${exportStatement}
926
939
  `);
927
940
  }
928
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
929
1193
  //#region src/virtualModules/virtualShared_preBuild.ts
930
1194
  /**
931
1195
  * Even the resolveId hook cannot interfere with vite pre-build,
@@ -1171,7 +1435,7 @@ function isWorkspaceFilePath(resolved) {
1171
1435
  try {
1172
1436
  realResolved = realpathSync.native(resolved);
1173
1437
  } catch {}
1174
- return !realResolved.includes("/node_modules/") && !realResolved.includes("\\node_modules\\");
1438
+ return !normalizeNodeModulePath(realResolved).includes("/node_modules/");
1175
1439
  }
1176
1440
  /**
1177
1441
  * When createRequire resolves a workspace package to a CJS entry (e.g. dist/index.cjs),
@@ -1283,10 +1547,104 @@ function getConcreteSharedImportSource(pkg, shareItem) {
1283
1547
  const preBuildCacheMap = {};
1284
1548
  const preBuildShareItemMap = {};
1285
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
+ }
1286
1643
  function writePreBuildLibPath(pkg, shareItem) {
1287
1644
  if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG, ".js");
1288
1645
  preBuildShareItemMap[pkg] = shareItem;
1289
1646
  const importSource = getConcreteSharedImportSource(pkg, shareItem) || pkg;
1647
+ writeTreeShakingSharedProvider(pkg, shareItem);
1290
1648
  if (pkg === "react/compiler-runtime") {
1291
1649
  const reactCacheDescriptor = getSharedCacheDescriptorLiteral("react", shareItem ?? {
1292
1650
  name: "react",
@@ -1341,16 +1699,27 @@ function writePreBuildLibPath(pkg, shareItem) {
1341
1699
  const __mfPrebuildExports = __mfPrebuildNamespace;
1342
1700
  ${declarations}
1343
1701
  ${namedExportLine}
1344
- export default __mfPrebuildNamespace.default ?? __mfPrebuildNamespace;
1702
+ export default Reflect.get(__mfPrebuildNamespace, "default") ?? __mfPrebuildNamespace;
1345
1703
  `, true);
1346
1704
  return;
1347
1705
  }
1348
1706
  preBuildCacheMap[pkg].writeSync(`
1349
1707
  import * as __mfPrebuildExports from ${escapeGeneratedStringLiteral(importSource)};
1350
1708
  export * from ${escapeGeneratedStringLiteral(importSource)};
1351
- 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;
1352
1713
  `, true);
1353
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
+ }
1354
1723
  function getPreBuildLibImportId(pkg) {
1355
1724
  if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG, ".js");
1356
1725
  return preBuildCacheMap[pkg].getImportId();
@@ -1396,12 +1765,15 @@ function materializeCachedLoadShareModule(options) {
1396
1765
  options.addUsedShares(pkg);
1397
1766
  options.writeLocalSharedImportMap();
1398
1767
  }
1399
- 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) {
1400
1772
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1401
1773
  const namedExportAssignments = namedExports.length > 0 ? `\n ${namedExports.map((name, i) => `const ${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`).join("\n ")}` : "";
1402
1774
  const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1403
1775
  return `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(importSource)};
1404
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1776
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1405
1777
  if (exportModule === undefined) {
1406
1778
  Promise.resolve().then(() => {
1407
1779
  if (__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor}) === undefined) {
@@ -1413,24 +1785,25 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
1413
1785
  const __mf_default = exportModule.default ?? exportModule;${namedExportAssignments}
1414
1786
  export { __mf_default as default };${namedExportLine}`;
1415
1787
  }
1416
- function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor) {
1788
+ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, treeShakingConsumer) {
1417
1789
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1418
1790
  const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
1419
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;";
1420
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);`;
1421
1796
  return `${declarations}
1422
1797
  const __mfApplyLazyShareExports = (mod) => {
1423
1798
  ${assignments}
1424
1799
  };
1425
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1800
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1426
1801
  if (exportModule === undefined) {
1427
1802
  if (import.meta.env.SSR) {
1428
- ${`exportModule = __mfNormalizeShareModule(__mfLocalShare);
1429
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1430
- __mfApplyLazyShareExports(exportModule);`}
1803
+ ${applyLocalFallback}
1431
1804
  } else {
1432
1805
  (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
1433
- exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1806
+ exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1434
1807
  if (exportModule !== undefined) {
1435
1808
  __mfApplyLazyShareExports(exportModule);
1436
1809
  return;
@@ -1457,16 +1830,19 @@ function prependWorkspaceSingletonSsrImport(code) {
1457
1830
  const quote = importMatch[1];
1458
1831
  return `import * as __mfLocalShare from ${quote}${importMatch[2]}${quote};\n${code}`;
1459
1832
  }
1460
- function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor) {
1833
+ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer) {
1461
1834
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1462
- 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}
1463
1839
  const __mfApplyHostProvidedExports = (exportModule) => {
1464
- ${[...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ")}
1840
+ ${assignments}
1465
1841
  };
1466
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1842
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1467
1843
  if (exportModule === undefined) {
1468
1844
  (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
1469
- exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1845
+ exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
1470
1846
  if (exportModule === undefined) {
1471
1847
  throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
1472
1848
  }
@@ -1475,7 +1851,7 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor)
1475
1851
  } else {
1476
1852
  __mfApplyHostProvidedExports(exportModule);
1477
1853
  }
1478
- 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}`;
1479
1855
  }
1480
1856
  function generateShareModuleUnwrapCode({ source, preserveNamedExports, stopWithReturn }) {
1481
1857
  return `let current = ${source};
@@ -1498,13 +1874,14 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1498
1874
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".js");
1499
1875
  let importLine = getRuntimeModuleCacheBootstrapCode();
1500
1876
  const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
1877
+ const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ? getNormalizeModuleFederationOptions().name : void 0;
1501
1878
  if (shareItem.shareConfig.import === false) {
1502
1879
  const namedExports = getPackageNamedExports(pkg);
1503
1880
  let exportLine;
1504
- if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor);
1881
+ if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer);
1505
1882
  else {
1506
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.`);
1507
- exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor);
1884
+ exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor, treeShakingConsumer);
1508
1885
  }
1509
1886
  loadShareCacheMap[pkg].writeSync(`
1510
1887
  ${getRuntimeInitPromiseBootstrapCode()}
@@ -1527,13 +1904,17 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1527
1904
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg);
1528
1905
  const usesEntryInjectedRemoteFallback = command !== "build" && !isWorkspaceSingleton && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && getNormalizeModuleFederationOptions().hostInitInjectLocation === "entry" && isConsumedByPeerSingleton;
1529
1906
  const usesEagerWorkspaceFallback = isWorkspaceSingleton && isConsumedByPeerSingleton;
1907
+ const usesDeferredTreeShakingFallback = Boolean(treeShakingConsumer);
1530
1908
  const namedExports = getSharedNamedExports(pkg, shareItem);
1531
1909
  let exportLine;
1532
1910
  let initBlock = "";
1533
- 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);
1534
1915
  else if (usesDeferredSingletonFallback) {
1535
1916
  importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
1536
- exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor);
1917
+ exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, treeShakingConsumer);
1537
1918
  } else if (namedExports.length > 0) {
1538
1919
  const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1539
1920
  const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
@@ -1554,9 +1935,9 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1554
1935
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1555
1936
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);`;
1556
1937
  }
1557
- const prebuildImportLine = usesDeferredSingletonFallback || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
1558
- const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
1559
- 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 ? `
1560
1941
  ${prebuildImportLine}
1561
1942
  ${devDynamicImportLine}
1562
1943
  ${importLine}
@@ -1569,7 +1950,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1569
1950
  ${importLine}
1570
1951
  ${sharedCacheHelperCode}
1571
1952
  ${normalizeLocalShareModuleCode}
1572
- let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor})
1953
+ let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)}
1573
1954
  if (exportModule === undefined) {
1574
1955
  ${initBlock}
1575
1956
  }
@@ -1616,29 +1997,43 @@ function getDirectSharedCacheSeedImportPath(pkg, shareItem) {
1616
1997
  function generateLocalSharedImportMap() {
1617
1998
  const useDirectReactImport = shouldUseDirectReactImport();
1618
1999
  const options = getNormalizeModuleFederationOptions();
2000
+ const orderedShares = getOrderedUsedShares();
1619
2001
  return `
1620
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")}
1621
2008
  const importMap = {
1622
- ${Array.from(getUsedShares()).sort().map((pkg) => {
2009
+ ${orderedShares.map((pkg, index) => {
1623
2010
  const shareItem = getNormalizeShareItem(pkg);
1624
2011
  return `
1625
2012
  ${JSON.stringify(pkg)}: async () => {
1626
- ${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))});
1627
2015
  return pkg;`}
1628
2016
  }
1629
2017
  `;
1630
2018
  }).join(",")}
1631
2019
  }
1632
2020
  const usedShared = {
1633
- ${Array.from(getUsedShares()).sort().map((key) => {
2021
+ ${getOrderedUsedShares().map((key) => {
1634
2022
  const shareItem = getNormalizeShareItem(key);
1635
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;
1636
2030
  return `
1637
2031
  ${JSON.stringify(key)}: {
1638
2032
  name: ${JSON.stringify(key)},
1639
2033
  version: ${JSON.stringify(shareItem.version)},
1640
2034
  scope: [${JSON.stringify(shareItem.scope)}],
1641
2035
  loaded: false,
2036
+ eager: ${Boolean(shareItem.shareConfig.eager)},
1642
2037
  from: ${JSON.stringify(options.name)},
1643
2038
  async get () {
1644
2039
  if (${shareItem.shareConfig.import === false}) {
@@ -1663,8 +2058,20 @@ function generateLocalSharedImportMap() {
1663
2058
  singleton: ${shareItem.shareConfig.singleton},
1664
2059
  requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
1665
2060
  strictVersion: ${shareItem.shareConfig.strictVersion},
2061
+ eager: ${Boolean(shareItem.shareConfig.eager)},
1666
2062
  ${shareItem.shareConfig.import === false ? "import: false," : ""}
1667
- }
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
+ }` : ""}
1668
2075
  }
1669
2076
  `;
1670
2077
  }).filter((x) => x !== null).join(",")}
@@ -1674,6 +2081,7 @@ function generateLocalSharedImportMap() {
1674
2081
  if (!remote) return null;
1675
2082
  return `
1676
2083
  {
2084
+ alias: ${JSON.stringify(key)},
1677
2085
  entryGlobalName: ${JSON.stringify(remote.entryGlobalName)},
1678
2086
  name: ${JSON.stringify(remote.name)},
1679
2087
  type: ${JSON.stringify(remote.type)},
@@ -1706,9 +2114,15 @@ function getOrderedUsedShares() {
1706
2114
  }
1707
2115
  function orderSharedDependenciesFirst(sharedPackages) {
1708
2116
  const sharedKeyByPackageName = /* @__PURE__ */ new Map();
2117
+ const subpathKeysByPackageName = /* @__PURE__ */ new Map();
1709
2118
  sharedPackages.forEach((pkg) => {
1710
2119
  const packageName = getPackageName(pkg);
1711
2120
  if (!sharedKeyByPackageName.get(packageName) || pkg === packageName) sharedKeyByPackageName.set(packageName, pkg);
2121
+ if (pkg !== packageName) {
2122
+ const subpaths = subpathKeysByPackageName.get(packageName);
2123
+ if (subpaths) subpaths.push(pkg);
2124
+ else subpathKeysByPackageName.set(packageName, [pkg]);
2125
+ }
1712
2126
  });
1713
2127
  const visiting = /* @__PURE__ */ new Set();
1714
2128
  const visited = /* @__PURE__ */ new Set();
@@ -1717,7 +2131,8 @@ function orderSharedDependenciesFirst(sharedPackages) {
1717
2131
  if (visited.has(pkg)) return;
1718
2132
  if (visiting.has(pkg)) return;
1719
2133
  visiting.add(pkg);
1720
- const packageJson = getInstalledPackageJson(pkg)?.packageJson;
2134
+ const packageName = getPackageName(pkg);
2135
+ const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
1721
2136
  const dependencies = {
1722
2137
  ...packageJson?.dependencies || {},
1723
2138
  ...packageJson?.peerDependencies || {},
@@ -1727,6 +2142,7 @@ function orderSharedDependenciesFirst(sharedPackages) {
1727
2142
  const sharedDependency = sharedKeyByPackageName.get(dependency);
1728
2143
  if (sharedDependency) visit(sharedDependency);
1729
2144
  });
2145
+ if (pkg === packageName) (subpathKeysByPackageName.get(packageName) || []).forEach(visit);
1730
2146
  visiting.delete(pkg);
1731
2147
  visited.add(pkg);
1732
2148
  ordered.push(pkg);
@@ -1800,10 +2216,39 @@ function hasImportFalseShared$1(options) {
1800
2216
  return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
1801
2217
  }
1802
2218
  function generateRuntimeSharedCacheSeedCode() {
2219
+ const seedOrder = getOrderedUsedShares();
1803
2220
  return `
1804
- for (const [pkg, share] of Object.entries(usedShared)) {
2221
+ const __mfSeedOrder = ${JSON.stringify(seedOrder)};
2222
+ const __mfSeedKeys = __mfSeedOrder.filter((pkg) => usedShared[pkg] !== undefined);
2223
+ const __mfSeedPackageName = (pkg) => pkg.startsWith('@')
2224
+ ? pkg.split('/').slice(0, 2).join('/')
2225
+ : pkg.split('/')[0];
2226
+ for (const pkg of Object.keys(usedShared)) {
2227
+ if (__mfSeedKeys.includes(pkg)) continue;
2228
+ const packageName = __mfSeedPackageName(pkg);
2229
+ const rootIndex = __mfSeedKeys.indexOf(packageName);
2230
+ if (rootIndex === -1) {
2231
+ __mfSeedKeys.push(pkg);
2232
+ continue;
2233
+ }
2234
+ let insertIndex = rootIndex;
2235
+ while (
2236
+ insertIndex > 0 &&
2237
+ __mfSeedPackageName(__mfSeedKeys[insertIndex - 1]) === packageName &&
2238
+ __mfSeedKeys[insertIndex - 1] !== packageName
2239
+ ) {
2240
+ insertIndex--;
2241
+ }
2242
+ __mfSeedKeys.splice(insertIndex, 0, pkg);
2243
+ }
2244
+ for (const pkg of __mfSeedKeys) {
2245
+ const share = usedShared[pkg];
1805
2246
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
1806
- 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
+ ) {
1807
2252
  continue;
1808
2253
  }
1809
2254
  const singletonCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, true, share.version, share.scope);
@@ -1833,7 +2278,7 @@ function getHostAutoInitSharedSeedItems() {
1833
2278
  return getOrderedUsedShares().map((pkg) => ({
1834
2279
  pkg,
1835
2280
  shareItem: getShareItemForPreload(pkg)
1836
- })).filter(({ shareItem }) => shareItem?.shareConfig.import === false).sort((a, b) => {
2281
+ })).filter(({ shareItem }) => shareItem?.shareConfig?.import === false).sort((a, b) => {
1837
2282
  const priority = (pkg) => pkg === "vue" ? 0 : pkg === "pinia" ? 1 : 2;
1838
2283
  const aIsLocal = !!getLocalProviderImportPath(a.pkg);
1839
2284
  const bIsLocal = !!getLocalProviderImportPath(b.pkg);
@@ -1854,8 +2299,176 @@ function getRemoteEntryId(options) {
1854
2299
  const SSR_ONLY_PLUGIN_SPECIFIERS = new Set(["@module-federation/vite/ssrEntryLoader"]);
1855
2300
  const isSsrOnlyPlugin = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].some((s) => importStatement.includes(s));
1856
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
+ }
1857
2462
  function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
1858
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"] : []];
1859
2472
  const pluginImportNames = options.runtimePlugins.map((p, i) => {
1860
2473
  if (typeof p === "string") return [
1861
2474
  `$runtimePlugin_${i}`,
@@ -1877,8 +2490,9 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1877
2490
  if (typeof __VUE_HMR_RUNTIME__ === 'undefined') {
1878
2491
  globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
1879
2492
  }
1880
- import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
1881
- ${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";` : ""}
1882
2496
  ${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
1883
2497
  ${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
1884
2498
  ${getRuntimeModuleCacheBootstrapCode()}
@@ -1906,14 +2520,16 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1906
2520
  }
1907
2521
  }
1908
2522
  }
2523
+ ${generateTreeShakingSnapshotPluginCode(hasTreeShakingShared)}
1909
2524
  ${needsSharedProviderSelectionHelper ? sharedProviderSelectionHelperCode : ""}
1910
2525
 
1911
2526
  async function getLocalSharedImportMap() {
1912
- if (!localSharedImportMapPromise) {
2527
+ ${hasEagerShared ? "return __mfLocalSharedImportMap;" : ""}
2528
+ ${hasEagerShared ? "" : `if (!localSharedImportMapPromise) {
1913
2529
  localSharedImportMapPromise = retrySharedInit(() => import("${getLocalSharedImportMapPath()}"))
1914
2530
  .catch((e) => { localSharedImportMapPromise = undefined; throw e; });
1915
2531
  }
1916
- return localSharedImportMapPromise
2532
+ return localSharedImportMapPromise`}
1917
2533
  }
1918
2534
 
1919
2535
  async function getExposesMap() {
@@ -1986,7 +2602,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1986
2602
  name: mfName,
1987
2603
  remotes: ${options.shareStrategy === "loaded-first" ? "[]" : "usedRemotes"},
1988
2604
  shared: usedShared,
1989
- plugins: [...__browserPlugins, ...__ssrPlugins],
2605
+ plugins: [${hasTreeShakingShared ? "__mfTreeShakingSnapshotPlugin()," : ""} ...__browserPlugins, ...__ssrPlugins],
1990
2606
  ${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
1991
2607
  });
1992
2608
  // handling circular init calls
@@ -2007,9 +2623,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
2007
2623
  } catch (e) {
2008
2624
  console.error('[Module Federation]', e)
2009
2625
  }
2626
+ ${generateTreeShakingSharedResolutionCode(hasTreeShakingShared)}
2010
2627
  for (const [pkg, share] of Object.entries(usedShared)) {
2011
2628
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2012
- 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;
2013
2633
  ${normalizeRuntimeShareCode}
2014
2634
  const versions = shared?.[pkg];
2015
2635
  const provider = __mfSelectSharedProvider(versions, pkg, share, '${options.shareStrategy}');
@@ -2042,6 +2662,7 @@ let currentHostAutoInitRemoteEntryId = REMOTE_ENTRY_ID;
2042
2662
  let currentHostAutoInitCommand = "build";
2043
2663
  function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
2044
2664
  const shouldPreloadShares = getNormalizeModuleFederationOptions().shareStrategy !== "loaded-first";
2665
+ const hostInitShareOrder = JSON.stringify(getOrderedUsedShares());
2045
2666
  return `
2046
2667
  ${getRuntimeModuleCacheBootstrapCode()}
2047
2668
  let hostInitPromise;
@@ -2055,7 +2676,15 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
2055
2676
  const {usedShared} = await import("${getLocalSharedImportMapPath()}");
2056
2677
  ${normalizeRuntimeShareCode}
2057
2678
  ${shouldPreloadShares ? `
2058
- for (const [pkg, share] of Object.entries(usedShared)) {
2679
+ const __mfHostInitShareOrder = ${hostInitShareOrder}
2680
+ .concat(Object.keys(usedShared).filter((pkg) => !${hostInitShareOrder}.includes(pkg)));
2681
+ for (const pkg of __mfHostInitShareOrder) {
2682
+ const share = usedShared[pkg];
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;
2059
2688
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
2060
2689
  if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) {
2061
2690
  continue;
@@ -2118,9 +2747,8 @@ function addUsedRemote(remoteKey, remoteModule) {
2118
2747
  function getUsedRemotesMap() {
2119
2748
  return usedRemotesMap;
2120
2749
  }
2121
- function getRemoteFromId(id, remotes) {
2122
- const remoteName = Object.keys(remotes).filter((name) => id === name || id.startsWith(name + "/")).sort((a, b) => b.length - a.length)[0];
2123
- 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];
2124
2752
  }
2125
2753
  function resolveRemoteInitMode(shareStrategy, consumer) {
2126
2754
  if (shareStrategy !== "loaded-first") return "eager";
@@ -2276,10 +2904,12 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
2276
2904
  const isLoadedFirst = options.shareStrategy === "loaded-first";
2277
2905
  const initMode = resolveRemoteInitMode(options.shareStrategy, consumer);
2278
2906
  const deferRemoteLoad = shouldDeferRemoteLoad(initMode);
2279
- const remote = getRemoteFromId(id, options.remotes);
2907
+ const remoteAlias = getRemoteAliasFromId(id, options.remotes);
2908
+ const remote = remoteAlias ? options.remotes[remoteAlias] : void 0;
2280
2909
  const registerRemoteCode = isLoadedFirst && remote ? `runtime.registerRemotes([${JSON.stringify({
2281
2910
  entryGlobalName: remote.entryGlobalName,
2282
2911
  name: remote.name,
2912
+ alias: remoteAlias,
2283
2913
  type: remote.type,
2284
2914
  entry: remote.entry,
2285
2915
  shareScope: remote.shareScope ?? "default"
@@ -2351,7 +2981,7 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
2351
2981
  const HOST_INIT_PRELOAD_CHUNKS = [
2352
2982
  (name) => name === "hostInit",
2353
2983
  (name) => name === "remoteEntry",
2354
- (name) => name.startsWith("_virtual_mf"),
2984
+ (name) => name.startsWith("_virtual_mf") && !name.includes("__prebuild__"),
2355
2985
  (name) => name === "index"
2356
2986
  ];
2357
2987
  function escapeHtmlAttr(value) {
@@ -2553,7 +3183,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2553
3183
  return decodeViteId(id).replace(/^\0/, "");
2554
3184
  }
2555
3185
  function normalizeModuleId(id) {
2556
- return id.split("?")[0].replace(/\\/g, "/");
3186
+ return normalizePathForImport(id.split("?")[0]);
2557
3187
  }
2558
3188
  function resolveProjectId(id) {
2559
3189
  if (id.startsWith("\0") || id.startsWith("virtual:")) return normalizeModuleId(id);
@@ -2590,8 +3220,8 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2590
3220
  const resolvedEntryPath = getEntryPath();
2591
3221
  if (resolvedEntryPath.startsWith("virtual:mf")) devEntryPath = config.base + VITE_ID_PREFIX.slice(1) + resolvedEntryPath;
2592
3222
  else {
2593
- const normalized = resolvedEntryPath.replace(/\\\\?/g, "/");
2594
- const root = config.root.replace(/\\\\?/g, "/").replace(/\/$/, "");
3223
+ const normalized = normalizePathForImport(resolvedEntryPath);
3224
+ const root = normalizePathForImport(config.root).replace(/\/$/, "");
2595
3225
  const relativePath = normalized.startsWith(root + "/") ? normalized.slice(root.length) : "/" + normalized.replace(/^[A-Za-z]:[\\/]/, "");
2596
3226
  devEntryPath = config.base + relativePath.replace(/^\//, "");
2597
3227
  }
@@ -3342,7 +3972,7 @@ function initVirtualModules(command, remoteEntryId, enableSsrInit = false) {
3342
3972
  function isOutputChunk$1(chunk) {
3343
3973
  return chunk.type === "chunk";
3344
3974
  }
3345
- function escapeRegExp(value) {
3975
+ function escapeRegExp$1(value) {
3346
3976
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3347
3977
  }
3348
3978
  function getProxyBaseName(fileName) {
@@ -3434,7 +4064,7 @@ function rewriteEsmProxyConsumers(code, proxyChunks) {
3434
4064
  const claimedLocals = /* @__PURE__ */ new Set();
3435
4065
  for (const [proxyFileName, proxyInfo] of Array.from(proxyChunks.entries())) {
3436
4066
  const proxyBaseName = getProxyBaseName(proxyFileName);
3437
- 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);
3438
4068
  if (!importMatch) continue;
3439
4069
  const fullImport = importMatch[0];
3440
4070
  const bindings = importMatch[1].split(",").map((s) => {
@@ -3491,7 +4121,7 @@ function rewriteSystemProxyConsumers(code, systemProxyInfo) {
3491
4121
  let nextCode = code;
3492
4122
  for (const [proxyFileName, proxyInfo] of Array.from(systemProxyInfo.entries())) {
3493
4123
  const proxyBaseName = getProxyBaseName(proxyFileName);
3494
- const depMatch = new RegExp(`["']([^"']*${escapeRegExp(proxyBaseName)}[^"']*)["']`).exec(nextCode);
4124
+ const depMatch = new RegExp(`["']([^"']*${escapeRegExp$1(proxyBaseName)}[^"']*)["']`).exec(nextCode);
3495
4125
  if (!depMatch) continue;
3496
4126
  let setterIndex = 0;
3497
4127
  const depListMatch = nextCode.match(/System\.register\(\[([\s\S]*?)\]/);
@@ -3850,10 +4480,28 @@ function createRemoteEntryAssetMap(fileName) {
3850
4480
  }
3851
4481
  };
3852
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
+ }
3853
4501
  const Manifest = () => {
3854
4502
  const mfOptions = getNormalizeModuleFederationOptions();
3855
4503
  const { name, filename, getPublicPath, manifest: manifestOptions, varFilename } = mfOptions;
3856
- 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;
3857
4505
  let mfManifestStatsName = mfManifestName ? getStatsFileName(mfManifestName) : void 0;
3858
4506
  const isConsumerProject = Object.keys(mfOptions.exposes).length === 0;
3859
4507
  let disableAssetsAnalyze = false;
@@ -3902,7 +4550,8 @@ const Manifest = () => {
3902
4550
  type: "app",
3903
4551
  buildInfo: {
3904
4552
  buildVersion: getBuildVersion(),
3905
- buildName: name
4553
+ buildName: name,
4554
+ ...getTreeShakingBuildInfo(mfOptions)
3906
4555
  },
3907
4556
  remoteEntry: {
3908
4557
  name: devRemoteEntryFile,
@@ -3957,6 +4606,16 @@ const Manifest = () => {
3957
4606
  if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
3958
4607
  ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(resolveDevRemoteEntryFileName(mfOptions.filename)) : expectedSsrRemoteEntryFile);
3959
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
+ }
3960
4619
  if (!disableAssetsAnalyze) {
3961
4620
  const exposesModules = Object.keys(mfOptions.exposes).map((item) => mfOptions.exposes[item].import);
3962
4621
  processModuleAssets(bundle, filesMap, (modulePath) => {
@@ -3968,7 +4627,7 @@ const Manifest = () => {
3968
4627
  stripKnownJsExtensions: true
3969
4628
  });
3970
4629
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(), this.resolve.bind(this));
3971
- processModuleAssets(bundle, filesMap, (modulePath) => fileToShareKey.get(modulePath));
4630
+ processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
3972
4631
  if (mfOptions.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
3973
4632
  filesMap = deduplicateAssets(filesMap);
3974
4633
  }
@@ -4010,24 +4669,39 @@ const Manifest = () => {
4010
4669
  const varRemoteEntry = varFilename ? {
4011
4670
  name: varFilename,
4012
4671
  path: "",
4013
- type: "module"
4672
+ type: "var"
4014
4673
  } : void 0;
4015
- const remotes = Array.from(Object.entries(getUsedRemotesMap())).flatMap(([remoteKey, modules]) => Array.from(modules).map((moduleKey) => ({
4016
- federationContainerName: options.remotes[remoteKey].entry,
4017
- moduleName: moduleKey.replace(remoteKey, "").replace("/", ""),
4018
- alias: remoteKey,
4019
- entry: "*"
4020
- })));
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
+ });
4021
4683
  const shared = Array.from(getUsedShares()).flatMap((shareKey) => {
4022
4684
  const shareItem = getNormalizeShareItem(shareKey);
4023
4685
  if (!shareItem) return [];
4024
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;
4025
4690
  return [{
4026
4691
  id: `${name}:${shareKey}`,
4027
4692
  name: shareKey,
4028
4693
  version: shareItem.version,
4029
4694
  singleton: shareItem.shareConfig.singleton,
4030
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
+ } : {},
4031
4705
  assets: {
4032
4706
  js: {
4033
4707
  async: assets.js.async,
@@ -4067,7 +4741,8 @@ const Manifest = () => {
4067
4741
  type: "app",
4068
4742
  buildInfo: {
4069
4743
  buildVersion: getBuildVersion(),
4070
- buildName: name
4744
+ buildName: name,
4745
+ ...getTreeShakingBuildInfo(options)
4071
4746
  },
4072
4747
  remoteEntry,
4073
4748
  ssrRemoteEntry,
@@ -4112,32 +4787,41 @@ function getStatsFileName(manifestFileName) {
4112
4787
  const fileExt = parsed.ext || ".json";
4113
4788
  const baseName = parsed.ext ? parsed.name : parsed.base;
4114
4789
  const fileName = `${baseName === "mf-manifest" ? "mf" : baseName}-stats${fileExt}`;
4115
- return parsed.dir ? path$1.join(parsed.dir, fileName) : fileName;
4790
+ return parsed.dir ? normalizePathForImport(path$1.join(parsed.dir, fileName)) : fileName;
4116
4791
  }
4117
4792
  //#endregion
4118
4793
  //#region src/plugins/pluginModuleParseEnd.ts
4119
4794
  let _resolve = null;
4120
4795
  let _parseTimeout = null;
4796
+ let _settleTimeout = null;
4121
4797
  let parsePromise = Promise.resolve(1);
4122
- let exposesParseEnd = false;
4123
- let expectsExposesParseEnd = false;
4124
4798
  let parseStartSet = /* @__PURE__ */ new Set();
4125
4799
  let parseEndSet = /* @__PURE__ */ new Set();
4800
+ let lastLoadedModule = "";
4801
+ let lastParsedModule = "";
4126
4802
  function clearParseTimeout() {
4127
4803
  if (_parseTimeout) {
4128
4804
  clearTimeout(_parseTimeout);
4129
4805
  _parseTimeout = null;
4130
4806
  }
4131
4807
  }
4808
+ function clearSettleTimeout() {
4809
+ if (_settleTimeout) {
4810
+ clearTimeout(_settleTimeout);
4811
+ _settleTimeout = null;
4812
+ }
4813
+ }
4132
4814
  function resetParseState() {
4133
4815
  clearParseTimeout();
4134
- exposesParseEnd = false;
4135
- expectsExposesParseEnd = false;
4816
+ clearSettleTimeout();
4136
4817
  parseStartSet = /* @__PURE__ */ new Set();
4137
4818
  parseEndSet = /* @__PURE__ */ new Set();
4819
+ lastLoadedModule = "";
4820
+ lastParsedModule = "";
4138
4821
  parsePromise = new Promise((resolve) => {
4139
4822
  _resolve = (v) => {
4140
4823
  clearParseTimeout();
4824
+ clearSettleTimeout();
4141
4825
  resolve(v);
4142
4826
  };
4143
4827
  });
@@ -4151,10 +4835,18 @@ function setParseTimeout(timeout) {
4151
4835
  function resetIdleTimeout(timeout) {
4152
4836
  clearParseTimeout();
4153
4837
  _parseTimeout = setTimeout(() => {
4154
- 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(", ")}` : ""));
4155
4840
  _resolve?.(1);
4156
4841
  }, timeout * 1e3);
4157
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
+ }
4158
4850
  function pluginModuleParseEnd_default(excludeFn, options) {
4159
4851
  const idleTimeout = options.moduleParseIdleTimeout ?? options.moduleParseTimeout;
4160
4852
  return [
@@ -4169,14 +4861,20 @@ function pluginModuleParseEnd_default(excludeFn, options) {
4169
4861
  enforce: "pre",
4170
4862
  name: "parseStart",
4171
4863
  apply: "build",
4172
- buildStart() {
4864
+ async buildStart() {
4173
4865
  resetParseState();
4174
4866
  if (idleTimeout) resetIdleTimeout(idleTimeout);
4175
- 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
+ }
4176
4872
  },
4177
4873
  load(id) {
4874
+ lastLoadedModule = id;
4178
4875
  if (excludeFn(id)) return;
4179
- if (id === options.virtualExposesId) expectsExposesParseEnd = true;
4876
+ clearSettleTimeout();
4877
+ if (idleTimeout) resetIdleTimeout(idleTimeout);
4180
4878
  parseStartSet.add(id);
4181
4879
  }
4182
4880
  },
@@ -4185,12 +4883,18 @@ function pluginModuleParseEnd_default(excludeFn, options) {
4185
4883
  name: "parseEnd",
4186
4884
  apply: "build",
4187
4885
  moduleParsed(module) {
4886
+ clearSettleTimeout();
4188
4887
  const id = module.id;
4189
- if (id === options.virtualExposesId) exposesParseEnd = true;
4888
+ lastParsedModule = id;
4190
4889
  if (idleTimeout) resetIdleTimeout(idleTimeout);
4191
- if (excludeFn(id)) return;
4192
- parseEndSet.add(id);
4193
- 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();
4194
4898
  },
4195
4899
  buildEnd() {
4196
4900
  _resolve?.(1);
@@ -4209,6 +4913,9 @@ function resolveDevHashEntryFileName(fileName) {
4209
4913
  function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
4210
4914
  let viteConfig, _command, root;
4211
4915
  let exposeRemoteDependencies = {};
4916
+ let exposeRemoteDependenciesDirty = true;
4917
+ let refreshPromise;
4918
+ let dependencyInvalidationVersion = 0;
4212
4919
  function isRemoteImport(source) {
4213
4920
  return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
4214
4921
  }
@@ -4247,12 +4954,26 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4247
4954
  return Array.from(dependencies).sort();
4248
4955
  }
4249
4956
  async function refreshExposeRemoteDependencies(ctx) {
4250
- const next = {};
4251
- for (const [exposeKey, expose] of Object.entries(options.exposes)) {
4252
- const resolved = await ctx.resolve(expose.import);
4253
- 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
+ });
4254
4971
  }
4255
- exposeRemoteDependencies = next;
4972
+ await refreshPromise;
4973
+ }
4974
+ function invalidateExposeRemoteDependencies() {
4975
+ exposeRemoteDependenciesDirty = true;
4976
+ dependencyInvalidationVersion += 1;
4256
4977
  }
4257
4978
  return {
4258
4979
  name: "proxyRemoteEntry",
@@ -4275,6 +4996,12 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4275
4996
  });
4276
4997
  }
4277
4998
  },
4999
+ watchChange() {
5000
+ invalidateExposeRemoteDependencies();
5001
+ },
5002
+ handleHotUpdate() {
5003
+ invalidateExposeRemoteDependencies();
5004
+ },
4278
5005
  async resolveId(id, importer) {
4279
5006
  if (id === remoteEntryId) return remoteEntryId;
4280
5007
  if (id === virtualExposesId) return virtualExposesId;
@@ -4285,16 +5012,22 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4285
5012
  if (resolved) return resolved;
4286
5013
  }
4287
5014
  },
4288
- load(id) {
5015
+ async load(id) {
4289
5016
  if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
4290
- if (id === virtualExposesId) return generateExposes(options, exposeRemoteDependencies, _command);
5017
+ if (id === virtualExposesId) {
5018
+ await refreshExposeRemoteDependencies(this);
5019
+ return generateExposes(options, exposeRemoteDependencies, _command);
5020
+ }
4291
5021
  if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
4292
5022
  },
4293
- transform(code, id) {
4294
- return mapCodeToCodeWithSourcemap((() => {
5023
+ async transform(code, id) {
5024
+ return mapCodeToCodeWithSourcemap(await (async () => {
4295
5025
  if (!filterId(id)) return;
4296
5026
  if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
4297
- if (id === virtualExposesId) return generateExposes(options, exposeRemoteDependencies, _command);
5027
+ if (id === virtualExposesId) {
5028
+ await refreshExposeRemoteDependencies(this);
5029
+ return generateExposes(options, exposeRemoteDependencies, _command);
5030
+ }
4298
5031
  if (id.includes(getHostAutoInitPath())) {
4299
5032
  if (_command === "serve") {
4300
5033
  const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
@@ -4369,6 +5102,9 @@ function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
4369
5102
  function isNodeModulesImporter(importer) {
4370
5103
  return importer?.includes("/node_modules/") || importer?.includes("\\node_modules\\");
4371
5104
  }
5105
+ function escapeRegExp(value) {
5106
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5107
+ }
4372
5108
  function appendAlias(config, alias) {
4373
5109
  config.resolve ??= {};
4374
5110
  const existingAlias = config.resolve.alias;
@@ -4411,10 +5147,9 @@ function pluginProxyRemotes_default(options) {
4411
5147
  config(config, { command: _command }) {
4412
5148
  command = _command;
4413
5149
  root = config.root || process.cwd();
4414
- Object.keys(remotes).forEach((key) => {
4415
- const remote = remotes[key];
5150
+ Object.keys(remotes).forEach((remoteAlias) => {
4416
5151
  appendAlias(config, {
4417
- find: new RegExp(`^(${remote.name}(\/.*|$))`),
5152
+ find: new RegExp(`^(${escapeRegExp(remoteAlias)}(\/.*|$))`),
4418
5153
  replacement: "$1"
4419
5154
  });
4420
5155
  });
@@ -4425,9 +5160,9 @@ function pluginProxyRemotes_default(options) {
4425
5160
  },
4426
5161
  resolveId(source, importer) {
4427
5162
  if (!filterId(source)) return;
4428
- for (const remote of Object.values(remotes)) {
4429
- if (source !== remote.name && !source.startsWith(`${remote.name}/`)) continue;
4430
- 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);
4431
5166
  }
4432
5167
  }
4433
5168
  };
@@ -4585,6 +5320,36 @@ function proxySharedModule(options) {
4585
5320
  const savePrebuild = new PromiseStore();
4586
5321
  let devServer;
4587
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
+ };
4588
5353
  return [
4589
5354
  {
4590
5355
  name: "generateLocalSharedImportMap",
@@ -4600,7 +5365,16 @@ function proxySharedModule(options) {
4600
5365
  if (source === getLocalSharedImportMapPath()) return getResolvedLocalSharedImportMapId();
4601
5366
  },
4602
5367
  load(id) {
4603
- 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
+ });
4604
5378
  },
4605
5379
  closeBundle() {
4606
5380
  if (devServer) return;
@@ -4612,6 +5386,9 @@ function proxySharedModule(options) {
4612
5386
  enforce: "post",
4613
5387
  config(config, { command }) {
4614
5388
  setPackageDetectionCwd(config.root || process.cwd());
5389
+ setTreeShakingBuildMode(command === "build");
5390
+ resetTreeShakingExports();
5391
+ emittedTreeShakingProviders.clear();
4615
5392
  const isVinext = hasPackageDependency("vinext");
4616
5393
  const isAstro = hasPackageDependency("astro");
4617
5394
  const isRolldown = getIsRolldown(this);
@@ -4635,12 +5412,62 @@ function proxySharedModule(options) {
4635
5412
  });
4636
5413
  writeLocalSharedImportMap();
4637
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
+ };
4638
5464
  }
4639
5465
  },
4640
5466
  {
4641
5467
  name: "proxyPreBuildShared:resolve-shared-loadShare",
4642
5468
  enforce: "pre",
4643
- async resolveId(source, importer) {
5469
+ async resolveId(source, importer, resolveOptions) {
5470
+ if (resolveOptions.custom?.__mfTreeShakingGraph) return;
4644
5471
  function shouldSkipTaggedImporterProxy(sharedKey, tag) {
4645
5472
  if (!importer?.includes(tag)) return false;
4646
5473
  const taggedModule = VirtualModule.findModule(tag, importer);
@@ -5602,10 +6429,10 @@ function hasImportFalseShared(options) {
5602
6429
  }
5603
6430
  function getRuntimeHelpersImplementation(runtimeImplementation) {
5604
6431
  const indexEntryMatch = runtimeImplementation.match(/^(.*[\\/])index(\.[cm]?js)$/);
5605
- if (indexEntryMatch) return `${indexEntryMatch[1]}helpers${indexEntryMatch[2]}`;
6432
+ if (indexEntryMatch) return normalizePathForImport(`${indexEntryMatch[1]}helpers${indexEntryMatch[2]}`);
5606
6433
  const extension = path$1.extname(runtimeImplementation);
5607
- if (extension) return path$1.join(path$1.dirname(runtimeImplementation), `helpers${extension}`);
5608
- 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"));
5609
6436
  return `${runtimeImplementation.replace(/\/$/, "")}/helpers`;
5610
6437
  }
5611
6438
  const UNSAFE_JS_SOURCE_CHAR_MAP = {
@@ -5788,7 +6615,7 @@ export default __mfShared.default ?? __mfShared;`
5788
6615
  const optimizeDeps = config.optimizeDeps ??= {};
5789
6616
  optimizeDeps.include ??= [];
5790
6617
  optimizeDeps.exclude ??= [];
5791
- const shouldBypassOptimizeDep = isLitShare(key) || key === "react" && shareItem.shareConfig?.singleton === true;
6618
+ const shouldBypassOptimizeDep = isLitShare(key);
5792
6619
  if (optimizeDeps.include.includes(key)) optimizeDeps.exclude = optimizeDeps.exclude.filter((dep) => dep !== key);
5793
6620
  else if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
5794
6621
  else optimizeDeps.include.push(key);
@@ -5843,13 +6670,14 @@ export default __mfShared.default ?? __mfShared;`
5843
6670
  const SSR_ONLY_PLUGINS = new Set(["@module-federation/vite/ssrEntryLoader"]);
5844
6671
  function loadPluginDts(options) {
5845
6672
  if (options.dts === false) return [];
5846
- 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))];
5847
6674
  }
5848
6675
  function federation(mfUserOptions) {
5849
6676
  if (isTestEnv()) return [];
5850
6677
  const options = normalizeModuleFederationOptions(mfUserOptions);
5851
6678
  const isVinext = hasPackageDependency("vinext");
5852
6679
  const { name, shared, filename, hostInitInjectLocation } = options;
6680
+ const hasTreeShakingShared = Object.values(shared).some((share) => !!share.shareConfig.treeShaking);
5853
6681
  if (!name) throw createModuleFederationError("name is required");
5854
6682
  const remoteEntryId = getRemoteEntryId(options);
5855
6683
  const virtualExposesId = getVirtualExposesId(options);
@@ -5955,11 +6783,11 @@ function federation(mfUserOptions) {
5955
6783
  pluginProxyRemotes_default(options),
5956
6784
  pluginRemoteNamedExports(options),
5957
6785
  ...pluginModuleParseEnd_default((id) => {
5958
- 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__");
5959
6787
  }, {
5960
6788
  moduleParseTimeout: options.moduleParseTimeout,
5961
6789
  moduleParseIdleTimeout: options.moduleParseIdleTimeout,
5962
- virtualExposesId
6790
+ exposedModuleImports: Object.values(options.exposes).map((expose) => expose.import)
5963
6791
  }),
5964
6792
  ...proxySharedModule({ shared }),
5965
6793
  {
@@ -5981,7 +6809,8 @@ function federation(mfUserOptions) {
5981
6809
  if (context.hostType === "js" && (hostFile === options.filename || hostFile.includes("hostInit") || hostFile.includes("virtualExposes") || hostFile.includes("localSharedImportMap"))) return [];
5982
6810
  const hasFederationHtmlDeps = context.hostType === "html" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
5983
6811
  const hasFederationJsDeps = context.hostType === "js" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
5984
- 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));
5985
6814
  }
5986
6815
  };
5987
6816
  }
@@ -6155,8 +6984,8 @@ function federation(mfUserOptions) {
6155
6984
  config(config, { command: _command }) {
6156
6985
  const isRolldown = getIsRolldown(this);
6157
6986
  isSsrBuild = _command === "build" && config.build?.ssr === true;
6158
- const needsSharedProviderSelectionHelper = hasImportFalseShared(options);
6159
- if (needsSharedProviderSelectionHelper) appendResolveAlias(config, {
6987
+ const needsRuntimeHelpers = hasImportFalseShared(options) || Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
6988
+ if (needsRuntimeHelpers) appendResolveAlias(config, {
6160
6989
  find: /^@module-federation\/runtime\/helpers$/,
6161
6990
  replacement: getRuntimeHelpersImplementation(options.implementation)
6162
6991
  });
@@ -6170,7 +6999,7 @@ function federation(mfUserOptions) {
6170
6999
  config.optimizeDeps ||= {};
6171
7000
  config.optimizeDeps.include ||= [];
6172
7001
  config.optimizeDeps.include.push("@module-federation/runtime");
6173
- if (needsSharedProviderSelectionHelper) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
7002
+ if (needsRuntimeHelpers) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
6174
7003
  options.runtimePlugins.forEach((p) => {
6175
7004
  const pluginPath = typeof p === "string" ? p : p[0];
6176
7005
  if (SSR_ONLY_PLUGINS.has(pluginPath)) return;