@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/README.md +29 -0
- package/lib/index.d.ts +13 -3
- package/lib/index.js +952 -123
- package/lib/{pluginDts-Bo95ELmX.js → pluginDts-BcvLBYP3.js} +67 -0
- package/package.json +1 -1
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-
|
|
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 (
|
|
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
|
-
|
|
397
|
-
|
|
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$
|
|
563
|
+
function escapeRegExp$2(value) {
|
|
553
564
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
554
565
|
}
|
|
555
566
|
function createViteEncodedIdPrefixRegExp(sourcePrefix = "") {
|
|
556
|
-
return new RegExp(`^(?:${escapeRegExp$
|
|
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
|
|
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 (
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
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/")
|
|
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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
1800
|
+
let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
|
|
1426
1801
|
if (exportModule === undefined) {
|
|
1427
1802
|
if (import.meta.env.SSR) {
|
|
1428
|
-
${
|
|
1429
|
-
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
|
|
1430
|
-
__mfApplyLazyShareExports(exportModule);`}
|
|
1803
|
+
${applyLocalFallback}
|
|
1431
1804
|
} else {
|
|
1432
1805
|
(__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
|
|
1433
|
-
exportModule =
|
|
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
|
-
|
|
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
|
-
${
|
|
1840
|
+
${assignments}
|
|
1465
1841
|
};
|
|
1466
|
-
let exportModule =
|
|
1842
|
+
let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
|
|
1467
1843
|
if (exportModule === undefined) {
|
|
1468
1844
|
(__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
|
|
1469
|
-
exportModule =
|
|
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 };${
|
|
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 (
|
|
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 =
|
|
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
|
-
${
|
|
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 =
|
|
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
|
-
${
|
|
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
|
|
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
|
-
|
|
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 (
|
|
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
|
|
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 {
|
|
1881
|
-
${
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
2122
|
-
|
|
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
|
|
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]
|
|
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
|
|
2594
|
-
const root = config.root
|
|
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: "
|
|
4672
|
+
type: "var"
|
|
4014
4673
|
} : void 0;
|
|
4015
|
-
const remotes = Array.from(Object.entries(getUsedRemotesMap())).flatMap(([remoteKey, modules]) =>
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4888
|
+
lastParsedModule = id;
|
|
4190
4889
|
if (idleTimeout) resetIdleTimeout(idleTimeout);
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
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
|
-
|
|
4251
|
-
|
|
4252
|
-
const
|
|
4253
|
-
|
|
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
|
-
|
|
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)
|
|
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)
|
|
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((
|
|
4415
|
-
const remote = remotes[key];
|
|
5150
|
+
Object.keys(remotes).forEach((remoteAlias) => {
|
|
4416
5151
|
appendAlias(config, {
|
|
4417
|
-
find: new RegExp(`^(${
|
|
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
|
|
4429
|
-
if (source !==
|
|
4430
|
-
return resolveRemoteId(this, source, importer,
|
|
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((_) =>
|
|
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)
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
6159
|
-
if (
|
|
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 (
|
|
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;
|