@module-federation/vite 1.21.6 → 1.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -4
- package/lib/{dtsConstants-BsaLBaaK.js → dtsConstants-dDsHZFC1.js} +40 -10
- package/lib/index.d.ts +25 -3
- package/lib/index.js +1130 -684
- package/lib/{pluginDts-4sHIZPIi.js → pluginDts-CQ088qGF.js} +1 -1
- package/lib/{sharedKeyMatcher-DiUzRVH1.js → sharedKeyMatcher-BRzBCbuR.js} +19 -25
- package/lib/{ssrEntryLoader-BqzV2t-n.js → ssrEntryLoader-BUXUQi0P.js} +11 -7
- package/lib/{ssrVmStrategy-CkmYR5_u.js → ssrVmStrategy-Ud06y3Xf.js} +2 -2
- package/lib/utils/ssrEntryLoader.js +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { _ as stripViteFsPrefix, a as ensureTrailingSlash, c as getCommonSharedSubpaths, d as isNodeModulePath, f as isNuxtClientBase, g as stripQueryAndHash, h as resolvePublicPath, l as getNodeModulesSuffix, m as normalizeNodeModulePath, n as invalidateSharedKeyMatcher, o as filterId, p as isViteOptimizableEntry, r as matchesSharedSource, s as getBasePath$1, t as findSharedKey, u as isAssetLikeImport } from "./sharedKeyMatcher-BRzBCbuR.js";
|
|
1
2
|
import { i as resolveHashPlaceholderFileName, n as normalizePathForImport, r as rebaseImport } from "./buildPaths-BoaQTkxt.js";
|
|
2
|
-
import { a as getPackageDetectionCwd, c as getSharedCacheDescriptor, d as
|
|
3
|
-
import { a as filterId, c as getCommonSharedSubpaths, d as isNodeModulePath, f as isNuxtClientBase, h as resolvePublicPath, i as ensureTrailingSlash, l as getMatchingNodeModuleSubpath, m as normalizeNodeModulePath, n as invalidateSharedKeyMatcher, o as getBasePath$1, p as isViteOptimizableEntry, r as matchesSharedSource, s as getCommonSharedSubpathFromNodeModulePath, t as findSharedKey, u as isAssetLikeImport } from "./sharedKeyMatcher-DiUzRVH1.js";
|
|
3
|
+
import { _ as sharedCacheHelperCode, a as getPackageDetectionCwd, b as mfWarn, c as getSharedCacheDescriptor, d as isPackageExportAvailable, f as isPackageInstalled, g as setPackageDetectionCwd, h as resolveImportPath, i as getIsRolldown, l as hasPackageDependency, m as packageNameEncode, n as getInstalledPackageEntry, o as getPackageName, p as packageNameDecode, r as getInstalledPackageJson, s as getPackageNameFromNodeModulePath, u as isNuxtProjectRoot, v as createModuleFederationError } from "./dtsConstants-dDsHZFC1.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import * as fs$2 from "fs";
|
|
6
6
|
import { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
|
|
@@ -373,6 +373,38 @@ async function mapCodeToCodeWithSourcemap(code) {
|
|
|
373
373
|
};
|
|
374
374
|
}
|
|
375
375
|
//#endregion
|
|
376
|
+
//#region src/utils/remoteConsumerTarget.ts
|
|
377
|
+
function getPluginEnvironmentName(ctx) {
|
|
378
|
+
if (ctx == null || typeof ctx !== "object") return void 0;
|
|
379
|
+
const environment = ctx["environment"];
|
|
380
|
+
if (environment == null || typeof environment !== "object") return void 0;
|
|
381
|
+
const name = environment["name"];
|
|
382
|
+
return typeof name === "string" ? name : void 0;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Classify a plugin hook context's Vite environment. Environment names are
|
|
386
|
+
* user-defined, so Vite's `config.consumer` is the semantic role; fall back to
|
|
387
|
+
* the name only when it is missing (Vite 5–7). Returns `undefined` when the hook
|
|
388
|
+
* has no environment context at all.
|
|
389
|
+
*/
|
|
390
|
+
function resolveEnvironmentConsumerTarget(ctx) {
|
|
391
|
+
if (ctx == null || typeof ctx !== "object") return void 0;
|
|
392
|
+
const environment = ctx["environment"];
|
|
393
|
+
if (environment == null || typeof environment !== "object") return void 0;
|
|
394
|
+
const consumer = environment.config?.consumer;
|
|
395
|
+
if (consumer === "client" || consumer === "server") return consumer;
|
|
396
|
+
const envName = getPluginEnvironmentName(ctx);
|
|
397
|
+
return !envName || envName === "client" ? "client" : "server";
|
|
398
|
+
}
|
|
399
|
+
/** Vite 5–7 hooks have no environment context and keep their client build behavior. */
|
|
400
|
+
function isClientEnvironment(ctx) {
|
|
401
|
+
return resolveEnvironmentConsumerTarget(ctx) !== "server";
|
|
402
|
+
}
|
|
403
|
+
function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
|
|
404
|
+
if (!hasMultiEnvironment) return "unified";
|
|
405
|
+
return resolveEnvironmentConsumerTarget(ctx) ?? "client";
|
|
406
|
+
}
|
|
407
|
+
//#endregion
|
|
376
408
|
//#region src/utils/codePositionMap.ts
|
|
377
409
|
const REGEX_PREFIX_KEYWORDS = /* @__PURE__ */ new Set([
|
|
378
410
|
"await",
|
|
@@ -399,7 +431,7 @@ function isJsxClosingTagSlash(code, slashIndex) {
|
|
|
399
431
|
return code[cursor] === ">";
|
|
400
432
|
}
|
|
401
433
|
/** Mark comments, string/template literals, and regular expressions as non-code. */
|
|
402
|
-
function createCodePositionMap(code) {
|
|
434
|
+
function createCodePositionMap(code, onComment) {
|
|
403
435
|
const positions = Array(code.length).fill(true);
|
|
404
436
|
const mask = (start, end) => {
|
|
405
437
|
for (let index = start; index < end; index++) positions[index] = false;
|
|
@@ -417,6 +449,7 @@ function createCodePositionMap(code) {
|
|
|
417
449
|
index += 2;
|
|
418
450
|
while (index < code.length && code[index] !== "\n" && code[index] !== "\r") index++;
|
|
419
451
|
mask(start, index);
|
|
452
|
+
onComment?.(start, index);
|
|
420
453
|
continue;
|
|
421
454
|
}
|
|
422
455
|
if (char === "/" && next === "*") {
|
|
@@ -425,6 +458,7 @@ function createCodePositionMap(code) {
|
|
|
425
458
|
while (index < code.length && !(code[index] === "*" && code[index + 1] === "/")) index++;
|
|
426
459
|
index = Math.min(code.length, index + 2);
|
|
427
460
|
mask(start, index);
|
|
461
|
+
onComment?.(start, index);
|
|
428
462
|
continue;
|
|
429
463
|
}
|
|
430
464
|
if (char === "\"" || char === "'" || char === "`") {
|
|
@@ -730,8 +764,8 @@ function normalizeRemoteItem(key, remote) {
|
|
|
730
764
|
* @param {string} sharedName
|
|
731
765
|
* @returns {string | undefined}
|
|
732
766
|
*/
|
|
733
|
-
function searchPackageVersion(sharedName) {
|
|
734
|
-
const version = getInstalledPackageJson(sharedName)?.packageJson.version;
|
|
767
|
+
function searchPackageVersion(sharedName, cwd) {
|
|
768
|
+
const version = getInstalledPackageJson(sharedName, { cwd })?.packageJson.version;
|
|
735
769
|
return typeof version === "string" ? version : void 0;
|
|
736
770
|
}
|
|
737
771
|
function inferVersionFromRequiredVersion(requiredVersion) {
|
|
@@ -766,36 +800,88 @@ const PACKAGE_SPECIFIER_PROTOCOL_RE = /^[a-z][a-z\d+.-]*:/i;
|
|
|
766
800
|
function isProtocolRequiredVersion(requiredVersion) {
|
|
767
801
|
return PACKAGE_SPECIFIER_PROTOCOL_RE.test(requiredVersion.trim());
|
|
768
802
|
}
|
|
803
|
+
const SEMVER_COMPARATOR_RE = /^(?:[<>=~^]*v?(?:\d+|[xX*])(?:\.(?:\d+|[xX*]))*(?:[-+][\w.-]+)?|[<>=~^]+|[xX*]|-)$/;
|
|
804
|
+
function isSemverRange(range) {
|
|
805
|
+
return range.split("||").every((alternative) => {
|
|
806
|
+
const comparators = alternative.trim().split(/\s+/).filter(Boolean);
|
|
807
|
+
return comparators.length > 0 && comparators.every((c) => SEMVER_COMPARATOR_RE.test(c));
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
function isUsableRequiredVersion(requiredVersion) {
|
|
811
|
+
return requiredVersion.trim() !== "" && !isProtocolRequiredVersion(requiredVersion) && isSemverRange(requiredVersion);
|
|
812
|
+
}
|
|
813
|
+
/** Bare specifiers name an installed package; relative/absolute paths do not. */
|
|
814
|
+
function isBareSpecifier(specifier) {
|
|
815
|
+
return !specifier.startsWith(".") && !specifier.startsWith("\0") && !path$1.isAbsolute(specifier) && !PACKAGE_SPECIFIER_PROTOCOL_RE.test(specifier);
|
|
816
|
+
}
|
|
817
|
+
function readProjectPackageJson(cwd, cache) {
|
|
818
|
+
if (cache.has(cwd)) return cache.get(cwd);
|
|
819
|
+
let packageJson;
|
|
820
|
+
try {
|
|
821
|
+
packageJson = JSON.parse(fs$2.readFileSync(path$1.join(cwd, "package.json"), "utf8"));
|
|
822
|
+
} catch {}
|
|
823
|
+
cache.set(cwd, packageJson);
|
|
824
|
+
return packageJson;
|
|
825
|
+
}
|
|
769
826
|
function getLitExportSubpathShares(sharedName) {
|
|
770
827
|
if (sharedName !== "lit") return [];
|
|
771
828
|
const exportsField = getInstalledPackageJson(sharedName, { packageName: sharedName })?.packageJson.exports;
|
|
772
829
|
if (!exportsField || typeof exportsField === "string") return [];
|
|
773
830
|
return Object.keys(exportsField).filter((key) => key.startsWith("./") && key !== "." && !key.includes("*")).map((key) => `${sharedName}/${key.slice(2)}`);
|
|
774
831
|
}
|
|
832
|
+
const sharedVersionConfigs = /* @__PURE__ */ new WeakMap();
|
|
833
|
+
function resolveSharedVersion(key, config, cwd, packageJsonCache = /* @__PURE__ */ new Map(), fallbackVersion) {
|
|
834
|
+
const source = typeof config.import === "string" && isBareSpecifier(config.import) ? config.import : key;
|
|
835
|
+
const version = config.version || searchPackageVersion(source, cwd) || inferVersionFromRequiredVersion(config.requiredVersion) || fallbackVersion;
|
|
836
|
+
let requiredVersion = config.requiredVersion;
|
|
837
|
+
if (requiredVersion === void 0 && !config.version) {
|
|
838
|
+
const packageJson = readProjectPackageJson(cwd, packageJsonCache);
|
|
839
|
+
const packageName = getPackageName(source);
|
|
840
|
+
requiredVersion = packageJson?.dependencies?.[packageName] ?? packageJson?.devDependencies?.[packageName] ?? packageJson?.peerDependencies?.[packageName] ?? packageJson?.optionalDependencies?.[packageName];
|
|
841
|
+
}
|
|
842
|
+
if (requiredVersion === false || typeof requiredVersion === "string" && isUsableRequiredVersion(requiredVersion)) return {
|
|
843
|
+
version,
|
|
844
|
+
requiredVersion
|
|
845
|
+
};
|
|
846
|
+
return {
|
|
847
|
+
version,
|
|
848
|
+
requiredVersion: config.import === false || config.version ? "*" : version ? `^${version}` : "*"
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
function resolveSharedVersions(shared, root) {
|
|
852
|
+
const packageJsonCache = /* @__PURE__ */ new Map();
|
|
853
|
+
for (const [key, item] of Object.entries(shared)) {
|
|
854
|
+
const config = sharedVersionConfigs.get(item);
|
|
855
|
+
if (!config) continue;
|
|
856
|
+
const { version, requiredVersion } = resolveSharedVersion(key, config, root, packageJsonCache, item.version);
|
|
857
|
+
item.version = version;
|
|
858
|
+
item.shareConfig.requiredVersion = requiredVersion;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
775
861
|
function normalizeShareItem(key, shareItem) {
|
|
776
|
-
const isImportFalse = typeof shareItem === "object" && shareItem.import === false;
|
|
777
|
-
const explicitVersion = typeof shareItem === "object" ? shareItem.version : void 0;
|
|
778
|
-
const inferredVersion = typeof shareItem === "object" ? inferVersionFromRequiredVersion(shareItem.requiredVersion) : void 0;
|
|
779
862
|
const treeShaking = typeof shareItem === "object" ? shareItem.treeShaking : void 0;
|
|
780
863
|
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".`);
|
|
781
864
|
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.`);
|
|
782
865
|
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.`);
|
|
783
|
-
const
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
866
|
+
const config = typeof shareItem === "object" ? shareItem : {};
|
|
867
|
+
const { version, requiredVersion } = resolveSharedVersion(key, config, getPackageDetectionCwd());
|
|
868
|
+
if (typeof shareItem === "string") {
|
|
869
|
+
const result = {
|
|
870
|
+
name: shareItem,
|
|
871
|
+
version,
|
|
872
|
+
scope: "default",
|
|
873
|
+
from: "",
|
|
874
|
+
shareConfig: {
|
|
875
|
+
import: void 0,
|
|
876
|
+
singleton: false,
|
|
877
|
+
eager: false,
|
|
878
|
+
requiredVersion
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
sharedVersionConfigs.set(result, { ...config });
|
|
882
|
+
return result;
|
|
883
|
+
}
|
|
884
|
+
const result = {
|
|
799
885
|
name: key,
|
|
800
886
|
from: "",
|
|
801
887
|
version,
|
|
@@ -804,12 +890,14 @@ function normalizeShareItem(key, shareItem) {
|
|
|
804
890
|
import: shareItem.import,
|
|
805
891
|
singleton: shareItem.singleton || false,
|
|
806
892
|
eager: shareItem.eager || false,
|
|
807
|
-
requiredVersion
|
|
893
|
+
requiredVersion,
|
|
808
894
|
strictVersion: !!shareItem.strictVersion,
|
|
809
895
|
...shareItem.suppressMissingImportWarning ? { suppressMissingImportWarning: true } : {},
|
|
810
896
|
...treeShaking ? { treeShaking: { ...treeShaking } } : {}
|
|
811
897
|
}
|
|
812
898
|
};
|
|
899
|
+
sharedVersionConfigs.set(result, { ...config });
|
|
900
|
+
return result;
|
|
813
901
|
}
|
|
814
902
|
/**
|
|
815
903
|
* Trailing-slash keys are package namespace prefixes (`lodash/`, `@scope/ui/`).
|
|
@@ -887,6 +975,11 @@ function normalizeExperiments(experiments) {
|
|
|
887
975
|
ssrMode: experiments?.ssrMode === "ISLAND" ? "ISLAND" : void 0
|
|
888
976
|
};
|
|
889
977
|
}
|
|
978
|
+
function normalizeSsrEntryLoader(ssrEntryLoader) {
|
|
979
|
+
const strategy = ssrEntryLoader?.strategy;
|
|
980
|
+
if (strategy !== "temp-file" && strategy !== "vm") return void 0;
|
|
981
|
+
return { strategy };
|
|
982
|
+
}
|
|
890
983
|
let config;
|
|
891
984
|
let explicitSharedKeys = /* @__PURE__ */ new Set();
|
|
892
985
|
const explicitSharedKeysByOptions = /* @__PURE__ */ new WeakMap();
|
|
@@ -905,11 +998,27 @@ function resolveRuntimeImplementation() {
|
|
|
905
998
|
function getNormalizeModuleFederationOptions() {
|
|
906
999
|
return config;
|
|
907
1000
|
}
|
|
1001
|
+
function hasRemotes(options = getNormalizeModuleFederationOptions()) {
|
|
1002
|
+
return Object.keys(options.remotes || {}).length > 0;
|
|
1003
|
+
}
|
|
1004
|
+
function hasShared(options = getNormalizeModuleFederationOptions()) {
|
|
1005
|
+
return Object.keys(options.shared || {}).length > 0;
|
|
1006
|
+
}
|
|
1007
|
+
function isRemoteContainer(options = getNormalizeModuleFederationOptions()) {
|
|
1008
|
+
return Object.keys(options.exposes || {}).length > 0;
|
|
1009
|
+
}
|
|
1010
|
+
function isRemoteOnlyContainer(options = getNormalizeModuleFederationOptions()) {
|
|
1011
|
+
return isRemoteContainer(options) && !hasRemotes(options);
|
|
1012
|
+
}
|
|
1013
|
+
function isLocalOnlyContainer(options = getNormalizeModuleFederationOptions()) {
|
|
1014
|
+
return !isRemoteContainer(options) && !hasRemotes(options);
|
|
1015
|
+
}
|
|
908
1016
|
function isExplicitSharedKey(key, options) {
|
|
909
1017
|
return (options ? explicitSharedKeysByOptions.get(options) : explicitSharedKeys)?.has(key) ?? false;
|
|
910
1018
|
}
|
|
911
1019
|
function getNormalizeShareItem(key, options = getNormalizeModuleFederationOptions()) {
|
|
912
|
-
|
|
1020
|
+
const matchedKey = findSharedKey(key, options.shared);
|
|
1021
|
+
return options.shared[key] || (matchedKey ? options.shared[matchedKey] : void 0) || options.shared[getPackageName(key)] || options.shared[getPackageName(key) + "/"];
|
|
913
1022
|
}
|
|
914
1023
|
function normalizeModuleFederationOptions(options) {
|
|
915
1024
|
warnOnReservedInternalNamePrefix(options.name, "containerName");
|
|
@@ -945,6 +1054,7 @@ function normalizeModuleFederationOptions(options) {
|
|
|
945
1054
|
varFilename: options.varFilename,
|
|
946
1055
|
target: options.target,
|
|
947
1056
|
ssrExternals: options.ssrExternals,
|
|
1057
|
+
ssrEntryLoader: normalizeSsrEntryLoader(options.ssrEntryLoader),
|
|
948
1058
|
disableRemote: options.disableRemote,
|
|
949
1059
|
disableShared: options.disableShared,
|
|
950
1060
|
disableSnapshot: options.disableSnapshot,
|
|
@@ -1022,11 +1132,14 @@ var VirtualModule = class VirtualModule {
|
|
|
1022
1132
|
cacheMap[this.tag][this.name] = this;
|
|
1023
1133
|
}
|
|
1024
1134
|
getImportId() {
|
|
1025
|
-
const
|
|
1135
|
+
const mfName = this.scopeName ?? getNormalizeModuleFederationOptions().internalName;
|
|
1136
|
+
const importIdKey = `${mfName}${this.tag}${this.name}${this.tag}`;
|
|
1026
1137
|
if (this.importId && this.importIdKey === importIdKey) return this.importId;
|
|
1027
1138
|
if (this.importId) delete idCacheMap[this.importId];
|
|
1028
1139
|
this.importIdKey = importIdKey;
|
|
1029
|
-
|
|
1140
|
+
const namePart = packageNameEncode(this.name);
|
|
1141
|
+
const mfNamePart = packageNameEncode(mfName);
|
|
1142
|
+
this.importId = `virtual:mf:${mfNamePart}${this.tag}${namePart}${this.tag}${this.suffix}`;
|
|
1030
1143
|
idCacheMap[this.importId] = this;
|
|
1031
1144
|
return this.importId;
|
|
1032
1145
|
}
|
|
@@ -1163,161 +1276,431 @@ function isParsableExpression(source) {
|
|
|
1163
1276
|
}
|
|
1164
1277
|
}
|
|
1165
1278
|
//#endregion
|
|
1166
|
-
//#region src/utils/
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
".jsx",
|
|
1170
|
-
".ts",
|
|
1171
|
-
".js",
|
|
1172
|
-
".mts",
|
|
1173
|
-
".mjs",
|
|
1174
|
-
".cts",
|
|
1175
|
-
".cjs"
|
|
1176
|
-
];
|
|
1177
|
-
function stripQueryAndHash$2(id) {
|
|
1178
|
-
return id.split(/[?#]/, 1)[0];
|
|
1279
|
+
//#region src/utils/treeShaking.ts
|
|
1280
|
+
function shouldAnalyzeSharedExports(shareItem) {
|
|
1281
|
+
return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
|
|
1179
1282
|
}
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
}
|
|
1283
|
+
const legacyTreeShakingState = {
|
|
1284
|
+
inferredUsage: /* @__PURE__ */ new Map(),
|
|
1285
|
+
buildMode: false
|
|
1286
|
+
};
|
|
1287
|
+
const treeShakingStates = /* @__PURE__ */ new WeakMap();
|
|
1288
|
+
function getTreeShakingState(options) {
|
|
1289
|
+
if (!options) return legacyTreeShakingState;
|
|
1290
|
+
let state = treeShakingStates.get(options);
|
|
1291
|
+
if (!state) {
|
|
1292
|
+
state = {
|
|
1293
|
+
inferredUsage: /* @__PURE__ */ new Map(),
|
|
1294
|
+
buildMode: false
|
|
1295
|
+
};
|
|
1296
|
+
treeShakingStates.set(options, state);
|
|
1297
|
+
}
|
|
1298
|
+
return state;
|
|
1195
1299
|
}
|
|
1196
|
-
function
|
|
1197
|
-
|
|
1198
|
-
return match?.[1]?.startsWith(".") ? match[1] : void 0;
|
|
1300
|
+
function setTreeShakingBuildMode(enabled, options) {
|
|
1301
|
+
getTreeShakingState(options).buildMode = enabled;
|
|
1199
1302
|
}
|
|
1200
|
-
function
|
|
1201
|
-
|
|
1202
|
-
const extension = path$1.extname(stripQueryAndHash$2(filePath)).toLowerCase();
|
|
1203
|
-
const canContainJsx = extension === ".tsx" || extension === ".jsx";
|
|
1204
|
-
const hasJsx = /<>|<\s*[A-Za-z][\w.:-]*(?:\s[^<>]*?)?\s*\/?>/.test(source);
|
|
1205
|
-
const importsReact = /\bfrom\s*["']react["']|\brequire\(\s*["']react["']\s*\)/.test(source);
|
|
1206
|
-
const usesReactApi = /\b(?:React\.)?(?:createElement|jsx|jsxs)\s*\(/.test(source);
|
|
1207
|
-
const isClientModule = /^\s*["']use client["']\s*;?/m.test(source);
|
|
1208
|
-
return canContainJsx && hasJsx || importsReact && (hasJsx || usesReactApi || isClientModule);
|
|
1303
|
+
function resetTreeShakingExports(options) {
|
|
1304
|
+
getTreeShakingState(options).inferredUsage.clear();
|
|
1209
1305
|
}
|
|
1210
|
-
function
|
|
1211
|
-
const
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
source = fs$1.readFileSync(normalizedPath, "utf8");
|
|
1217
|
-
} catch {
|
|
1218
|
-
return false;
|
|
1306
|
+
function getOrCreateExportRecord(sharedKey, request, options) {
|
|
1307
|
+
const inferredUsage = getTreeShakingState(options).inferredUsage;
|
|
1308
|
+
let byRequest = inferredUsage.get(sharedKey);
|
|
1309
|
+
if (!byRequest) {
|
|
1310
|
+
byRequest = /* @__PURE__ */ new Map();
|
|
1311
|
+
inferredUsage.set(sharedKey, byRequest);
|
|
1219
1312
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
}
|
|
1226
|
-
|
|
1227
|
-
* React is shared by the normal MF runtime when explicitly configured. When it
|
|
1228
|
-
* is local, UI exposes can safely advertise an island capability in addition
|
|
1229
|
-
* to their unchanged default export.
|
|
1230
|
-
*/
|
|
1231
|
-
function getReactIslandExposes(options, root) {
|
|
1232
|
-
if (options.experiments.ssrMode !== "ISLAND") return /* @__PURE__ */ new Set();
|
|
1233
|
-
if (Object.hasOwn(options.shared, "react")) return /* @__PURE__ */ new Set();
|
|
1234
|
-
const islandExposes = /* @__PURE__ */ new Set();
|
|
1235
|
-
for (const [key, expose] of Object.entries(options.exposes)) {
|
|
1236
|
-
const sourceFile = resolveSourceFile(expose.import, root);
|
|
1237
|
-
if (sourceFile && isReactComponentFile(sourceFile)) islandExposes.add(key);
|
|
1313
|
+
let record = byRequest.get(request);
|
|
1314
|
+
if (!record) {
|
|
1315
|
+
record = {
|
|
1316
|
+
requiresFullBundle: false,
|
|
1317
|
+
usedExports: /* @__PURE__ */ new Set()
|
|
1318
|
+
};
|
|
1319
|
+
byRequest.set(request, record);
|
|
1238
1320
|
}
|
|
1239
|
-
return
|
|
1240
|
-
}
|
|
1241
|
-
function generateReactIslandBrowserDefinition(enabled) {
|
|
1242
|
-
if (!enabled) return "";
|
|
1243
|
-
return `
|
|
1244
|
-
exportModule.__mf_island = {
|
|
1245
|
-
version: 1,
|
|
1246
|
-
renderToHtml() {
|
|
1247
|
-
return Promise.reject(new Error("[Module Federation] renderToHtml is only available in the SSR remote entry"));
|
|
1248
|
-
},
|
|
1249
|
-
hydrate(element, props) {
|
|
1250
|
-
const root = element && element.hasAttribute && element.hasAttribute("data-mf-island-state")
|
|
1251
|
-
? element
|
|
1252
|
-
: element && element.querySelector
|
|
1253
|
-
? element.querySelector("[data-mf-island-state]") || element
|
|
1254
|
-
: element;
|
|
1255
|
-
if (!root) {
|
|
1256
|
-
return Promise.reject(new Error("[Module Federation] Cannot hydrate an island without a root element"));
|
|
1257
|
-
}
|
|
1258
|
-
let serverProps = {};
|
|
1259
|
-
const encodedState = root.getAttribute && root.getAttribute("data-mf-island-state");
|
|
1260
|
-
if (encodedState) {
|
|
1261
|
-
try {
|
|
1262
|
-
serverProps = JSON.parse(decodeURIComponent(encodedState));
|
|
1263
|
-
} catch {
|
|
1264
|
-
serverProps = {};
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
const finalProps = Object.assign({}, serverProps, props || {});
|
|
1268
|
-
return Promise.all([import("react"), import("react-dom/client")]).then(([React, ReactDOMClient]) => {
|
|
1269
|
-
if (typeof ReactDOMClient.hydrateRoot !== "function") {
|
|
1270
|
-
throw new Error("[Module Federation] react-dom/client does not provide hydrateRoot");
|
|
1271
|
-
}
|
|
1272
|
-
return ReactDOMClient.hydrateRoot(
|
|
1273
|
-
root,
|
|
1274
|
-
React.createElement(importModule.default, finalProps)
|
|
1275
|
-
);
|
|
1276
|
-
});
|
|
1277
|
-
}
|
|
1278
|
-
}`;
|
|
1321
|
+
return record;
|
|
1279
1322
|
}
|
|
1280
|
-
function
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
exportModule.__mf_island = {
|
|
1284
|
-
version: 1,
|
|
1285
|
-
async renderToHtml(props) {
|
|
1286
|
-
if (typeof importModule.default !== "function" && typeof importModule.default !== "object") {
|
|
1287
|
-
throw new Error("[Module Federation] A React island expose must have a default component export");
|
|
1288
|
-
}
|
|
1289
|
-
const loadedProps = typeof importModule.load === "function" ? await importModule.load() : {};
|
|
1290
|
-
const finalProps = Object.assign({}, loadedProps || {}, props || {});
|
|
1291
|
-
const [React, ReactDOMServer] = await Promise.all([
|
|
1292
|
-
import("react"),
|
|
1293
|
-
import("react-dom/server")
|
|
1294
|
-
]);
|
|
1295
|
-
const body = ReactDOMServer.renderToString(
|
|
1296
|
-
React.createElement(importModule.default, finalProps)
|
|
1297
|
-
);
|
|
1298
|
-
const state = encodeURIComponent(JSON.stringify(finalProps));
|
|
1299
|
-
return '<div data-mf-island-state="' + state + '">' + body + '</div>';
|
|
1300
|
-
},
|
|
1301
|
-
hydrate() {
|
|
1302
|
-
return Promise.reject(new Error("[Module Federation] hydrate is only available in the browser remote entry"));
|
|
1303
|
-
}
|
|
1304
|
-
}`;
|
|
1323
|
+
function recordTreeShakingExports(sharedKey, exports, request = sharedKey, options) {
|
|
1324
|
+
const record = getOrCreateExportRecord(sharedKey, request, options);
|
|
1325
|
+
exports.forEach((name) => record.usedExports.add(name));
|
|
1305
1326
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
const RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX = `\0${REACT_ISLAND_CLIENT_ID_PREFIX}`;
|
|
1309
|
-
const RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX = `\0${REACT_ISLAND_SERVER_ID_PREFIX}`;
|
|
1310
|
-
function encodeIslandRemoteId(remoteId) {
|
|
1311
|
-
return encodeURIComponent(remoteId);
|
|
1327
|
+
function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey, options) {
|
|
1328
|
+
getOrCreateExportRecord(sharedKey, request, options).requiresFullBundle = true;
|
|
1312
1329
|
}
|
|
1313
|
-
function
|
|
1314
|
-
|
|
1330
|
+
function getExportRecords(sharedKey, request, options) {
|
|
1331
|
+
const inferredUsage = getTreeShakingState(options).inferredUsage;
|
|
1332
|
+
if (sharedKey) {
|
|
1333
|
+
const records = inferredUsage.get(sharedKey);
|
|
1334
|
+
const wildcard = records?.get("*");
|
|
1335
|
+
const exact = records?.get(request);
|
|
1336
|
+
return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
|
|
1337
|
+
}
|
|
1338
|
+
const records = [];
|
|
1339
|
+
inferredUsage.forEach((byRequest, configuredKey) => {
|
|
1340
|
+
const wildcard = byRequest.get("*");
|
|
1341
|
+
const exact = byRequest.get(request);
|
|
1342
|
+
const keyBase = configuredKey.endsWith("/") ? configuredKey.slice(0, -1) : configuredKey;
|
|
1343
|
+
const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
|
|
1344
|
+
if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
|
|
1345
|
+
if (exact && exact !== wildcard) records.push(exact);
|
|
1346
|
+
});
|
|
1347
|
+
return records;
|
|
1315
1348
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1349
|
+
/**
|
|
1350
|
+
* Return the analyzed requirement for one concrete shared request.
|
|
1351
|
+
*
|
|
1352
|
+
* Callers that know the configured share key should pass it explicitly. The
|
|
1353
|
+
* fallback lookup across keys keeps aliases/backwards-compatible callers
|
|
1354
|
+
* working, while still keeping each concrete request's exports isolated.
|
|
1355
|
+
*/
|
|
1356
|
+
function getSharedExportUsage(request, shareItem, sharedKey, options) {
|
|
1357
|
+
const treeShaking = shareItem?.shareConfig.treeShaking;
|
|
1358
|
+
if (!shouldAnalyzeSharedExports(shareItem) || !getTreeShakingState(options).buildMode) return;
|
|
1359
|
+
const records = getExportRecords(sharedKey, request, options);
|
|
1360
|
+
if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
|
|
1361
|
+
const configured = treeShaking?.usedExports ?? [];
|
|
1362
|
+
const result = new Set(configured);
|
|
1363
|
+
records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
|
|
1364
|
+
if (result.size > 0) return {
|
|
1365
|
+
kind: "exports",
|
|
1366
|
+
usedExports: [...result].sort()
|
|
1367
|
+
};
|
|
1368
|
+
return records.length > 0 ? {
|
|
1369
|
+
kind: "exports",
|
|
1370
|
+
usedExports: []
|
|
1371
|
+
} : { kind: "unknown" };
|
|
1372
|
+
}
|
|
1373
|
+
function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
|
|
1374
|
+
if (!shareItem?.shareConfig.treeShaking) return void 0;
|
|
1375
|
+
return getSharedExportUsage(request, shareItem, sharedKey, options);
|
|
1376
|
+
}
|
|
1377
|
+
function getModuleSource(node) {
|
|
1378
|
+
if (!node || typeof node !== "object") return void 0;
|
|
1379
|
+
const source = node;
|
|
1380
|
+
if (source.type === "Literal" && typeof source.value === "string") return source.value;
|
|
1381
|
+
if (source.type === "StringLiteral" && typeof source.value === "string") return source.value;
|
|
1382
|
+
if (source.type !== "TemplateLiteral") return void 0;
|
|
1383
|
+
const expressions = Array.isArray(source.expressions) ? source.expressions : [];
|
|
1384
|
+
const quasis = Array.isArray(source.quasis) ? source.quasis : [];
|
|
1385
|
+
if (expressions.length > 0 || quasis.length !== 1) return void 0;
|
|
1386
|
+
const value = quasis[0]?.value;
|
|
1387
|
+
return typeof value?.cooked === "string" ? value.cooked : typeof value?.raw === "string" ? value.raw : void 0;
|
|
1388
|
+
}
|
|
1389
|
+
function getExportedName(node) {
|
|
1390
|
+
if (!node || typeof node !== "object") return void 0;
|
|
1391
|
+
const exported = node;
|
|
1392
|
+
if (exported.type === "Identifier" && typeof exported.name === "string") return exported.name;
|
|
1393
|
+
if ((exported.type === "Literal" || exported.type === "StringLiteral") && typeof exported.value === "string") return exported.value;
|
|
1394
|
+
}
|
|
1395
|
+
function isTypeOnly(node) {
|
|
1396
|
+
return node.importKind === "type" || node.exportKind === "type";
|
|
1397
|
+
}
|
|
1398
|
+
function forEachAstNode(root, visit) {
|
|
1399
|
+
const stack = [root];
|
|
1400
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1401
|
+
while (stack.length > 0) {
|
|
1402
|
+
const value = stack.pop();
|
|
1403
|
+
if (!value || typeof value !== "object") continue;
|
|
1404
|
+
if (seen.has(value)) continue;
|
|
1405
|
+
seen.add(value);
|
|
1406
|
+
if (Array.isArray(value)) {
|
|
1407
|
+
for (let index = value.length - 1; index >= 0; index--) stack.push(value[index]);
|
|
1408
|
+
continue;
|
|
1409
|
+
}
|
|
1410
|
+
const node = value;
|
|
1411
|
+
if (typeof node.type === "string") visit(node);
|
|
1412
|
+
Object.entries(node).forEach(([key, child]) => {
|
|
1413
|
+
if (key !== "parent" && key !== "loc") stack.push(child);
|
|
1414
|
+
});
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
function collectImportDeclaration(node, source, record, markUnsafe) {
|
|
1418
|
+
if (isTypeOnly(node)) return;
|
|
1419
|
+
const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
|
|
1420
|
+
if (specifiers.length === 0) {
|
|
1421
|
+
markUnsafe(source);
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
const names = [];
|
|
1425
|
+
for (const specifier of specifiers) {
|
|
1426
|
+
if (isTypeOnly(specifier)) continue;
|
|
1427
|
+
if (specifier.type === "ImportNamespaceSpecifier") {
|
|
1428
|
+
markUnsafe(source);
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
if (specifier.type === "ImportDefaultSpecifier") {
|
|
1432
|
+
names.push("default");
|
|
1433
|
+
continue;
|
|
1434
|
+
}
|
|
1435
|
+
if (specifier.type === "ImportSpecifier") {
|
|
1436
|
+
const imported = specifier.imported;
|
|
1437
|
+
if (imported?.type === "Literal" || imported?.type === "StringLiteral") {
|
|
1438
|
+
markUnsafe(source);
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
const name = getExportedName(specifier.imported);
|
|
1442
|
+
if (!name) {
|
|
1443
|
+
markUnsafe(source);
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
names.push(name);
|
|
1447
|
+
continue;
|
|
1448
|
+
}
|
|
1449
|
+
markUnsafe(source);
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
record(names, source);
|
|
1453
|
+
}
|
|
1454
|
+
function collectReExport(node, source, record, markUnsafe) {
|
|
1455
|
+
if (isTypeOnly(node)) return;
|
|
1456
|
+
if (node.type === "ExportAllDeclaration") {
|
|
1457
|
+
markUnsafe(source);
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
|
|
1461
|
+
if (specifiers.length === 0) {
|
|
1462
|
+
markUnsafe(source);
|
|
1463
|
+
return;
|
|
1464
|
+
}
|
|
1465
|
+
const names = [];
|
|
1466
|
+
for (const specifier of specifiers) {
|
|
1467
|
+
if (isTypeOnly(specifier)) continue;
|
|
1468
|
+
if (specifier.type !== "ExportSpecifier") {
|
|
1469
|
+
markUnsafe(source);
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
const local = specifier.local;
|
|
1473
|
+
if (local?.type === "Literal" || local?.type === "StringLiteral") {
|
|
1474
|
+
markUnsafe(source);
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
const name = getExportedName(specifier.local);
|
|
1478
|
+
if (!name) {
|
|
1479
|
+
markUnsafe(source);
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
names.push(name);
|
|
1483
|
+
}
|
|
1484
|
+
record(names, source);
|
|
1485
|
+
}
|
|
1486
|
+
/**
|
|
1487
|
+
* Collect the exports required by a consumer's ESM graph.
|
|
1488
|
+
*
|
|
1489
|
+
* Parsing the module avoids treating import-looking text in comments, strings,
|
|
1490
|
+
* templates, or regular expressions as real dependencies. If parsing fails,
|
|
1491
|
+
* every configured share whose exports are analyzed is conservatively marked
|
|
1492
|
+
* as requiring its full export surface instead of guessing from source text.
|
|
1493
|
+
*
|
|
1494
|
+
* Generated federation wrappers are excluded because their imports describe
|
|
1495
|
+
* the wrapper implementation, not the consumer's requirements.
|
|
1496
|
+
*/
|
|
1497
|
+
async function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe) {
|
|
1498
|
+
const normalizedId = normalizePathForImport(id);
|
|
1499
|
+
if (normalizedId.includes("__prebuild__") || normalizedId.includes("__loadShare__") || normalizedId.includes("__mf_tree_shaking_graph__")) return;
|
|
1500
|
+
let ast;
|
|
1501
|
+
try {
|
|
1502
|
+
ast = parseAst(code);
|
|
1503
|
+
} catch {
|
|
1504
|
+
Object.entries(shared).forEach(([sharedKey, shareItem]) => {
|
|
1505
|
+
if (shouldAnalyzeSharedExports(shareItem)) markUnsafe(sharedKey, "*");
|
|
1506
|
+
});
|
|
1507
|
+
return;
|
|
1508
|
+
}
|
|
1509
|
+
const pending = [];
|
|
1510
|
+
const withSharedSource = (source, use) => {
|
|
1511
|
+
const apply = (key) => {
|
|
1512
|
+
if (key && shouldAnalyzeSharedExports(shared[key])) use(key);
|
|
1513
|
+
};
|
|
1514
|
+
const key = findSharedKey(source, shared);
|
|
1515
|
+
if (key instanceof Promise) pending.push(key.then(apply));
|
|
1516
|
+
else apply(key);
|
|
1517
|
+
};
|
|
1518
|
+
const recordSource = (names, source) => {
|
|
1519
|
+
withSharedSource(source, (key) => record(key, names, source));
|
|
1520
|
+
};
|
|
1521
|
+
const markSourceUnsafe = (source) => {
|
|
1522
|
+
withSharedSource(source, (key) => markUnsafe(key, source));
|
|
1523
|
+
};
|
|
1524
|
+
forEachAstNode(ast, (node) => {
|
|
1525
|
+
if (node.type === "ImportDeclaration") {
|
|
1526
|
+
const source = getModuleSource(node.source);
|
|
1527
|
+
if (source) collectImportDeclaration(node, source, recordSource, markSourceUnsafe);
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
|
|
1531
|
+
const source = getModuleSource(node.source);
|
|
1532
|
+
if (source) collectReExport(node, source, recordSource, markSourceUnsafe);
|
|
1533
|
+
return;
|
|
1534
|
+
}
|
|
1535
|
+
if (node.type === "ImportExpression") {
|
|
1536
|
+
const source = getModuleSource(node.source);
|
|
1537
|
+
if (source) markSourceUnsafe(source);
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1540
|
+
if (node.type === "CallExpression") {
|
|
1541
|
+
const callee = node.callee;
|
|
1542
|
+
const args = Array.isArray(node.arguments) ? node.arguments : [];
|
|
1543
|
+
if (callee?.type === "Identifier" && callee.name === "require" && args.length > 0) {
|
|
1544
|
+
const source = getModuleSource(args[0]);
|
|
1545
|
+
if (source) markSourceUnsafe(source);
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
});
|
|
1549
|
+
await Promise.all(pending);
|
|
1550
|
+
}
|
|
1551
|
+
//#endregion
|
|
1552
|
+
//#region src/utils/reactIsland.ts
|
|
1553
|
+
const SOURCE_EXTENSIONS$1 = [
|
|
1554
|
+
".tsx",
|
|
1555
|
+
".jsx",
|
|
1556
|
+
".ts",
|
|
1557
|
+
".js",
|
|
1558
|
+
".mts",
|
|
1559
|
+
".mjs",
|
|
1560
|
+
".cts",
|
|
1561
|
+
".cjs"
|
|
1562
|
+
];
|
|
1563
|
+
function resolveSourceFile(importPath, root) {
|
|
1564
|
+
const cleanImport = stripQueryAndHash(importPath);
|
|
1565
|
+
if (!cleanImport.startsWith(".") && !path$1.isAbsolute(cleanImport)) return;
|
|
1566
|
+
const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
|
|
1567
|
+
return [
|
|
1568
|
+
candidate,
|
|
1569
|
+
...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
|
|
1570
|
+
...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
|
|
1571
|
+
].find((filePath) => {
|
|
1572
|
+
try {
|
|
1573
|
+
return fs$1.statSync(filePath).isFile();
|
|
1574
|
+
} catch {
|
|
1575
|
+
return false;
|
|
1576
|
+
}
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
function localDefaultReexport(source) {
|
|
1580
|
+
const match = source.match(/export\s*{\s*(?:default(?:\s+as\s+default)?|[A-Za-z_$][\w$]*\s+as\s+default)\s*}\s*from\s*["']([^"']+)["']/);
|
|
1581
|
+
return match?.[1]?.startsWith(".") ? match[1] : void 0;
|
|
1582
|
+
}
|
|
1583
|
+
function isReactComponentSource(source, filePath = "component.tsx") {
|
|
1584
|
+
if (!(/\bexport\s+default\b/.test(source) || /\bexport\s*{[^}]*\bdefault\b[^}]*}(?:\s*from\s*["'][^"']+["'])?/.test(source))) return false;
|
|
1585
|
+
const extension = path$1.extname(stripQueryAndHash(filePath)).toLowerCase();
|
|
1586
|
+
const canContainJsx = extension === ".tsx" || extension === ".jsx";
|
|
1587
|
+
const hasJsx = /<>|<\s*[A-Za-z][\w.:-]*(?:\s[^<>]*?)?\s*\/?>/.test(source);
|
|
1588
|
+
const importsReact = /\bfrom\s*["']react["']|\brequire\(\s*["']react["']\s*\)/.test(source);
|
|
1589
|
+
const usesReactApi = /\b(?:React\.)?(?:createElement|jsx|jsxs)\s*\(/.test(source);
|
|
1590
|
+
const isClientModule = /^\s*["']use client["']\s*;?/m.test(source);
|
|
1591
|
+
return canContainJsx && hasJsx || importsReact && (hasJsx || usesReactApi || isClientModule);
|
|
1592
|
+
}
|
|
1593
|
+
function isReactComponentFile(filePath, seen = /* @__PURE__ */ new Set()) {
|
|
1594
|
+
const normalizedPath = path$1.resolve(filePath);
|
|
1595
|
+
if (seen.has(normalizedPath)) return false;
|
|
1596
|
+
seen.add(normalizedPath);
|
|
1597
|
+
let source;
|
|
1598
|
+
try {
|
|
1599
|
+
source = fs$1.readFileSync(normalizedPath, "utf8");
|
|
1600
|
+
} catch {
|
|
1601
|
+
return false;
|
|
1602
|
+
}
|
|
1603
|
+
if (isReactComponentSource(source, normalizedPath)) return true;
|
|
1604
|
+
const reexport = localDefaultReexport(source);
|
|
1605
|
+
if (!reexport) return false;
|
|
1606
|
+
const reexportPath = resolveSourceFile(reexport, path$1.dirname(normalizedPath));
|
|
1607
|
+
return reexportPath ? isReactComponentFile(reexportPath, seen) : false;
|
|
1608
|
+
}
|
|
1609
|
+
/**
|
|
1610
|
+
* React is shared by the normal MF runtime when explicitly configured. When it
|
|
1611
|
+
* is local, UI exposes can safely advertise an island capability in addition
|
|
1612
|
+
* to their unchanged default export.
|
|
1613
|
+
*/
|
|
1614
|
+
function getReactIslandExposes(options, root) {
|
|
1615
|
+
if (options.experiments.ssrMode !== "ISLAND") return /* @__PURE__ */ new Set();
|
|
1616
|
+
if (Object.hasOwn(options.shared, "react")) return /* @__PURE__ */ new Set();
|
|
1617
|
+
const islandExposes = /* @__PURE__ */ new Set();
|
|
1618
|
+
for (const [key, expose] of Object.entries(options.exposes)) {
|
|
1619
|
+
const sourceFile = resolveSourceFile(expose.import, root);
|
|
1620
|
+
if (sourceFile && isReactComponentFile(sourceFile)) islandExposes.add(key);
|
|
1621
|
+
}
|
|
1622
|
+
return islandExposes;
|
|
1623
|
+
}
|
|
1624
|
+
function generateReactIslandBrowserDefinition(enabled) {
|
|
1625
|
+
if (!enabled) return "";
|
|
1626
|
+
return `
|
|
1627
|
+
exportModule.__mf_island = {
|
|
1628
|
+
version: 1,
|
|
1629
|
+
renderToHtml() {
|
|
1630
|
+
return Promise.reject(new Error("[Module Federation] renderToHtml is only available in the SSR remote entry"));
|
|
1631
|
+
},
|
|
1632
|
+
hydrate(element, props) {
|
|
1633
|
+
const root = element && element.hasAttribute && element.hasAttribute("data-mf-island-state")
|
|
1634
|
+
? element
|
|
1635
|
+
: element && element.querySelector
|
|
1636
|
+
? element.querySelector("[data-mf-island-state]") || element
|
|
1637
|
+
: element;
|
|
1638
|
+
if (!root) {
|
|
1639
|
+
return Promise.reject(new Error("[Module Federation] Cannot hydrate an island without a root element"));
|
|
1640
|
+
}
|
|
1641
|
+
let serverProps = {};
|
|
1642
|
+
const encodedState = root.getAttribute && root.getAttribute("data-mf-island-state");
|
|
1643
|
+
if (encodedState) {
|
|
1644
|
+
try {
|
|
1645
|
+
serverProps = JSON.parse(decodeURIComponent(encodedState));
|
|
1646
|
+
} catch {
|
|
1647
|
+
serverProps = {};
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
const finalProps = Object.assign({}, serverProps, props || {});
|
|
1651
|
+
return Promise.all([import("react"), import("react-dom/client")]).then(([React, ReactDOMClient]) => {
|
|
1652
|
+
if (typeof ReactDOMClient.hydrateRoot !== "function") {
|
|
1653
|
+
throw new Error("[Module Federation] react-dom/client does not provide hydrateRoot");
|
|
1654
|
+
}
|
|
1655
|
+
return ReactDOMClient.hydrateRoot(
|
|
1656
|
+
root,
|
|
1657
|
+
React.createElement(importModule.default, finalProps)
|
|
1658
|
+
);
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1661
|
+
}`;
|
|
1662
|
+
}
|
|
1663
|
+
function generateReactIslandSSRDefinition(enabled) {
|
|
1664
|
+
if (!enabled) return "";
|
|
1665
|
+
return `
|
|
1666
|
+
exportModule.__mf_island = {
|
|
1667
|
+
version: 1,
|
|
1668
|
+
async renderToHtml(props) {
|
|
1669
|
+
if (typeof importModule.default !== "function" && typeof importModule.default !== "object") {
|
|
1670
|
+
throw new Error("[Module Federation] A React island expose must have a default component export");
|
|
1671
|
+
}
|
|
1672
|
+
const loadedProps = typeof importModule.load === "function" ? await importModule.load() : {};
|
|
1673
|
+
const finalProps = Object.assign({}, loadedProps || {}, props || {});
|
|
1674
|
+
const [React, ReactDOMServer] = await Promise.all([
|
|
1675
|
+
import("react"),
|
|
1676
|
+
import("react-dom/server")
|
|
1677
|
+
]);
|
|
1678
|
+
const body = ReactDOMServer.renderToString(
|
|
1679
|
+
React.createElement(importModule.default, finalProps)
|
|
1680
|
+
);
|
|
1681
|
+
const state = encodeURIComponent(JSON.stringify(finalProps));
|
|
1682
|
+
return '<div data-mf-island-state="' + state + '">' + body + '</div>';
|
|
1683
|
+
},
|
|
1684
|
+
hydrate() {
|
|
1685
|
+
return Promise.reject(new Error("[Module Federation] hydrate is only available in the browser remote entry"));
|
|
1686
|
+
}
|
|
1687
|
+
}`;
|
|
1688
|
+
}
|
|
1689
|
+
const REACT_ISLAND_CLIENT_ID_PREFIX = "virtual:mf-react-island-client:";
|
|
1690
|
+
const REACT_ISLAND_SERVER_ID_PREFIX = "virtual:mf-react-island-server:";
|
|
1691
|
+
const RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX = `\0${REACT_ISLAND_CLIENT_ID_PREFIX}`;
|
|
1692
|
+
const RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX = `\0${REACT_ISLAND_SERVER_ID_PREFIX}`;
|
|
1693
|
+
function encodeIslandRemoteId(remoteId) {
|
|
1694
|
+
return encodeURIComponent(remoteId);
|
|
1695
|
+
}
|
|
1696
|
+
function decodeIslandRemoteId(encodedRemoteId) {
|
|
1697
|
+
return decodeURIComponent(encodedRemoteId);
|
|
1698
|
+
}
|
|
1699
|
+
function getReactIslandImportRemoteId(source) {
|
|
1700
|
+
const queryIndex = source.indexOf("?");
|
|
1701
|
+
if (queryIndex === -1) return;
|
|
1702
|
+
if (!new URLSearchParams(source.slice(queryIndex + 1)).has("mf-island")) return;
|
|
1703
|
+
return source.slice(0, queryIndex);
|
|
1321
1704
|
}
|
|
1322
1705
|
function getReactIslandServerImportId(remoteId) {
|
|
1323
1706
|
return `${REACT_ISLAND_SERVER_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
|
|
@@ -1741,328 +2124,59 @@ for (const __mfShareKey of Object.keys(__mfModuleCache.share)) {
|
|
|
1741
2124
|
}
|
|
1742
2125
|
}
|
|
1743
2126
|
}
|
|
1744
|
-
`;
|
|
1745
|
-
}
|
|
1746
|
-
function getRuntimeInitPromiseBootstrapCode(enableSsrInit = false, ownerImportId, ssrRemotes, hostInitImportId = ownerImportId) {
|
|
1747
|
-
return getRuntimeInitStateBootstrapCode({
|
|
1748
|
-
globalKeyVar: "__mfPromiseGlobalKey",
|
|
1749
|
-
stateVar: "__mfPromiseState",
|
|
1750
|
-
exposedConst: "initPromise",
|
|
1751
|
-
exposedProperty: "initPromise",
|
|
1752
|
-
enableSsrInit,
|
|
1753
|
-
ownerImportId,
|
|
1754
|
-
hostInitImportId,
|
|
1755
|
-
ssrRemotes
|
|
1756
|
-
});
|
|
1757
|
-
}
|
|
1758
|
-
function getRuntimeInitResolveBootstrapCode(enableSsrInit = false, ownerImportId, ssrRemotes, hostInitImportId = ownerImportId) {
|
|
1759
|
-
return getRuntimeInitStateBootstrapCode({
|
|
1760
|
-
globalKeyVar: "__mfResolveGlobalKey",
|
|
1761
|
-
stateVar: "__mfResolveState",
|
|
1762
|
-
exposedConst: "initResolve",
|
|
1763
|
-
exposedProperty: "initResolve",
|
|
1764
|
-
enableSsrInit,
|
|
1765
|
-
ownerImportId,
|
|
1766
|
-
hostInitImportId,
|
|
1767
|
-
ssrRemotes
|
|
1768
|
-
});
|
|
1769
|
-
}
|
|
1770
|
-
function writeRuntimeInitStatus(command, enableSsrInit = false, hostInitImportId, options, ssrRemotes = _ssrRemotes) {
|
|
1771
|
-
const exportStatement = command === "build" ? `const { initPromise, initResolve, initReject, moduleCache } = globalThis[globalKey];
|
|
1772
|
-
export { initPromise, initResolve, initReject, moduleCache };` : `module.exports = globalThis[globalKey];`;
|
|
1773
|
-
const ownerImportId = options ? getRuntimeInitStatusImportId(options) : hostInitImportId;
|
|
1774
|
-
getRuntimeInitModule(options).writeSync(`
|
|
1775
|
-
${getRuntimeInitBootstrapCode(enableSsrInit, ownerImportId, ssrRemotes, hostInitImportId)}
|
|
1776
|
-
${exportStatement}
|
|
1777
|
-
`);
|
|
1778
|
-
}
|
|
1779
|
-
//#endregion
|
|
1780
|
-
//#region src/plugins/pluginReactMixedModeGuard.ts
|
|
1781
|
-
function createReactMixedModeRuntimeGuard() {
|
|
1782
|
-
return `const __mfReactInternals = mod["__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE"];
|
|
1783
|
-
if (__mfReactInternals && "A" in __mfReactInternals) {
|
|
1784
|
-
let __mfReactDispatcher = __mfReactInternals.A;
|
|
1785
|
-
Object.defineProperty(__mfReactInternals, "A", {
|
|
1786
|
-
configurable: true,
|
|
1787
|
-
enumerable: true,
|
|
1788
|
-
get: () => __mfReactDispatcher,
|
|
1789
|
-
set: (next) => {
|
|
1790
|
-
if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
|
|
1791
|
-
__mfReactDispatcher = next;
|
|
1792
|
-
},
|
|
1793
|
-
});
|
|
1794
|
-
__mfReactInternals.A = __mfReactDispatcher;
|
|
1795
|
-
}`;
|
|
1796
|
-
}
|
|
1797
|
-
//#endregion
|
|
1798
|
-
//#region src/utils/treeShaking.ts
|
|
1799
|
-
function shouldAnalyzeSharedExports(shareItem) {
|
|
1800
|
-
return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
|
|
1801
|
-
}
|
|
1802
|
-
const legacyTreeShakingState = {
|
|
1803
|
-
inferredUsage: /* @__PURE__ */ new Map(),
|
|
1804
|
-
buildMode: false
|
|
1805
|
-
};
|
|
1806
|
-
const treeShakingStates = /* @__PURE__ */ new WeakMap();
|
|
1807
|
-
function getTreeShakingState(options) {
|
|
1808
|
-
if (!options) return legacyTreeShakingState;
|
|
1809
|
-
let state = treeShakingStates.get(options);
|
|
1810
|
-
if (!state) {
|
|
1811
|
-
state = {
|
|
1812
|
-
inferredUsage: /* @__PURE__ */ new Map(),
|
|
1813
|
-
buildMode: false
|
|
1814
|
-
};
|
|
1815
|
-
treeShakingStates.set(options, state);
|
|
1816
|
-
}
|
|
1817
|
-
return state;
|
|
1818
|
-
}
|
|
1819
|
-
function setTreeShakingBuildMode(enabled, options) {
|
|
1820
|
-
getTreeShakingState(options).buildMode = enabled;
|
|
1821
|
-
}
|
|
1822
|
-
function resetTreeShakingExports(options) {
|
|
1823
|
-
getTreeShakingState(options).inferredUsage.clear();
|
|
1824
|
-
}
|
|
1825
|
-
function getOrCreateExportRecord(sharedKey, request, options) {
|
|
1826
|
-
const inferredUsage = getTreeShakingState(options).inferredUsage;
|
|
1827
|
-
let byRequest = inferredUsage.get(sharedKey);
|
|
1828
|
-
if (!byRequest) {
|
|
1829
|
-
byRequest = /* @__PURE__ */ new Map();
|
|
1830
|
-
inferredUsage.set(sharedKey, byRequest);
|
|
1831
|
-
}
|
|
1832
|
-
let record = byRequest.get(request);
|
|
1833
|
-
if (!record) {
|
|
1834
|
-
record = {
|
|
1835
|
-
requiresFullBundle: false,
|
|
1836
|
-
usedExports: /* @__PURE__ */ new Set()
|
|
1837
|
-
};
|
|
1838
|
-
byRequest.set(request, record);
|
|
1839
|
-
}
|
|
1840
|
-
return record;
|
|
1841
|
-
}
|
|
1842
|
-
function recordTreeShakingExports(sharedKey, exports, request = sharedKey, options) {
|
|
1843
|
-
const record = getOrCreateExportRecord(sharedKey, request, options);
|
|
1844
|
-
exports.forEach((name) => record.usedExports.add(name));
|
|
1845
|
-
}
|
|
1846
|
-
function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey, options) {
|
|
1847
|
-
getOrCreateExportRecord(sharedKey, request, options).requiresFullBundle = true;
|
|
1848
|
-
}
|
|
1849
|
-
function getExportRecords(sharedKey, request, options) {
|
|
1850
|
-
const inferredUsage = getTreeShakingState(options).inferredUsage;
|
|
1851
|
-
if (sharedKey) {
|
|
1852
|
-
const records = inferredUsage.get(sharedKey);
|
|
1853
|
-
const wildcard = records?.get("*");
|
|
1854
|
-
const exact = records?.get(request);
|
|
1855
|
-
return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
|
|
1856
|
-
}
|
|
1857
|
-
const records = [];
|
|
1858
|
-
inferredUsage.forEach((byRequest, configuredKey) => {
|
|
1859
|
-
const wildcard = byRequest.get("*");
|
|
1860
|
-
const exact = byRequest.get(request);
|
|
1861
|
-
const keyBase = configuredKey.endsWith("/") ? configuredKey.slice(0, -1) : configuredKey;
|
|
1862
|
-
const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
|
|
1863
|
-
if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
|
|
1864
|
-
if (exact && exact !== wildcard) records.push(exact);
|
|
1865
|
-
});
|
|
1866
|
-
return records;
|
|
1867
|
-
}
|
|
1868
|
-
/**
|
|
1869
|
-
* Return the analyzed requirement for one concrete shared request.
|
|
1870
|
-
*
|
|
1871
|
-
* Callers that know the configured share key should pass it explicitly. The
|
|
1872
|
-
* fallback lookup across keys keeps aliases/backwards-compatible callers
|
|
1873
|
-
* working, while still keeping each concrete request's exports isolated.
|
|
1874
|
-
*/
|
|
1875
|
-
function getSharedExportUsage(request, shareItem, sharedKey, options) {
|
|
1876
|
-
const treeShaking = shareItem?.shareConfig.treeShaking;
|
|
1877
|
-
if (!shouldAnalyzeSharedExports(shareItem) || !getTreeShakingState(options).buildMode) return;
|
|
1878
|
-
const records = getExportRecords(sharedKey, request, options);
|
|
1879
|
-
if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
|
|
1880
|
-
const configured = treeShaking?.usedExports ?? [];
|
|
1881
|
-
const result = new Set(configured);
|
|
1882
|
-
records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
|
|
1883
|
-
if (result.size > 0) return {
|
|
1884
|
-
kind: "exports",
|
|
1885
|
-
usedExports: [...result].sort()
|
|
1886
|
-
};
|
|
1887
|
-
return records.length > 0 ? {
|
|
1888
|
-
kind: "exports",
|
|
1889
|
-
usedExports: []
|
|
1890
|
-
} : { kind: "unknown" };
|
|
1891
|
-
}
|
|
1892
|
-
function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
|
|
1893
|
-
if (!shareItem?.shareConfig.treeShaking) return void 0;
|
|
1894
|
-
return getSharedExportUsage(request, shareItem, sharedKey, options);
|
|
1895
|
-
}
|
|
1896
|
-
function getModuleSource(node) {
|
|
1897
|
-
if (!node || typeof node !== "object") return void 0;
|
|
1898
|
-
const source = node;
|
|
1899
|
-
if (source.type === "Literal" && typeof source.value === "string") return source.value;
|
|
1900
|
-
if (source.type === "StringLiteral" && typeof source.value === "string") return source.value;
|
|
1901
|
-
if (source.type !== "TemplateLiteral") return void 0;
|
|
1902
|
-
const expressions = Array.isArray(source.expressions) ? source.expressions : [];
|
|
1903
|
-
const quasis = Array.isArray(source.quasis) ? source.quasis : [];
|
|
1904
|
-
if (expressions.length > 0 || quasis.length !== 1) return void 0;
|
|
1905
|
-
const value = quasis[0]?.value;
|
|
1906
|
-
return typeof value?.cooked === "string" ? value.cooked : typeof value?.raw === "string" ? value.raw : void 0;
|
|
1907
|
-
}
|
|
1908
|
-
function getExportedName(node) {
|
|
1909
|
-
if (!node || typeof node !== "object") return void 0;
|
|
1910
|
-
const exported = node;
|
|
1911
|
-
if (exported.type === "Identifier" && typeof exported.name === "string") return exported.name;
|
|
1912
|
-
if ((exported.type === "Literal" || exported.type === "StringLiteral") && typeof exported.value === "string") return exported.value;
|
|
1913
|
-
}
|
|
1914
|
-
function isTypeOnly(node) {
|
|
1915
|
-
return node.importKind === "type" || node.exportKind === "type";
|
|
1916
|
-
}
|
|
1917
|
-
function forEachAstNode(root, visit) {
|
|
1918
|
-
const stack = [root];
|
|
1919
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1920
|
-
while (stack.length > 0) {
|
|
1921
|
-
const value = stack.pop();
|
|
1922
|
-
if (!value || typeof value !== "object") continue;
|
|
1923
|
-
if (seen.has(value)) continue;
|
|
1924
|
-
seen.add(value);
|
|
1925
|
-
if (Array.isArray(value)) {
|
|
1926
|
-
for (let index = value.length - 1; index >= 0; index--) stack.push(value[index]);
|
|
1927
|
-
continue;
|
|
1928
|
-
}
|
|
1929
|
-
const node = value;
|
|
1930
|
-
if (typeof node.type === "string") visit(node);
|
|
1931
|
-
Object.entries(node).forEach(([key, child]) => {
|
|
1932
|
-
if (key !== "parent" && key !== "loc") stack.push(child);
|
|
1933
|
-
});
|
|
1934
|
-
}
|
|
1935
|
-
}
|
|
1936
|
-
function collectImportDeclaration(node, source, record, markUnsafe) {
|
|
1937
|
-
if (isTypeOnly(node)) return;
|
|
1938
|
-
const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
|
|
1939
|
-
if (specifiers.length === 0) {
|
|
1940
|
-
markUnsafe(source);
|
|
1941
|
-
return;
|
|
1942
|
-
}
|
|
1943
|
-
const names = [];
|
|
1944
|
-
for (const specifier of specifiers) {
|
|
1945
|
-
if (isTypeOnly(specifier)) continue;
|
|
1946
|
-
if (specifier.type === "ImportNamespaceSpecifier") {
|
|
1947
|
-
markUnsafe(source);
|
|
1948
|
-
return;
|
|
1949
|
-
}
|
|
1950
|
-
if (specifier.type === "ImportDefaultSpecifier") {
|
|
1951
|
-
names.push("default");
|
|
1952
|
-
continue;
|
|
1953
|
-
}
|
|
1954
|
-
if (specifier.type === "ImportSpecifier") {
|
|
1955
|
-
const imported = specifier.imported;
|
|
1956
|
-
if (imported?.type === "Literal" || imported?.type === "StringLiteral") {
|
|
1957
|
-
markUnsafe(source);
|
|
1958
|
-
return;
|
|
1959
|
-
}
|
|
1960
|
-
const name = getExportedName(specifier.imported);
|
|
1961
|
-
if (!name) {
|
|
1962
|
-
markUnsafe(source);
|
|
1963
|
-
return;
|
|
1964
|
-
}
|
|
1965
|
-
names.push(name);
|
|
1966
|
-
continue;
|
|
1967
|
-
}
|
|
1968
|
-
markUnsafe(source);
|
|
1969
|
-
return;
|
|
1970
|
-
}
|
|
1971
|
-
record(names, source);
|
|
1972
|
-
}
|
|
1973
|
-
function collectReExport(node, source, record, markUnsafe) {
|
|
1974
|
-
if (isTypeOnly(node)) return;
|
|
1975
|
-
if (node.type === "ExportAllDeclaration") {
|
|
1976
|
-
markUnsafe(source);
|
|
1977
|
-
return;
|
|
1978
|
-
}
|
|
1979
|
-
const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
|
|
1980
|
-
if (specifiers.length === 0) {
|
|
1981
|
-
markUnsafe(source);
|
|
1982
|
-
return;
|
|
1983
|
-
}
|
|
1984
|
-
const names = [];
|
|
1985
|
-
for (const specifier of specifiers) {
|
|
1986
|
-
if (isTypeOnly(specifier)) continue;
|
|
1987
|
-
if (specifier.type !== "ExportSpecifier") {
|
|
1988
|
-
markUnsafe(source);
|
|
1989
|
-
return;
|
|
1990
|
-
}
|
|
1991
|
-
const local = specifier.local;
|
|
1992
|
-
if (local?.type === "Literal" || local?.type === "StringLiteral") {
|
|
1993
|
-
markUnsafe(source);
|
|
1994
|
-
return;
|
|
1995
|
-
}
|
|
1996
|
-
const name = getExportedName(specifier.local);
|
|
1997
|
-
if (!name) {
|
|
1998
|
-
markUnsafe(source);
|
|
1999
|
-
return;
|
|
2000
|
-
}
|
|
2001
|
-
names.push(name);
|
|
2002
|
-
}
|
|
2003
|
-
record(names, source);
|
|
2127
|
+
`;
|
|
2004
2128
|
}
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
}
|
|
2028
|
-
const matchShared = (source) => {
|
|
2029
|
-
const sharedKey = findSharedKey(source, shared);
|
|
2030
|
-
return sharedKey && shouldAnalyzeSharedExports(shared[sharedKey]) ? sharedKey : void 0;
|
|
2031
|
-
};
|
|
2032
|
-
const recordSource = (names, source) => {
|
|
2033
|
-
const sharedKey = matchShared(source);
|
|
2034
|
-
if (sharedKey) record(sharedKey, names, source);
|
|
2035
|
-
};
|
|
2036
|
-
const markSourceUnsafe = (source) => {
|
|
2037
|
-
const sharedKey = matchShared(source);
|
|
2038
|
-
if (sharedKey) markUnsafe(sharedKey, source);
|
|
2039
|
-
};
|
|
2040
|
-
forEachAstNode(ast, (node) => {
|
|
2041
|
-
if (node.type === "ImportDeclaration") {
|
|
2042
|
-
const source = getModuleSource(node.source);
|
|
2043
|
-
if (source) collectImportDeclaration(node, source, recordSource, markSourceUnsafe);
|
|
2044
|
-
return;
|
|
2045
|
-
}
|
|
2046
|
-
if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
|
|
2047
|
-
const source = getModuleSource(node.source);
|
|
2048
|
-
if (source) collectReExport(node, source, recordSource, markSourceUnsafe);
|
|
2049
|
-
return;
|
|
2050
|
-
}
|
|
2051
|
-
if (node.type === "ImportExpression") {
|
|
2052
|
-
const source = getModuleSource(node.source);
|
|
2053
|
-
if (source) markSourceUnsafe(source);
|
|
2054
|
-
return;
|
|
2055
|
-
}
|
|
2056
|
-
if (node.type === "CallExpression") {
|
|
2057
|
-
const callee = node.callee;
|
|
2058
|
-
const args = Array.isArray(node.arguments) ? node.arguments : [];
|
|
2059
|
-
if (callee?.type === "Identifier" && callee.name === "require" && args.length > 0) {
|
|
2060
|
-
const source = getModuleSource(args[0]);
|
|
2061
|
-
if (source) markSourceUnsafe(source);
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2129
|
+
function getRuntimeInitPromiseBootstrapCode(enableSsrInit = false, ownerImportId, ssrRemotes, hostInitImportId = ownerImportId) {
|
|
2130
|
+
return getRuntimeInitStateBootstrapCode({
|
|
2131
|
+
globalKeyVar: "__mfPromiseGlobalKey",
|
|
2132
|
+
stateVar: "__mfPromiseState",
|
|
2133
|
+
exposedConst: "initPromise",
|
|
2134
|
+
exposedProperty: "initPromise",
|
|
2135
|
+
enableSsrInit,
|
|
2136
|
+
ownerImportId,
|
|
2137
|
+
hostInitImportId,
|
|
2138
|
+
ssrRemotes
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
function getRuntimeInitResolveBootstrapCode(enableSsrInit = false, ownerImportId, ssrRemotes, hostInitImportId = ownerImportId) {
|
|
2142
|
+
return getRuntimeInitStateBootstrapCode({
|
|
2143
|
+
globalKeyVar: "__mfResolveGlobalKey",
|
|
2144
|
+
stateVar: "__mfResolveState",
|
|
2145
|
+
exposedConst: "initResolve",
|
|
2146
|
+
exposedProperty: "initResolve",
|
|
2147
|
+
enableSsrInit,
|
|
2148
|
+
ownerImportId,
|
|
2149
|
+
hostInitImportId,
|
|
2150
|
+
ssrRemotes
|
|
2064
2151
|
});
|
|
2065
2152
|
}
|
|
2153
|
+
function writeRuntimeInitStatus(command, enableSsrInit = false, hostInitImportId, options, ssrRemotes = _ssrRemotes) {
|
|
2154
|
+
const exportStatement = command === "build" ? `const { initPromise, initResolve, initReject, moduleCache } = globalThis[globalKey];
|
|
2155
|
+
export { initPromise, initResolve, initReject, moduleCache };` : `module.exports = globalThis[globalKey];`;
|
|
2156
|
+
const ownerImportId = options ? getRuntimeInitStatusImportId(options) : hostInitImportId;
|
|
2157
|
+
getRuntimeInitModule(options).writeSync(`
|
|
2158
|
+
${getRuntimeInitBootstrapCode(enableSsrInit, ownerImportId, ssrRemotes, hostInitImportId)}
|
|
2159
|
+
${exportStatement}
|
|
2160
|
+
`);
|
|
2161
|
+
}
|
|
2162
|
+
//#endregion
|
|
2163
|
+
//#region src/plugins/pluginReactMixedModeGuard.ts
|
|
2164
|
+
function createReactMixedModeRuntimeGuard() {
|
|
2165
|
+
return `const __mfReactInternals = mod["__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE"];
|
|
2166
|
+
if (__mfReactInternals && "A" in __mfReactInternals) {
|
|
2167
|
+
let __mfReactDispatcher = __mfReactInternals.A;
|
|
2168
|
+
Object.defineProperty(__mfReactInternals, "A", {
|
|
2169
|
+
configurable: true,
|
|
2170
|
+
enumerable: true,
|
|
2171
|
+
get: () => __mfReactDispatcher,
|
|
2172
|
+
set: (next) => {
|
|
2173
|
+
if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
|
|
2174
|
+
__mfReactDispatcher = next;
|
|
2175
|
+
},
|
|
2176
|
+
});
|
|
2177
|
+
__mfReactInternals.A = __mfReactDispatcher;
|
|
2178
|
+
}`;
|
|
2179
|
+
}
|
|
2066
2180
|
//#endregion
|
|
2067
2181
|
//#region src/utils/typeArgumentScanner.ts
|
|
2068
2182
|
function getTypeArgumentStartContext(source, start) {
|
|
@@ -2191,8 +2305,12 @@ function getPackageEsmEntryPath(pkg) {
|
|
|
2191
2305
|
}
|
|
2192
2306
|
const packageNamedExportsCache = /* @__PURE__ */ new Map();
|
|
2193
2307
|
const sharedExportInspectionCache = /* @__PURE__ */ new Map();
|
|
2308
|
+
const sharedMutableExportsCache = /* @__PURE__ */ new Map();
|
|
2194
2309
|
function invalidateSharedExportInspectionCache(filePath) {
|
|
2195
|
-
if (!/(?:^|[/\\])node_modules(?:[/\\]|$)/.test(filePath))
|
|
2310
|
+
if (!/(?:^|[/\\])node_modules(?:[/\\]|$)/.test(filePath)) {
|
|
2311
|
+
sharedExportInspectionCache.clear();
|
|
2312
|
+
sharedMutableExportsCache.clear();
|
|
2313
|
+
}
|
|
2196
2314
|
}
|
|
2197
2315
|
const DEFAULT_SHARED_EXPORT_CONDITIONS = [
|
|
2198
2316
|
"browser",
|
|
@@ -2200,6 +2318,18 @@ const DEFAULT_SHARED_EXPORT_CONDITIONS = [
|
|
|
2200
2318
|
"module",
|
|
2201
2319
|
"default"
|
|
2202
2320
|
];
|
|
2321
|
+
function getSharedExportSource(source) {
|
|
2322
|
+
const parts = [];
|
|
2323
|
+
let offset = 0;
|
|
2324
|
+
const codePositions = createCodePositionMap(source, (start, end) => {
|
|
2325
|
+
parts.push(source.slice(offset, start), source.slice(start, end).replace(/[^\r\n\u2028\u2029]/g, " "));
|
|
2326
|
+
offset = end;
|
|
2327
|
+
});
|
|
2328
|
+
return {
|
|
2329
|
+
source: parts.length ? parts.join("") + source.slice(offset) : source,
|
|
2330
|
+
codePositions
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2203
2333
|
function hasCodeMatch(source, regex, codePositions) {
|
|
2204
2334
|
regex.lastIndex = 0;
|
|
2205
2335
|
let match;
|
|
@@ -2244,8 +2374,7 @@ function getMutableExportsFromFile(entryPath, exportConditions = DEFAULT_SHARED_
|
|
|
2244
2374
|
if (!entryPath || visited.has(entryPath)) return [];
|
|
2245
2375
|
visited.add(entryPath);
|
|
2246
2376
|
try {
|
|
2247
|
-
const source = readFileSync(entryPath, "utf-8");
|
|
2248
|
-
const codePositions = createCodePositionMap(source);
|
|
2377
|
+
const { source, codePositions } = getSharedExportSource(readFileSync(entryPath, "utf-8"));
|
|
2249
2378
|
const mutableBindings = /* @__PURE__ */ new Set();
|
|
2250
2379
|
const mutableExports = /* @__PURE__ */ new Set();
|
|
2251
2380
|
let match;
|
|
@@ -2278,7 +2407,7 @@ function getMutableExportsFromFile(entryPath, exportConditions = DEFAULT_SHARED_
|
|
|
2278
2407
|
if (isValidEsmExportName(exported) && (mutableBindings.has(local) || reExportedMutable.has(local))) mutableExports.add(exported);
|
|
2279
2408
|
}
|
|
2280
2409
|
}
|
|
2281
|
-
const starExportRegex = /export\s
|
|
2410
|
+
const starExportRegex = /export\s*\*\s*from\s*['"]([^'"]+)['"]/g;
|
|
2282
2411
|
while ((match = starExportRegex.exec(source)) !== null) {
|
|
2283
2412
|
if (!codePositions[match.index]) continue;
|
|
2284
2413
|
const resolved = resolveReExportModule(entryPath, match[1], exportConditions);
|
|
@@ -2293,10 +2422,18 @@ function getMutableExportsFromFile(entryPath, exportConditions = DEFAULT_SHARED_
|
|
|
2293
2422
|
}
|
|
2294
2423
|
function getSharedMutableExports(pkg, shareItem, exportConditions = DEFAULT_SHARED_EXPORT_CONDITIONS) {
|
|
2295
2424
|
const configuredImport = shareItem?.shareConfig.import;
|
|
2296
|
-
|
|
2425
|
+
const entryPath = typeof configuredImport === "string" ? resolveConfiguredImportPath(configuredImport, exportConditions) : getInstalledPackageEntry(pkg, {
|
|
2297
2426
|
conditions: exportConditions,
|
|
2298
2427
|
resolveSubpathWithRequire: false
|
|
2299
|
-
})
|
|
2428
|
+
});
|
|
2429
|
+
if (!entryPath) return [];
|
|
2430
|
+
const cacheKey = `${entryPath}\0${exportConditions.join("\0")}`;
|
|
2431
|
+
let mutableExports = sharedMutableExportsCache.get(cacheKey);
|
|
2432
|
+
if (!mutableExports) {
|
|
2433
|
+
mutableExports = getMutableExportsFromFile(entryPath, exportConditions);
|
|
2434
|
+
sharedMutableExportsCache.set(cacheKey, mutableExports);
|
|
2435
|
+
}
|
|
2436
|
+
return mutableExports;
|
|
2300
2437
|
}
|
|
2301
2438
|
function resolveConfiguredImportPath(importSource, exportConditions = DEFAULT_SHARED_EXPORT_CONDITIONS) {
|
|
2302
2439
|
if (path$1.isAbsolute(importSource)) return resolveFileLikeModule(importSource);
|
|
@@ -2551,7 +2688,9 @@ function hasUnsupportedBindingPattern(source, start) {
|
|
|
2551
2688
|
}
|
|
2552
2689
|
function getNamedExportsViaRegex(source, filePath, visited, scanState = { complete: true }, exportConditions = DEFAULT_SHARED_EXPORT_CONDITIONS) {
|
|
2553
2690
|
const names = /* @__PURE__ */ new Set();
|
|
2554
|
-
const
|
|
2691
|
+
const inspected = getSharedExportSource(source);
|
|
2692
|
+
source = inspected.source;
|
|
2693
|
+
const codePositions = inspected.codePositions;
|
|
2555
2694
|
const recognizedExportStarts = /* @__PURE__ */ new Set();
|
|
2556
2695
|
visited = visited || /* @__PURE__ */ new Set();
|
|
2557
2696
|
if (filePath) visited.add(filePath);
|
|
@@ -2609,15 +2748,15 @@ function getNamedExportsViaRegex(source, filePath, visited, scanState = { comple
|
|
|
2609
2748
|
else if (name === "default" || name === "__esModule") {} else scanState.complete = false;
|
|
2610
2749
|
}
|
|
2611
2750
|
}
|
|
2612
|
-
const namespaceReExportRegex = new RegExp(`export\\s
|
|
2751
|
+
const namespaceReExportRegex = new RegExp(`export\\s*\\*\\s*as\\s+(${JS_IDENTIFIER_PATTERN})\\s*from\\s*['"][^'"]+['"]`, "gu");
|
|
2613
2752
|
while ((match = namespaceReExportRegex.exec(source)) !== null) {
|
|
2614
2753
|
if (!codePositions[match.index]) continue;
|
|
2615
2754
|
recognizedExportStarts.add(match.index);
|
|
2616
2755
|
if (isValidEsmExportName(match[1])) names.add(match[1]);
|
|
2617
2756
|
}
|
|
2618
|
-
if (hasCodeMatch(source, /export\s
|
|
2757
|
+
if (hasCodeMatch(source, /export\s*\*\s*as\s*['"]/g, codePositions)) scanState.complete = false;
|
|
2619
2758
|
if (filePath) {
|
|
2620
|
-
const starExportRegex = /export\s
|
|
2759
|
+
const starExportRegex = /export\s*\*\s*from\s*['"]([^'"]+)['"]/g;
|
|
2621
2760
|
while ((match = starExportRegex.exec(source)) !== null) {
|
|
2622
2761
|
if (!codePositions[match.index]) continue;
|
|
2623
2762
|
recognizedExportStarts.add(match.index);
|
|
@@ -2852,12 +2991,6 @@ function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFedera
|
|
|
2852
2991
|
};
|
|
2853
2992
|
return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && reachesPkg(sharedPkg, /* @__PURE__ */ new Set([sharedPkg])));
|
|
2854
2993
|
}
|
|
2855
|
-
function isRemoteOnlyContainer(options = getNormalizeModuleFederationOptions()) {
|
|
2856
|
-
return Object.keys(options.exposes || {}).length > 0 && Object.keys(options.remotes || {}).length === 0;
|
|
2857
|
-
}
|
|
2858
|
-
function isLocalOnlyContainer(options = getNormalizeModuleFederationOptions()) {
|
|
2859
|
-
return Object.keys(options.exposes || {}).length === 0 && Object.keys(options.remotes || {}).length === 0;
|
|
2860
|
-
}
|
|
2861
2994
|
function tryResolveImportFromPackageRoot(pkg, root) {
|
|
2862
2995
|
try {
|
|
2863
2996
|
return resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(root, "package.json"))).resolve(pkg), root);
|
|
@@ -3378,11 +3511,10 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3378
3511
|
const liveNamedExportLine = liveNamedExports.length ? `export { ${liveNamedExports.join(", ")} } from ${escapeGeneratedStringLiteral(sharedImportSource)};` : "";
|
|
3379
3512
|
const hasCompleteExportCoverage = detectedNamedExports !== void 0;
|
|
3380
3513
|
const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
|
|
3381
|
-
const
|
|
3382
|
-
const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer(resolvedOptions) && (shareItem.shareConfig.singleton === true || isDefaultShareScope) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
|
|
3514
|
+
const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteContainer(resolvedOptions) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
|
|
3383
3515
|
const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
|
|
3384
3516
|
const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
|
|
3385
|
-
const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton &&
|
|
3517
|
+
const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
|
|
3386
3518
|
const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
|
|
3387
3519
|
const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
|
|
3388
3520
|
const reactMixedModeGuard = pkg === "react" ? createReactMixedModeRuntimeGuard() : "";
|
|
@@ -3566,6 +3698,7 @@ function generateLocalSharedImportMap(options) {
|
|
|
3566
3698
|
const useDirectReactImport = shouldUseDirectReactImport();
|
|
3567
3699
|
const orderedShares = getOrderedUsedShares(options);
|
|
3568
3700
|
const sharesToMaterialize = new Set(getMaterializedShares(options));
|
|
3701
|
+
const hasConsumeOnlyShare = orderedShares.some((pkg) => getNormalizeShareItem(pkg, resolvedOptions)?.shareConfig.import === false);
|
|
3569
3702
|
return `
|
|
3570
3703
|
import {loadShare} from "@module-federation/runtime";
|
|
3571
3704
|
${orderedShares.map((pkg, index) => {
|
|
@@ -3574,12 +3707,47 @@ function generateLocalSharedImportMap(options) {
|
|
|
3574
3707
|
return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
|
|
3575
3708
|
}).filter(Boolean).join("\n")}
|
|
3576
3709
|
${normalizeRuntimeShareCode}
|
|
3710
|
+
const __mfGetCachedReactFamily = (keys, reactKeys, localVersion, requiredExport) => {
|
|
3711
|
+
const cache = globalThis.__mf_module_cache__?.share;
|
|
3712
|
+
const react = reactKeys.map((key) => cache?.[key]).find((value) => value !== undefined);
|
|
3713
|
+
const reactVersion = react?.version ?? react?.default?.version;
|
|
3714
|
+
const actual = String(reactVersion || '').split(/[^0-9]+/).map(Number);
|
|
3715
|
+
const expected = String(localVersion || '').split(/[^0-9]+/).map(Number);
|
|
3716
|
+
for (let index = 0; index < Math.max(actual.length, expected.length); index++) {
|
|
3717
|
+
if ((actual[index] || 0) < (expected[index] || 0)) return undefined;
|
|
3718
|
+
if ((actual[index] || 0) > (expected[index] || 0)) break;
|
|
3719
|
+
}
|
|
3720
|
+
for (const key of keys) {
|
|
3721
|
+
const cached = cache?.[key];
|
|
3722
|
+
if (cached === undefined) continue;
|
|
3723
|
+
if (!requiredExport || typeof cached?.[requiredExport] === 'function' || typeof cached?.default?.[requiredExport] === 'function') return cached;
|
|
3724
|
+
}
|
|
3725
|
+
return undefined;
|
|
3726
|
+
};
|
|
3727
|
+
${hasConsumeOnlyShare ? `// A consume-only share has no local module: its entry is the same shape for every key, so one helper builds it instead of a literal per key
|
|
3728
|
+
const __mfHostOnly = (name) => async () => {
|
|
3729
|
+
throw new Error(\`[Module Federation] Shared module '\${name}' must be provided by host\`);
|
|
3730
|
+
};
|
|
3731
|
+
const __mfConsumeOnly = (name, version, scope, materialize, shareConfig) => ({
|
|
3732
|
+
name,
|
|
3733
|
+
version,
|
|
3734
|
+
scope: [scope],
|
|
3735
|
+
loaded: false,
|
|
3736
|
+
materialize,
|
|
3737
|
+
eager: shareConfig.eager,
|
|
3738
|
+
from: ${toSafeJsLiteral(resolvedOptions.name)},
|
|
3739
|
+
canLiveRebind: true,
|
|
3740
|
+
get: __mfHostOnly(name),
|
|
3741
|
+
shareConfig: { ...shareConfig, import: false },
|
|
3742
|
+
});` : ""}
|
|
3577
3743
|
const importMap = {
|
|
3578
3744
|
${orderedShares.map((pkg, index) => {
|
|
3579
3745
|
const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
|
|
3746
|
+
if (shareItem?.shareConfig.import === false) return `
|
|
3747
|
+
${toSafeJsLiteral(pkg)}: __mfHostOnly(${toSafeJsLiteral(pkg)})`;
|
|
3580
3748
|
return `
|
|
3581
3749
|
${toSafeJsLiteral(pkg)}: async () => {
|
|
3582
|
-
${shareItem?.shareConfig.
|
|
3750
|
+
${shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
|
|
3583
3751
|
return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))});
|
|
3584
3752
|
return pkg;`}
|
|
3585
3753
|
}
|
|
@@ -3590,9 +3758,20 @@ function generateLocalSharedImportMap(options) {
|
|
|
3590
3758
|
${orderedShares.map((key) => {
|
|
3591
3759
|
const shareItem = getNormalizeShareItem(key, resolvedOptions);
|
|
3592
3760
|
if (!shareItem) return null;
|
|
3761
|
+
const isReactFamily = key.startsWith("react/") || key === "react-dom/client";
|
|
3762
|
+
const cacheKeys = [key, ...key === "react-dom/client" ? ["react-dom"] : []].flatMap((pkg) => {
|
|
3763
|
+
const descriptor = getSharedCacheDescriptor(pkg, shareItem);
|
|
3764
|
+
return [descriptor.canonical, ...descriptor.aliases ?? []];
|
|
3765
|
+
});
|
|
3766
|
+
const reactCacheKeys = ["react"].flatMap((pkg) => {
|
|
3767
|
+
const descriptor = getSharedCacheDescriptor(pkg, shareItem);
|
|
3768
|
+
return [descriptor.canonical, ...descriptor.aliases ?? []];
|
|
3769
|
+
});
|
|
3593
3770
|
const detectedNamedExports = getSharedNamedExports(key, shareItem);
|
|
3594
3771
|
const canLiveRebind = shareItem.shareConfig.import === false || detectedNamedExports !== void 0;
|
|
3595
3772
|
const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
|
|
3773
|
+
if (shareItem.shareConfig.import === false && !treeShakingConfig) return `
|
|
3774
|
+
${toSafeJsLiteral(key)}: __mfConsumeOnly(${toSafeJsLiteral(key)}, ${toSafeJsLiteral(shareItem.version)}, ${toSafeJsLiteral(shareItem.scope)}, ${sharesToMaterialize.has(key)}, {singleton: ${shareItem.shareConfig.singleton}, requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)}, strictVersion: ${shareItem.shareConfig.strictVersion}, eager: ${Boolean(shareItem.shareConfig.eager)}})`;
|
|
3596
3775
|
const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, options) : void 0;
|
|
3597
3776
|
const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
|
|
3598
3777
|
const treeShakingUsedExports = resolvedOptions.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
|
|
@@ -3609,26 +3788,54 @@ function generateLocalSharedImportMap(options) {
|
|
|
3609
3788
|
eager: ${Boolean(shareItem.shareConfig.eager)},
|
|
3610
3789
|
from: ${toSafeJsLiteral(resolvedOptions.name)},
|
|
3611
3790
|
canLiveRebind: ${canLiveRebind},
|
|
3612
|
-
|
|
3791
|
+
get () {
|
|
3613
3792
|
if (${shareItem.shareConfig.import === false}) {
|
|
3614
3793
|
throw new Error(\`[Module Federation] Shared module '\${${toSafeJsLiteral(key)}}' must be provided by host\`);
|
|
3615
3794
|
}
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
const
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3795
|
+
// A webpack consumer built with eager: true calls get() synchronously and needs the
|
|
3796
|
+
// factory, not a promise: once the module is loaded, hand the same factory back directly,
|
|
3797
|
+
// and while it is loading hand every caller the same pending promise.
|
|
3798
|
+
const share = usedShared[${toSafeJsLiteral(key)}]
|
|
3799
|
+
if (share.lib) return share.lib
|
|
3800
|
+
if (share.loading) return share.loading
|
|
3801
|
+
const cachedSingleton = ${shareItem.shareConfig.singleton && isReactFamily}
|
|
3802
|
+
? __mfGetCachedReactFamily(
|
|
3803
|
+
${toSafeJsLiteral(cacheKeys)},
|
|
3804
|
+
${toSafeJsLiteral(reactCacheKeys)},
|
|
3805
|
+
${toSafeJsLiteral(shareItem.version)},
|
|
3806
|
+
${toSafeJsLiteral(key === "react-dom/client" ? "createRoot" : void 0)}
|
|
3807
|
+
)
|
|
3808
|
+
: undefined
|
|
3809
|
+
if (cachedSingleton !== undefined) {
|
|
3810
|
+
share.lib = function () { return cachedSingleton }
|
|
3811
|
+
share.loaded = true
|
|
3812
|
+
return share.lib
|
|
3631
3813
|
}
|
|
3814
|
+
share.loading = (async () => {
|
|
3815
|
+
try {
|
|
3816
|
+
const {${toSafeJsLiteral(key)}: pkgDynamicImport} = importMap
|
|
3817
|
+
const res = await pkgDynamicImport()
|
|
3818
|
+
const exportModule = ${toSafeJsLiteral(useDirectReactImport)} && ${toSafeJsLiteral(key)} === "react"
|
|
3819
|
+
? (res?.default ?? res)
|
|
3820
|
+
: __mfNormalizeRuntimeShare({...res})
|
|
3821
|
+
// All npm packages pre-built by vite will be converted to esm
|
|
3822
|
+
if (exportModule.__esModule !== true) {
|
|
3823
|
+
Object.defineProperty(exportModule, "__esModule", {
|
|
3824
|
+
value: true,
|
|
3825
|
+
enumerable: false
|
|
3826
|
+
})
|
|
3827
|
+
}
|
|
3828
|
+
share.lib = function () {
|
|
3829
|
+
return exportModule
|
|
3830
|
+
}
|
|
3831
|
+
share.loaded = true
|
|
3832
|
+
return share.lib
|
|
3833
|
+
} finally {
|
|
3834
|
+
// A failed import must not pin the rejection: the next get() retries
|
|
3835
|
+
share.loading = undefined
|
|
3836
|
+
}
|
|
3837
|
+
})()
|
|
3838
|
+
return share.loading
|
|
3632
3839
|
},
|
|
3633
3840
|
shareConfig: {
|
|
3634
3841
|
singleton: ${shareItem.shareConfig.singleton},
|
|
@@ -3673,10 +3880,11 @@ function generateLocalSharedImportMap(options) {
|
|
|
3673
3880
|
}
|
|
3674
3881
|
`;
|
|
3675
3882
|
}
|
|
3676
|
-
/** Expand `pkg/` → package root + matching usedShares; never returns the prefix string. */
|
|
3883
|
+
/** Expand `pkg/` → package root (if importable) + matching usedShares; never returns the prefix string. */
|
|
3677
3884
|
function expandSharedPrefixKey(prefixKey, used) {
|
|
3678
3885
|
const base = prefixKey.slice(0, -1);
|
|
3679
|
-
const
|
|
3886
|
+
const baseImportable = isPackageInstalled(base) && isPackageExportAvailable(base);
|
|
3887
|
+
const expanded = new Set(baseImportable ? [base] : []);
|
|
3680
3888
|
for (const pkg of used) {
|
|
3681
3889
|
if (pkg.endsWith("/")) continue;
|
|
3682
3890
|
if (pkg === base || pkg.startsWith(`${base}/`)) expanded.add(pkg);
|
|
@@ -3854,6 +4062,8 @@ const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
|
|
|
3854
4062
|
};`;
|
|
3855
4063
|
const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbol("mf.originalSharedProvider");
|
|
3856
4064
|
const __mfResolveShareHook = { emit: (params) => params };
|
|
4065
|
+
const __mfGetShareScopeNames = (share) =>
|
|
4066
|
+
Array.isArray(share.scope) ? share.scope : [share.scope || "default"];
|
|
3857
4067
|
const __mfCreateProviderSelectionVersions = (versions, strategy) => {
|
|
3858
4068
|
if (strategy !== "version-first") return versions;
|
|
3859
4069
|
const selectionVersions = {};
|
|
@@ -3895,7 +4105,7 @@ const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbo
|
|
|
3895
4105
|
Object.entries(versions).filter(([, provider]) => provider?.shareConfig?.import !== false)
|
|
3896
4106
|
);
|
|
3897
4107
|
if (Object.keys(candidates).length === 0) return undefined;
|
|
3898
|
-
const scopes =
|
|
4108
|
+
const scopes = __mfGetShareScopeNames(share);
|
|
3899
4109
|
const selectionVersions = __mfCreateProviderSelectionVersions(candidates, strategy);
|
|
3900
4110
|
const shareScopeMap = {};
|
|
3901
4111
|
for (const scope of scopes) {
|
|
@@ -4054,10 +4264,26 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
|
|
|
4054
4264
|
);
|
|
4055
4265
|
return;
|
|
4056
4266
|
}
|
|
4057
|
-
const
|
|
4058
|
-
?
|
|
4267
|
+
const externalProvider = typeof __mfGetExternalSharedProvider === 'function'
|
|
4268
|
+
? __mfGetExternalSharedProvider(pkg, share)
|
|
4059
4269
|
: undefined;
|
|
4060
|
-
if (
|
|
4270
|
+
if (externalProvider) {
|
|
4271
|
+
let externalFactory = externalProvider.lib;
|
|
4272
|
+
if (!externalFactory && externalProvider.loading) externalFactory = await externalProvider.loading;
|
|
4273
|
+
if (!externalFactory && externalProvider.loaded && typeof externalProvider.get === 'function') {
|
|
4274
|
+
externalFactory = await externalProvider.get();
|
|
4275
|
+
}
|
|
4276
|
+
if (externalFactory) {
|
|
4277
|
+
const externalModule = typeof externalFactory === "function" ? externalFactory() : externalFactory;
|
|
4278
|
+
const externalResolved = await Promise.resolve(externalModule);
|
|
4279
|
+
${normalizeRuntimeShareCode}
|
|
4280
|
+
__mfWriteSharedCache(
|
|
4281
|
+
__mfModuleCache.share,
|
|
4282
|
+
cacheDescriptor,
|
|
4283
|
+
__mfNormalizeRuntimeShare(externalResolved),
|
|
4284
|
+
externalProvider.from
|
|
4285
|
+
);
|
|
4286
|
+
}
|
|
4061
4287
|
return;
|
|
4062
4288
|
}
|
|
4063
4289
|
const providerKey = cacheDescriptor.canonical;
|
|
@@ -4339,10 +4565,10 @@ function generateTreeShakingSnapshotPluginCode(enabled) {
|
|
|
4339
4565
|
});`;
|
|
4340
4566
|
}
|
|
4341
4567
|
function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build", exportConditions) {
|
|
4342
|
-
const needsSharedProviderSelectionHelper =
|
|
4568
|
+
const needsSharedProviderSelectionHelper = hasShared(options);
|
|
4343
4569
|
const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
|
|
4344
4570
|
const hasMultipleShareScopes = Array.isArray(options.shareScope);
|
|
4345
|
-
const guardHostAutoInit = command === "build" &&
|
|
4571
|
+
const guardHostAutoInit = command === "build" && isRemoteContainer(options) && hasRemotes(options);
|
|
4346
4572
|
const materializedShareBatches = toSafeJsLiteral(getShareBatches(options, false));
|
|
4347
4573
|
const runtimeImports = [
|
|
4348
4574
|
"init as runtimeInit",
|
|
@@ -4397,6 +4623,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
4397
4623
|
import {${runtimeImports}} from "@module-federation/runtime";
|
|
4398
4624
|
${runtimeHelperImports.length ? `import {${runtimeHelperImports.join(", ")}} from "@module-federation/runtime/helpers";` : ""}
|
|
4399
4625
|
${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
|
|
4626
|
+
import __mfExposesMap from "${virtualExposesId}"
|
|
4400
4627
|
${command === "build" ? getRuntimeInitResolveBootstrapCode(false, getRuntimeInitStatusImportId(options)) : getRuntimeInitBootstrapCode(false, getRuntimeInitStatusImportId(options), void 0, void 0, exportConditions) + "\n const { initResolve } = globalThis[globalKey];"}
|
|
4401
4628
|
${getRuntimeModuleCacheBootstrapCode(exportConditions)}
|
|
4402
4629
|
const initTokens = {}
|
|
@@ -4405,7 +4632,6 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
4405
4632
|
const mfName = ${toSafeJsLiteral(options.name)}
|
|
4406
4633
|
const __mfMaterializedShareBatches = ${materializedShareBatches}
|
|
4407
4634
|
let localSharedImportMapPromise
|
|
4408
|
-
let exposesMapPromise
|
|
4409
4635
|
let __mfLateBridgeShared
|
|
4410
4636
|
const shouldRetrySharedInitError = ${command !== "build"} && ((error) => {
|
|
4411
4637
|
const message = String((error && error.message) || error || '');
|
|
@@ -4439,12 +4665,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
4439
4665
|
}
|
|
4440
4666
|
|
|
4441
4667
|
async function getExposesMap() {
|
|
4442
|
-
|
|
4443
|
-
exposesMapPromise = retrySharedInit(() => import("${virtualExposesId}"))
|
|
4444
|
-
.then((mod) => mod.default ?? mod)
|
|
4445
|
-
.catch((e) => { exposesMapPromise = undefined; throw e; });
|
|
4446
|
-
}
|
|
4447
|
-
return exposesMapPromise
|
|
4668
|
+
return __mfExposesMap
|
|
4448
4669
|
}
|
|
4449
4670
|
|
|
4450
4671
|
async function init(shared = {}, initScope = [], remoteEntryInitOptions = {}) {
|
|
@@ -4560,29 +4781,33 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
4560
4781
|
const parts = pkg.split('/');
|
|
4561
4782
|
return pkg.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
|
|
4562
4783
|
};
|
|
4563
|
-
const
|
|
4784
|
+
const __mfGetExternalSharedProvider = (pkg, share, versionMap, includePackage) => {
|
|
4564
4785
|
if (typeof __mfSelectExternalSharedProvider !== 'function') return undefined;
|
|
4565
4786
|
const packageName = __mfGetSharePackageName(pkg);
|
|
4566
|
-
const candidates = packageName === pkg
|
|
4787
|
+
const candidates = !includePackage || packageName === pkg
|
|
4567
4788
|
? [[pkg, share]]
|
|
4568
4789
|
: [[pkg, share], [packageName, usedShared[packageName]]];
|
|
4569
4790
|
for (const [candidatePkg, candidateShare] of candidates) {
|
|
4570
4791
|
if (!candidateShare) continue;
|
|
4571
4792
|
const candidateVersionMap = versionMap
|
|
4572
4793
|
? (candidatePkg === pkg ? versionMap : initialShared[candidatePkg])
|
|
4573
|
-
: ${hasMultipleShareScopes ? "getShareVersions(candidatePkg, candidateShare)" : "shared[candidatePkg]"};
|
|
4794
|
+
: (initialShared[candidatePkg] ?? ${hasMultipleShareScopes ? "getShareVersions(candidatePkg, candidateShare)" : "shared[candidatePkg]"});
|
|
4574
4795
|
const provider = __mfSelectExternalSharedProvider(
|
|
4575
4796
|
candidateVersionMap,
|
|
4576
4797
|
candidatePkg,
|
|
4577
4798
|
candidateShare,
|
|
4578
4799
|
'${options.shareStrategy}'
|
|
4579
4800
|
);
|
|
4580
|
-
if (provider
|
|
4581
|
-
return provider;
|
|
4582
|
-
}
|
|
4801
|
+
if (provider) return provider;
|
|
4583
4802
|
}
|
|
4584
4803
|
return undefined;
|
|
4585
4804
|
};
|
|
4805
|
+
const __mfGetPendingExternalSharedProvider = (pkg, share, versionMap) => {
|
|
4806
|
+
const provider = __mfGetExternalSharedProvider(pkg, share, versionMap, true);
|
|
4807
|
+
return provider && isWebpackProvider(provider) && !provider.lib && !provider.loaded
|
|
4808
|
+
? provider
|
|
4809
|
+
: undefined;
|
|
4810
|
+
};
|
|
4586
4811
|
// handling circular init calls before an external provider can re-enter this container
|
|
4587
4812
|
${hasMultipleShareScopes ? `const shareScopeNamesToInitialize = [];
|
|
4588
4813
|
for (const shareScopeName of shareScopeNames) {
|
|
@@ -5320,7 +5545,28 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
|
|
|
5320
5545
|
const hostInitShareBatches = toSafeJsLiteral(getShareBatches(options, false));
|
|
5321
5546
|
const cacheOwner = toSafeJsLiteral(resolvedOptions.name);
|
|
5322
5547
|
const preferLocalVinextReact = hasPackageDependency("vinext") && (!exportConditions?.includes("browser") || exportConditions.includes("worker"));
|
|
5548
|
+
const hasConfiguredShared = hasShared(resolvedOptions);
|
|
5549
|
+
const hostInitSharedProviderHelperImport = shouldPreloadShares && hasConfiguredShared ? "import {share as runtimeShare} from \"@module-federation/runtime/helpers\";" : "";
|
|
5550
|
+
const hostInitSharedProviderHelperCode = shouldPreloadShares && hasConfiguredShared ? `
|
|
5551
|
+
${sharedProviderSelectionHelperCode}
|
|
5552
|
+
const __mfHasUsableProvider = (versions, pkg, share, scopeName) => {
|
|
5553
|
+
// Keep runtime singleton negotiation unchanged. A singleton already
|
|
5554
|
+
// registered in this scope is authoritative, even when runtime-core
|
|
5555
|
+
// reports a version mismatch.
|
|
5556
|
+
if (share.shareConfig?.singleton) {
|
|
5557
|
+
return Object.values(versions || {}).some(
|
|
5558
|
+
(provider) => provider?.shareConfig?.import !== false
|
|
5559
|
+
);
|
|
5560
|
+
}
|
|
5561
|
+
return Boolean(__mfSelectSharedProvider(
|
|
5562
|
+
versions,
|
|
5563
|
+
pkg,
|
|
5564
|
+
{ ...share, scope: [scopeName] },
|
|
5565
|
+
${toSafeJsLiteral(resolvedOptions.shareStrategy)}
|
|
5566
|
+
));
|
|
5567
|
+
};` : "";
|
|
5323
5568
|
return `
|
|
5569
|
+
${hostInitSharedProviderHelperImport}
|
|
5324
5570
|
${getRuntimeModuleCacheBootstrapCode(exportConditions)}
|
|
5325
5571
|
let hostInitPromise;
|
|
5326
5572
|
async function initHost() {
|
|
@@ -5334,12 +5580,13 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
|
|
|
5334
5580
|
${normalizeRuntimeShareCode}
|
|
5335
5581
|
${shouldPreloadShares ? `
|
|
5336
5582
|
const __mfHasAlternativeSharedVersion = (pkg, share) =>
|
|
5337
|
-
(
|
|
5583
|
+
__mfGetShareScopeNames(share).some(
|
|
5338
5584
|
(scopeName) => Object.keys(runtime.shareScopeMap?.[scopeName]?.[pkg] || {}).some(
|
|
5339
5585
|
(version) => version !== share.version
|
|
5340
5586
|
)
|
|
5341
5587
|
);
|
|
5342
5588
|
const __mfHostInitShareBatches = ${hostInitShareBatches};
|
|
5589
|
+
${hostInitSharedProviderHelperCode}
|
|
5343
5590
|
for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
|
|
5344
5591
|
await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
|
|
5345
5592
|
const share = usedShared[pkg];
|
|
@@ -5357,18 +5604,57 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
|
|
|
5357
5604
|
)`}
|
|
5358
5605
|
) return;
|
|
5359
5606
|
// An import:false share has nothing to load until a foreign provider
|
|
5360
|
-
// registers: its own stub getter throws by construction.
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5607
|
+
// registers: its own stub getter throws by construction. A standalone
|
|
5608
|
+
// container initialized on the same page keeps its providers in its
|
|
5609
|
+
// own runtime scope (#1307), so adopt those before giving up.
|
|
5610
|
+
if (share.shareConfig?.import === false) {
|
|
5611
|
+
const __mfScopeNames = __mfGetShareScopeNames(share);
|
|
5612
|
+
const __mfNeedsSiblingProvider = (scopeName) =>
|
|
5613
|
+
!__mfHasUsableProvider(
|
|
5614
|
+
runtime.shareScopeMap?.[scopeName]?.[pkg],
|
|
5615
|
+
pkg,
|
|
5616
|
+
share,
|
|
5617
|
+
scopeName
|
|
5618
|
+
);
|
|
5619
|
+
if (__mfScopeNames.some(__mfNeedsSiblingProvider)) {
|
|
5620
|
+
// loadShare() re-runs initializeSharing(), which re-registers this
|
|
5621
|
+
// container's own stub and lets it displace an unloaded adopted
|
|
5622
|
+
// provider whenever this container's name sorts after the provider's
|
|
5623
|
+
// (#1311). Put the provider back: a stub never outranks a provider.
|
|
5624
|
+
if (!runtime.__mfKeepAdoptedProviders) {
|
|
5625
|
+
runtime.__mfKeepAdoptedProviders = true;
|
|
5626
|
+
runtime.sharedHandler?.hooks?.lifecycle?.afterRegisterShare?.on?.((args) => {
|
|
5627
|
+
const { shared, previousShared, registeredShared } = args || {};
|
|
5628
|
+
if (
|
|
5629
|
+
shared?.shareConfig?.import !== false ||
|
|
5630
|
+
registeredShared !== shared ||
|
|
5631
|
+
!previousShared ||
|
|
5632
|
+
previousShared.shareConfig?.import === false
|
|
5633
|
+
) return;
|
|
5634
|
+
const versions = runtime.shareScopeMap?.[args.scope]?.[args.pkgName];
|
|
5635
|
+
if (versions && versions[shared.version] === shared) versions[shared.version] = previousShared;
|
|
5636
|
+
});
|
|
5637
|
+
}
|
|
5638
|
+
for (const instance of globalThis.__FEDERATION__?.__INSTANCES__ || []) {
|
|
5639
|
+
for (const scopeName of __mfScopeNames) {
|
|
5640
|
+
const versions = instance?.shareScopeMap?.[scopeName]?.[pkg];
|
|
5641
|
+
if (!__mfHasUsableProvider(versions, pkg, share, scopeName)) continue;
|
|
5642
|
+
if (!__mfNeedsSiblingProvider(scopeName)) continue;
|
|
5643
|
+
const target = (runtime.shareScopeMap[scopeName] ||= {})[pkg] ||= {};
|
|
5644
|
+
for (const [version, provider] of Object.entries(versions)) {
|
|
5645
|
+
if (provider?.shareConfig?.import === false) continue;
|
|
5646
|
+
if (target[version] && target[version].shareConfig?.import !== false) continue;
|
|
5647
|
+
target[version] = provider;
|
|
5648
|
+
}
|
|
5649
|
+
}
|
|
5650
|
+
}
|
|
5651
|
+
}
|
|
5652
|
+
if (__mfScopeNames.every(__mfNeedsSiblingProvider)) return;
|
|
5653
|
+
}
|
|
5369
5654
|
await runtime.loadShare(pkg, {
|
|
5370
5655
|
customShareInfo: { shareConfig: share.shareConfig }
|
|
5371
5656
|
}).then(async (factory) => {
|
|
5657
|
+
if (factory === false) return;
|
|
5372
5658
|
const mod = typeof factory === "function" ? factory() : factory;
|
|
5373
5659
|
let resolved = __mfNormalizeRuntimeShare(await Promise.resolve(mod));
|
|
5374
5660
|
${preferLocalVinextReact ? `if (
|
|
@@ -5451,6 +5737,7 @@ function generatePendingSharesCode(command = "build", options) {
|
|
|
5451
5737
|
const pendingShareImports = command === "build" ? getMaterializedShares(options).filter((pkg) => {
|
|
5452
5738
|
const shareItem = getShareItemForPreload(pkg, resolvedOptions);
|
|
5453
5739
|
if (!shareItem || pkg.endsWith("/")) return false;
|
|
5740
|
+
if (shareItem.shareConfig.eager) return false;
|
|
5454
5741
|
return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
|
|
5455
5742
|
}).map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`) : [];
|
|
5456
5743
|
return `
|
|
@@ -5793,9 +6080,10 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
|
|
|
5793
6080
|
const devRuntimeBootstrap = `${getRuntimeInitBootstrapCode(enableSsrInit, getRuntimeInitStatusImportId(options), ssrRemotes, hostAutoInitPath, exportConditions)}
|
|
5794
6081
|
const { initPromise, initResolve, initReject, moduleCache: __mfModuleCache } = globalThis[globalKey];`;
|
|
5795
6082
|
const importLine = command === "build" ? `${getRuntimeModuleCacheBootstrapCode(exportConditions)}
|
|
5796
|
-
|
|
6083
|
+
const __mfHostInitPromise = () => import(${JSON.stringify(hostAutoInitPath)})
|
|
6084
|
+
.then((mod) => mod.hostInitPromise);` : `${devRuntimeBootstrap}
|
|
5797
6085
|
${command === "serve" && consumer !== "server" ? browserHostInitCode : ""}`;
|
|
5798
|
-
const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise" : "initPromise";
|
|
6086
|
+
const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise()" : "initPromise";
|
|
5799
6087
|
const remoteCacheKey = `${getRuntimeRemoteCachePrefix(options)}${id}`;
|
|
5800
6088
|
const remoteLoadFailureHandler = command === "build" ? `.catch((error) => {
|
|
5801
6089
|
delete __mfModuleCache.remote[pendingKey];
|
|
@@ -5859,24 +6147,19 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
|
|
|
5859
6147
|
}
|
|
5860
6148
|
//#endregion
|
|
5861
6149
|
//#region src/plugins/pluginAddEntry.ts
|
|
5862
|
-
const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !name.includes("__prebuild__") && !name.includes("__loadShare__");
|
|
6150
|
+
const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !name.includes("__prebuild__") && !name.includes("__loadShare__") && !name.includes("__loadRemote__");
|
|
5863
6151
|
const HOST_INIT_PRELOAD_CHUNKS = [
|
|
5864
6152
|
(name) => name === "hostInit",
|
|
5865
6153
|
(name) => name === "remoteEntry",
|
|
5866
|
-
(name) => name === "virtualExposes",
|
|
5867
6154
|
isPreloadableVirtualMfChunk,
|
|
5868
6155
|
(name) => name === "index"
|
|
5869
6156
|
];
|
|
5870
6157
|
const isRemoteWarmupExcluded = (name) => name.includes("__prebuild__") || name.includes("__loadShare__");
|
|
5871
|
-
const REMOTE_ENTRY_WARMUP_CHUNKS = [
|
|
5872
|
-
(name) => name === "hostInit",
|
|
5873
|
-
(name) => name === "virtualExposes",
|
|
5874
|
-
(name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)
|
|
5875
|
-
];
|
|
6158
|
+
const REMOTE_ENTRY_WARMUP_CHUNKS = [(name) => name === "hostInit", (name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)];
|
|
5876
6159
|
function getChunksByFileName(bundle) {
|
|
5877
6160
|
return new Map(Object.values(bundle).filter((chunk) => chunk.type === "chunk").map((chunk) => [chunk.fileName, chunk]));
|
|
5878
6161
|
}
|
|
5879
|
-
function collectPreloadChunkFiles(chunksByFileName, seeds, excludeFromClosure = (name) => name.includes(
|
|
6162
|
+
function collectPreloadChunkFiles(chunksByFileName, seeds, excludeFromClosure = (name) => name.includes(PREBUILD_TAG)) {
|
|
5880
6163
|
const seenFiles = /* @__PURE__ */ new Set();
|
|
5881
6164
|
const files = [];
|
|
5882
6165
|
const queue = [...seeds];
|
|
@@ -5955,9 +6238,6 @@ if (typeof document !== 'undefined' && document.head) {
|
|
|
5955
6238
|
function getFirstHtmlEntryFile(entryFiles) {
|
|
5956
6239
|
return entryFiles.find((file) => file.endsWith(".html"));
|
|
5957
6240
|
}
|
|
5958
|
-
function stripQueryAndHash$1(file) {
|
|
5959
|
-
return file.split(/[?#]/)[0];
|
|
5960
|
-
}
|
|
5961
6241
|
function isReactRouterClientRouteInput(file) {
|
|
5962
6242
|
return /[?&]__react-router-build-client-route(?:[=&]|$)/.test(file);
|
|
5963
6243
|
}
|
|
@@ -6008,6 +6288,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
6008
6288
|
let emitFileId;
|
|
6009
6289
|
let pendingSharesEmitId;
|
|
6010
6290
|
let viteConfig;
|
|
6291
|
+
let devServer;
|
|
6011
6292
|
let skipHtmlDevFallback = forceClientInjected ?? false;
|
|
6012
6293
|
let clientInjected = false;
|
|
6013
6294
|
let emittedFileName;
|
|
@@ -6081,9 +6362,31 @@ const __mfCurrentScript = document.currentScript;
|
|
|
6081
6362
|
const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(federationOptions));
|
|
6082
6363
|
return Array.from(new Set(remoteSources.flatMap((remote) => {
|
|
6083
6364
|
const registration = getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions);
|
|
6084
|
-
return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) ? [registration.entry] : [];
|
|
6365
|
+
return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) && !/\.json(?:[?#]|$)/i.test(registration.entry) ? [registration.entry] : [];
|
|
6085
6366
|
})));
|
|
6086
6367
|
}
|
|
6368
|
+
async function warmupDevEntryGraph(entryUrl) {
|
|
6369
|
+
const server = devServer;
|
|
6370
|
+
if (!server) return;
|
|
6371
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6372
|
+
const cacheDir = normalizePathForImport(server.config?.cacheDir ?? "").replace(/\/$/, "") + "/";
|
|
6373
|
+
const visit = async (url) => {
|
|
6374
|
+
if (seen.has(url)) return;
|
|
6375
|
+
seen.add(url);
|
|
6376
|
+
try {
|
|
6377
|
+
await server.transformRequest(url);
|
|
6378
|
+
} catch {
|
|
6379
|
+
return;
|
|
6380
|
+
}
|
|
6381
|
+
const deps = [...(await server.moduleGraph.getModuleByUrl(url))?.importedModules ?? []].filter((dep) => {
|
|
6382
|
+
if (!dep.file || dep.type !== "js" || !path$1.isAbsolute(dep.file)) return false;
|
|
6383
|
+
const file = normalizePathForImport(dep.file);
|
|
6384
|
+
return !file.includes("/node_modules/") && !file.startsWith(cacheDir);
|
|
6385
|
+
});
|
|
6386
|
+
await Promise.all(deps.map((dep) => visit(dep.url)));
|
|
6387
|
+
};
|
|
6388
|
+
await visit(entryUrl).catch(() => {});
|
|
6389
|
+
}
|
|
6087
6390
|
function getBootstrapSource(initSrc, entrySrc, useSystemImportFallback = false, options) {
|
|
6088
6391
|
const importHelper = useSystemImportFallback ? `const __mfImport = (src) =>
|
|
6089
6392
|
globalThis.System && typeof globalThis.System.import === 'function'
|
|
@@ -6109,7 +6412,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6109
6412
|
import(/* @vite-ignore */ __mfRemoteEntryPrefetchUrl).catch(() => {});
|
|
6110
6413
|
}
|
|
6111
6414
|
` : "";
|
|
6112
|
-
const sharedPreloadSources = _command === "serve" && waitsForInit &&
|
|
6415
|
+
const sharedPreloadSources = _command === "serve" && waitsForInit && isRemoteOnlyContainer(normalizedOptions) && federationOptions ? Array.from(getUsedShares(federationOptions)).filter((pkg) => !pkg.endsWith("/")).filter((pkg) => {
|
|
6113
6416
|
const shareItem = federationOptions.shared[pkg] || Object.entries(federationOptions.shared).find(([key]) => key.endsWith("/") && pkg.startsWith(key))?.[1];
|
|
6114
6417
|
const isExplicitShare = Object.hasOwn(federationOptions.shared, pkg);
|
|
6115
6418
|
return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
|
|
@@ -6195,12 +6498,12 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6195
6498
|
}
|
|
6196
6499
|
function isFederationInternalVirtualId(id) {
|
|
6197
6500
|
const normalized = decodeViteId(id).replace(/^\0+/, "");
|
|
6198
|
-
return normalized.includes("virtual:mf:") || /__(?:loadShare|prebuild|loadRemote)__/.test(normalized);
|
|
6501
|
+
return normalized.includes("virtual:mf:") || normalized.startsWith("virtual:mf-") || /__(?:loadShare|prebuild|loadRemote)__/.test(normalized);
|
|
6199
6502
|
}
|
|
6200
6503
|
function isWorkspaceSourceId(id) {
|
|
6201
6504
|
const normalized = normalizeModuleId(decodeViteId(id));
|
|
6202
6505
|
if (normalized.startsWith("\0") || normalized.startsWith("virtual:")) return false;
|
|
6203
|
-
const filePath = stripQueryAndHash
|
|
6506
|
+
const filePath = stripQueryAndHash(normalized);
|
|
6204
6507
|
if (filePath.startsWith("/@fs/")) return true;
|
|
6205
6508
|
if (!path$1.isAbsolute(filePath)) return false;
|
|
6206
6509
|
const root = normalizePathForImport(path$1.resolve(viteConfig.root));
|
|
@@ -6222,7 +6525,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6222
6525
|
ignoredHtmlScriptSources.add(match[1]);
|
|
6223
6526
|
continue;
|
|
6224
6527
|
}
|
|
6225
|
-
const scriptSrc = stripQueryAndHash
|
|
6528
|
+
const scriptSrc = stripQueryAndHash(match[1]);
|
|
6226
6529
|
if (/^(?:[a-z]+:)?\/\//i.test(scriptSrc)) continue;
|
|
6227
6530
|
addEntryFile(scriptSrc);
|
|
6228
6531
|
addEntryFile(scriptSrc.startsWith("/") ? path$1.resolve(viteConfig.root, scriptSrc.slice(1)) : path$1.resolve(path$1.dirname(htmlPath), scriptSrc));
|
|
@@ -6230,7 +6533,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6230
6533
|
}
|
|
6231
6534
|
function addEntryRemoteImports(entrySrc) {
|
|
6232
6535
|
if (!federationOptions || /^(?:[a-z]+:)?\/\//i.test(entrySrc)) return;
|
|
6233
|
-
const file = path$1.resolve(viteConfig.root, stripQueryAndHash
|
|
6536
|
+
const file = path$1.resolve(viteConfig.root, stripQueryAndHash(entrySrc).replace(/^\//, ""));
|
|
6234
6537
|
if (!fs$2.existsSync(file)) return;
|
|
6235
6538
|
const code = fs$2.readFileSync(file, "utf-8");
|
|
6236
6539
|
for (const source of findModuleImportSources(code)) {
|
|
@@ -6257,6 +6560,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6257
6560
|
skipTransformIds = new Set(skipTransformFor.map(resolveProjectId));
|
|
6258
6561
|
},
|
|
6259
6562
|
configureServer(server) {
|
|
6563
|
+
devServer = server;
|
|
6260
6564
|
server.middlewares.use((req, res, next) => {
|
|
6261
6565
|
const rawUrl = req.url?.split("#")[0] ?? "";
|
|
6262
6566
|
if (normalizeDevHtmlProxyId(rawUrl.split("?")[0]) === DEV_HTML_PROXY_PREFIX.slice(0, -1)) {
|
|
@@ -6266,9 +6570,12 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6266
6570
|
const entrySrc = params.get("entry");
|
|
6267
6571
|
if (initSrc && entrySrc) {
|
|
6268
6572
|
const withBase = (src) => viteConfig.base + src.replace(/^\//, "");
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6573
|
+
const source = getBootstrapSource(withBase(initSrc), withBase(entrySrc));
|
|
6574
|
+
warmupDevEntryGraph(entrySrc).finally(() => {
|
|
6575
|
+
res.statusCode = 200;
|
|
6576
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
6577
|
+
res.end(source);
|
|
6578
|
+
});
|
|
6272
6579
|
return;
|
|
6273
6580
|
}
|
|
6274
6581
|
}
|
|
@@ -6316,7 +6623,8 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6316
6623
|
const initSrc = params.get("init");
|
|
6317
6624
|
const entrySrc = params.get("entry");
|
|
6318
6625
|
if (!initSrc || !entrySrc) return;
|
|
6319
|
-
|
|
6626
|
+
const source = getBootstrapSource(initSrc, entrySrc);
|
|
6627
|
+
return warmupDevEntryGraph(entrySrc).then(() => source);
|
|
6320
6628
|
},
|
|
6321
6629
|
transform(code, id) {
|
|
6322
6630
|
if (id.includes("node_modules") || inject !== "html" || htmlFilePath) return;
|
|
@@ -6334,15 +6642,24 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6334
6642
|
configResolved(config) {
|
|
6335
6643
|
viteConfig = config;
|
|
6336
6644
|
skipTransformIds = new Set(skipTransformFor.map(resolveProjectId));
|
|
6337
|
-
const
|
|
6338
|
-
const
|
|
6339
|
-
|
|
6340
|
-
|
|
6645
|
+
const clientEnvironmentInputs = [];
|
|
6646
|
+
for (const environment of Object.values(config.environments ?? {})) {
|
|
6647
|
+
if (environment.consumer !== "client") continue;
|
|
6648
|
+
const input = getBuildInput(environment);
|
|
6649
|
+
if (!input) {
|
|
6650
|
+
htmlFilePath ??= path$1.resolve(config.root, "index.html");
|
|
6651
|
+
continue;
|
|
6652
|
+
}
|
|
6653
|
+
if (typeof input === "string") clientEnvironmentInputs.push(input);
|
|
6654
|
+
else if (Array.isArray(input)) clientEnvironmentInputs.push(...input);
|
|
6655
|
+
else clientEnvironmentInputs.push(...Object.values(input));
|
|
6656
|
+
}
|
|
6657
|
+
const inputOptions = clientEnvironmentInputs.length > 0 ? clientEnvironmentInputs : getBuildInput(config);
|
|
6341
6658
|
if (!inputOptions) htmlFilePath = path$1.resolve(config.root, "index.html");
|
|
6342
6659
|
else if (typeof inputOptions === "string") entryFiles = [resolveProjectId(inputOptions)];
|
|
6343
6660
|
else if (Array.isArray(inputOptions)) entryFiles = inputOptions.filter((input) => !isReactRouterClientRouteInput(String(input))).map(resolveProjectId);
|
|
6344
6661
|
else if (typeof inputOptions === "object") entryFiles = Object.values(inputOptions).filter((input) => !isReactRouterClientRouteInput(String(input))).map((input) => resolveProjectId(String(input)));
|
|
6345
|
-
if (entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles);
|
|
6662
|
+
if (entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles) ?? htmlFilePath;
|
|
6346
6663
|
if (config.command === "serve" && !htmlFilePath) {
|
|
6347
6664
|
const rootIndexHtml = path$1.resolve(config.root, "index.html");
|
|
6348
6665
|
if (fs$2.existsSync(rootIndexHtml)) htmlFilePath = rootIndexHtml;
|
|
@@ -6457,14 +6774,13 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6457
6774
|
},
|
|
6458
6775
|
transform(code, id) {
|
|
6459
6776
|
if (skipSvelteKitSsrBuild()) return;
|
|
6777
|
+
if (viteConfig?.command === "build" && !waitsForInit) return;
|
|
6460
6778
|
if (isSvelteKitServerModule(id)) return;
|
|
6461
6779
|
if (hasEntryBootstrapParam(id)) return;
|
|
6462
6780
|
if (normalizeModuleId(id).endsWith(".html")) return;
|
|
6463
6781
|
const projectId = resolveProjectId(id);
|
|
6464
6782
|
if (skipTransformIds.has(projectId)) return;
|
|
6465
|
-
|
|
6466
|
-
const transformEnv = transformCtx != null && typeof transformCtx === "object" ? transformCtx["environment"] : void 0;
|
|
6467
|
-
if (transformEnv?.name && transformEnv.name !== "client") return;
|
|
6783
|
+
if (!isClientEnvironment(this)) return;
|
|
6468
6784
|
const isVinext = hasPackageDependency("vinext");
|
|
6469
6785
|
if (isVinext && inject === "html" && id.includes("virtual:vite-rsc/remove-duplicate-server-css")) {
|
|
6470
6786
|
const namespaceReactImport = `import * as React from 'react';`;
|
|
@@ -7252,7 +7568,7 @@ function pluginExternalRuntimeCore() {
|
|
|
7252
7568
|
}
|
|
7253
7569
|
//#endregion
|
|
7254
7570
|
//#region package.json
|
|
7255
|
-
var version$1 = "1.
|
|
7571
|
+
var version$1 = "1.22.1";
|
|
7256
7572
|
//#endregion
|
|
7257
7573
|
//#region src/virtualModules/index.ts
|
|
7258
7574
|
function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
|
|
@@ -7341,16 +7657,31 @@ const collectStaticChunks = (bundle, roots) => {
|
|
|
7341
7657
|
};
|
|
7342
7658
|
/**
|
|
7343
7659
|
* Analyzes assets associated with a chunk without mutating the output map.
|
|
7344
|
-
*
|
|
7660
|
+
* Dynamic imports are collected transitively (a lazy route nested behind another
|
|
7661
|
+
* lazy route is still reachable), following both static and dynamic edges.
|
|
7662
|
+
* The traversal is cycle-safe and ignores missing bundle entries.
|
|
7345
7663
|
*/
|
|
7346
7664
|
const analyzeChunkAssets = (bundle, fileName, chunk) => {
|
|
7347
7665
|
const dynamicAssets = [];
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7666
|
+
const visited = /* @__PURE__ */ new Set([fileName]);
|
|
7667
|
+
const queue = [fileName];
|
|
7668
|
+
const enqueue = (imported) => {
|
|
7669
|
+
if (visited.has(imported)) return;
|
|
7670
|
+
visited.add(imported);
|
|
7671
|
+
queue.push(imported);
|
|
7672
|
+
};
|
|
7673
|
+
for (let queueIndex = 0; queueIndex < queue.length; queueIndex++) {
|
|
7674
|
+
const currentChunk = bundle[queue[queueIndex]];
|
|
7675
|
+
if (!currentChunk || currentChunk.type !== "chunk") continue;
|
|
7676
|
+
for (const imported of currentChunk.imports ?? []) enqueue(imported);
|
|
7677
|
+
for (const dynamicImport of currentChunk.dynamicImports ?? []) {
|
|
7678
|
+
if (!bundle[dynamicImport]) continue;
|
|
7679
|
+
dynamicAssets.push({
|
|
7680
|
+
fileName: dynamicImport,
|
|
7681
|
+
type: isCSSFile(dynamicImport) ? "css" : "js"
|
|
7682
|
+
});
|
|
7683
|
+
enqueue(dynamicImport);
|
|
7684
|
+
}
|
|
7354
7685
|
}
|
|
7355
7686
|
return {
|
|
7356
7687
|
importedCss: Array.from(chunk.viteMetadata?.importedCss ?? []),
|
|
@@ -7699,8 +8030,38 @@ function collectImportedCss(chunks) {
|
|
|
7699
8030
|
for (const chunk of chunks) for (const cssFile of chunk.viteMetadata?.importedCss ?? []) css.add(cssFile);
|
|
7700
8031
|
return Array.from(css);
|
|
7701
8032
|
}
|
|
7702
|
-
|
|
8033
|
+
/**
|
|
8034
|
+
* Collects the virtual module ids of the `__loadShare__` wrappers belonging to shares
|
|
8035
|
+
* that are not eager.
|
|
8036
|
+
*
|
|
8037
|
+
* Such a wrapper resolves its share through the host at runtime, so it is a deferred
|
|
8038
|
+
* dependency even though the expose statically imports it. Advertising it as a sync
|
|
8039
|
+
* asset makes a preloader fetch a provider the host is going to supply anyway.
|
|
8040
|
+
*/
|
|
8041
|
+
function collectDeferredShareModules(options, isRolldown) {
|
|
8042
|
+
const deferred = /* @__PURE__ */ new Set();
|
|
8043
|
+
for (const shareKey of getUsedShares(options)) {
|
|
8044
|
+
const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
|
|
8045
|
+
if (shareConfig?.eager === true) continue;
|
|
8046
|
+
if (shareConfig?.import === false) continue;
|
|
8047
|
+
deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)));
|
|
8048
|
+
}
|
|
8049
|
+
return deferred;
|
|
8050
|
+
}
|
|
8051
|
+
/**
|
|
8052
|
+
* True when the chunk exists to load a deferred share rather than expose code.
|
|
8053
|
+
*
|
|
8054
|
+
* `chunk.moduleIds` carry Rollup's `\0` virtual-module prefix while
|
|
8055
|
+
* `getLoadShareModulePath` returns the unprefixed id, so both sides are normalized —
|
|
8056
|
+
* the same comparison `isContainerBootstrapChunk` makes.
|
|
8057
|
+
*/
|
|
8058
|
+
function isDeferredShareChunk(chunk, deferredShareModules) {
|
|
8059
|
+
if (!chunk || chunk.type !== "chunk" || deferredShareModules.size === 0) return false;
|
|
8060
|
+
return [chunk.facadeModuleId, ...chunk.moduleIds ?? []].some((id) => typeof id === "string" && deferredShareModules.has(normalizeVirtualModuleId(id)));
|
|
8061
|
+
}
|
|
8062
|
+
function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options, isRolldown) {
|
|
7703
8063
|
if (exposeModules.length === 0) return;
|
|
8064
|
+
const deferredShareModules = collectDeferredShareModules(options, isRolldown);
|
|
7704
8065
|
const containerChunks = remoteEntryFileName ? collectStaticChunks(bundle, [remoteEntryFileName]) : [];
|
|
7705
8066
|
const bootstrapChunks = containerChunks.slice(1);
|
|
7706
8067
|
const seen = new Set(containerChunks.map((chunk) => chunk.fileName));
|
|
@@ -7721,11 +8082,13 @@ function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName
|
|
|
7721
8082
|
for (const exposeModule of exposeModules) {
|
|
7722
8083
|
const assets = filesMap[exposeModule];
|
|
7723
8084
|
if (!assets) continue;
|
|
7724
|
-
const
|
|
8085
|
+
const allSyncChunks = collectStaticChunks(bundle, assets.js.sync);
|
|
8086
|
+
const syncChunks = allSyncChunks.filter((chunk) => !isDeferredShareChunk(chunk, deferredShareModules));
|
|
8087
|
+
const deferredChunks = allSyncChunks.filter((chunk) => isDeferredShareChunk(chunk, deferredShareModules));
|
|
7725
8088
|
const sync = Array.from(/* @__PURE__ */ new Set([...bootstrapAssets, ...syncChunks.map((chunk) => chunk.fileName)]));
|
|
7726
8089
|
const syncSet = new Set(sync);
|
|
7727
|
-
const asyncChunks = collectStaticChunks(bundle, assets.js.async);
|
|
7728
|
-
const async = asyncChunks.map((chunk) => chunk.fileName).filter((fileName) => !syncSet.has(fileName));
|
|
8090
|
+
const asyncChunks = [...collectStaticChunks(bundle, assets.js.async), ...deferredChunks];
|
|
8091
|
+
const async = Array.from(new Set(asyncChunks.map((chunk) => chunk.fileName))).filter((fileName) => !syncSet.has(fileName));
|
|
7729
8092
|
assets.js.sync = sync;
|
|
7730
8093
|
assets.js.async = async;
|
|
7731
8094
|
const syncCss = Array.from(/* @__PURE__ */ new Set([
|
|
@@ -7901,17 +8264,28 @@ const Manifest = (providedOptions) => {
|
|
|
7901
8264
|
root,
|
|
7902
8265
|
stripKnownJsExtensions: true
|
|
7903
8266
|
});
|
|
7904
|
-
expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions);
|
|
8267
|
+
expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions, getIsRolldown(this));
|
|
7905
8268
|
const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(mfOptions), this.resolve.bind(this), mfOptions);
|
|
7906
8269
|
processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
|
|
8270
|
+
const deferredSharedAssets = {
|
|
8271
|
+
js: /* @__PURE__ */ new Set(),
|
|
8272
|
+
css: /* @__PURE__ */ new Set()
|
|
8273
|
+
};
|
|
7907
8274
|
for (const shareKey of getUsedShares(mfOptions)) {
|
|
7908
8275
|
const shareItem = getNormalizeShareItem(shareKey, mfOptions);
|
|
7909
8276
|
const assets = filesMap[shareKey];
|
|
7910
8277
|
if (!assets || shareItem?.shareConfig.eager === true) continue;
|
|
7911
|
-
|
|
7912
|
-
|
|
8278
|
+
for (const type of ASSET_TYPES) {
|
|
8279
|
+
assets[type].async.push(...assets[type].sync.splice(0));
|
|
8280
|
+
for (const asset of assets[type].async) deferredSharedAssets[type].add(asset);
|
|
8281
|
+
}
|
|
7913
8282
|
}
|
|
7914
8283
|
if (mfOptions.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
|
|
8284
|
+
for (const exposeModule of exposesModules) {
|
|
8285
|
+
const assets = filesMap[exposeModule];
|
|
8286
|
+
if (!assets) continue;
|
|
8287
|
+
for (const type of ASSET_TYPES) for (const timing of LOAD_TIMINGS) assets[type][timing] = assets[type][timing].filter((asset) => !deferredSharedAssets[type].has(asset));
|
|
8288
|
+
}
|
|
7915
8289
|
filesMap = deduplicateAssets(filesMap);
|
|
7916
8290
|
}
|
|
7917
8291
|
const manifest = await applyManifestAdditionalData(generateMFManifest(filesMap, disableAssetsAnalyze), void 0);
|
|
@@ -8438,21 +8812,6 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
8438
8812
|
};
|
|
8439
8813
|
}
|
|
8440
8814
|
//#endregion
|
|
8441
|
-
//#region src/utils/remoteConsumerTarget.ts
|
|
8442
|
-
function getPluginEnvironmentName(ctx) {
|
|
8443
|
-
if (ctx == null || typeof ctx !== "object") return void 0;
|
|
8444
|
-
const environment = ctx["environment"];
|
|
8445
|
-
if (environment == null || typeof environment !== "object") return void 0;
|
|
8446
|
-
const name = environment["name"];
|
|
8447
|
-
return typeof name === "string" ? name : void 0;
|
|
8448
|
-
}
|
|
8449
|
-
function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
|
|
8450
|
-
if (!hasMultiEnvironment) return "unified";
|
|
8451
|
-
const envName = getPluginEnvironmentName(ctx);
|
|
8452
|
-
if (!envName || envName === "client") return "client";
|
|
8453
|
-
return "server";
|
|
8454
|
-
}
|
|
8455
|
-
//#endregion
|
|
8456
8815
|
//#region src/plugins/pluginProxyRemotes.ts
|
|
8457
8816
|
function isNodeModulesImporter(importer) {
|
|
8458
8817
|
return importer?.includes("/node_modules/") || importer?.includes("\\node_modules\\");
|
|
@@ -8532,6 +8891,81 @@ function pluginProxyRemotes_default(options) {
|
|
|
8532
8891
|
};
|
|
8533
8892
|
}
|
|
8534
8893
|
//#endregion
|
|
8894
|
+
//#region src/utils/sharedSource.ts
|
|
8895
|
+
/** Identify shared entries through Vite, with a cache scoped to this federation instance. */
|
|
8896
|
+
function createSharedSourceResolver(shared, getResolutionConfig) {
|
|
8897
|
+
const caches = /* @__PURE__ */ new Map();
|
|
8898
|
+
async function matchEntry(source, suffix, resolveEntry) {
|
|
8899
|
+
const packageName = getPackageNameFromNodeModulePath(source);
|
|
8900
|
+
if (!packageName) return;
|
|
8901
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
8902
|
+
if (findSharedKey(packageName, shared)) candidates.add(packageName);
|
|
8903
|
+
if (findSharedKey(suffix, shared)) candidates.add(suffix);
|
|
8904
|
+
for (const key of Object.keys(shared)) {
|
|
8905
|
+
if (getPackageName(key) !== packageName) continue;
|
|
8906
|
+
if (!key.endsWith("/")) candidates.add(key);
|
|
8907
|
+
for (const subpath of getCommonSharedSubpaths(key)) if (findSharedKey(subpath, shared)) candidates.add(subpath);
|
|
8908
|
+
}
|
|
8909
|
+
if (candidates.size === 0) return;
|
|
8910
|
+
const resolvedSource = await resolveEntry(source);
|
|
8911
|
+
if (!resolvedSource) return;
|
|
8912
|
+
for (const candidate of candidates) {
|
|
8913
|
+
const entry = await resolveEntry(candidate);
|
|
8914
|
+
if (!entry) continue;
|
|
8915
|
+
if (normalizeNodeModulePath(entry) === normalizeNodeModulePath(resolvedSource) || getNodeModulesSuffix(entry) === suffix) return candidate;
|
|
8916
|
+
}
|
|
8917
|
+
}
|
|
8918
|
+
return {
|
|
8919
|
+
clear() {
|
|
8920
|
+
caches.clear();
|
|
8921
|
+
},
|
|
8922
|
+
async resolve(context, source, options = {}) {
|
|
8923
|
+
if (source.startsWith("\0") || source.includes("#")) return;
|
|
8924
|
+
const queryIndex = source.indexOf("?");
|
|
8925
|
+
const query = queryIndex === -1 ? "" : source.slice(queryIndex + 1);
|
|
8926
|
+
if (query && [...new URLSearchParams(query).keys()].some((key) => ![
|
|
8927
|
+
"v",
|
|
8928
|
+
"t",
|
|
8929
|
+
"import"
|
|
8930
|
+
].includes(key))) return;
|
|
8931
|
+
if (findSharedKey(source, shared)) return source;
|
|
8932
|
+
const suffix = getNodeModulesSuffix(source);
|
|
8933
|
+
if (!suffix) return;
|
|
8934
|
+
const normalizedSource = stripViteFsPrefix(normalizeNodeModulePath(source));
|
|
8935
|
+
const environment = context.environment ?? !!options.ssr;
|
|
8936
|
+
const cacheable = !options.isEntry && !options.scan && (!options.kind || options.kind === "import-statement") && Object.keys(options.attributes ?? {}).length === 0 && Object.keys(options.custom ?? {}).length === 0;
|
|
8937
|
+
let cache = cacheable ? caches.get(environment) : void 0;
|
|
8938
|
+
if (cacheable && !cache) {
|
|
8939
|
+
cache = /* @__PURE__ */ new Map();
|
|
8940
|
+
caches.set(environment, cache);
|
|
8941
|
+
}
|
|
8942
|
+
if (cache?.has(normalizedSource)) return cache.get(normalizedSource);
|
|
8943
|
+
const { root, conditions } = getResolutionConfig(context, options);
|
|
8944
|
+
const result = await matchEntry(normalizedSource, suffix, async (request) => {
|
|
8945
|
+
if (!path$1.isAbsolute(request) && !isPackageExportAvailable(request, {
|
|
8946
|
+
cwd: root,
|
|
8947
|
+
conditions
|
|
8948
|
+
})) return void 0;
|
|
8949
|
+
try {
|
|
8950
|
+
const resolved = await context.resolve(request, path$1.join(root, "package.json"), {
|
|
8951
|
+
...options,
|
|
8952
|
+
skipSelf: true,
|
|
8953
|
+
custom: {
|
|
8954
|
+
...options.custom,
|
|
8955
|
+
__mfSharedEntryLookup: true
|
|
8956
|
+
}
|
|
8957
|
+
});
|
|
8958
|
+
return resolved && !resolved.external ? resolved.id : void 0;
|
|
8959
|
+
} catch {
|
|
8960
|
+
return;
|
|
8961
|
+
}
|
|
8962
|
+
});
|
|
8963
|
+
cache?.set(normalizedSource, result);
|
|
8964
|
+
return result;
|
|
8965
|
+
}
|
|
8966
|
+
};
|
|
8967
|
+
}
|
|
8968
|
+
//#endregion
|
|
8535
8969
|
//#region src/utils/PromiseStore.ts
|
|
8536
8970
|
/**
|
|
8537
8971
|
* example:
|
|
@@ -8581,23 +9015,6 @@ function isBuildConfigImporter(importer) {
|
|
|
8581
9015
|
if (!importer) return false;
|
|
8582
9016
|
return /(^|\/)(?:nuxt|vite|vitest|webpack|rollup|rspack)\.config\.[cm]?[jt]sx?$/.test(importer.replace(/\\/g, "/"));
|
|
8583
9017
|
}
|
|
8584
|
-
function findSharedKeyForSource(source, shared) {
|
|
8585
|
-
const key = findSharedKey(source, shared);
|
|
8586
|
-
if (key) return key;
|
|
8587
|
-
const explicitSharedSubpathKeys = Object.keys(shared || {}).filter((sharedKey) => getPackageName(sharedKey) !== sharedKey && !sharedKey.endsWith("/"));
|
|
8588
|
-
if (isNodeModulePath(source)) {
|
|
8589
|
-
const explicitSubpathKey = getMatchingNodeModuleSubpath(source, explicitSharedSubpathKeys);
|
|
8590
|
-
if (explicitSubpathKey) return explicitSubpathKey;
|
|
8591
|
-
const normalizedSource = normalizeNodeModulePath(source);
|
|
8592
|
-
const explicitSubpathEntryKey = explicitSharedSubpathKeys.find((sharedKey) => {
|
|
8593
|
-
const entry = getInstalledPackageEntry(sharedKey, { cwd: getPackageDetectionCwd() });
|
|
8594
|
-
return entry ? normalizeNodeModulePath(entry) === normalizedSource : false;
|
|
8595
|
-
});
|
|
8596
|
-
if (explicitSubpathEntryKey) return explicitSubpathEntryKey;
|
|
8597
|
-
}
|
|
8598
|
-
const packageName = getPackageNameFromNodeModulePath(source);
|
|
8599
|
-
return packageName ? findSharedKey(packageName, shared) : void 0;
|
|
8600
|
-
}
|
|
8601
9018
|
/**
|
|
8602
9019
|
* Reads the dependencies of an installed package from its package.json.
|
|
8603
9020
|
*/
|
|
@@ -8755,6 +9172,21 @@ function isSharedPackageDependency(sharedKey, dependency) {
|
|
|
8755
9172
|
}
|
|
8756
9173
|
return reachable.has(dependency);
|
|
8757
9174
|
}
|
|
9175
|
+
function isConfiguredSharedPackage(pkg, shared) {
|
|
9176
|
+
return Object.keys(shared).some((key) => getPackageName(key) === pkg);
|
|
9177
|
+
}
|
|
9178
|
+
function shouldKeepSharedImportLocal(source, importer, sharedKey, shared, importerPackage) {
|
|
9179
|
+
if (!importer || shared[sharedKey]?.shareConfig.import === false) return false;
|
|
9180
|
+
const prebuildImporter = importer.includes("__prebuild__") ? VirtualModule.findModule(PREBUILD_TAG, importer) : void 0;
|
|
9181
|
+
const fallbackPackage = prebuildImporter ? getPackageName(prebuildImporter.name) : importerPackage;
|
|
9182
|
+
if (!fallbackPackage || !isConfiguredSharedPackage(fallbackPackage, shared)) return false;
|
|
9183
|
+
const sourcePackage = getPackageName(sharedKey);
|
|
9184
|
+
if (fallbackPackage !== "react-dom" || sourcePackage !== "react") return false;
|
|
9185
|
+
if (prebuildImporter && matchesSharedSource(source, prebuildImporter.name)) return false;
|
|
9186
|
+
if (!isSharedPackageDependency(prebuildImporter?.name ?? fallbackPackage, sourcePackage)) return false;
|
|
9187
|
+
if (isSharedPackageDependency(sharedKey, fallbackPackage)) return false;
|
|
9188
|
+
return true;
|
|
9189
|
+
}
|
|
8758
9190
|
const sharedRuntimeDependencyCache = /* @__PURE__ */ new Map();
|
|
8759
9191
|
const SOURCE_FILE_RE = /\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/;
|
|
8760
9192
|
const NON_RUNTIME_SOURCE_RE = /(?:\.d\.[cm]?ts|\.(?:test|spec|stories)\.[cm]?[jt]sx?)$/;
|
|
@@ -8956,6 +9388,10 @@ function proxySharedModule(options) {
|
|
|
8956
9388
|
ssrTarget
|
|
8957
9389
|
});
|
|
8958
9390
|
};
|
|
9391
|
+
const sharedSourceResolver = createSharedSourceResolver(shared, (context, resolveOptions) => ({
|
|
9392
|
+
root: _config?.root || getPackageDetectionCwd(),
|
|
9393
|
+
conditions: getRuntimeDependencyConditions(context, resolveOptions)
|
|
9394
|
+
}));
|
|
8959
9395
|
const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command, getIsRolldown(context), getEnvironmentConditions(context));
|
|
8960
9396
|
const normalizeTreeShakingOutputPath = (value) => {
|
|
8961
9397
|
const normalized = normalizePathForImport(value);
|
|
@@ -9005,7 +9441,7 @@ function proxySharedModule(options) {
|
|
|
9005
9441
|
refreshTreeShakingForEnvironment(this);
|
|
9006
9442
|
const providerPackages = /* @__PURE__ */ new Set([...Object.keys(shared).filter((pkg) => !pkg.endsWith("/")), ...getUsedShares(federationOptions)]);
|
|
9007
9443
|
for (const pkg of providerPackages) {
|
|
9008
|
-
const sharedKey =
|
|
9444
|
+
const sharedKey = findSharedKey(pkg, shared);
|
|
9009
9445
|
const shareItem = shared[pkg] || (sharedKey ? shared[sharedKey] : void 0);
|
|
9010
9446
|
if (shareItem) emitTreeShakingProvider(this, pkg, shareItem);
|
|
9011
9447
|
}
|
|
@@ -9025,6 +9461,7 @@ function proxySharedModule(options) {
|
|
|
9025
9461
|
setTreeShakingBuildMode(command === "build", federationOptions);
|
|
9026
9462
|
resetTreeShakingExports(federationOptions);
|
|
9027
9463
|
emittedTreeShakingProviders.clear();
|
|
9464
|
+
sharedSourceResolver.clear();
|
|
9028
9465
|
sharedDependencyCache.clear();
|
|
9029
9466
|
dependencyManifestCache.clear();
|
|
9030
9467
|
sharedRuntimeDependencyCache.clear();
|
|
@@ -9059,7 +9496,11 @@ function proxySharedModule(options) {
|
|
|
9059
9496
|
writeLocalSharedImportMap(federationOptions);
|
|
9060
9497
|
refreshHostAutoInit(federationOptions);
|
|
9061
9498
|
},
|
|
9499
|
+
watchChange() {
|
|
9500
|
+
sharedSourceResolver.clear();
|
|
9501
|
+
},
|
|
9062
9502
|
buildStart() {
|
|
9503
|
+
sharedSourceResolver.clear();
|
|
9063
9504
|
if (_command !== "build") return;
|
|
9064
9505
|
resetTreeShakingExports(federationOptions);
|
|
9065
9506
|
emittedTreeShakingProviders.clear();
|
|
@@ -9068,9 +9509,12 @@ function proxySharedModule(options) {
|
|
|
9068
9509
|
shouldTransformCachedModule() {
|
|
9069
9510
|
return _command === "build" && hasAnalyzableShares;
|
|
9070
9511
|
},
|
|
9071
|
-
transform(code, id) {
|
|
9512
|
+
async transform(code, id, transformOptions) {
|
|
9072
9513
|
if (_command !== "build" || !hasAnalyzableShares) return;
|
|
9073
|
-
collectTreeShakingImports(code, id, shared,
|
|
9514
|
+
await collectTreeShakingImports(code, id, shared, async (source, shares) => {
|
|
9515
|
+
const request = await sharedSourceResolver.resolve(this, source, transformOptions);
|
|
9516
|
+
return request ? findSharedKey(request, shares) : void 0;
|
|
9517
|
+
}, (sharedKey, exports, request) => recordTreeShakingExports(sharedKey, exports, request, federationOptions), (sharedKey, request) => markTreeShakingPackageUnsafe(sharedKey, request, federationOptions));
|
|
9074
9518
|
refreshTreeShakingForEnvironment(this);
|
|
9075
9519
|
}
|
|
9076
9520
|
},
|
|
@@ -9079,6 +9523,7 @@ function proxySharedModule(options) {
|
|
|
9079
9523
|
enforce: "pre",
|
|
9080
9524
|
apply: "build",
|
|
9081
9525
|
async resolveId(source, importer, resolveOptions) {
|
|
9526
|
+
if (resolveOptions.custom?.__mfSharedEntryLookup) return;
|
|
9082
9527
|
const sourceToken = getTreeShakingGraphToken(source);
|
|
9083
9528
|
const importerToken = getTreeShakingGraphToken(importer);
|
|
9084
9529
|
const token = sourceToken || importerToken;
|
|
@@ -9086,7 +9531,8 @@ function proxySharedModule(options) {
|
|
|
9086
9531
|
const cleanSource = normalizePathForImport(stripTreeShakingGraphQuery(source));
|
|
9087
9532
|
const cleanImporter = importer ? normalizePathForImport(stripTreeShakingGraphQuery(importer)) : void 0;
|
|
9088
9533
|
if (!sourceToken && importerToken) {
|
|
9089
|
-
const
|
|
9534
|
+
const request = await sharedSourceResolver.resolve(this, cleanSource, resolveOptions);
|
|
9535
|
+
const nestedSharedKey = request ? findSharedKey(request, shared) : void 0;
|
|
9090
9536
|
if (nestedSharedKey && getPackageName(nestedSharedKey) !== getPackageName(importerToken)) return this.resolve(cleanSource, cleanImporter, {
|
|
9091
9537
|
...resolveOptions,
|
|
9092
9538
|
skipSelf: true
|
|
@@ -9113,20 +9559,22 @@ function proxySharedModule(options) {
|
|
|
9113
9559
|
name: "proxyPreBuildShared:resolve-shared-loadShare",
|
|
9114
9560
|
enforce: "pre",
|
|
9115
9561
|
async resolveId(source, importer, resolveOptions) {
|
|
9116
|
-
if (resolveOptions.custom?.__mfTreeShakingGraph) return;
|
|
9117
|
-
|
|
9562
|
+
if (resolveOptions.custom?.__mfSharedEntryLookup || resolveOptions.custom?.__mfTreeShakingGraph) return;
|
|
9563
|
+
const sharedSource = await sharedSourceResolver.resolve(this, source, resolveOptions);
|
|
9564
|
+
if (!sharedSource) return;
|
|
9565
|
+
const key = findSharedKey(sharedSource, shared);
|
|
9566
|
+
if (!key) return;
|
|
9567
|
+
const shouldSkipTaggedImporterProxy = (sharedKey, tag) => {
|
|
9118
9568
|
if (!importer?.includes(tag)) return false;
|
|
9119
9569
|
const taggedModule = VirtualModule.findModule(tag, importer);
|
|
9120
9570
|
if (!taggedModule) return true;
|
|
9121
|
-
return taggedModule.name === sharedKey || matchesSharedSource(
|
|
9122
|
-
}
|
|
9123
|
-
const key = findSharedKeyForSource(source, shared);
|
|
9124
|
-
if (!key) return;
|
|
9571
|
+
return taggedModule.name === sharedKey || matchesSharedSource(sharedSource, taggedModule.name);
|
|
9572
|
+
};
|
|
9125
9573
|
const importerPackage = getSharedPackageFromFile(importer, shared);
|
|
9126
9574
|
if (importerPackage === getPackageName(key)) return;
|
|
9127
|
-
if (importerPackage) {
|
|
9575
|
+
if (importerPackage && shared[key].shareConfig.import !== false) {
|
|
9128
9576
|
const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
|
|
9129
|
-
const runtimeDependencyRequest = key.endsWith("/") && matchesSharedSource(
|
|
9577
|
+
const runtimeDependencyRequest = key.endsWith("/") && matchesSharedSource(sharedSource, key) ? sharedSource : key;
|
|
9130
9578
|
if (importerIsUnsharedWorkspacePackage ? isSharedPackageRuntimeDependency(runtimeDependencyRequest, importerPackage, getRuntimeDependencyConditions(this, resolveOptions)) : isSharedPackageDependency(key, importerPackage)) return;
|
|
9131
9579
|
}
|
|
9132
9580
|
if (useDirectReactImport && key === "react") return;
|
|
@@ -9137,7 +9585,11 @@ function proxySharedModule(options) {
|
|
|
9137
9585
|
if (importer && (importer.includes("hostAutoInit") || importer.includes("__H_A_I__"))) return;
|
|
9138
9586
|
if (shouldSkipTaggedImporterProxy(key, "__loadShare__")) return;
|
|
9139
9587
|
if (shouldSkipTaggedImporterProxy(key, "__prebuild__")) return;
|
|
9140
|
-
const shareSource = key === "vue" &&
|
|
9588
|
+
const shareSource = key === "vue" && sharedSource.startsWith("vue/dist/") ? key : sharedSource;
|
|
9589
|
+
if (shouldKeepSharedImportLocal(sharedSource, importer, key, shared, importerPackage)) {
|
|
9590
|
+
const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
|
|
9591
|
+
return tryResolveFromProjectRoot(localSource) || localSource;
|
|
9592
|
+
}
|
|
9141
9593
|
const loadSharePath = getLoadShareModulePath(shareSource, useRolldown, federationOptions);
|
|
9142
9594
|
if (!materializedLoadShareSources.has(shareSource)) {
|
|
9143
9595
|
materializedLoadShareSources.add(shareSource);
|
|
@@ -9460,7 +9912,6 @@ function pluginRemoteNamedExports(options) {
|
|
|
9460
9912
|
const MAX_RUNNER_BODY_BYTES = 1024 * 1024;
|
|
9461
9913
|
const MAX_RUNNER_START_OFFSET = 1024 * 1024;
|
|
9462
9914
|
const ALLOWED_RUNNER_INVOKE_NAMES = /* @__PURE__ */ new Set(["fetchModule", "getBuiltins"]);
|
|
9463
|
-
const VITE_FS_PREFIX = "/@fs/";
|
|
9464
9915
|
function isPlainObject(value) {
|
|
9465
9916
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
9466
9917
|
}
|
|
@@ -9479,12 +9930,6 @@ function isSafeRunnerFetchModuleOptions(value) {
|
|
|
9479
9930
|
}
|
|
9480
9931
|
return true;
|
|
9481
9932
|
}
|
|
9482
|
-
function stripQueryAndHash(id) {
|
|
9483
|
-
const queryIndex = id.indexOf("?");
|
|
9484
|
-
const hashIndex = id.indexOf("#");
|
|
9485
|
-
const endIndex = queryIndex === -1 ? hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
|
|
9486
|
-
return endIndex === -1 ? id : id.slice(0, endIndex);
|
|
9487
|
-
}
|
|
9488
9933
|
function decodeRunnerFilePath(filePath) {
|
|
9489
9934
|
try {
|
|
9490
9935
|
return decodeURIComponent(filePath);
|
|
@@ -9528,8 +9973,8 @@ function isSafeRunnerFetchModuleId(id, config) {
|
|
|
9528
9973
|
const cleanId = decodeRunnerFilePath(stripQueryAndHash(decoded));
|
|
9529
9974
|
if (!cleanId || hasRelativeTraversal(cleanId)) return false;
|
|
9530
9975
|
const allowedDirectories = getRunnerAllowedDirectories(config);
|
|
9531
|
-
if (cleanId.startsWith(
|
|
9532
|
-
const fsPath =
|
|
9976
|
+
if (cleanId.startsWith("/@fs/")) {
|
|
9977
|
+
const fsPath = stripViteFsPrefix(cleanId);
|
|
9533
9978
|
return path$1.isAbsolute(fsPath) && isPathWithinAllowedDirectories(fsPath, allowedDirectories);
|
|
9534
9979
|
}
|
|
9535
9980
|
if (path$1.isAbsolute(cleanId)) {
|
|
@@ -9944,11 +10389,7 @@ var aliasToArrayPlugin_default = {
|
|
|
9944
10389
|
};
|
|
9945
10390
|
//#endregion
|
|
9946
10391
|
//#region src/utils/controlChunkSanitizer.ts
|
|
9947
|
-
const FEDERATION_CONTROL_CHUNK_HINTS = [
|
|
9948
|
-
"hostInit",
|
|
9949
|
-
"virtualExposes",
|
|
9950
|
-
"localSharedImportMap"
|
|
9951
|
-
];
|
|
10392
|
+
const FEDERATION_CONTROL_CHUNK_HINTS = ["hostInit", "localSharedImportMap"];
|
|
9952
10393
|
function stripEmptyPreloadCalls(code) {
|
|
9953
10394
|
const helperImportRegex = /import\s*\{\s*_\s*as\s*([A-Za-z_$][\w$]*)\s*\}\s*from\s*["'][^"']+["']\s*;?/g;
|
|
9954
10395
|
const helperAliases = [];
|
|
@@ -10068,7 +10509,7 @@ function applyRuntimeCapabilityDefines(define, options, { defaultDisableSnapshot
|
|
|
10068
10509
|
function getRuntimeCapabilityConfigurationWarnings(options) {
|
|
10069
10510
|
const warnings = [];
|
|
10070
10511
|
if (options.disableRemote && Object.keys(options.remotes).length > 0) warnings.push("disableRemote is true, but remotes are configured. Remote loading will be unavailable at runtime.");
|
|
10071
|
-
if (options.disableShared &&
|
|
10512
|
+
if (options.disableShared && hasShared(options)) warnings.push("disableShared is true, but shared dependencies are configured. Shared dependency loading will be unavailable at runtime.");
|
|
10072
10513
|
return warnings;
|
|
10073
10514
|
}
|
|
10074
10515
|
//#endregion
|
|
@@ -10159,7 +10600,7 @@ function escapeUnsafeJsSourceChars(str) {
|
|
|
10159
10600
|
}
|
|
10160
10601
|
function isFederationHtmlPreloadDependency(dep, includeSharedRuntime = false) {
|
|
10161
10602
|
const file = path$1.basename(dep);
|
|
10162
|
-
if (file.includes("__mfe_internal__") || file.includes("virtual_mf-") || file.includes("
|
|
10603
|
+
if (file.includes("__mfe_internal__") || file.includes("virtual_mf-") || file.includes("localSharedImportMap") || file.includes("hostInit")) return true;
|
|
10163
10604
|
return includeSharedRuntime && (file.includes("preload-helper") || file.includes("rolldown-runtime") || file.startsWith("dist-"));
|
|
10164
10605
|
}
|
|
10165
10606
|
function canResolveSharedSubpath(subpath, projectRoot) {
|
|
@@ -10379,6 +10820,7 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
10379
10820
|
const resolvedConfiguredEntryFiles = (typeof buildInput === "string" ? [buildInput] : Array.isArray(buildInput) ? buildInput : buildInput && typeof buildInput === "object" ? Object.values(buildInput) : []).map((entry) => String(entry)).filter((entry) => !isReactRouterBuildClientRouteInput(entry)).map((entry) => entry.split(/[?#]/)[0]).map((entry) => path$1.isAbsolute(entry) ? entry : path$1.resolve(root, entry));
|
|
10380
10821
|
resetConcreteSharedImportSourceCache();
|
|
10381
10822
|
setPackageDetectionCwd(root);
|
|
10823
|
+
resolveSharedVersions(shared, root);
|
|
10382
10824
|
const isVinext = hasPackageDependency("vinext");
|
|
10383
10825
|
initVirtualModules(_command, getRemoteEntryId(options), false, options);
|
|
10384
10826
|
const isRolldown = getIsRolldown(this);
|
|
@@ -10391,11 +10833,11 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
10391
10833
|
config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
|
|
10392
10834
|
}
|
|
10393
10835
|
}
|
|
10394
|
-
if (!config.build?.ssr && (
|
|
10836
|
+
if (!config.build?.ssr && (hasShared(options) || hasRemotes(options))) {
|
|
10395
10837
|
const hasJsxSource = registerEntryImports(options, root, _command === "serve", resolvedConfiguredEntryFiles);
|
|
10396
10838
|
if (_command === "serve") hasClientJsxSource = hasJsxSource;
|
|
10397
10839
|
}
|
|
10398
|
-
if (
|
|
10840
|
+
if (hasShared(options)) {
|
|
10399
10841
|
if (_command === "serve") {
|
|
10400
10842
|
excludeSharedSubDependencies(shared);
|
|
10401
10843
|
config.optimizeDeps = config.optimizeDeps || {};
|
|
@@ -10568,9 +11010,7 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
10568
11010
|
const automaticJsxRuntime = getAutomaticJsxRuntime(config);
|
|
10569
11011
|
if (automaticJsxRuntime && materializeAutomaticJsxRuntime(options, automaticJsxRuntime)) writeLocalSharedImportMap(options);
|
|
10570
11012
|
}
|
|
10571
|
-
|
|
10572
|
-
const hasRemotes = Object.keys(options.remotes).length > 0;
|
|
10573
|
-
if (!getSsrCapabilities(viteMajor, config.command, hasRemotes).injectSsrEntryLoader) return;
|
|
11013
|
+
if (!getSsrCapabilities(parseInt(version, 10), config.command, hasRemotes(options)).injectSsrEntryLoader) return;
|
|
10574
11014
|
if (options.runtimePlugins.some((p) => {
|
|
10575
11015
|
return (typeof p === "string" ? p : p[0]) === "@module-federation/vite/ssrEntryLoader";
|
|
10576
11016
|
})) return;
|
|
@@ -10597,7 +11037,10 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
10597
11037
|
const ssrEntryLoaderSpecifier = SSR_ENTRY_LOADER_SPECIFIER;
|
|
10598
11038
|
try {
|
|
10599
11039
|
resolveImportPath(ssrEntryLoaderSpecifier);
|
|
10600
|
-
options.runtimePlugins.push([ssrEntryLoaderSpecifier, {
|
|
11040
|
+
options.runtimePlugins.push([ssrEntryLoaderSpecifier, {
|
|
11041
|
+
resolvedShared,
|
|
11042
|
+
...options.ssrEntryLoader?.strategy ? { strategy: options.ssrEntryLoader.strategy } : {}
|
|
11043
|
+
}]);
|
|
10601
11044
|
} catch {}
|
|
10602
11045
|
}
|
|
10603
11046
|
};
|
|
@@ -10613,7 +11056,7 @@ function applyBuildTimeRuntimeDefines(define, options, { target, isAstro, defaul
|
|
|
10613
11056
|
}
|
|
10614
11057
|
function loadPluginDts(options) {
|
|
10615
11058
|
if (options.dts === false) return [];
|
|
10616
|
-
return [import("./pluginDts-
|
|
11059
|
+
return [import("./pluginDts-CQ088qGF.js").then(({ default: pluginDts }) => pluginDts(options))];
|
|
10617
11060
|
}
|
|
10618
11061
|
const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
|
|
10619
11062
|
function isInjectExternalRuntimeCorePlugin(specifier) {
|
|
@@ -10638,7 +11081,6 @@ function resolveInjectExternalRuntimeCorePlugin() {
|
|
|
10638
11081
|
function applyExternalRuntimeExperiments(options) {
|
|
10639
11082
|
const { experiments } = options;
|
|
10640
11083
|
if (experiments.provideExternalRuntime) {
|
|
10641
|
-
if (Object.keys(options.exposes).length > 0) throw createModuleFederationError("You can only set provideExternalRuntime: true in pure consumer which not expose modules.");
|
|
10642
11084
|
if (!hasInjectExternalRuntimeCorePlugin(options.runtimePlugins)) options.runtimePlugins = options.runtimePlugins.concat(resolveInjectExternalRuntimeCorePlugin());
|
|
10643
11085
|
}
|
|
10644
11086
|
}
|
|
@@ -10654,7 +11096,7 @@ function federation(mfUserOptions) {
|
|
|
10654
11096
|
const virtualExposesId = getVirtualExposesId(options);
|
|
10655
11097
|
const moduleParseController = createModuleParseController();
|
|
10656
11098
|
const moduleParsePlugins = pluginModuleParseEnd_default((id) => {
|
|
10657
|
-
return id.includes(getHostAutoInitPath(options)) || id.includes(getPendingSharesPath(options)) || id.includes(
|
|
11099
|
+
return id.includes(getHostAutoInitPath(options)) || id.includes(getPendingSharesPath(options)) || id.includes("virtual:mf-REMOTE_ENTRY_ID") || id.includes(virtualExposesId) || id.includes("virtual:mf-localSharedImportMap") || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
|
|
10658
11100
|
}, {
|
|
10659
11101
|
moduleParseTimeout: options.moduleParseTimeout,
|
|
10660
11102
|
moduleParseIdleTimeout: options.moduleParseIdleTimeout,
|
|
@@ -10795,6 +11237,7 @@ function federation(mfUserOptions) {
|
|
|
10795
11237
|
ssrTarget = config.ssr?.target ?? "node";
|
|
10796
11238
|
isProduction = config.isProduction;
|
|
10797
11239
|
const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, Object.keys(options.remotes).length > 0);
|
|
11240
|
+
resolveSharedVersions(shared, config.root);
|
|
10798
11241
|
initVirtualModules(command, remoteEntryId, ssrCapabilities.enableSsrInitBootstrap, options);
|
|
10799
11242
|
}
|
|
10800
11243
|
},
|
|
@@ -10829,11 +11272,6 @@ function federation(mfUserOptions) {
|
|
|
10829
11272
|
skipTransformFor: Object.values(options.exposes).map((expose) => expose.import),
|
|
10830
11273
|
federationOptions: options
|
|
10831
11274
|
}),
|
|
10832
|
-
...addEntry({
|
|
10833
|
-
entryName: "virtualExposes",
|
|
10834
|
-
entryPath: virtualExposesId,
|
|
10835
|
-
federationOptions: options
|
|
10836
|
-
}),
|
|
10837
11275
|
pluginProxyRemoteEntry_default({
|
|
10838
11276
|
options,
|
|
10839
11277
|
remoteEntryId,
|
|
@@ -10857,6 +11295,10 @@ function federation(mfUserOptions) {
|
|
|
10857
11295
|
const runtimeInitId = getRuntimeInitStatusImportId(options);
|
|
10858
11296
|
config.build = config.build || {};
|
|
10859
11297
|
if (config.build.modulePreload !== false) {
|
|
11298
|
+
const remoteEntryBasename = path$1.posix.basename(options.filename);
|
|
11299
|
+
const hashParts = remoteEntryBasename.split(/\[hash(?::\d+)?\]/);
|
|
11300
|
+
const remoteEntryFilePattern = new RegExp(`^${hashParts.map((part) => escapeRegExp(part)).join("[\\w-]+")}${hashParts.length > 1 && !/\.[^/.]+$/.test(remoteEntryBasename) ? "\\.js" : ""}$`);
|
|
11301
|
+
const isRemoteEntryFile = (file) => file === remoteEntryBasename || remoteEntryFilePattern.test(file);
|
|
10860
11302
|
const currentModulePreload = config.build.modulePreload && typeof config.build.modulePreload === "object" ? config.build.modulePreload : {};
|
|
10861
11303
|
const existingResolveDependencies = currentModulePreload.resolveDependencies;
|
|
10862
11304
|
config.build.modulePreload = {
|
|
@@ -10864,7 +11306,7 @@ function federation(mfUserOptions) {
|
|
|
10864
11306
|
resolveDependencies(filename, deps, context) {
|
|
10865
11307
|
const resolvedDeps = existingResolveDependencies ? existingResolveDependencies(filename, deps, context) : deps;
|
|
10866
11308
|
const hostFile = path$1.basename(context.hostId);
|
|
10867
|
-
if (context.hostType === "js" && (hostFile
|
|
11309
|
+
if (context.hostType === "js" && (isRemoteEntryFile(hostFile) || hostFile.includes("hostInit") || hostFile.includes("localSharedImportMap"))) return [];
|
|
10868
11310
|
const hasFederationHtmlDeps = context.hostType === "html" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
|
|
10869
11311
|
const hasFederationJsDeps = context.hostType === "js" && resolvedDeps.some((dep) => isFederationHtmlPreloadDependency(dep));
|
|
10870
11312
|
const treeShakingFallbackDeps = hasTreeShakingShared ? (dep) => dep.includes("__prebuild__") : () => false;
|
|
@@ -10903,6 +11345,10 @@ function federation(mfUserOptions) {
|
|
|
10903
11345
|
const mfChunkName = function(id) {
|
|
10904
11346
|
if (id.includes(runtimeInitId) || id.includes("__mf_v__runtimeInit__mf_v__")) return "runtimeInit";
|
|
10905
11347
|
if (id.includes("__loadShare__")) {
|
|
11348
|
+
const pkg = getCachedLoadSharePkg(id);
|
|
11349
|
+
const key = pkg && findSharedKey(pkg, shared);
|
|
11350
|
+
if (key && shared[key].shareConfig.eager === true) return "loadShare-eager";
|
|
11351
|
+
if (key && shared[key].shareConfig.import === false) return null;
|
|
10906
11352
|
const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
|
|
10907
11353
|
return match ? match[1] : "loadShare";
|
|
10908
11354
|
}
|
|
@@ -11011,8 +11457,8 @@ function federation(mfUserOptions) {
|
|
|
11011
11457
|
const virtualModule = VirtualModule.findById(id);
|
|
11012
11458
|
if (!virtualModule?.code) return null;
|
|
11013
11459
|
let code = virtualModule.code;
|
|
11014
|
-
const
|
|
11015
|
-
if (
|
|
11460
|
+
const consumerTarget = resolveEnvironmentConsumerTarget(this);
|
|
11461
|
+
if (consumerTarget === "server" || !consumerTarget && isSsrBuild) code = prependWorkspaceSingletonSsrImport(code);
|
|
11016
11462
|
code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
11017
11463
|
code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
11018
11464
|
if (!(/\b(?:var|let|const)\s+__moduleExports\b/.test(code) || /\bexport\s+const\s+__moduleExports\b/.test(code) || /\bexport\s*\{[^}]*__moduleExports/.test(code))) {
|
|
@@ -11078,7 +11524,7 @@ function federation(mfUserOptions) {
|
|
|
11078
11524
|
config(config, { command: _command }) {
|
|
11079
11525
|
const isRolldown = getIsRolldown(this);
|
|
11080
11526
|
isSsrBuild = _command === "build" && Boolean(config.build?.ssr);
|
|
11081
|
-
const needsRuntimeHelpers =
|
|
11527
|
+
const needsRuntimeHelpers = hasShared(options);
|
|
11082
11528
|
if (needsRuntimeHelpers) appendResolveAlias(config, {
|
|
11083
11529
|
find: /^@module-federation\/runtime\/helpers$/,
|
|
11084
11530
|
replacement: getRuntimeHelpersImplementation(options.implementation)
|