@module-federation/vite 1.22.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -1
- package/lib/{dtsConstants-BEGrtvcw.js → dtsConstants-DEMpRfBz.js} +248 -62
- package/lib/index.d.ts +14 -1
- package/lib/index.js +1689 -721
- package/lib/{pluginDts-D7Faa4NJ.js → pluginDts-VSLhAx6d.js} +1 -1
- package/lib/{sharedKeyMatcher-DiUzRVH1.js → sharedKeyMatcher-Od_nYxJA.js} +57 -34
- package/lib/{ssrEntryLoader-CMVCDSsG.js → ssrEntryLoader-BvAkpCyi.js} +1 -1
- package/lib/{ssrVmStrategy-Cx9WlTsx.js → ssrVmStrategy-CDbcwMnf.js} +2 -2
- package/lib/utils/ssrEntryLoader.js +1 -1
- package/package.json +4 -4
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { _ as resolvePublicPath, a as matchesSharedSource, c as filterId, d as getNodeModulesSuffix, f as isAssetLikeImport, g as normalizeNodeModulePath, h as isViteOptimizableEntry, i as invalidateSharedKeyMatcher, l as getBasePath$1, m as isNuxtClientBase, n as getSharedRequest, p as isNodeModulePath, r as getSharedRuntimeKey, s as ensureTrailingSlash, t as findSharedKey, u as getCommonSharedSubpaths, v as stripQueryAndHash, y as stripViteFsPrefix } from "./sharedKeyMatcher-Od_nYxJA.js";
|
|
1
2
|
import { i as resolveHashPlaceholderFileName, n as normalizePathForImport, r as rebaseImport } from "./buildPaths-BoaQTkxt.js";
|
|
2
|
-
import { a 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 { C as isReactCoreShare, E as mfWarn, S as REACT_DOM_CLIENT_SHARE, _ as resolveModulePath, a as getIsRolldown, b as supportsCodeSplittingGroupDebugName, c as getPackageNameFromNodeModulePath, d as isNuxtProjectRoot, f as isPackageExportAvailable, g as resolveImportPath, h as packageNameEncode, i as getInstalledPackageJson, l as getSharedCacheDescriptor, m as packageNameDecode, n as getDependencyNames, o as getPackageDetectionCwd, p as isPackageInstalled, r as getInstalledPackageEntry, s as getPackageName, u as hasPackageDependency, v as setPackageDetectionCwd, w as createModuleFederationError, x as REACT_CLIENT_INTERNALS_KEY, y as sharedCacheHelperCode } from "./dtsConstants-DEMpRfBz.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";
|
|
@@ -8,6 +8,7 @@ import { createRequire as createRequire$1, isBuiltin } from "module";
|
|
|
8
8
|
import * as path$1 from "node:path";
|
|
9
9
|
import path, { basename } from "node:path";
|
|
10
10
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
11
|
+
import * as vite from "vite";
|
|
11
12
|
import { parseAst, version } from "vite";
|
|
12
13
|
import { createHash } from "node:crypto";
|
|
13
14
|
import * as fs$1 from "node:fs";
|
|
@@ -400,6 +401,16 @@ function resolveEnvironmentConsumerTarget(ctx) {
|
|
|
400
401
|
function isClientEnvironment(ctx) {
|
|
401
402
|
return resolveEnvironmentConsumerTarget(ctx) !== "server";
|
|
402
403
|
}
|
|
404
|
+
/**
|
|
405
|
+
* Whether a build hook runs for a server graph. Vite 6+ hooks carry an
|
|
406
|
+
* environment; Vite 5 (and hooks invoked before `configResolved`) fall back to
|
|
407
|
+
* the legacy root `build.ssr` flag.
|
|
408
|
+
*/
|
|
409
|
+
function isServerBuildContext(ctx, config) {
|
|
410
|
+
const target = resolveEnvironmentConsumerTarget(ctx);
|
|
411
|
+
if (target) return target === "server";
|
|
412
|
+
return Boolean(config?.build?.ssr);
|
|
413
|
+
}
|
|
403
414
|
function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
|
|
404
415
|
if (!hasMultiEnvironment) return "unified";
|
|
405
416
|
return resolveEnvironmentConsumerTarget(ctx) ?? "client";
|
|
@@ -431,7 +442,7 @@ function isJsxClosingTagSlash(code, slashIndex) {
|
|
|
431
442
|
return code[cursor] === ">";
|
|
432
443
|
}
|
|
433
444
|
/** Mark comments, string/template literals, and regular expressions as non-code. */
|
|
434
|
-
function createCodePositionMap(code) {
|
|
445
|
+
function createCodePositionMap(code, onComment) {
|
|
435
446
|
const positions = Array(code.length).fill(true);
|
|
436
447
|
const mask = (start, end) => {
|
|
437
448
|
for (let index = start; index < end; index++) positions[index] = false;
|
|
@@ -449,6 +460,7 @@ function createCodePositionMap(code) {
|
|
|
449
460
|
index += 2;
|
|
450
461
|
while (index < code.length && code[index] !== "\n" && code[index] !== "\r") index++;
|
|
451
462
|
mask(start, index);
|
|
463
|
+
onComment?.(start, index);
|
|
452
464
|
continue;
|
|
453
465
|
}
|
|
454
466
|
if (char === "/" && next === "*") {
|
|
@@ -457,6 +469,7 @@ function createCodePositionMap(code) {
|
|
|
457
469
|
while (index < code.length && !(code[index] === "*" && code[index + 1] === "/")) index++;
|
|
458
470
|
index = Math.min(code.length, index + 2);
|
|
459
471
|
mask(start, index);
|
|
472
|
+
onComment?.(start, index);
|
|
460
473
|
continue;
|
|
461
474
|
}
|
|
462
475
|
if (char === "\"" || char === "'" || char === "`") {
|
|
@@ -762,8 +775,8 @@ function normalizeRemoteItem(key, remote) {
|
|
|
762
775
|
* @param {string} sharedName
|
|
763
776
|
* @returns {string | undefined}
|
|
764
777
|
*/
|
|
765
|
-
function searchPackageVersion(sharedName) {
|
|
766
|
-
const version = getInstalledPackageJson(sharedName)?.packageJson.version;
|
|
778
|
+
function searchPackageVersion(sharedName, cwd) {
|
|
779
|
+
const version = getInstalledPackageJson(sharedName, { cwd })?.packageJson.version;
|
|
767
780
|
return typeof version === "string" ? version : void 0;
|
|
768
781
|
}
|
|
769
782
|
function inferVersionFromRequiredVersion(requiredVersion) {
|
|
@@ -798,36 +811,93 @@ const PACKAGE_SPECIFIER_PROTOCOL_RE = /^[a-z][a-z\d+.-]*:/i;
|
|
|
798
811
|
function isProtocolRequiredVersion(requiredVersion) {
|
|
799
812
|
return PACKAGE_SPECIFIER_PROTOCOL_RE.test(requiredVersion.trim());
|
|
800
813
|
}
|
|
814
|
+
const SEMVER_COMPARATOR_RE = /^(?:[<>=~^]*v?(?:\d+|[xX*])(?:\.(?:\d+|[xX*]))*(?:[-+][\w.-]+)?|[<>=~^]+|[xX*]|-)$/;
|
|
815
|
+
function isSemverRange(range) {
|
|
816
|
+
return range.split("||").every((alternative) => {
|
|
817
|
+
const comparators = alternative.trim().split(/\s+/).filter(Boolean);
|
|
818
|
+
return comparators.length > 0 && comparators.every((c) => SEMVER_COMPARATOR_RE.test(c));
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
function isUsableRequiredVersion(requiredVersion) {
|
|
822
|
+
return requiredVersion.trim() !== "" && !isProtocolRequiredVersion(requiredVersion) && isSemverRange(requiredVersion);
|
|
823
|
+
}
|
|
824
|
+
/** Bare specifiers name an installed package; relative/absolute paths do not. */
|
|
825
|
+
function isBareSpecifier(specifier) {
|
|
826
|
+
return !specifier.startsWith(".") && !specifier.startsWith("\0") && !path$1.isAbsolute(specifier) && !PACKAGE_SPECIFIER_PROTOCOL_RE.test(specifier);
|
|
827
|
+
}
|
|
828
|
+
function readProjectPackageJson(cwd, cache) {
|
|
829
|
+
if (cache.has(cwd)) return cache.get(cwd);
|
|
830
|
+
let packageJson;
|
|
831
|
+
try {
|
|
832
|
+
packageJson = JSON.parse(fs$2.readFileSync(path$1.join(cwd, "package.json"), "utf8"));
|
|
833
|
+
} catch {}
|
|
834
|
+
cache.set(cwd, packageJson);
|
|
835
|
+
return packageJson;
|
|
836
|
+
}
|
|
801
837
|
function getLitExportSubpathShares(sharedName) {
|
|
802
838
|
if (sharedName !== "lit") return [];
|
|
803
839
|
const exportsField = getInstalledPackageJson(sharedName, { packageName: sharedName })?.packageJson.exports;
|
|
804
840
|
if (!exportsField || typeof exportsField === "string") return [];
|
|
805
841
|
return Object.keys(exportsField).filter((key) => key.startsWith("./") && key !== "." && !key.includes("*")).map((key) => `${sharedName}/${key.slice(2)}`);
|
|
806
842
|
}
|
|
843
|
+
const sharedVersionConfigs = /* @__PURE__ */ new WeakMap();
|
|
844
|
+
function resolveSharedVersion(key, config, cwd, packageJsonCache = /* @__PURE__ */ new Map(), fallbackVersion) {
|
|
845
|
+
const source = typeof config.import === "string" && isBareSpecifier(config.import) ? config.import : key;
|
|
846
|
+
const version = config.version || searchPackageVersion(source, cwd) || inferVersionFromRequiredVersion(config.requiredVersion) || fallbackVersion;
|
|
847
|
+
let requiredVersion = config.requiredVersion;
|
|
848
|
+
if (requiredVersion === void 0 && !config.version) {
|
|
849
|
+
const packageJson = readProjectPackageJson(cwd, packageJsonCache);
|
|
850
|
+
const packageName = getPackageName(source);
|
|
851
|
+
requiredVersion = packageJson?.dependencies?.[packageName] ?? packageJson?.devDependencies?.[packageName] ?? packageJson?.peerDependencies?.[packageName] ?? packageJson?.optionalDependencies?.[packageName];
|
|
852
|
+
}
|
|
853
|
+
if (requiredVersion === false || typeof requiredVersion === "string" && isUsableRequiredVersion(requiredVersion)) return {
|
|
854
|
+
version,
|
|
855
|
+
requiredVersion
|
|
856
|
+
};
|
|
857
|
+
return {
|
|
858
|
+
version,
|
|
859
|
+
requiredVersion: config.import === false || config.version ? "*" : version ? `^${version}` : "*"
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
function resolveSharedVersions(shared, root) {
|
|
863
|
+
const packageJsonCache = /* @__PURE__ */ new Map();
|
|
864
|
+
for (const [key, item] of Object.entries(shared)) {
|
|
865
|
+
const config = sharedVersionConfigs.get(item);
|
|
866
|
+
if (!config) continue;
|
|
867
|
+
const { version, requiredVersion } = resolveSharedVersion(key, config, root, packageJsonCache, item.version);
|
|
868
|
+
item.version = version;
|
|
869
|
+
item.shareConfig.requiredVersion = requiredVersion;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
807
872
|
function normalizeShareItem(key, shareItem) {
|
|
808
|
-
const isImportFalse = typeof shareItem === "object" && shareItem.import === false;
|
|
809
|
-
const explicitVersion = typeof shareItem === "object" ? shareItem.version : void 0;
|
|
810
|
-
const inferredVersion = typeof shareItem === "object" ? inferVersionFromRequiredVersion(shareItem.requiredVersion) : void 0;
|
|
811
873
|
const treeShaking = typeof shareItem === "object" ? shareItem.treeShaking : void 0;
|
|
812
874
|
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".`);
|
|
813
875
|
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.`);
|
|
876
|
+
if (typeof shareItem === "object") {
|
|
877
|
+
const request = typeof shareItem.request === "string" ? shareItem.request : key;
|
|
878
|
+
const shareKey = typeof shareItem.shareKey === "string" ? shareItem.shareKey : key;
|
|
879
|
+
if (request.endsWith("/") !== shareKey.endsWith("/")) throw createModuleFederationError(`Invalid shared config for "${key}": "request" and "shareKey" must both end with "/" for a prefix share, or neither. Got request "${request}" and shareKey "${shareKey}".`);
|
|
880
|
+
}
|
|
814
881
|
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.`);
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
882
|
+
const config = typeof shareItem === "object" ? shareItem : {};
|
|
883
|
+
const { version, requiredVersion } = resolveSharedVersion(key, config, getPackageDetectionCwd());
|
|
884
|
+
if (typeof shareItem === "string") {
|
|
885
|
+
const result = {
|
|
886
|
+
name: shareItem,
|
|
887
|
+
version,
|
|
888
|
+
scope: "default",
|
|
889
|
+
from: "",
|
|
890
|
+
shareConfig: {
|
|
891
|
+
import: void 0,
|
|
892
|
+
singleton: false,
|
|
893
|
+
eager: false,
|
|
894
|
+
requiredVersion
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
sharedVersionConfigs.set(result, { ...config });
|
|
898
|
+
return result;
|
|
899
|
+
}
|
|
900
|
+
const result = {
|
|
831
901
|
name: key,
|
|
832
902
|
from: "",
|
|
833
903
|
version,
|
|
@@ -836,12 +906,17 @@ function normalizeShareItem(key, shareItem) {
|
|
|
836
906
|
import: shareItem.import,
|
|
837
907
|
singleton: shareItem.singleton || false,
|
|
838
908
|
eager: shareItem.eager || false,
|
|
839
|
-
requiredVersion
|
|
909
|
+
requiredVersion,
|
|
840
910
|
strictVersion: !!shareItem.strictVersion,
|
|
911
|
+
...shareItem.request !== void 0 ? { request: shareItem.request } : {},
|
|
912
|
+
...shareItem.shareKey !== void 0 ? { shareKey: shareItem.shareKey } : {},
|
|
913
|
+
...shareItem.allowNodeModulesSuffixMatch !== void 0 ? { allowNodeModulesSuffixMatch: shareItem.allowNodeModulesSuffixMatch } : {},
|
|
841
914
|
...shareItem.suppressMissingImportWarning ? { suppressMissingImportWarning: true } : {},
|
|
842
915
|
...treeShaking ? { treeShaking: { ...treeShaking } } : {}
|
|
843
916
|
}
|
|
844
917
|
};
|
|
918
|
+
sharedVersionConfigs.set(result, { ...config });
|
|
919
|
+
return result;
|
|
845
920
|
}
|
|
846
921
|
/**
|
|
847
922
|
* Trailing-slash keys are package namespace prefixes (`lodash/`, `@scope/ui/`).
|
|
@@ -885,7 +960,8 @@ function normalizeShared(shared) {
|
|
|
885
960
|
const value = shared[key];
|
|
886
961
|
const hadConfiguredPackageSubpath = (result[normalizedKey]?.shareConfig)?.__mfConfiguredPackageSubpath === true;
|
|
887
962
|
result[normalizedKey] = normalizeShareItem(normalizedKey, value);
|
|
888
|
-
|
|
963
|
+
const requestIsPrefix = typeof value?.request === "string" && value.request.endsWith("/");
|
|
964
|
+
if (key.endsWith("/") || requestIsPrefix || hadConfiguredPackageSubpath) result[normalizedKey].shareConfig.__mfConfiguredPackageSubpath = true;
|
|
889
965
|
explicitSharedKeys.add(normalizedKey);
|
|
890
966
|
sourceEntries.push([normalizedKey, value]);
|
|
891
967
|
});
|
|
@@ -945,6 +1021,9 @@ function getNormalizeModuleFederationOptions() {
|
|
|
945
1021
|
function hasRemotes(options = getNormalizeModuleFederationOptions()) {
|
|
946
1022
|
return Object.keys(options.remotes || {}).length > 0;
|
|
947
1023
|
}
|
|
1024
|
+
function hasShared(options = getNormalizeModuleFederationOptions()) {
|
|
1025
|
+
return Object.keys(options.shared || {}).length > 0;
|
|
1026
|
+
}
|
|
948
1027
|
function isRemoteContainer(options = getNormalizeModuleFederationOptions()) {
|
|
949
1028
|
return Object.keys(options.exposes || {}).length > 0;
|
|
950
1029
|
}
|
|
@@ -958,7 +1037,13 @@ function isExplicitSharedKey(key, options) {
|
|
|
958
1037
|
return (options ? explicitSharedKeysByOptions.get(options) : explicitSharedKeys)?.has(key) ?? false;
|
|
959
1038
|
}
|
|
960
1039
|
function getNormalizeShareItem(key, options = getNormalizeModuleFederationOptions()) {
|
|
961
|
-
|
|
1040
|
+
const matchedKey = findSharedKey(key, options.shared);
|
|
1041
|
+
const shareItem = options.shared[key] || (matchedKey ? options.shared[matchedKey] : void 0) || options.shared[getPackageName(key)] || options.shared[getPackageName(key) + "/"];
|
|
1042
|
+
if (shareItem) return shareItem;
|
|
1043
|
+
return Object.entries(options.shared).find(([sharedKey, item]) => {
|
|
1044
|
+
const runtimeKey = typeof item.shareConfig.shareKey === "string" ? item.shareConfig.shareKey : sharedKey;
|
|
1045
|
+
return runtimeKey.endsWith("/") ? key === runtimeKey.slice(0, -1) || key.startsWith(runtimeKey) : runtimeKey === key;
|
|
1046
|
+
})?.[1];
|
|
962
1047
|
}
|
|
963
1048
|
function normalizeModuleFederationOptions(options) {
|
|
964
1049
|
warnOnReservedInternalNamePrefix(options.name, "containerName");
|
|
@@ -966,6 +1051,7 @@ function normalizeModuleFederationOptions(options) {
|
|
|
966
1051
|
const normalized = {
|
|
967
1052
|
exposes: normalizeExposes(options.exposes),
|
|
968
1053
|
filename: options.filename || "remoteEntry-[hash]",
|
|
1054
|
+
ssrFilename: options.ssrFilename || void 0,
|
|
969
1055
|
internalName: toInternalModuleFederationName(options.name),
|
|
970
1056
|
library: normalizeLibrary(options.library),
|
|
971
1057
|
name: options.name,
|
|
@@ -1071,6 +1157,10 @@ var VirtualModule = class VirtualModule {
|
|
|
1071
1157
|
if (!cacheMap[this.tag]) cacheMap[this.tag] = {};
|
|
1072
1158
|
cacheMap[this.tag][this.name] = this;
|
|
1073
1159
|
}
|
|
1160
|
+
/** The federation scope this module was created under, if it was scoped. */
|
|
1161
|
+
getScopeName() {
|
|
1162
|
+
return this.scopeName;
|
|
1163
|
+
}
|
|
1074
1164
|
getImportId() {
|
|
1075
1165
|
const mfName = this.scopeName ?? getNormalizeModuleFederationOptions().internalName;
|
|
1076
1166
|
const importIdKey = `${mfName}${this.tag}${this.name}${this.tag}`;
|
|
@@ -1102,17 +1192,38 @@ const SERVER_ENV_GUARD = "import.meta.env.SSR";
|
|
|
1102
1192
|
const SSR_ENTRY_LOADER_SPECIFIER = "@module-federation/vite/ssrEntryLoader";
|
|
1103
1193
|
const SSR_ONLY_RUNTIME_PLUGINS = /* @__PURE__ */ new Set([SSR_ENTRY_LOADER_SPECIFIER]);
|
|
1104
1194
|
/**
|
|
1195
|
+
* Whether a Vite environment builds a server graph.
|
|
1196
|
+
*
|
|
1197
|
+
* Vite 6+ sets `consumer` on the environment config; `build.ssr` covers the
|
|
1198
|
+
* legacy `vite build --ssr` flag. Environment names are user-defined, so `ssr`
|
|
1199
|
+
* and `server` are only a fallback for configs that carry neither field.
|
|
1200
|
+
*/
|
|
1201
|
+
function isServerEnvironment(name, config) {
|
|
1202
|
+
return config?.consumer === "server" || Boolean(config?.build?.ssr) || name === "ssr" || name === "server";
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Whether a resolved Vite config includes a server graph: the legacy
|
|
1206
|
+
* `build.ssr` flag, or any server environment. Vite always registers an `ssr`
|
|
1207
|
+
* environment for `serve`, so this only gates builds.
|
|
1208
|
+
*/
|
|
1209
|
+
function isSsrConfig(config) {
|
|
1210
|
+
if (Boolean(config.build?.ssr)) return true;
|
|
1211
|
+
return Object.entries(config.environments ?? {}).some(([name, environment]) => isServerEnvironment(name, environment));
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1105
1214
|
* Single source of truth for SSR-related feature gates.
|
|
1106
1215
|
*
|
|
1107
|
-
* - Vite 8+
|
|
1108
|
-
*
|
|
1216
|
+
* - Vite 8+ server environments: ModuleRunner + FetchableDevEnvironment for
|
|
1217
|
+
* `/__mf_ssr__/` entries.
|
|
1218
|
+
* - SSR builds on any Vite major: HTTP fetch + temp-file import via
|
|
1219
|
+
* ssrEntryLoader.
|
|
1109
1220
|
*/
|
|
1110
|
-
function getSsrCapabilities(viteMajor, command, hasRemotes) {
|
|
1221
|
+
function getSsrCapabilities(viteMajor, command, hasRemotes, isSsr = false) {
|
|
1111
1222
|
if (!hasRemotes) return {
|
|
1112
1223
|
enableSsrInitBootstrap: false,
|
|
1113
1224
|
injectSsrEntryLoader: false
|
|
1114
1225
|
};
|
|
1115
|
-
const supported = command === "build" || command === "serve" && viteMajor >= 8;
|
|
1226
|
+
const supported = isSsr && (command === "build" || command === "serve" && viteMajor >= 8);
|
|
1116
1227
|
return {
|
|
1117
1228
|
enableSsrInitBootstrap: supported,
|
|
1118
1229
|
injectSsrEntryLoader: supported
|
|
@@ -1216,171 +1327,517 @@ function isParsableExpression(source) {
|
|
|
1216
1327
|
}
|
|
1217
1328
|
}
|
|
1218
1329
|
//#endregion
|
|
1219
|
-
//#region src/utils/
|
|
1220
|
-
|
|
1221
|
-
"
|
|
1222
|
-
".jsx",
|
|
1223
|
-
".ts",
|
|
1224
|
-
".js",
|
|
1225
|
-
".mts",
|
|
1226
|
-
".mjs",
|
|
1227
|
-
".cts",
|
|
1228
|
-
".cjs"
|
|
1229
|
-
];
|
|
1230
|
-
function stripQueryAndHash$2(id) {
|
|
1231
|
-
return id.split(/[?#]/, 1)[0];
|
|
1232
|
-
}
|
|
1233
|
-
function resolveSourceFile(importPath, root) {
|
|
1234
|
-
const cleanImport = stripQueryAndHash$2(importPath);
|
|
1235
|
-
if (!cleanImport.startsWith(".") && !path$1.isAbsolute(cleanImport)) return;
|
|
1236
|
-
const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
|
|
1237
|
-
return [
|
|
1238
|
-
candidate,
|
|
1239
|
-
...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
|
|
1240
|
-
...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
|
|
1241
|
-
].find((filePath) => {
|
|
1242
|
-
try {
|
|
1243
|
-
return fs$1.statSync(filePath).isFile();
|
|
1244
|
-
} catch {
|
|
1245
|
-
return false;
|
|
1246
|
-
}
|
|
1247
|
-
});
|
|
1248
|
-
}
|
|
1249
|
-
function localDefaultReexport(source) {
|
|
1250
|
-
const match = source.match(/export\s*{\s*(?:default(?:\s+as\s+default)?|[A-Za-z_$][\w$]*\s+as\s+default)\s*}\s*from\s*["']([^"']+)["']/);
|
|
1251
|
-
return match?.[1]?.startsWith(".") ? match[1] : void 0;
|
|
1252
|
-
}
|
|
1253
|
-
function isReactComponentSource(source, filePath = "component.tsx") {
|
|
1254
|
-
if (!(/\bexport\s+default\b/.test(source) || /\bexport\s*{[^}]*\bdefault\b[^}]*}(?:\s*from\s*["'][^"']+["'])?/.test(source))) return false;
|
|
1255
|
-
const extension = path$1.extname(stripQueryAndHash$2(filePath)).toLowerCase();
|
|
1256
|
-
const canContainJsx = extension === ".tsx" || extension === ".jsx";
|
|
1257
|
-
const hasJsx = /<>|<\s*[A-Za-z][\w.:-]*(?:\s[^<>]*?)?\s*\/?>/.test(source);
|
|
1258
|
-
const importsReact = /\bfrom\s*["']react["']|\brequire\(\s*["']react["']\s*\)/.test(source);
|
|
1259
|
-
const usesReactApi = /\b(?:React\.)?(?:createElement|jsx|jsxs)\s*\(/.test(source);
|
|
1260
|
-
const isClientModule = /^\s*["']use client["']\s*;?/m.test(source);
|
|
1261
|
-
return canContainJsx && hasJsx || importsReact && (hasJsx || usesReactApi || isClientModule);
|
|
1330
|
+
//#region src/utils/runtimePluginSpecifier.ts
|
|
1331
|
+
function getRuntimePluginSpecifier(plugin) {
|
|
1332
|
+
return typeof plugin === "string" ? plugin : plugin[0];
|
|
1262
1333
|
}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
if (
|
|
1266
|
-
|
|
1267
|
-
let source;
|
|
1268
|
-
try {
|
|
1269
|
-
source = fs$1.readFileSync(normalizedPath, "utf8");
|
|
1270
|
-
} catch {
|
|
1271
|
-
return false;
|
|
1272
|
-
}
|
|
1273
|
-
if (isReactComponentSource(source, normalizedPath)) return true;
|
|
1274
|
-
const reexport = localDefaultReexport(source);
|
|
1275
|
-
if (!reexport) return false;
|
|
1276
|
-
const reexportPath = resolveSourceFile(reexport, path$1.dirname(normalizedPath));
|
|
1277
|
-
return reexportPath ? isReactComponentFile(reexportPath, seen) : false;
|
|
1334
|
+
/** Drop SSR-only plugins from a client graph; a server graph keeps them all. */
|
|
1335
|
+
function filterRuntimePluginsForTarget(runtimePlugins, ssrOnlySpecifiers, isServer) {
|
|
1336
|
+
if (isServer) return [...runtimePlugins];
|
|
1337
|
+
return runtimePlugins.filter((plugin) => !ssrOnlySpecifiers.has(getRuntimePluginSpecifier(plugin)));
|
|
1278
1338
|
}
|
|
1339
|
+
//#endregion
|
|
1340
|
+
//#region src/utils/importAnalysis.ts
|
|
1341
|
+
const analysisByBuild = /* @__PURE__ */ new WeakMap();
|
|
1279
1342
|
/**
|
|
1280
|
-
*
|
|
1281
|
-
*
|
|
1282
|
-
*
|
|
1343
|
+
* Share source analysis within one build environment. Callers still resolve
|
|
1344
|
+
* requests and apply their own sharing configuration. Clear at buildStart and
|
|
1345
|
+
* buildEnd so watch rebuilds start fresh and completed builds release source.
|
|
1283
1346
|
*/
|
|
1284
|
-
function
|
|
1285
|
-
|
|
1286
|
-
if (
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1347
|
+
function getImportAnalysis(build) {
|
|
1348
|
+
let analysis = analysisByBuild.get(build);
|
|
1349
|
+
if (!analysis) {
|
|
1350
|
+
const importsByCode = /* @__PURE__ */ new Map();
|
|
1351
|
+
analysis = {
|
|
1352
|
+
analyze(code) {
|
|
1353
|
+
const cached = importsByCode.get(code);
|
|
1354
|
+
if (cached !== void 0) return cached;
|
|
1355
|
+
const imports = analyzeImports(code);
|
|
1356
|
+
importsByCode.set(code, imports);
|
|
1357
|
+
return imports;
|
|
1358
|
+
},
|
|
1359
|
+
clear() {
|
|
1360
|
+
importsByCode.clear();
|
|
1361
|
+
}
|
|
1362
|
+
};
|
|
1363
|
+
analysisByBuild.set(build, analysis);
|
|
1291
1364
|
}
|
|
1292
|
-
return
|
|
1293
|
-
}
|
|
1294
|
-
function generateReactIslandBrowserDefinition(enabled) {
|
|
1295
|
-
if (!enabled) return "";
|
|
1296
|
-
return `
|
|
1297
|
-
exportModule.__mf_island = {
|
|
1298
|
-
version: 1,
|
|
1299
|
-
renderToHtml() {
|
|
1300
|
-
return Promise.reject(new Error("[Module Federation] renderToHtml is only available in the SSR remote entry"));
|
|
1301
|
-
},
|
|
1302
|
-
hydrate(element, props) {
|
|
1303
|
-
const root = element && element.hasAttribute && element.hasAttribute("data-mf-island-state")
|
|
1304
|
-
? element
|
|
1305
|
-
: element && element.querySelector
|
|
1306
|
-
? element.querySelector("[data-mf-island-state]") || element
|
|
1307
|
-
: element;
|
|
1308
|
-
if (!root) {
|
|
1309
|
-
return Promise.reject(new Error("[Module Federation] Cannot hydrate an island without a root element"));
|
|
1310
|
-
}
|
|
1311
|
-
let serverProps = {};
|
|
1312
|
-
const encodedState = root.getAttribute && root.getAttribute("data-mf-island-state");
|
|
1313
|
-
if (encodedState) {
|
|
1314
|
-
try {
|
|
1315
|
-
serverProps = JSON.parse(decodeURIComponent(encodedState));
|
|
1316
|
-
} catch {
|
|
1317
|
-
serverProps = {};
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1320
|
-
const finalProps = Object.assign({}, serverProps, props || {});
|
|
1321
|
-
return Promise.all([import("react"), import("react-dom/client")]).then(([React, ReactDOMClient]) => {
|
|
1322
|
-
if (typeof ReactDOMClient.hydrateRoot !== "function") {
|
|
1323
|
-
throw new Error("[Module Federation] react-dom/client does not provide hydrateRoot");
|
|
1324
|
-
}
|
|
1325
|
-
return ReactDOMClient.hydrateRoot(
|
|
1326
|
-
root,
|
|
1327
|
-
React.createElement(importModule.default, finalProps)
|
|
1328
|
-
);
|
|
1329
|
-
});
|
|
1330
|
-
}
|
|
1331
|
-
}`;
|
|
1365
|
+
return analysis;
|
|
1332
1366
|
}
|
|
1333
|
-
function
|
|
1334
|
-
|
|
1335
|
-
return `
|
|
1336
|
-
exportModule.__mf_island = {
|
|
1337
|
-
version: 1,
|
|
1338
|
-
async renderToHtml(props) {
|
|
1339
|
-
if (typeof importModule.default !== "function" && typeof importModule.default !== "object") {
|
|
1340
|
-
throw new Error("[Module Federation] A React island expose must have a default component export");
|
|
1341
|
-
}
|
|
1342
|
-
const loadedProps = typeof importModule.load === "function" ? await importModule.load() : {};
|
|
1343
|
-
const finalProps = Object.assign({}, loadedProps || {}, props || {});
|
|
1344
|
-
const [React, ReactDOMServer] = await Promise.all([
|
|
1345
|
-
import("react"),
|
|
1346
|
-
import("react-dom/server")
|
|
1347
|
-
]);
|
|
1348
|
-
const body = ReactDOMServer.renderToString(
|
|
1349
|
-
React.createElement(importModule.default, finalProps)
|
|
1350
|
-
);
|
|
1351
|
-
const state = encodeURIComponent(JSON.stringify(finalProps));
|
|
1352
|
-
return '<div data-mf-island-state="' + state + '">' + body + '</div>';
|
|
1353
|
-
},
|
|
1354
|
-
hydrate() {
|
|
1355
|
-
return Promise.reject(new Error("[Module Federation] hydrate is only available in the browser remote entry"));
|
|
1356
|
-
}
|
|
1357
|
-
}`;
|
|
1367
|
+
function isRecord(value) {
|
|
1368
|
+
return value !== null && typeof value === "object";
|
|
1358
1369
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
const
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1370
|
+
function getModuleSource(node) {
|
|
1371
|
+
if (!isRecord(node)) return void 0;
|
|
1372
|
+
const source = node;
|
|
1373
|
+
if (source.type === "Literal" && typeof source.value === "string") return source.value;
|
|
1374
|
+
if (source.type === "StringLiteral" && typeof source.value === "string") return source.value;
|
|
1375
|
+
if (source.type !== "TemplateLiteral") return void 0;
|
|
1376
|
+
const expressions = Array.isArray(source.expressions) ? source.expressions : [];
|
|
1377
|
+
const quasis = Array.isArray(source.quasis) ? source.quasis : [];
|
|
1378
|
+
if (expressions.length > 0 || quasis.length !== 1) return void 0;
|
|
1379
|
+
const quasi = quasis[0];
|
|
1380
|
+
if (!isRecord(quasi) || !isRecord(quasi.value)) return void 0;
|
|
1381
|
+
const value = quasi.value;
|
|
1382
|
+
return typeof value.cooked === "string" ? value.cooked : typeof value.raw === "string" ? value.raw : void 0;
|
|
1365
1383
|
}
|
|
1366
|
-
function
|
|
1367
|
-
|
|
1384
|
+
function getExportedName(node) {
|
|
1385
|
+
if (!isRecord(node)) return void 0;
|
|
1386
|
+
const exported = node;
|
|
1387
|
+
if (exported.type === "Identifier" && typeof exported.name === "string") return exported.name;
|
|
1388
|
+
if ((exported.type === "Literal" || exported.type === "StringLiteral") && typeof exported.value === "string") return exported.value;
|
|
1368
1389
|
}
|
|
1369
|
-
function
|
|
1370
|
-
|
|
1371
|
-
if (queryIndex === -1) return;
|
|
1372
|
-
if (!new URLSearchParams(source.slice(queryIndex + 1)).has("mf-island")) return;
|
|
1373
|
-
return source.slice(0, queryIndex);
|
|
1390
|
+
function isTypeOnly(node) {
|
|
1391
|
+
return node.importKind === "type" || node.exportKind === "type";
|
|
1374
1392
|
}
|
|
1375
|
-
function
|
|
1376
|
-
|
|
1393
|
+
function forEachAstNode(root, visit) {
|
|
1394
|
+
const stack = [root];
|
|
1395
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1396
|
+
while (stack.length > 0) {
|
|
1397
|
+
const value = stack.pop();
|
|
1398
|
+
if (!isRecord(value)) continue;
|
|
1399
|
+
if (seen.has(value)) continue;
|
|
1400
|
+
seen.add(value);
|
|
1401
|
+
if (Array.isArray(value)) {
|
|
1402
|
+
for (let index = value.length - 1; index >= 0; index--) stack.push(value[index]);
|
|
1403
|
+
continue;
|
|
1404
|
+
}
|
|
1405
|
+
const node = value;
|
|
1406
|
+
if (typeof node.type === "string") visit(node);
|
|
1407
|
+
Object.entries(node).forEach(([key, child]) => {
|
|
1408
|
+
if (key !== "parent" && key !== "loc") stack.push(child);
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1377
1411
|
}
|
|
1378
|
-
function
|
|
1379
|
-
|
|
1412
|
+
function collectImportDeclaration(node, source, record, requireAllExports) {
|
|
1413
|
+
if (isTypeOnly(node)) return;
|
|
1414
|
+
const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
|
|
1415
|
+
if (specifiers.length === 0) {
|
|
1416
|
+
requireAllExports(source);
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
const names = [];
|
|
1420
|
+
for (const specifier of specifiers) {
|
|
1421
|
+
if (!isRecord(specifier)) {
|
|
1422
|
+
requireAllExports(source);
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
if (isTypeOnly(specifier)) continue;
|
|
1426
|
+
if (specifier.type === "ImportNamespaceSpecifier") {
|
|
1427
|
+
requireAllExports(source);
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
if (specifier.type === "ImportDefaultSpecifier") {
|
|
1431
|
+
names.push("default");
|
|
1432
|
+
continue;
|
|
1433
|
+
}
|
|
1434
|
+
if (specifier.type === "ImportSpecifier") {
|
|
1435
|
+
const imported = specifier.imported;
|
|
1436
|
+
if (isRecord(imported) && (imported.type === "Literal" || imported.type === "StringLiteral")) {
|
|
1437
|
+
requireAllExports(source);
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1440
|
+
const name = getExportedName(specifier.imported);
|
|
1441
|
+
if (!name) {
|
|
1442
|
+
requireAllExports(source);
|
|
1443
|
+
return;
|
|
1444
|
+
}
|
|
1445
|
+
names.push(name);
|
|
1446
|
+
continue;
|
|
1447
|
+
}
|
|
1448
|
+
requireAllExports(source);
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
record(names, source);
|
|
1380
1452
|
}
|
|
1381
|
-
function
|
|
1382
|
-
if (
|
|
1383
|
-
if (
|
|
1453
|
+
function collectReExport(node, source, record, requireAllExports) {
|
|
1454
|
+
if (isTypeOnly(node)) return;
|
|
1455
|
+
if (node.type === "ExportAllDeclaration") {
|
|
1456
|
+
requireAllExports(source);
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
|
|
1460
|
+
if (specifiers.length === 0) {
|
|
1461
|
+
requireAllExports(source);
|
|
1462
|
+
return;
|
|
1463
|
+
}
|
|
1464
|
+
const names = [];
|
|
1465
|
+
for (const specifier of specifiers) {
|
|
1466
|
+
if (!isRecord(specifier)) {
|
|
1467
|
+
requireAllExports(source);
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
if (isTypeOnly(specifier)) continue;
|
|
1471
|
+
if (specifier.type !== "ExportSpecifier") {
|
|
1472
|
+
requireAllExports(source);
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1475
|
+
const local = specifier.local;
|
|
1476
|
+
if (isRecord(local) && (local.type === "Literal" || local.type === "StringLiteral")) {
|
|
1477
|
+
requireAllExports(source);
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
const name = getExportedName(specifier.local);
|
|
1481
|
+
if (!name) {
|
|
1482
|
+
requireAllExports(source);
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
names.push(name);
|
|
1486
|
+
}
|
|
1487
|
+
record(names, source);
|
|
1488
|
+
}
|
|
1489
|
+
function analyzeImports(code) {
|
|
1490
|
+
let ast;
|
|
1491
|
+
try {
|
|
1492
|
+
ast = vite.parseAst(code);
|
|
1493
|
+
} catch {
|
|
1494
|
+
return null;
|
|
1495
|
+
}
|
|
1496
|
+
const imports = [];
|
|
1497
|
+
const recordSource = (names, source) => imports.push({
|
|
1498
|
+
source,
|
|
1499
|
+
usedExports: names
|
|
1500
|
+
});
|
|
1501
|
+
const requireAllExports = (source) => imports.push({
|
|
1502
|
+
source,
|
|
1503
|
+
usedExports: null
|
|
1504
|
+
});
|
|
1505
|
+
const collectImport = (node) => {
|
|
1506
|
+
if (node.type === "ImportDeclaration") {
|
|
1507
|
+
const source = getModuleSource(node.source);
|
|
1508
|
+
if (source) collectImportDeclaration(node, source, recordSource, requireAllExports);
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
|
|
1512
|
+
const source = getModuleSource(node.source);
|
|
1513
|
+
if (source) collectReExport(node, source, recordSource, requireAllExports);
|
|
1514
|
+
return;
|
|
1515
|
+
}
|
|
1516
|
+
if (node.type === "ImportExpression") {
|
|
1517
|
+
const source = getModuleSource(node.source);
|
|
1518
|
+
if (source) requireAllExports(source);
|
|
1519
|
+
return;
|
|
1520
|
+
}
|
|
1521
|
+
if (node.type === "CallExpression") {
|
|
1522
|
+
const callee = node.callee;
|
|
1523
|
+
const args = Array.isArray(node.arguments) ? node.arguments : [];
|
|
1524
|
+
if (isRecord(callee) && callee.type === "Identifier" && callee.name === "require" && args.length > 0) {
|
|
1525
|
+
const source = getModuleSource(args[0]);
|
|
1526
|
+
if (source) requireAllExports(source);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
};
|
|
1530
|
+
if ("Visitor" in vite && typeof vite.Visitor === "function") {
|
|
1531
|
+
const visit = (node) => {
|
|
1532
|
+
if (isRecord(node)) collectImport(node);
|
|
1533
|
+
};
|
|
1534
|
+
try {
|
|
1535
|
+
new vite.Visitor({
|
|
1536
|
+
ImportDeclaration: visit,
|
|
1537
|
+
ExportNamedDeclaration: visit,
|
|
1538
|
+
ExportAllDeclaration: visit,
|
|
1539
|
+
ImportExpression: visit,
|
|
1540
|
+
CallExpression: visit
|
|
1541
|
+
}).visit(ast);
|
|
1542
|
+
return imports;
|
|
1543
|
+
} catch {
|
|
1544
|
+
imports.length = 0;
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
forEachAstNode(ast, collectImport);
|
|
1548
|
+
return imports;
|
|
1549
|
+
}
|
|
1550
|
+
//#endregion
|
|
1551
|
+
//#region src/utils/treeShaking.ts
|
|
1552
|
+
function shouldAnalyzeSharedExports(shareItem) {
|
|
1553
|
+
return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
|
|
1554
|
+
}
|
|
1555
|
+
const legacyTreeShakingState = {
|
|
1556
|
+
inferredUsage: /* @__PURE__ */ new Map(),
|
|
1557
|
+
buildMode: false
|
|
1558
|
+
};
|
|
1559
|
+
const treeShakingStates = /* @__PURE__ */ new WeakMap();
|
|
1560
|
+
function getTreeShakingState(options) {
|
|
1561
|
+
if (!options) return legacyTreeShakingState;
|
|
1562
|
+
let state = treeShakingStates.get(options);
|
|
1563
|
+
if (!state) {
|
|
1564
|
+
state = {
|
|
1565
|
+
inferredUsage: /* @__PURE__ */ new Map(),
|
|
1566
|
+
buildMode: false
|
|
1567
|
+
};
|
|
1568
|
+
treeShakingStates.set(options, state);
|
|
1569
|
+
}
|
|
1570
|
+
return state;
|
|
1571
|
+
}
|
|
1572
|
+
function setTreeShakingBuildMode(enabled, options) {
|
|
1573
|
+
getTreeShakingState(options).buildMode = enabled;
|
|
1574
|
+
}
|
|
1575
|
+
function resetTreeShakingExports(options) {
|
|
1576
|
+
getTreeShakingState(options).inferredUsage.clear();
|
|
1577
|
+
}
|
|
1578
|
+
function getOrCreateExportRecord(sharedKey, request, options) {
|
|
1579
|
+
const inferredUsage = getTreeShakingState(options).inferredUsage;
|
|
1580
|
+
let byRequest = inferredUsage.get(sharedKey);
|
|
1581
|
+
if (!byRequest) {
|
|
1582
|
+
byRequest = /* @__PURE__ */ new Map();
|
|
1583
|
+
inferredUsage.set(sharedKey, byRequest);
|
|
1584
|
+
}
|
|
1585
|
+
let record = byRequest.get(request);
|
|
1586
|
+
if (!record) {
|
|
1587
|
+
record = {
|
|
1588
|
+
requiresFullBundle: false,
|
|
1589
|
+
usedExports: /* @__PURE__ */ new Set()
|
|
1590
|
+
};
|
|
1591
|
+
byRequest.set(request, record);
|
|
1592
|
+
}
|
|
1593
|
+
return record;
|
|
1594
|
+
}
|
|
1595
|
+
function recordTreeShakingExports(sharedKey, exports, request = sharedKey, options) {
|
|
1596
|
+
const record = getOrCreateExportRecord(sharedKey, request, options);
|
|
1597
|
+
exports.forEach((name) => record.usedExports.add(name));
|
|
1598
|
+
}
|
|
1599
|
+
function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey, options) {
|
|
1600
|
+
getOrCreateExportRecord(sharedKey, request, options).requiresFullBundle = true;
|
|
1601
|
+
}
|
|
1602
|
+
function getExportRecords(sharedKey, request, options) {
|
|
1603
|
+
const inferredUsage = getTreeShakingState(options).inferredUsage;
|
|
1604
|
+
if (sharedKey) {
|
|
1605
|
+
const records = inferredUsage.get(sharedKey);
|
|
1606
|
+
const wildcard = records?.get("*");
|
|
1607
|
+
const exact = records?.get(request);
|
|
1608
|
+
return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
|
|
1609
|
+
}
|
|
1610
|
+
const records = [];
|
|
1611
|
+
inferredUsage.forEach((byRequest, configuredKey) => {
|
|
1612
|
+
const wildcard = byRequest.get("*");
|
|
1613
|
+
const exact = byRequest.get(request);
|
|
1614
|
+
const configuredRequest = getSharedRequest(configuredKey, options?.shared?.[configuredKey]);
|
|
1615
|
+
const keyBase = configuredRequest.endsWith("/") ? configuredRequest.slice(0, -1) : configuredRequest;
|
|
1616
|
+
const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
|
|
1617
|
+
if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
|
|
1618
|
+
if (exact && exact !== wildcard) records.push(exact);
|
|
1619
|
+
});
|
|
1620
|
+
return records;
|
|
1621
|
+
}
|
|
1622
|
+
/**
|
|
1623
|
+
* Return the analyzed requirement for one concrete shared request.
|
|
1624
|
+
*
|
|
1625
|
+
* Callers that know the configured share key should pass it explicitly. The
|
|
1626
|
+
* fallback lookup across keys keeps aliases/backwards-compatible callers
|
|
1627
|
+
* working, while still keeping each concrete request's exports isolated.
|
|
1628
|
+
*/
|
|
1629
|
+
function getSharedExportUsage(request, shareItem, sharedKey, options) {
|
|
1630
|
+
const treeShaking = shareItem?.shareConfig.treeShaking;
|
|
1631
|
+
if (!shouldAnalyzeSharedExports(shareItem) || !getTreeShakingState(options).buildMode) return;
|
|
1632
|
+
const records = getExportRecords(sharedKey, request, options);
|
|
1633
|
+
if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
|
|
1634
|
+
const configured = treeShaking?.usedExports ?? [];
|
|
1635
|
+
const result = new Set(configured);
|
|
1636
|
+
records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
|
|
1637
|
+
if (result.size > 0) return {
|
|
1638
|
+
kind: "exports",
|
|
1639
|
+
usedExports: [...result].sort()
|
|
1640
|
+
};
|
|
1641
|
+
return records.length > 0 ? {
|
|
1642
|
+
kind: "exports",
|
|
1643
|
+
usedExports: []
|
|
1644
|
+
} : { kind: "unknown" };
|
|
1645
|
+
}
|
|
1646
|
+
function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
|
|
1647
|
+
if (!shareItem?.shareConfig.treeShaking) return void 0;
|
|
1648
|
+
return getSharedExportUsage(request, shareItem, sharedKey, options);
|
|
1649
|
+
}
|
|
1650
|
+
/**
|
|
1651
|
+
* Record consumer imports against this instance's sharing configuration.
|
|
1652
|
+
* Generated wrappers do not contribute consumer usage. If parsing fails,
|
|
1653
|
+
* every share enabled for analysis requires all of its exports.
|
|
1654
|
+
*/
|
|
1655
|
+
async function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe, analysis = getImportAnalysis(shared)) {
|
|
1656
|
+
const normalizedId = normalizePathForImport(id);
|
|
1657
|
+
if (normalizedId.includes("__prebuild__") || normalizedId.includes("__loadShare__") || normalizedId.includes("__mf_tree_shaking_graph__")) return;
|
|
1658
|
+
const imports = analysis.analyze(code);
|
|
1659
|
+
if (imports === null) {
|
|
1660
|
+
Object.entries(shared).forEach(([sharedKey, shareItem]) => {
|
|
1661
|
+
if (shouldAnalyzeSharedExports(shareItem)) markUnsafe(sharedKey, "*");
|
|
1662
|
+
});
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
const pending = [];
|
|
1666
|
+
for (const { source, usedExports } of imports) {
|
|
1667
|
+
const apply = (key) => {
|
|
1668
|
+
if (!key || !shouldAnalyzeSharedExports(shared[key])) return;
|
|
1669
|
+
if (usedExports === null) markUnsafe(key, source);
|
|
1670
|
+
else record(key, usedExports, source);
|
|
1671
|
+
};
|
|
1672
|
+
const key = findSharedKey(source, shared);
|
|
1673
|
+
if (key instanceof Promise) pending.push(key.then(apply));
|
|
1674
|
+
else apply(key);
|
|
1675
|
+
}
|
|
1676
|
+
await Promise.all(pending);
|
|
1677
|
+
}
|
|
1678
|
+
//#endregion
|
|
1679
|
+
//#region src/utils/reactIsland.ts
|
|
1680
|
+
const SOURCE_EXTENSIONS$1 = [
|
|
1681
|
+
".tsx",
|
|
1682
|
+
".jsx",
|
|
1683
|
+
".ts",
|
|
1684
|
+
".js",
|
|
1685
|
+
".mts",
|
|
1686
|
+
".mjs",
|
|
1687
|
+
".cts",
|
|
1688
|
+
".cjs"
|
|
1689
|
+
];
|
|
1690
|
+
function resolveSourceFile(importPath, root) {
|
|
1691
|
+
const cleanImport = stripQueryAndHash(importPath);
|
|
1692
|
+
if (!cleanImport.startsWith(".") && !path$1.isAbsolute(cleanImport)) return;
|
|
1693
|
+
const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
|
|
1694
|
+
return [
|
|
1695
|
+
candidate,
|
|
1696
|
+
...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
|
|
1697
|
+
...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
|
|
1698
|
+
].find((filePath) => {
|
|
1699
|
+
try {
|
|
1700
|
+
return fs$1.statSync(filePath).isFile();
|
|
1701
|
+
} catch {
|
|
1702
|
+
return false;
|
|
1703
|
+
}
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
function localDefaultReexport(source) {
|
|
1707
|
+
const match = source.match(/export\s*{\s*(?:default(?:\s+as\s+default)?|[A-Za-z_$][\w$]*\s+as\s+default)\s*}\s*from\s*["']([^"']+)["']/);
|
|
1708
|
+
return match?.[1]?.startsWith(".") ? match[1] : void 0;
|
|
1709
|
+
}
|
|
1710
|
+
function isReactComponentSource(source, filePath = "component.tsx") {
|
|
1711
|
+
if (!(/\bexport\s+default\b/.test(source) || /\bexport\s*{[^}]*\bdefault\b[^}]*}(?:\s*from\s*["'][^"']+["'])?/.test(source))) return false;
|
|
1712
|
+
const extension = path$1.extname(stripQueryAndHash(filePath)).toLowerCase();
|
|
1713
|
+
const canContainJsx = extension === ".tsx" || extension === ".jsx";
|
|
1714
|
+
const hasJsx = /<>|<\s*[A-Za-z][\w.:-]*(?:\s[^<>]*?)?\s*\/?>/.test(source);
|
|
1715
|
+
const importsReact = /\bfrom\s*["']react["']|\brequire\(\s*["']react["']\s*\)/.test(source);
|
|
1716
|
+
const usesReactApi = /\b(?:React\.)?(?:createElement|jsx|jsxs)\s*\(/.test(source);
|
|
1717
|
+
const isClientModule = /^\s*["']use client["']\s*;?/m.test(source);
|
|
1718
|
+
return canContainJsx && hasJsx || importsReact && (hasJsx || usesReactApi || isClientModule);
|
|
1719
|
+
}
|
|
1720
|
+
function isReactComponentFile(filePath, seen = /* @__PURE__ */ new Set()) {
|
|
1721
|
+
const normalizedPath = path$1.resolve(filePath);
|
|
1722
|
+
if (seen.has(normalizedPath)) return false;
|
|
1723
|
+
seen.add(normalizedPath);
|
|
1724
|
+
let source;
|
|
1725
|
+
try {
|
|
1726
|
+
source = fs$1.readFileSync(normalizedPath, "utf8");
|
|
1727
|
+
} catch {
|
|
1728
|
+
return false;
|
|
1729
|
+
}
|
|
1730
|
+
if (isReactComponentSource(source, normalizedPath)) return true;
|
|
1731
|
+
const reexport = localDefaultReexport(source);
|
|
1732
|
+
if (!reexport) return false;
|
|
1733
|
+
const reexportPath = resolveSourceFile(reexport, path$1.dirname(normalizedPath));
|
|
1734
|
+
return reexportPath ? isReactComponentFile(reexportPath, seen) : false;
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* React is shared by the normal MF runtime when explicitly configured. When it
|
|
1738
|
+
* is local, UI exposes can safely advertise an island capability in addition
|
|
1739
|
+
* to their unchanged default export.
|
|
1740
|
+
*/
|
|
1741
|
+
function getReactIslandExposes(options, root) {
|
|
1742
|
+
if (options.experiments.ssrMode !== "ISLAND") return /* @__PURE__ */ new Set();
|
|
1743
|
+
if (Object.hasOwn(options.shared, "react")) return /* @__PURE__ */ new Set();
|
|
1744
|
+
const islandExposes = /* @__PURE__ */ new Set();
|
|
1745
|
+
for (const [key, expose] of Object.entries(options.exposes)) {
|
|
1746
|
+
const sourceFile = resolveSourceFile(expose.import, root);
|
|
1747
|
+
if (sourceFile && isReactComponentFile(sourceFile)) islandExposes.add(key);
|
|
1748
|
+
}
|
|
1749
|
+
return islandExposes;
|
|
1750
|
+
}
|
|
1751
|
+
function generateReactIslandBrowserDefinition(enabled) {
|
|
1752
|
+
if (!enabled) return "";
|
|
1753
|
+
return `
|
|
1754
|
+
exportModule.__mf_island = {
|
|
1755
|
+
version: 1,
|
|
1756
|
+
renderToHtml() {
|
|
1757
|
+
return Promise.reject(new Error("[Module Federation] renderToHtml is only available in the SSR remote entry"));
|
|
1758
|
+
},
|
|
1759
|
+
hydrate(element, props) {
|
|
1760
|
+
const root = element && element.hasAttribute && element.hasAttribute("data-mf-island-state")
|
|
1761
|
+
? element
|
|
1762
|
+
: element && element.querySelector
|
|
1763
|
+
? element.querySelector("[data-mf-island-state]") || element
|
|
1764
|
+
: element;
|
|
1765
|
+
if (!root) {
|
|
1766
|
+
return Promise.reject(new Error("[Module Federation] Cannot hydrate an island without a root element"));
|
|
1767
|
+
}
|
|
1768
|
+
let serverProps = {};
|
|
1769
|
+
const encodedState = root.getAttribute && root.getAttribute("data-mf-island-state");
|
|
1770
|
+
if (encodedState) {
|
|
1771
|
+
try {
|
|
1772
|
+
serverProps = JSON.parse(decodeURIComponent(encodedState));
|
|
1773
|
+
} catch {
|
|
1774
|
+
serverProps = {};
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
const finalProps = Object.assign({}, serverProps, props || {});
|
|
1778
|
+
return Promise.all([import("react"), import("react-dom/client")]).then(([React, ReactDOMClient]) => {
|
|
1779
|
+
if (typeof ReactDOMClient.hydrateRoot !== "function") {
|
|
1780
|
+
throw new Error("[Module Federation] react-dom/client does not provide hydrateRoot");
|
|
1781
|
+
}
|
|
1782
|
+
return ReactDOMClient.hydrateRoot(
|
|
1783
|
+
root,
|
|
1784
|
+
React.createElement(importModule.default, finalProps)
|
|
1785
|
+
);
|
|
1786
|
+
});
|
|
1787
|
+
}
|
|
1788
|
+
}`;
|
|
1789
|
+
}
|
|
1790
|
+
function generateReactIslandSSRDefinition(enabled) {
|
|
1791
|
+
if (!enabled) return "";
|
|
1792
|
+
return `
|
|
1793
|
+
exportModule.__mf_island = {
|
|
1794
|
+
version: 1,
|
|
1795
|
+
async renderToHtml(props) {
|
|
1796
|
+
if (typeof importModule.default !== "function" && typeof importModule.default !== "object") {
|
|
1797
|
+
throw new Error("[Module Federation] A React island expose must have a default component export");
|
|
1798
|
+
}
|
|
1799
|
+
const loadedProps = typeof importModule.load === "function" ? await importModule.load() : {};
|
|
1800
|
+
const finalProps = Object.assign({}, loadedProps || {}, props || {});
|
|
1801
|
+
const [React, ReactDOMServer] = await Promise.all([
|
|
1802
|
+
import("react"),
|
|
1803
|
+
import("react-dom/server")
|
|
1804
|
+
]);
|
|
1805
|
+
const body = ReactDOMServer.renderToString(
|
|
1806
|
+
React.createElement(importModule.default, finalProps)
|
|
1807
|
+
);
|
|
1808
|
+
const state = encodeURIComponent(JSON.stringify(finalProps));
|
|
1809
|
+
return '<div data-mf-island-state="' + state + '">' + body + '</div>';
|
|
1810
|
+
},
|
|
1811
|
+
hydrate() {
|
|
1812
|
+
return Promise.reject(new Error("[Module Federation] hydrate is only available in the browser remote entry"));
|
|
1813
|
+
}
|
|
1814
|
+
}`;
|
|
1815
|
+
}
|
|
1816
|
+
const REACT_ISLAND_CLIENT_ID_PREFIX = "virtual:mf-react-island-client:";
|
|
1817
|
+
const REACT_ISLAND_SERVER_ID_PREFIX = "virtual:mf-react-island-server:";
|
|
1818
|
+
const RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX = `\0${REACT_ISLAND_CLIENT_ID_PREFIX}`;
|
|
1819
|
+
const RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX = `\0${REACT_ISLAND_SERVER_ID_PREFIX}`;
|
|
1820
|
+
function encodeIslandRemoteId(remoteId) {
|
|
1821
|
+
return encodeURIComponent(remoteId);
|
|
1822
|
+
}
|
|
1823
|
+
function decodeIslandRemoteId(encodedRemoteId) {
|
|
1824
|
+
return decodeURIComponent(encodedRemoteId);
|
|
1825
|
+
}
|
|
1826
|
+
function getReactIslandImportRemoteId(source) {
|
|
1827
|
+
const queryIndex = source.indexOf("?");
|
|
1828
|
+
if (queryIndex === -1) return;
|
|
1829
|
+
if (!new URLSearchParams(source.slice(queryIndex + 1)).has("mf-island")) return;
|
|
1830
|
+
return source.slice(0, queryIndex);
|
|
1831
|
+
}
|
|
1832
|
+
function getReactIslandServerImportId(remoteId) {
|
|
1833
|
+
return `${REACT_ISLAND_SERVER_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
|
|
1834
|
+
}
|
|
1835
|
+
function getReactIslandClientImportId(remoteId) {
|
|
1836
|
+
return `${REACT_ISLAND_CLIENT_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
|
|
1837
|
+
}
|
|
1838
|
+
function resolveReactIslandConsumerId(id) {
|
|
1839
|
+
if (id.startsWith("virtual:mf-react-island-server:")) return `\0${id}`;
|
|
1840
|
+
if (id.startsWith("virtual:mf-react-island-client:")) return `\0${id}`;
|
|
1384
1841
|
}
|
|
1385
1842
|
function remoteIdFromResolvedIslandId(id, prefix) {
|
|
1386
1843
|
if (!id.startsWith(prefix)) return;
|
|
@@ -1832,7 +2289,7 @@ ${exportStatement}
|
|
|
1832
2289
|
//#endregion
|
|
1833
2290
|
//#region src/plugins/pluginReactMixedModeGuard.ts
|
|
1834
2291
|
function createReactMixedModeRuntimeGuard() {
|
|
1835
|
-
return `const __mfReactInternals = mod[
|
|
2292
|
+
return `const __mfReactInternals = mod[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
|
|
1836
2293
|
if (__mfReactInternals && "A" in __mfReactInternals) {
|
|
1837
2294
|
let __mfReactDispatcher = __mfReactInternals.A;
|
|
1838
2295
|
Object.defineProperty(__mfReactInternals, "A", {
|
|
@@ -1842,279 +2299,10 @@ if (__mfReactInternals && "A" in __mfReactInternals) {
|
|
|
1842
2299
|
set: (next) => {
|
|
1843
2300
|
if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
|
|
1844
2301
|
__mfReactDispatcher = next;
|
|
1845
|
-
},
|
|
1846
|
-
});
|
|
1847
|
-
__mfReactInternals.A = __mfReactDispatcher;
|
|
1848
|
-
}`;
|
|
1849
|
-
}
|
|
1850
|
-
//#endregion
|
|
1851
|
-
//#region src/utils/treeShaking.ts
|
|
1852
|
-
function shouldAnalyzeSharedExports(shareItem) {
|
|
1853
|
-
return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
|
|
1854
|
-
}
|
|
1855
|
-
const legacyTreeShakingState = {
|
|
1856
|
-
inferredUsage: /* @__PURE__ */ new Map(),
|
|
1857
|
-
buildMode: false
|
|
1858
|
-
};
|
|
1859
|
-
const treeShakingStates = /* @__PURE__ */ new WeakMap();
|
|
1860
|
-
function getTreeShakingState(options) {
|
|
1861
|
-
if (!options) return legacyTreeShakingState;
|
|
1862
|
-
let state = treeShakingStates.get(options);
|
|
1863
|
-
if (!state) {
|
|
1864
|
-
state = {
|
|
1865
|
-
inferredUsage: /* @__PURE__ */ new Map(),
|
|
1866
|
-
buildMode: false
|
|
1867
|
-
};
|
|
1868
|
-
treeShakingStates.set(options, state);
|
|
1869
|
-
}
|
|
1870
|
-
return state;
|
|
1871
|
-
}
|
|
1872
|
-
function setTreeShakingBuildMode(enabled, options) {
|
|
1873
|
-
getTreeShakingState(options).buildMode = enabled;
|
|
1874
|
-
}
|
|
1875
|
-
function resetTreeShakingExports(options) {
|
|
1876
|
-
getTreeShakingState(options).inferredUsage.clear();
|
|
1877
|
-
}
|
|
1878
|
-
function getOrCreateExportRecord(sharedKey, request, options) {
|
|
1879
|
-
const inferredUsage = getTreeShakingState(options).inferredUsage;
|
|
1880
|
-
let byRequest = inferredUsage.get(sharedKey);
|
|
1881
|
-
if (!byRequest) {
|
|
1882
|
-
byRequest = /* @__PURE__ */ new Map();
|
|
1883
|
-
inferredUsage.set(sharedKey, byRequest);
|
|
1884
|
-
}
|
|
1885
|
-
let record = byRequest.get(request);
|
|
1886
|
-
if (!record) {
|
|
1887
|
-
record = {
|
|
1888
|
-
requiresFullBundle: false,
|
|
1889
|
-
usedExports: /* @__PURE__ */ new Set()
|
|
1890
|
-
};
|
|
1891
|
-
byRequest.set(request, record);
|
|
1892
|
-
}
|
|
1893
|
-
return record;
|
|
1894
|
-
}
|
|
1895
|
-
function recordTreeShakingExports(sharedKey, exports, request = sharedKey, options) {
|
|
1896
|
-
const record = getOrCreateExportRecord(sharedKey, request, options);
|
|
1897
|
-
exports.forEach((name) => record.usedExports.add(name));
|
|
1898
|
-
}
|
|
1899
|
-
function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey, options) {
|
|
1900
|
-
getOrCreateExportRecord(sharedKey, request, options).requiresFullBundle = true;
|
|
1901
|
-
}
|
|
1902
|
-
function getExportRecords(sharedKey, request, options) {
|
|
1903
|
-
const inferredUsage = getTreeShakingState(options).inferredUsage;
|
|
1904
|
-
if (sharedKey) {
|
|
1905
|
-
const records = inferredUsage.get(sharedKey);
|
|
1906
|
-
const wildcard = records?.get("*");
|
|
1907
|
-
const exact = records?.get(request);
|
|
1908
|
-
return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
|
|
1909
|
-
}
|
|
1910
|
-
const records = [];
|
|
1911
|
-
inferredUsage.forEach((byRequest, configuredKey) => {
|
|
1912
|
-
const wildcard = byRequest.get("*");
|
|
1913
|
-
const exact = byRequest.get(request);
|
|
1914
|
-
const keyBase = configuredKey.endsWith("/") ? configuredKey.slice(0, -1) : configuredKey;
|
|
1915
|
-
const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
|
|
1916
|
-
if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
|
|
1917
|
-
if (exact && exact !== wildcard) records.push(exact);
|
|
1918
|
-
});
|
|
1919
|
-
return records;
|
|
1920
|
-
}
|
|
1921
|
-
/**
|
|
1922
|
-
* Return the analyzed requirement for one concrete shared request.
|
|
1923
|
-
*
|
|
1924
|
-
* Callers that know the configured share key should pass it explicitly. The
|
|
1925
|
-
* fallback lookup across keys keeps aliases/backwards-compatible callers
|
|
1926
|
-
* working, while still keeping each concrete request's exports isolated.
|
|
1927
|
-
*/
|
|
1928
|
-
function getSharedExportUsage(request, shareItem, sharedKey, options) {
|
|
1929
|
-
const treeShaking = shareItem?.shareConfig.treeShaking;
|
|
1930
|
-
if (!shouldAnalyzeSharedExports(shareItem) || !getTreeShakingState(options).buildMode) return;
|
|
1931
|
-
const records = getExportRecords(sharedKey, request, options);
|
|
1932
|
-
if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
|
|
1933
|
-
const configured = treeShaking?.usedExports ?? [];
|
|
1934
|
-
const result = new Set(configured);
|
|
1935
|
-
records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
|
|
1936
|
-
if (result.size > 0) return {
|
|
1937
|
-
kind: "exports",
|
|
1938
|
-
usedExports: [...result].sort()
|
|
1939
|
-
};
|
|
1940
|
-
return records.length > 0 ? {
|
|
1941
|
-
kind: "exports",
|
|
1942
|
-
usedExports: []
|
|
1943
|
-
} : { kind: "unknown" };
|
|
1944
|
-
}
|
|
1945
|
-
function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
|
|
1946
|
-
if (!shareItem?.shareConfig.treeShaking) return void 0;
|
|
1947
|
-
return getSharedExportUsage(request, shareItem, sharedKey, options);
|
|
1948
|
-
}
|
|
1949
|
-
function getModuleSource(node) {
|
|
1950
|
-
if (!node || typeof node !== "object") return void 0;
|
|
1951
|
-
const source = node;
|
|
1952
|
-
if (source.type === "Literal" && typeof source.value === "string") return source.value;
|
|
1953
|
-
if (source.type === "StringLiteral" && typeof source.value === "string") return source.value;
|
|
1954
|
-
if (source.type !== "TemplateLiteral") return void 0;
|
|
1955
|
-
const expressions = Array.isArray(source.expressions) ? source.expressions : [];
|
|
1956
|
-
const quasis = Array.isArray(source.quasis) ? source.quasis : [];
|
|
1957
|
-
if (expressions.length > 0 || quasis.length !== 1) return void 0;
|
|
1958
|
-
const value = quasis[0]?.value;
|
|
1959
|
-
return typeof value?.cooked === "string" ? value.cooked : typeof value?.raw === "string" ? value.raw : void 0;
|
|
1960
|
-
}
|
|
1961
|
-
function getExportedName(node) {
|
|
1962
|
-
if (!node || typeof node !== "object") return void 0;
|
|
1963
|
-
const exported = node;
|
|
1964
|
-
if (exported.type === "Identifier" && typeof exported.name === "string") return exported.name;
|
|
1965
|
-
if ((exported.type === "Literal" || exported.type === "StringLiteral") && typeof exported.value === "string") return exported.value;
|
|
1966
|
-
}
|
|
1967
|
-
function isTypeOnly(node) {
|
|
1968
|
-
return node.importKind === "type" || node.exportKind === "type";
|
|
1969
|
-
}
|
|
1970
|
-
function forEachAstNode(root, visit) {
|
|
1971
|
-
const stack = [root];
|
|
1972
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1973
|
-
while (stack.length > 0) {
|
|
1974
|
-
const value = stack.pop();
|
|
1975
|
-
if (!value || typeof value !== "object") continue;
|
|
1976
|
-
if (seen.has(value)) continue;
|
|
1977
|
-
seen.add(value);
|
|
1978
|
-
if (Array.isArray(value)) {
|
|
1979
|
-
for (let index = value.length - 1; index >= 0; index--) stack.push(value[index]);
|
|
1980
|
-
continue;
|
|
1981
|
-
}
|
|
1982
|
-
const node = value;
|
|
1983
|
-
if (typeof node.type === "string") visit(node);
|
|
1984
|
-
Object.entries(node).forEach(([key, child]) => {
|
|
1985
|
-
if (key !== "parent" && key !== "loc") stack.push(child);
|
|
1986
|
-
});
|
|
1987
|
-
}
|
|
1988
|
-
}
|
|
1989
|
-
function collectImportDeclaration(node, source, record, markUnsafe) {
|
|
1990
|
-
if (isTypeOnly(node)) return;
|
|
1991
|
-
const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
|
|
1992
|
-
if (specifiers.length === 0) {
|
|
1993
|
-
markUnsafe(source);
|
|
1994
|
-
return;
|
|
1995
|
-
}
|
|
1996
|
-
const names = [];
|
|
1997
|
-
for (const specifier of specifiers) {
|
|
1998
|
-
if (isTypeOnly(specifier)) continue;
|
|
1999
|
-
if (specifier.type === "ImportNamespaceSpecifier") {
|
|
2000
|
-
markUnsafe(source);
|
|
2001
|
-
return;
|
|
2002
|
-
}
|
|
2003
|
-
if (specifier.type === "ImportDefaultSpecifier") {
|
|
2004
|
-
names.push("default");
|
|
2005
|
-
continue;
|
|
2006
|
-
}
|
|
2007
|
-
if (specifier.type === "ImportSpecifier") {
|
|
2008
|
-
const imported = specifier.imported;
|
|
2009
|
-
if (imported?.type === "Literal" || imported?.type === "StringLiteral") {
|
|
2010
|
-
markUnsafe(source);
|
|
2011
|
-
return;
|
|
2012
|
-
}
|
|
2013
|
-
const name = getExportedName(specifier.imported);
|
|
2014
|
-
if (!name) {
|
|
2015
|
-
markUnsafe(source);
|
|
2016
|
-
return;
|
|
2017
|
-
}
|
|
2018
|
-
names.push(name);
|
|
2019
|
-
continue;
|
|
2020
|
-
}
|
|
2021
|
-
markUnsafe(source);
|
|
2022
|
-
return;
|
|
2023
|
-
}
|
|
2024
|
-
record(names, source);
|
|
2025
|
-
}
|
|
2026
|
-
function collectReExport(node, source, record, markUnsafe) {
|
|
2027
|
-
if (isTypeOnly(node)) return;
|
|
2028
|
-
if (node.type === "ExportAllDeclaration") {
|
|
2029
|
-
markUnsafe(source);
|
|
2030
|
-
return;
|
|
2031
|
-
}
|
|
2032
|
-
const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
|
|
2033
|
-
if (specifiers.length === 0) {
|
|
2034
|
-
markUnsafe(source);
|
|
2035
|
-
return;
|
|
2036
|
-
}
|
|
2037
|
-
const names = [];
|
|
2038
|
-
for (const specifier of specifiers) {
|
|
2039
|
-
if (isTypeOnly(specifier)) continue;
|
|
2040
|
-
if (specifier.type !== "ExportSpecifier") {
|
|
2041
|
-
markUnsafe(source);
|
|
2042
|
-
return;
|
|
2043
|
-
}
|
|
2044
|
-
const local = specifier.local;
|
|
2045
|
-
if (local?.type === "Literal" || local?.type === "StringLiteral") {
|
|
2046
|
-
markUnsafe(source);
|
|
2047
|
-
return;
|
|
2048
|
-
}
|
|
2049
|
-
const name = getExportedName(specifier.local);
|
|
2050
|
-
if (!name) {
|
|
2051
|
-
markUnsafe(source);
|
|
2052
|
-
return;
|
|
2053
|
-
}
|
|
2054
|
-
names.push(name);
|
|
2055
|
-
}
|
|
2056
|
-
record(names, source);
|
|
2057
|
-
}
|
|
2058
|
-
/**
|
|
2059
|
-
* Collect the exports required by a consumer's ESM graph.
|
|
2060
|
-
*
|
|
2061
|
-
* Parsing the module avoids treating import-looking text in comments, strings,
|
|
2062
|
-
* templates, or regular expressions as real dependencies. If parsing fails,
|
|
2063
|
-
* every configured share whose exports are analyzed is conservatively marked
|
|
2064
|
-
* as requiring its full export surface instead of guessing from source text.
|
|
2065
|
-
*
|
|
2066
|
-
* Generated federation wrappers are excluded because their imports describe
|
|
2067
|
-
* the wrapper implementation, not the consumer's requirements.
|
|
2068
|
-
*/
|
|
2069
|
-
function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe) {
|
|
2070
|
-
const normalizedId = normalizePathForImport(id);
|
|
2071
|
-
if (normalizedId.includes("__prebuild__") || normalizedId.includes("__loadShare__") || normalizedId.includes("__mf_tree_shaking_graph__")) return;
|
|
2072
|
-
let ast;
|
|
2073
|
-
try {
|
|
2074
|
-
ast = parseAst(code);
|
|
2075
|
-
} catch {
|
|
2076
|
-
Object.entries(shared).forEach(([sharedKey, shareItem]) => {
|
|
2077
|
-
if (shouldAnalyzeSharedExports(shareItem)) markUnsafe(sharedKey, "*");
|
|
2078
|
-
});
|
|
2079
|
-
return;
|
|
2080
|
-
}
|
|
2081
|
-
const matchShared = (source) => {
|
|
2082
|
-
const sharedKey = findSharedKey(source, shared);
|
|
2083
|
-
return sharedKey && shouldAnalyzeSharedExports(shared[sharedKey]) ? sharedKey : void 0;
|
|
2084
|
-
};
|
|
2085
|
-
const recordSource = (names, source) => {
|
|
2086
|
-
const sharedKey = matchShared(source);
|
|
2087
|
-
if (sharedKey) record(sharedKey, names, source);
|
|
2088
|
-
};
|
|
2089
|
-
const markSourceUnsafe = (source) => {
|
|
2090
|
-
const sharedKey = matchShared(source);
|
|
2091
|
-
if (sharedKey) markUnsafe(sharedKey, source);
|
|
2092
|
-
};
|
|
2093
|
-
forEachAstNode(ast, (node) => {
|
|
2094
|
-
if (node.type === "ImportDeclaration") {
|
|
2095
|
-
const source = getModuleSource(node.source);
|
|
2096
|
-
if (source) collectImportDeclaration(node, source, recordSource, markSourceUnsafe);
|
|
2097
|
-
return;
|
|
2098
|
-
}
|
|
2099
|
-
if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
|
|
2100
|
-
const source = getModuleSource(node.source);
|
|
2101
|
-
if (source) collectReExport(node, source, recordSource, markSourceUnsafe);
|
|
2102
|
-
return;
|
|
2103
|
-
}
|
|
2104
|
-
if (node.type === "ImportExpression") {
|
|
2105
|
-
const source = getModuleSource(node.source);
|
|
2106
|
-
if (source) markSourceUnsafe(source);
|
|
2107
|
-
return;
|
|
2108
|
-
}
|
|
2109
|
-
if (node.type === "CallExpression") {
|
|
2110
|
-
const callee = node.callee;
|
|
2111
|
-
const args = Array.isArray(node.arguments) ? node.arguments : [];
|
|
2112
|
-
if (callee?.type === "Identifier" && callee.name === "require" && args.length > 0) {
|
|
2113
|
-
const source = getModuleSource(args[0]);
|
|
2114
|
-
if (source) markSourceUnsafe(source);
|
|
2115
|
-
}
|
|
2116
|
-
}
|
|
2117
|
-
});
|
|
2302
|
+
},
|
|
2303
|
+
});
|
|
2304
|
+
__mfReactInternals.A = __mfReactDispatcher;
|
|
2305
|
+
}`;
|
|
2118
2306
|
}
|
|
2119
2307
|
//#endregion
|
|
2120
2308
|
//#region src/utils/typeArgumentScanner.ts
|
|
@@ -2191,6 +2379,77 @@ function findLikelyTypeArgumentEnd(source, start, codePositions) {
|
|
|
2191
2379
|
}
|
|
2192
2380
|
}
|
|
2193
2381
|
//#endregion
|
|
2382
|
+
//#region src/virtualModules/shareTags.ts
|
|
2383
|
+
const LOAD_SHARE_TAG = "__loadShare__";
|
|
2384
|
+
/** A share's local copy. Reachable only through `import()`, so it stays lazy. */
|
|
2385
|
+
const PREBUILD_TAG = "__prebuild__";
|
|
2386
|
+
//#endregion
|
|
2387
|
+
//#region src/virtualModules/loadShareSharedChunk.ts
|
|
2388
|
+
const HELPERS_MODULE_NAME = "loadShareHelpers";
|
|
2389
|
+
const HELPERS_MODULE_TAG = "__mf_v__";
|
|
2390
|
+
const HELPERS_MODULE_MARKER = `${HELPERS_MODULE_TAG}${HELPERS_MODULE_NAME}${HELPERS_MODULE_TAG}`;
|
|
2391
|
+
const SHARED_CHUNK_SUFFIX = `${LOAD_SHARE_TAG}shared`;
|
|
2392
|
+
const HELPER_EXPORT_LIST = [
|
|
2393
|
+
"__mfGetSharedCacheDescriptor",
|
|
2394
|
+
"__mfReadSharedCache",
|
|
2395
|
+
"__mfSharedCacheListenersKey",
|
|
2396
|
+
"__mfGetSharedCacheListeners",
|
|
2397
|
+
"__mfSubscribeSharedCache",
|
|
2398
|
+
"__mfSharedCacheOwnersKey",
|
|
2399
|
+
"__mfGetSharedCacheOwners",
|
|
2400
|
+
"__mfReadSharedCacheOwner",
|
|
2401
|
+
"__mfGetSharedModuleIdentity",
|
|
2402
|
+
"__mfIsSameSharedModule",
|
|
2403
|
+
"__mfWriteSharedCache",
|
|
2404
|
+
"__mfTreeShakingSharedCacheKey",
|
|
2405
|
+
"__mfGetTreeShakingSharedCache",
|
|
2406
|
+
"__mfReadTreeShakingSharedCache",
|
|
2407
|
+
"__mfWriteTreeShakingSharedCache",
|
|
2408
|
+
"__mfTreeShakingSelectionCacheKey",
|
|
2409
|
+
"__mfGetTreeShakingSelectionCache",
|
|
2410
|
+
"__mfReadTreeShakingSharedSelection",
|
|
2411
|
+
"__mfWriteTreeShakingSharedSelection"
|
|
2412
|
+
].join(", ");
|
|
2413
|
+
const helperModules = /* @__PURE__ */ new WeakMap();
|
|
2414
|
+
function getSharedCacheHelpersModule(options) {
|
|
2415
|
+
let module = helperModules.get(options);
|
|
2416
|
+
if (!module) {
|
|
2417
|
+
module = new VirtualModule(HELPERS_MODULE_NAME, HELPERS_MODULE_TAG, "", getFederationScopeKey(options));
|
|
2418
|
+
module.writeSync(`${sharedCacheHelperCode}\nexport { ${HELPER_EXPORT_LIST} };`);
|
|
2419
|
+
helperModules.set(options, module);
|
|
2420
|
+
}
|
|
2421
|
+
return module;
|
|
2422
|
+
}
|
|
2423
|
+
function getSharedCacheHelpersImportCode(options) {
|
|
2424
|
+
const importId = getSharedCacheHelpersModule(options).getImportId();
|
|
2425
|
+
return `import { ${HELPER_EXPORT_LIST} } from ${JSON.stringify(importId)};`;
|
|
2426
|
+
}
|
|
2427
|
+
function isSharedCacheHelpersId(id) {
|
|
2428
|
+
return id.includes(HELPERS_MODULE_MARKER);
|
|
2429
|
+
}
|
|
2430
|
+
function getSharedChunkName(id) {
|
|
2431
|
+
const ownerTag = isSharedCacheHelpersId(id) ? HELPERS_MODULE_MARKER : LOAD_SHARE_TAG;
|
|
2432
|
+
return `${id.slice(0, id.indexOf(ownerTag))}${SHARED_CHUNK_SUFFIX}`;
|
|
2433
|
+
}
|
|
2434
|
+
function isSharedChunk(chunk) {
|
|
2435
|
+
return chunk.name?.endsWith(SHARED_CHUNK_SUFFIX) ?? false;
|
|
2436
|
+
}
|
|
2437
|
+
/**
|
|
2438
|
+
* Fallbacks inlined into a shared chunk, which means they are no longer lazy.
|
|
2439
|
+
* Only inlined modules count: a shared chunk also imports fallback chunks with
|
|
2440
|
+
* the experiment off, because Rolldown hoists its runtime helpers into whichever
|
|
2441
|
+
* chunk first uses them.
|
|
2442
|
+
*/
|
|
2443
|
+
function findEagerFallbacksInSharedChunk(bundle) {
|
|
2444
|
+
const offenders = /* @__PURE__ */ new Map();
|
|
2445
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
2446
|
+
if (chunk.type !== "chunk" || !isSharedChunk(chunk)) continue;
|
|
2447
|
+
const inlined = Object.keys(chunk.modules ?? {}).filter((id) => id.includes(PREBUILD_TAG));
|
|
2448
|
+
if (inlined.length > 0) offenders.set(fileName, inlined);
|
|
2449
|
+
}
|
|
2450
|
+
return offenders;
|
|
2451
|
+
}
|
|
2452
|
+
//#endregion
|
|
2194
2453
|
//#region src/virtualModules/virtualShared_preBuild.ts
|
|
2195
2454
|
/**
|
|
2196
2455
|
* Even the resolveId hook cannot interfere with vite pre-build,
|
|
@@ -2226,7 +2485,7 @@ function isValidEsmExportName(name) {
|
|
|
2226
2485
|
const JS_IDENTIFIER_PATTERN = `[\$_\\p{ID_Start}][\$_\\u200C\\u200D\\p{ID_Continue}]*`;
|
|
2227
2486
|
function resolvePackageEntryFromProjectRoot(pkg) {
|
|
2228
2487
|
try {
|
|
2229
|
-
return
|
|
2488
|
+
return resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json"));
|
|
2230
2489
|
} catch {
|
|
2231
2490
|
return;
|
|
2232
2491
|
}
|
|
@@ -2257,6 +2516,18 @@ const DEFAULT_SHARED_EXPORT_CONDITIONS = [
|
|
|
2257
2516
|
"module",
|
|
2258
2517
|
"default"
|
|
2259
2518
|
];
|
|
2519
|
+
function getSharedExportSource(source) {
|
|
2520
|
+
const parts = [];
|
|
2521
|
+
let offset = 0;
|
|
2522
|
+
const codePositions = createCodePositionMap(source, (start, end) => {
|
|
2523
|
+
parts.push(source.slice(offset, start), source.slice(start, end).replace(/[^\r\n\u2028\u2029]/g, " "));
|
|
2524
|
+
offset = end;
|
|
2525
|
+
});
|
|
2526
|
+
return {
|
|
2527
|
+
source: parts.length ? parts.join("") + source.slice(offset) : source,
|
|
2528
|
+
codePositions
|
|
2529
|
+
};
|
|
2530
|
+
}
|
|
2260
2531
|
function hasCodeMatch(source, regex, codePositions) {
|
|
2261
2532
|
regex.lastIndex = 0;
|
|
2262
2533
|
let match;
|
|
@@ -2301,8 +2572,7 @@ function getMutableExportsFromFile(entryPath, exportConditions = DEFAULT_SHARED_
|
|
|
2301
2572
|
if (!entryPath || visited.has(entryPath)) return [];
|
|
2302
2573
|
visited.add(entryPath);
|
|
2303
2574
|
try {
|
|
2304
|
-
const source = readFileSync(entryPath, "utf-8");
|
|
2305
|
-
const codePositions = createCodePositionMap(source);
|
|
2575
|
+
const { source, codePositions } = getSharedExportSource(readFileSync(entryPath, "utf-8"));
|
|
2306
2576
|
const mutableBindings = /* @__PURE__ */ new Set();
|
|
2307
2577
|
const mutableExports = /* @__PURE__ */ new Set();
|
|
2308
2578
|
let match;
|
|
@@ -2373,7 +2643,7 @@ function resolveConfiguredImportPath(importSource, exportConditions = DEFAULT_SH
|
|
|
2373
2643
|
});
|
|
2374
2644
|
if (esmEntry) return esmEntry;
|
|
2375
2645
|
try {
|
|
2376
|
-
return
|
|
2646
|
+
return resolveModulePath(importSource, path$1.join(projectRoot, "package.json"));
|
|
2377
2647
|
} catch {
|
|
2378
2648
|
return;
|
|
2379
2649
|
}
|
|
@@ -2428,7 +2698,7 @@ function resolveReExportModule(filePath, specifier, exportConditions) {
|
|
|
2428
2698
|
});
|
|
2429
2699
|
if (esmEntry) return esmEntry;
|
|
2430
2700
|
try {
|
|
2431
|
-
return resolveFileLikeModule(
|
|
2701
|
+
return resolveFileLikeModule(resolveModulePath(specifier, filePath));
|
|
2432
2702
|
} catch {
|
|
2433
2703
|
return;
|
|
2434
2704
|
}
|
|
@@ -2616,7 +2886,9 @@ function hasUnsupportedBindingPattern(source, start) {
|
|
|
2616
2886
|
}
|
|
2617
2887
|
function getNamedExportsViaRegex(source, filePath, visited, scanState = { complete: true }, exportConditions = DEFAULT_SHARED_EXPORT_CONDITIONS) {
|
|
2618
2888
|
const names = /* @__PURE__ */ new Set();
|
|
2619
|
-
const
|
|
2889
|
+
const inspected = getSharedExportSource(source);
|
|
2890
|
+
source = inspected.source;
|
|
2891
|
+
const codePositions = inspected.codePositions;
|
|
2620
2892
|
const recognizedExportStarts = /* @__PURE__ */ new Set();
|
|
2621
2893
|
visited = visited || /* @__PURE__ */ new Set();
|
|
2622
2894
|
if (filePath) visited.add(filePath);
|
|
@@ -2754,7 +3026,8 @@ function getRequiredNamedExports(specifier) {
|
|
|
2754
3026
|
const getActiveHandles = process._getActiveHandles;
|
|
2755
3027
|
const handlesBeforeRequire = typeof getActiveHandles === "function" ? new Set(getActiveHandles.call(process)) : void 0;
|
|
2756
3028
|
try {
|
|
2757
|
-
const
|
|
3029
|
+
const projectPackageJson = path$1.join(getPackageDetectionCwd(), "package.json");
|
|
3030
|
+
const mod = createRequire$1(pathToFileURL(projectPackageJson))(resolveModulePath(specifier, projectPackageJson));
|
|
2758
3031
|
const runtimeNamedKeys = Object.keys(mod).filter((key) => key !== "default" && key !== "__esModule");
|
|
2759
3032
|
if (runtimeNamedKeys.some((key) => !isValidEsmExportName(key))) return void 0;
|
|
2760
3033
|
return runtimeNamedKeys;
|
|
@@ -2797,7 +3070,7 @@ function getSharedNamedExports(pkg, shareItem, exportConditions = DEFAULT_SHARED
|
|
|
2797
3070
|
}
|
|
2798
3071
|
function getLocalProviderImportPath(pkg) {
|
|
2799
3072
|
try {
|
|
2800
|
-
const resolved = resolveWorkspaceEsmEntry(pkg,
|
|
3073
|
+
const resolved = resolveWorkspaceEsmEntry(pkg, resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json")));
|
|
2801
3074
|
return isWorkspaceFilePath(resolved) ? resolved : void 0;
|
|
2802
3075
|
} catch {
|
|
2803
3076
|
const resolved = getInstalledPackageEntry(pkg, {
|
|
@@ -2818,7 +3091,7 @@ function getProjectResolvedImportPath(pkg) {
|
|
|
2818
3091
|
if (esmEntry) return esmEntry;
|
|
2819
3092
|
}
|
|
2820
3093
|
try {
|
|
2821
|
-
return resolveWorkspaceEsmEntry(pkg,
|
|
3094
|
+
return resolveWorkspaceEsmEntry(pkg, resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json")));
|
|
2822
3095
|
} catch {
|
|
2823
3096
|
return;
|
|
2824
3097
|
}
|
|
@@ -2874,25 +3147,11 @@ function getSharedDependencyGraphPackageJson(pkg) {
|
|
|
2874
3147
|
const installedPackageJson = getInstalledPackageJson(pkg, { packageName: getPackageName(pkg) })?.packageJson;
|
|
2875
3148
|
if (installedPackageJson) return installedPackageJson;
|
|
2876
3149
|
try {
|
|
2877
|
-
const packageJsonPath =
|
|
3150
|
+
const packageJsonPath = resolveModulePath(`${getPackageName(pkg)}/package.json`, path$1.join(getPackageDetectionCwd(), "package.json"));
|
|
2878
3151
|
return JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
2879
3152
|
} catch {}
|
|
2880
3153
|
return getWorkspacePackageJson(pkg);
|
|
2881
3154
|
}
|
|
2882
|
-
function getDependencyNames(packageJson) {
|
|
2883
|
-
if (!packageJson) return [];
|
|
2884
|
-
const names = /* @__PURE__ */ new Set();
|
|
2885
|
-
for (const field of [
|
|
2886
|
-
"dependencies",
|
|
2887
|
-
"peerDependencies",
|
|
2888
|
-
"optionalDependencies"
|
|
2889
|
-
]) {
|
|
2890
|
-
const deps = packageJson[field];
|
|
2891
|
-
if (!deps || typeof deps !== "object") continue;
|
|
2892
|
-
for (const dep of Object.keys(deps)) names.add(dep);
|
|
2893
|
-
}
|
|
2894
|
-
return Array.from(names);
|
|
2895
|
-
}
|
|
2896
3155
|
function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFederationOptions(), requireFederationRuntimeDependency = false) {
|
|
2897
3156
|
const shared = options?.shared || {};
|
|
2898
3157
|
if (!requireFederationRuntimeDependency && Object.entries(shared).some(([key, item]) => key !== pkg && key.startsWith(`${pkg}/`) && item.shareConfig.singleton === true)) return true;
|
|
@@ -2901,25 +3160,39 @@ function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFedera
|
|
|
2901
3160
|
const packageName = getPackageName(key);
|
|
2902
3161
|
if (!sharedKeyByPackageName.get(packageName) || key === packageName) sharedKeyByPackageName.set(packageName, key);
|
|
2903
3162
|
});
|
|
2904
|
-
const
|
|
3163
|
+
const runtimeDependencyCache = /* @__PURE__ */ new Map();
|
|
3164
|
+
const reachesFederationRuntime = (current, seen) => {
|
|
3165
|
+
if (runtimeDependencyCache.has(current)) return runtimeDependencyCache.get(current);
|
|
3166
|
+
const result = getDependencyNames(getSharedDependencyGraphPackageJson(current)).some((dependency) => {
|
|
3167
|
+
if (dependency === "@module-federation/enhanced" || dependency === "@module-federation/runtime" || dependency === "@module-federation/runtime-core") return true;
|
|
3168
|
+
if (seen.has(dependency)) return false;
|
|
3169
|
+
seen.add(dependency);
|
|
3170
|
+
const reachable = reachesFederationRuntime(dependency, seen);
|
|
3171
|
+
seen.delete(dependency);
|
|
3172
|
+
return reachable;
|
|
3173
|
+
});
|
|
3174
|
+
runtimeDependencyCache.set(current, result);
|
|
3175
|
+
return result;
|
|
3176
|
+
};
|
|
3177
|
+
const reachesPkg = (current, seen) => {
|
|
2905
3178
|
const dependencies = getDependencyNames(getSharedDependencyGraphPackageJson(current));
|
|
2906
|
-
const usesFederationRuntime = dependencies.some((dependency) => dependency === "@module-federation/enhanced" || dependency === "@module-federation/runtime" || dependency === "@module-federation/runtime-core");
|
|
2907
|
-
const runtimeIsReachable = hasFederationRuntimeDependency || usesFederationRuntime;
|
|
2908
3179
|
for (const dependency of dependencies) {
|
|
2909
3180
|
const sharedDependency = sharedKeyByPackageName.get(dependency);
|
|
2910
|
-
if (
|
|
2911
|
-
if (sharedDependency
|
|
2912
|
-
|
|
2913
|
-
seen.
|
|
2914
|
-
|
|
3181
|
+
if (sharedDependency === pkg) return true;
|
|
3182
|
+
if (!sharedDependency && !requireFederationRuntimeDependency) continue;
|
|
3183
|
+
const next = sharedDependency || dependency;
|
|
3184
|
+
if (seen.has(next)) continue;
|
|
3185
|
+
seen.add(next);
|
|
3186
|
+
if (reachesPkg(next, seen)) return true;
|
|
3187
|
+
seen.delete(next);
|
|
2915
3188
|
}
|
|
2916
3189
|
return false;
|
|
2917
3190
|
};
|
|
2918
|
-
return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && reachesPkg(sharedPkg, /* @__PURE__ */ new Set([sharedPkg])));
|
|
3191
|
+
return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && (!requireFederationRuntimeDependency || reachesFederationRuntime(sharedPkg, /* @__PURE__ */ new Set([sharedPkg]))) && reachesPkg(sharedPkg, /* @__PURE__ */ new Set([sharedPkg])));
|
|
2919
3192
|
}
|
|
2920
3193
|
function tryResolveImportFromPackageRoot(pkg, root) {
|
|
2921
3194
|
try {
|
|
2922
|
-
return resolveWorkspaceEsmEntry(pkg,
|
|
3195
|
+
return resolveWorkspaceEsmEntry(pkg, resolveModulePath(pkg, path$1.join(root, "package.json")), root);
|
|
2923
3196
|
} catch {
|
|
2924
3197
|
return;
|
|
2925
3198
|
}
|
|
@@ -2952,9 +3225,11 @@ function resolveConcreteSharedImportSource(pkg, projectRoot) {
|
|
|
2952
3225
|
if (resolved) return resolved;
|
|
2953
3226
|
currentDir = path$1.dirname(currentDir);
|
|
2954
3227
|
}
|
|
2955
|
-
return tryResolveImportFromPackageRoot(pkg, currentDir)
|
|
3228
|
+
return tryResolveImportFromPackageRoot(pkg, currentDir) ?? getInstalledPackageEntry(pkg, {
|
|
3229
|
+
conditions: DEFAULT_SHARED_EXPORT_CONDITIONS,
|
|
3230
|
+
resolveSubpathWithRequire: false
|
|
3231
|
+
});
|
|
2956
3232
|
}
|
|
2957
|
-
const PREBUILD_TAG = "__prebuild__";
|
|
2958
3233
|
const TREE_SHAKING_PROVIDER_TAG = "__treeShakingProvider__";
|
|
2959
3234
|
const TREE_SHAKING_GRAPH_QUERY = "__mf_tree_shaking_graph__";
|
|
2960
3235
|
const legacySharedVirtualModuleState = {
|
|
@@ -2963,9 +3238,11 @@ const legacySharedVirtualModuleState = {
|
|
|
2963
3238
|
treeShakingProviderCacheMap: {},
|
|
2964
3239
|
materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
|
|
2965
3240
|
loadShareCacheMap: {},
|
|
2966
|
-
warnedMissingImportFalse: /* @__PURE__ */ new Set()
|
|
3241
|
+
warnedMissingImportFalse: /* @__PURE__ */ new Set(),
|
|
3242
|
+
coalescableLoadShares: /* @__PURE__ */ new Set()
|
|
2967
3243
|
};
|
|
2968
3244
|
const sharedVirtualModuleStates = /* @__PURE__ */ new WeakMap();
|
|
3245
|
+
const sharedVirtualModuleStatesByOwner = /* @__PURE__ */ new Map();
|
|
2969
3246
|
function getSharedVirtualModuleState(options) {
|
|
2970
3247
|
if (!options) try {
|
|
2971
3248
|
const currentOptions = getNormalizeModuleFederationOptions();
|
|
@@ -2982,12 +3259,19 @@ function getSharedVirtualModuleState(options) {
|
|
|
2982
3259
|
materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
|
|
2983
3260
|
loadShareCacheMap: {},
|
|
2984
3261
|
warnedMissingImportFalse: /* @__PURE__ */ new Set(),
|
|
3262
|
+
coalescableLoadShares: /* @__PURE__ */ new Set(),
|
|
2985
3263
|
ownerKey: getFederationScopeKey(options)
|
|
2986
3264
|
};
|
|
2987
3265
|
sharedVirtualModuleStates.set(options, state);
|
|
3266
|
+
if (state.ownerKey !== void 0) sharedVirtualModuleStatesByOwner.set(state.ownerKey, state);
|
|
2988
3267
|
}
|
|
2989
3268
|
return state;
|
|
2990
3269
|
}
|
|
3270
|
+
/** State of the instance that owns a scoped virtual id; `options` covers unscoped ids. */
|
|
3271
|
+
function getSharedVirtualModuleStateForId(id, options) {
|
|
3272
|
+
const ownerKey = id === void 0 ? void 0 : VirtualModule.findById(id)?.getScopeName();
|
|
3273
|
+
return (ownerKey !== void 0 ? sharedVirtualModuleStatesByOwner.get(ownerKey) : void 0) ?? getSharedVirtualModuleState(options);
|
|
3274
|
+
}
|
|
2991
3275
|
function createScopedSharedVirtualModule(pkg, tag, options) {
|
|
2992
3276
|
return new VirtualModule(pkg, tag, ".js", getSharedVirtualModuleState(options).ownerKey);
|
|
2993
3277
|
}
|
|
@@ -3104,7 +3388,7 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
|
|
|
3104
3388
|
const cache = globalThis[__mfCacheGlobalKey]?.share;
|
|
3105
3389
|
const sharedReact = cache && __mfReadSharedCache(cache, ${reactCacheDescriptor});
|
|
3106
3390
|
const reactExports = sharedReact?.default ?? sharedReact;
|
|
3107
|
-
const internals = reactExports?.
|
|
3391
|
+
const internals = reactExports?.[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
|
|
3108
3392
|
return internals?.H?.useMemoCache(size);
|
|
3109
3393
|
};
|
|
3110
3394
|
export default { c };
|
|
@@ -3182,7 +3466,6 @@ function getPreBuildShareItem(pkg, options) {
|
|
|
3182
3466
|
function getSharedImportSource(pkg, shareItem, options) {
|
|
3183
3467
|
return getConcreteSharedImportSource(pkg, shareItem) || getPreBuildLibImportId(pkg, options);
|
|
3184
3468
|
}
|
|
3185
|
-
const LOAD_SHARE_TAG = "__loadShare__";
|
|
3186
3469
|
function getLoadShareImportId(pkg, _isRolldown, options) {
|
|
3187
3470
|
const { loadShareCacheMap } = getSharedVirtualModuleState(options);
|
|
3188
3471
|
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
|
|
@@ -3242,14 +3525,14 @@ function getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer) {
|
|
|
3242
3525
|
* a merged chunk, TDZ bindings otherwise), so the exports stay unassigned until the deferred cache write
|
|
3243
3526
|
* re-applies them; a host-provided copy re-applies them through the cache subscription as before.
|
|
3244
3527
|
*/
|
|
3245
|
-
function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, mutableExports = []) {
|
|
3528
|
+
function generateEagerWorkspaceSingletonExports(edges, namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, mutableExports = []) {
|
|
3246
3529
|
const copiedExports = namedExports.filter((name) => !mutableExports.includes(name));
|
|
3247
3530
|
const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
|
|
3248
3531
|
const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
|
|
3249
3532
|
const assignments = [...copiedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = mod.default ?? mod;"].join("\n ");
|
|
3250
3533
|
const namedExportLine = copiedExports.length > 0 ? `\n export { ${copiedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
|
|
3251
|
-
const mutableExportLine = mutableExports.length ? `\n
|
|
3252
|
-
return
|
|
3534
|
+
const mutableExportLine = mutableExports.length ? `\n ${edges.reExportNames(mutableExports, importSource)}` : "";
|
|
3535
|
+
return `${edges.importNamespace(importSource)}
|
|
3253
3536
|
let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
|
|
3254
3537
|
if (exportModule === undefined) {
|
|
3255
3538
|
Promise.resolve().then(() => {
|
|
@@ -3277,28 +3560,26 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
|
|
|
3277
3560
|
__mfApplyEagerShareExportsWhenReady(exportModule);
|
|
3278
3561
|
export { __mf_default as default };${namedExportLine}${mutableExportLine}`;
|
|
3279
3562
|
}
|
|
3280
|
-
function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, serveLocalFallback = false, mutableExports = []) {
|
|
3563
|
+
function generateLazyWorkspaceSingletonExports(edges, namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, serveLocalFallback = false, mutableExports = [], deferredEntryFallback = false) {
|
|
3281
3564
|
const copiedExports = namedExports.filter((name) => !mutableExports.includes(name));
|
|
3282
3565
|
const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
|
|
3283
3566
|
const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
|
|
3284
3567
|
const assignments = copiedExports.length > 0 ? [...copiedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = mod.default ?? mod;"].join("\n ") : "__mf_default = mod.default ?? mod;";
|
|
3285
3568
|
const namedExportLine = copiedExports.length > 0 ? `\n export { ${copiedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
|
|
3286
|
-
const mutableExportLine = mutableExports.length ? `\n
|
|
3569
|
+
const mutableExportLine = mutableExports.length ? `\n ${edges.reExportNames(mutableExports, importSource)}` : "";
|
|
3287
3570
|
const applyLocalFallback = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
3288
3571
|
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
|
|
3289
3572
|
__mfApplyLazyShareExports(exportModule);`;
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
__mfTrackPendingShareLoad(initPromise.then(() => {
|
|
3301
|
-
exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
|
|
3573
|
+
const readDeferredShare = getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer);
|
|
3574
|
+
const deferredEntryLoad = `Promise.race([
|
|
3575
|
+
initPromise.then(() => ${readDeferredShare}),
|
|
3576
|
+
new Promise((resolve) => {
|
|
3577
|
+
const current = ${readDeferredShare};
|
|
3578
|
+
if (current !== undefined) resolve(current);
|
|
3579
|
+
else __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, resolve);
|
|
3580
|
+
})
|
|
3581
|
+
]).then((cached) => {
|
|
3582
|
+
exportModule = cached;
|
|
3302
3583
|
if (exportModule !== undefined) {
|
|
3303
3584
|
__mfApplyLazyShareExports(exportModule);
|
|
3304
3585
|
return;
|
|
@@ -3307,8 +3588,32 @@ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cache
|
|
|
3307
3588
|
exportModule = __mfNormalizeShareModule(mod);
|
|
3308
3589
|
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
|
|
3309
3590
|
});
|
|
3310
|
-
})
|
|
3311
|
-
|
|
3591
|
+
})`;
|
|
3592
|
+
const deferredInitLoad = `initPromise.then(() => {
|
|
3593
|
+
exportModule = ${readDeferredShare};
|
|
3594
|
+
if (exportModule !== undefined) {
|
|
3595
|
+
__mfApplyLazyShareExports(exportModule);
|
|
3596
|
+
return;
|
|
3597
|
+
}
|
|
3598
|
+
return import(${escapeGeneratedStringLiteral(importSource)}).then((mod) => {
|
|
3599
|
+
exportModule = __mfNormalizeShareModule(mod);
|
|
3600
|
+
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
|
|
3601
|
+
});
|
|
3602
|
+
})`;
|
|
3603
|
+
const synchronousFallbackConditions = [...deferredEntryFallback ? [] : ["import.meta.env.SSR"], ...serveLocalFallback ? ["(import.meta.env.DEV && typeof __mfLocalShare !== 'undefined')"] : []];
|
|
3604
|
+
const trackPendingLoad = `__mfTrackPendingShareLoad(${deferredEntryFallback ? deferredEntryLoad : deferredInitLoad});`;
|
|
3605
|
+
return `${declarations}
|
|
3606
|
+
const __mfApplyLazyShareExports = (mod) => {
|
|
3607
|
+
${assignments}
|
|
3608
|
+
};
|
|
3609
|
+
__mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyLazyShareExports);
|
|
3610
|
+
let exportModule = ${readDeferredShare};
|
|
3611
|
+
if (exportModule === undefined) {
|
|
3612
|
+
${synchronousFallbackConditions.length > 0 ? `if (${synchronousFallbackConditions.join(" || ")}) {
|
|
3613
|
+
${applyLocalFallback}
|
|
3614
|
+
} else {
|
|
3615
|
+
${trackPendingLoad}
|
|
3616
|
+
}` : trackPendingLoad}
|
|
3312
3617
|
} else {
|
|
3313
3618
|
__mfApplyLazyShareExports(exportModule);
|
|
3314
3619
|
}
|
|
@@ -3344,6 +3649,14 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor,
|
|
|
3344
3649
|
if (exportModule === undefined) {
|
|
3345
3650
|
__mfTrackPendingShareLoad(initPromise.then(() => {
|
|
3346
3651
|
exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
|
|
3652
|
+
// A share init() left to its dynamic import is normally bridged before that import runs;
|
|
3653
|
+
// bridge it here when this wrapper is reached another way.
|
|
3654
|
+
if (exportModule === undefined && typeof __mfPromiseState.loadLazyShares === "function") {
|
|
3655
|
+
return __mfPromiseState.loadLazyShares([${escapeGeneratedStringLiteral(pkg)}]).then(() => {
|
|
3656
|
+
exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
|
|
3657
|
+
});
|
|
3658
|
+
}
|
|
3659
|
+
}).then(() => {
|
|
3347
3660
|
if (exportModule === undefined) {
|
|
3348
3661
|
throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
|
|
3349
3662
|
}
|
|
@@ -3352,7 +3665,7 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor,
|
|
|
3352
3665
|
} else {
|
|
3353
3666
|
__mfApplyHostProvidedExports(exportModule);
|
|
3354
3667
|
}
|
|
3355
|
-
export { __mf_default as default };${namedExportLine}`;
|
|
3668
|
+
export { __mf_default as default, exportModule as __moduleExports };${namedExportLine}`;
|
|
3356
3669
|
}
|
|
3357
3670
|
function selectImportFalseNamedExports(detectedNamedExports, usage) {
|
|
3358
3671
|
if (!detectedNamedExports || usage?.kind !== "exports") return detectedNamedExports ?? [];
|
|
@@ -3391,9 +3704,49 @@ const initializedLocalShareModuleCode = `const __mfInitializedLocalShare = (mod)
|
|
|
3391
3704
|
throw error;
|
|
3392
3705
|
}
|
|
3393
3706
|
};`;
|
|
3707
|
+
function createLocalPayloadEdges() {
|
|
3708
|
+
let edges = 0;
|
|
3709
|
+
return {
|
|
3710
|
+
importNamespace(source) {
|
|
3711
|
+
edges++;
|
|
3712
|
+
return `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(source)};`;
|
|
3713
|
+
},
|
|
3714
|
+
reExportAll(source) {
|
|
3715
|
+
edges++;
|
|
3716
|
+
return `export * from ${escapeGeneratedStringLiteral(source)}`;
|
|
3717
|
+
},
|
|
3718
|
+
reExportNames(names, source) {
|
|
3719
|
+
if (names.length === 0) return "";
|
|
3720
|
+
edges++;
|
|
3721
|
+
return `export { ${names.join(", ")} } from ${escapeGeneratedStringLiteral(source)};`;
|
|
3722
|
+
},
|
|
3723
|
+
get none() {
|
|
3724
|
+
return edges === 0;
|
|
3725
|
+
}
|
|
3726
|
+
};
|
|
3727
|
+
}
|
|
3728
|
+
function recordCoalescability(pkg, hasNoLocalPayloadEdge, command, shareConfig, coalescableLoadShares) {
|
|
3729
|
+
const coalescable = command === "build" && shareConfig.eager !== true && shareConfig.import !== false && hasNoLocalPayloadEdge;
|
|
3730
|
+
if (coalescable) coalescableLoadShares.add(pkg);
|
|
3731
|
+
else coalescableLoadShares.delete(pkg);
|
|
3732
|
+
return coalescable;
|
|
3733
|
+
}
|
|
3734
|
+
/**
|
|
3735
|
+
* `prependWorkspaceSingletonSsrImport` adds a local-payload edge in the server
|
|
3736
|
+
* build's load hook, after this module has generated the wrapper. `id` names
|
|
3737
|
+
* the owning instance when the hook belongs to a different one.
|
|
3738
|
+
*/
|
|
3739
|
+
function markLoadShareWrapperNotCoalescable(pkg, options, id) {
|
|
3740
|
+
getSharedVirtualModuleStateForId(id, options).coalescableLoadShares.delete(pkg);
|
|
3741
|
+
}
|
|
3742
|
+
/** With `id`, answers from the owning instance's state, whichever instance asks. */
|
|
3743
|
+
function isCoalescableLoadShareWrapper(pkg, options, id) {
|
|
3744
|
+
return getSharedVirtualModuleStateForId(id, options).coalescableLoadShares.has(pkg);
|
|
3745
|
+
}
|
|
3394
3746
|
function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exportConditions, importFalseExportUsage) {
|
|
3395
3747
|
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
3396
|
-
const { loadShareCacheMap } = getSharedVirtualModuleState(options);
|
|
3748
|
+
const { loadShareCacheMap, coalescableLoadShares } = getSharedVirtualModuleState(options);
|
|
3749
|
+
const edges = createLocalPayloadEdges();
|
|
3397
3750
|
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
|
|
3398
3751
|
let importLine = getRuntimeModuleCacheBootstrapCode(exportConditions);
|
|
3399
3752
|
const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
|
|
@@ -3413,6 +3766,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3413
3766
|
}
|
|
3414
3767
|
exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor, treeShakingConsumer);
|
|
3415
3768
|
}
|
|
3769
|
+
recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares);
|
|
3416
3770
|
loadShareCacheMap[pkg].writeSync(`
|
|
3417
3771
|
${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}
|
|
3418
3772
|
${importLine}
|
|
@@ -3434,13 +3788,14 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3434
3788
|
const mutableExports = new Set(isLocalOnlyContainer(resolvedOptions) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
|
|
3435
3789
|
const copiedNamedExports = namedExports.filter((name) => !mutableExports.has(name));
|
|
3436
3790
|
const liveNamedExports = namedExports.filter((name) => mutableExports.has(name));
|
|
3437
|
-
const liveNamedExportLine =
|
|
3791
|
+
const liveNamedExportLine = edges.reExportNames(liveNamedExports, sharedImportSource);
|
|
3438
3792
|
const hasCompleteExportCoverage = detectedNamedExports !== void 0;
|
|
3439
3793
|
const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
|
|
3440
3794
|
const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteContainer(resolvedOptions) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
|
|
3441
3795
|
const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
|
|
3442
3796
|
const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
|
|
3443
3797
|
const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
|
|
3798
|
+
const usesDeferredEntryInjectedSingletonFallback = usesEntryInjectedRemoteFallback && !isReactCoreShare(pkg) && (pkg === "react-dom/client" || shareItem.shareConfig.eager !== true && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
|
|
3444
3799
|
const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
|
|
3445
3800
|
const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
|
|
3446
3801
|
const reactMixedModeGuard = pkg === "react" ? createReactMixedModeRuntimeGuard() : "";
|
|
@@ -3448,11 +3803,14 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3448
3803
|
let initBlock = "";
|
|
3449
3804
|
if (usesDeferredTreeShakingFallback) {
|
|
3450
3805
|
importLine = `${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}\n ${importLine}`;
|
|
3451
|
-
exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
|
|
3452
|
-
} else if (
|
|
3806
|
+
exportLine = generateLazyWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
|
|
3807
|
+
} else if (usesDeferredEntryInjectedSingletonFallback) {
|
|
3808
|
+
importLine = `${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}\n ${importLine}`;
|
|
3809
|
+
exportLine = generateLazyWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, false, liveNamedExports, true);
|
|
3810
|
+
} else if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, liveNamedExports);
|
|
3453
3811
|
else if (usesDeferredSingletonFallback) {
|
|
3454
3812
|
importLine = `${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}\n ${importLine}`;
|
|
3455
|
-
exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
|
|
3813
|
+
exportLine = generateLazyWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
|
|
3456
3814
|
} else if (detectedNamedExports === void 0) {
|
|
3457
3815
|
exportLine = `const __mfDefaultExport = (() => {
|
|
3458
3816
|
${generateShareModuleUnwrapCode({
|
|
@@ -3462,7 +3820,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3462
3820
|
})}
|
|
3463
3821
|
})();
|
|
3464
3822
|
export default __mfDefaultExport;
|
|
3465
|
-
|
|
3823
|
+
${edges.reExportAll(coherentLocalSource)}`;
|
|
3466
3824
|
initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
3467
3825
|
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
|
|
3468
3826
|
} else if (namedExports.length > 0 && shareItem.shareConfig.singleton === true) {
|
|
@@ -3513,21 +3871,23 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3513
3871
|
__mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplySharedDefaultExport);
|
|
3514
3872
|
__mfApplySharedDefaultExport(exportModule);
|
|
3515
3873
|
export { __mfDefaultExport as default };
|
|
3516
|
-
|
|
3874
|
+
${edges.reExportAll(sharedImportSource)}`;
|
|
3517
3875
|
initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
3518
3876
|
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
|
|
3519
3877
|
} else {
|
|
3520
|
-
exportLine = `export default exportModule.default ?? exportModule\n
|
|
3878
|
+
exportLine = `export default exportModule.default ?? exportModule\n ${edges.reExportAll(sharedImportSource)}`;
|
|
3521
3879
|
initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
3522
3880
|
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
|
|
3523
3881
|
}
|
|
3524
|
-
const
|
|
3525
|
-
const
|
|
3526
|
-
const
|
|
3527
|
-
|
|
3882
|
+
const staticLocalShareSource = detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource;
|
|
3883
|
+
const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? !servesRemoteSingletonFallback && usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? edges.importNamespace(lazyLocalFallbackSource) : "" : edges.importNamespace(staticLocalShareSource);
|
|
3884
|
+
const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
3885
|
+
const cacheHelpers = recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares) ? getSharedCacheHelpersImportCode(resolvedOptions) : sharedCacheHelperCode;
|
|
3886
|
+
const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback || usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? `
|
|
3887
|
+
${usesDeferredEntryInjectedSingletonFallback ? "" : prebuildImportLine}
|
|
3528
3888
|
${devDynamicImportLine}
|
|
3529
3889
|
${importLine}
|
|
3530
|
-
${
|
|
3890
|
+
${cacheHelpers}
|
|
3531
3891
|
${normalizeLocalShareModuleCode}
|
|
3532
3892
|
${initializedLocalShareModuleCode}
|
|
3533
3893
|
${exportLine}
|
|
@@ -3535,7 +3895,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3535
3895
|
${prebuildImportLine}
|
|
3536
3896
|
${devDynamicImportLine}
|
|
3537
3897
|
${importLine}
|
|
3538
|
-
${
|
|
3898
|
+
${cacheHelpers}
|
|
3539
3899
|
${normalizeLocalShareModuleCode}
|
|
3540
3900
|
let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)}
|
|
3541
3901
|
if (exportModule === undefined) {
|
|
@@ -3579,6 +3939,7 @@ function addConfiguredShare(pkg, options) {
|
|
|
3579
3939
|
if (options) getScopedUsedShares(options).add(pkg);
|
|
3580
3940
|
}
|
|
3581
3941
|
const LOCAL_SHARED_IMPORT_MAP_ID = "virtual:mf-localSharedImportMap";
|
|
3942
|
+
const LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER = "__MF_LAZY_CONSUME_ONLY_SHARES__";
|
|
3582
3943
|
const localOwnerIds = /* @__PURE__ */ new WeakMap();
|
|
3583
3944
|
let nextLocalOwnerId = 1;
|
|
3584
3945
|
function getLocalOwnerKey(options) {
|
|
@@ -3616,6 +3977,10 @@ function getLocalSharedPackagePath(pkg, shareItem, options) {
|
|
|
3616
3977
|
if (shouldUseDirectReactImport() && pkg === "react") return "react";
|
|
3617
3978
|
return getConcreteSharedImportSource(pkg, shareItem) || getLocalProviderImportPath(pkg) || getSharedImportSource(pkg, shareItem, options);
|
|
3618
3979
|
}
|
|
3980
|
+
function getCanonicalSharedKey(pkg, shareItem) {
|
|
3981
|
+
const { request, shareKey } = shareItem.shareConfig;
|
|
3982
|
+
return request !== void 0 || shareKey !== void 0 ? getSharedRuntimeKey(pkg, shareItem) : pkg;
|
|
3983
|
+
}
|
|
3619
3984
|
function getDirectSharedCacheSeedImportPath(pkg, shareItem) {
|
|
3620
3985
|
return getConcreteSharedImportSource(pkg, shareItem) || getProjectResolvedImportPath(pkg) || getLocalProviderImportPath(pkg) || pkg;
|
|
3621
3986
|
}
|
|
@@ -3629,7 +3994,7 @@ function generateLocalSharedImportMap(options) {
|
|
|
3629
3994
|
import {loadShare} from "@module-federation/runtime";
|
|
3630
3995
|
${orderedShares.map((pkg, index) => {
|
|
3631
3996
|
const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
|
|
3632
|
-
if (!shareItem
|
|
3997
|
+
if (!shareItem || !shareItem.shareConfig.eager || shareItem.shareConfig.import === false) return "";
|
|
3633
3998
|
return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
|
|
3634
3999
|
}).filter(Boolean).join("\n")}
|
|
3635
4000
|
${normalizeRuntimeShareCode}
|
|
@@ -3654,12 +4019,17 @@ function generateLocalSharedImportMap(options) {
|
|
|
3654
4019
|
const __mfHostOnly = (name) => async () => {
|
|
3655
4020
|
throw new Error(\`[Module Federation] Shared module '\${name}' must be provided by host\`);
|
|
3656
4021
|
};
|
|
4022
|
+
// Replaced by the lazy consume-only share plugin with the keys that only a dynamic
|
|
4023
|
+
// import() reaches, so init() leaves them to that import; an unreplaced string matches no key.
|
|
4024
|
+
const __mfLazyShares = ${JSON.stringify(LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER)};
|
|
4025
|
+
const __mfIsLazyShare = (name) => Array.isArray(__mfLazyShares) && __mfLazyShares.includes(name);
|
|
3657
4026
|
const __mfConsumeOnly = (name, version, scope, materialize, shareConfig) => ({
|
|
3658
4027
|
name,
|
|
3659
4028
|
version,
|
|
3660
4029
|
scope: [scope],
|
|
3661
4030
|
loaded: false,
|
|
3662
|
-
materialize,
|
|
4031
|
+
materialize: materialize && !__mfIsLazyShare(name),
|
|
4032
|
+
lazy: __mfIsLazyShare(name),
|
|
3663
4033
|
eager: shareConfig.eager,
|
|
3664
4034
|
from: ${toSafeJsLiteral(resolvedOptions.name)},
|
|
3665
4035
|
canLiveRebind: true,
|
|
@@ -3669,7 +4039,8 @@ function generateLocalSharedImportMap(options) {
|
|
|
3669
4039
|
const importMap = {
|
|
3670
4040
|
${orderedShares.map((pkg, index) => {
|
|
3671
4041
|
const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
|
|
3672
|
-
if (shareItem
|
|
4042
|
+
if (!shareItem) return "";
|
|
4043
|
+
if (shareItem.shareConfig.import === false) return `
|
|
3673
4044
|
${toSafeJsLiteral(pkg)}: __mfHostOnly(${toSafeJsLiteral(pkg)})`;
|
|
3674
4045
|
return `
|
|
3675
4046
|
${toSafeJsLiteral(pkg)}: async () => {
|
|
@@ -3685,7 +4056,7 @@ function generateLocalSharedImportMap(options) {
|
|
|
3685
4056
|
const shareItem = getNormalizeShareItem(key, resolvedOptions);
|
|
3686
4057
|
if (!shareItem) return null;
|
|
3687
4058
|
const isReactFamily = key.startsWith("react/") || key === "react-dom/client";
|
|
3688
|
-
const cacheKeys = [key, ...key === "react-dom/client" ? [
|
|
4059
|
+
const cacheKeys = [key, ...key === "react-dom/client" ? [getPackageName(REACT_DOM_CLIENT_SHARE)] : []].flatMap((pkg) => {
|
|
3689
4060
|
const descriptor = getSharedCacheDescriptor(pkg, shareItem);
|
|
3690
4061
|
return [descriptor.canonical, ...descriptor.aliases ?? []];
|
|
3691
4062
|
});
|
|
@@ -3697,7 +4068,7 @@ function generateLocalSharedImportMap(options) {
|
|
|
3697
4068
|
const canLiveRebind = shareItem.shareConfig.import === false || detectedNamedExports !== void 0;
|
|
3698
4069
|
const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
|
|
3699
4070
|
if (shareItem.shareConfig.import === false && !treeShakingConfig) return `
|
|
3700
|
-
${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)}})`;
|
|
4071
|
+
${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)}, ${shareItem.shareConfig.request !== void 0 ? `request: ${toSafeJsLiteral(shareItem.shareConfig.request)},` : ""} ${shareItem.shareConfig.shareKey !== void 0 ? `shareKey: ${toSafeJsLiteral(shareItem.shareConfig.shareKey)},` : ""}})`;
|
|
3701
4072
|
const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, options) : void 0;
|
|
3702
4073
|
const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
|
|
3703
4074
|
const treeShakingUsedExports = resolvedOptions.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
|
|
@@ -3768,6 +4139,8 @@ function generateLocalSharedImportMap(options) {
|
|
|
3768
4139
|
requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)},
|
|
3769
4140
|
strictVersion: ${shareItem.shareConfig.strictVersion},
|
|
3770
4141
|
eager: ${Boolean(shareItem.shareConfig.eager)},
|
|
4142
|
+
${shareItem.shareConfig.request !== void 0 ? `request: ${toSafeJsLiteral(shareItem.shareConfig.request)},` : ""}
|
|
4143
|
+
${shareItem.shareConfig.shareKey !== void 0 ? `shareKey: ${toSafeJsLiteral(shareItem.shareConfig.shareKey)},` : ""}
|
|
3771
4144
|
${shareItem.shareConfig.import === false ? "import: false," : ""}
|
|
3772
4145
|
},
|
|
3773
4146
|
${treeShakingConfig ? `treeShaking: {
|
|
@@ -3806,10 +4179,11 @@ function generateLocalSharedImportMap(options) {
|
|
|
3806
4179
|
}
|
|
3807
4180
|
`;
|
|
3808
4181
|
}
|
|
3809
|
-
/** Expand `pkg/` → package root + matching usedShares; never returns the prefix string. */
|
|
4182
|
+
/** Expand `pkg/` → package root (if importable) + matching usedShares; never returns the prefix string. */
|
|
3810
4183
|
function expandSharedPrefixKey(prefixKey, used) {
|
|
3811
4184
|
const base = prefixKey.slice(0, -1);
|
|
3812
|
-
const
|
|
4185
|
+
const baseImportable = isPackageInstalled(base) && isPackageExportAvailable(base);
|
|
4186
|
+
const expanded = new Set(baseImportable ? [base] : []);
|
|
3813
4187
|
for (const pkg of used) {
|
|
3814
4188
|
if (pkg.endsWith("/")) continue;
|
|
3815
4189
|
if (pkg === base || pkg.startsWith(`${base}/`)) expanded.add(pkg);
|
|
@@ -3819,11 +4193,17 @@ function expandSharedPrefixKey(prefixKey, used) {
|
|
|
3819
4193
|
function getOrderedUsedShares(options) {
|
|
3820
4194
|
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
3821
4195
|
const used = getUsedShares(options);
|
|
3822
|
-
const shares = new Set(
|
|
4196
|
+
const shares = /* @__PURE__ */ new Set();
|
|
4197
|
+
const addShare = (pkg) => {
|
|
4198
|
+
const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
|
|
4199
|
+
shares.add(shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg);
|
|
4200
|
+
};
|
|
4201
|
+
used.forEach(addShare);
|
|
3823
4202
|
Object.keys(resolvedOptions.shared ?? {}).forEach((pkg) => {
|
|
3824
|
-
|
|
4203
|
+
const share = resolvedOptions.shared?.[pkg];
|
|
4204
|
+
if (share && !getSharedRequest(pkg, share).endsWith("/")) addShare(pkg);
|
|
3825
4205
|
});
|
|
3826
|
-
for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) if (pkg.endsWith("/")
|
|
4206
|
+
for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) if (share.shareConfig?.eager && getSharedRequest(pkg, share).endsWith("/")) for (const concrete of expandSharedPrefixKey(getSharedRequest(pkg, share), used)) addShare(concrete);
|
|
3827
4207
|
return orderSharedDependenciesFirst(Array.from(shares).sort((a, b) => {
|
|
3828
4208
|
const priority = (pkg) => pkg === "react" ? 0 : pkg === "react-dom" ? 1 : pkg.startsWith("react/") ? 2 : 3;
|
|
3829
4209
|
return priority(a) - priority(b) || a.localeCompare(b);
|
|
@@ -3836,7 +4216,8 @@ function getMaterializedShares(options) {
|
|
|
3836
4216
|
const usedForEager = options ? usedSharesByOptions.get(options) ?? [] : usedShares;
|
|
3837
4217
|
for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) {
|
|
3838
4218
|
if (!share.shareConfig?.eager) continue;
|
|
3839
|
-
|
|
4219
|
+
const request = getSharedRequest(pkg, share);
|
|
4220
|
+
if (request.endsWith("/")) for (const concrete of expandSharedPrefixKey(request, usedForEager)) shares.add(concrete);
|
|
3840
4221
|
else shares.add(pkg);
|
|
3841
4222
|
}
|
|
3842
4223
|
const configured = /* @__PURE__ */ new Map();
|
|
@@ -3864,10 +4245,14 @@ function getMaterializedShares(options) {
|
|
|
3864
4245
|
}
|
|
3865
4246
|
}
|
|
3866
4247
|
}
|
|
3867
|
-
|
|
4248
|
+
const sorted = [...shares].sort((a, b) => {
|
|
3868
4249
|
const priority = (pkg) => pkg === "react" ? 0 : pkg === "react-dom" ? 1 : pkg.startsWith("react/") ? 2 : 3;
|
|
3869
4250
|
return priority(a) - priority(b) || a.localeCompare(b);
|
|
3870
|
-
})
|
|
4251
|
+
});
|
|
4252
|
+
return orderSharedDependenciesFirst([...new Set(sorted.map((pkg) => {
|
|
4253
|
+
const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
|
|
4254
|
+
return shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg;
|
|
4255
|
+
}))]);
|
|
3871
4256
|
}
|
|
3872
4257
|
/** Shared keys a share's package.json depends on (roots stand in for their subpaths, subpaths for their root), keyed by share. */
|
|
3873
4258
|
function getSharePrerequisites(ordered) {
|
|
@@ -3955,9 +4340,30 @@ function orderSharedDependenciesFirst(sharedPackages) {
|
|
|
3955
4340
|
}
|
|
3956
4341
|
function getShareItemForPreload(pkg, options = getNormalizeModuleFederationOptions()) {
|
|
3957
4342
|
const shared = options.shared;
|
|
3958
|
-
const
|
|
4343
|
+
const packageName = getPackageName(pkg);
|
|
4344
|
+
const wildcardKey = `${packageName}/`;
|
|
3959
4345
|
if (isExplicitSharedKey(pkg, options)) return shared[pkg];
|
|
3960
4346
|
if (isExplicitSharedKey(wildcardKey, options)) return shared[wildcardKey];
|
|
4347
|
+
if (pkg !== packageName && isExplicitSharedKey(packageName, options) && shared[packageName]?.shareConfig.import !== false && getCommonSharedSubpaths(packageName).includes(pkg)) return shared[packageName];
|
|
4348
|
+
const shareItem = getNormalizeShareItem(pkg, options);
|
|
4349
|
+
if (!shareItem) return void 0;
|
|
4350
|
+
if (shareItem.shareConfig.request === void 0 && shareItem.shareConfig.shareKey === void 0) return;
|
|
4351
|
+
const runtimeKey = getSharedRuntimeKey(pkg, shareItem);
|
|
4352
|
+
if (runtimeKey === pkg || runtimeKey.endsWith("/") && (pkg === runtimeKey.slice(0, -1) || pkg.startsWith(runtimeKey))) return shareItem;
|
|
4353
|
+
}
|
|
4354
|
+
/**
|
|
4355
|
+
* Entry-injected renderer wrappers (see `REACT_DOM_CLIENT_SHARE`) assign
|
|
4356
|
+
* `createRoot` only after `initPromise` and a dynamic import, so a standalone
|
|
4357
|
+
* remote must evaluate that wrapper before the app entry. The subpath is often
|
|
4358
|
+
* absent from `getMaterializedShares()` when pending shares is emitted:
|
|
4359
|
+
* `react-dom/` collapses to `react-dom`, and the entry import may not be
|
|
4360
|
+
* recorded yet.
|
|
4361
|
+
*/
|
|
4362
|
+
function shouldPreloadEntryDeferredReactDomClient(options) {
|
|
4363
|
+
if (options.hostInitInjectLocation !== "entry" || !isRemoteContainer(options)) return false;
|
|
4364
|
+
const shareItem = getShareItemForPreload(REACT_DOM_CLIENT_SHARE, options);
|
|
4365
|
+
if (!shareItem || shareItem.shareConfig.singleton !== true) return false;
|
|
4366
|
+
return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
|
|
3961
4367
|
}
|
|
3962
4368
|
function generateSharedCacheSeedItem(pkg, shareItem, importPath, options = getNormalizeModuleFederationOptions()) {
|
|
3963
4369
|
const cacheDescriptor = getSharedCacheDescriptor(pkg, shareItem);
|
|
@@ -3987,6 +4393,8 @@ const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
|
|
|
3987
4393
|
};`;
|
|
3988
4394
|
const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbol("mf.originalSharedProvider");
|
|
3989
4395
|
const __mfResolveShareHook = { emit: (params) => params };
|
|
4396
|
+
const __mfGetShareScopeNames = (share) =>
|
|
4397
|
+
Array.isArray(share.scope) ? share.scope : [share.scope || "default"];
|
|
3990
4398
|
const __mfCreateProviderSelectionVersions = (versions, strategy) => {
|
|
3991
4399
|
if (strategy !== "version-first") return versions;
|
|
3992
4400
|
const selectionVersions = {};
|
|
@@ -4028,7 +4436,7 @@ const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbo
|
|
|
4028
4436
|
Object.entries(versions).filter(([, provider]) => provider?.shareConfig?.import !== false)
|
|
4029
4437
|
);
|
|
4030
4438
|
if (Object.keys(candidates).length === 0) return undefined;
|
|
4031
|
-
const scopes =
|
|
4439
|
+
const scopes = __mfGetShareScopeNames(share);
|
|
4032
4440
|
const selectionVersions = __mfCreateProviderSelectionVersions(candidates, strategy);
|
|
4033
4441
|
const shareScopeMap = {};
|
|
4034
4442
|
for (const scope of scopes) {
|
|
@@ -4140,7 +4548,28 @@ const externalSharedProviderSelectionHelperCode = `const __mfSelectExternalShare
|
|
|
4140
4548
|
) return undefined;
|
|
4141
4549
|
return { provider, scopeRootProvider };
|
|
4142
4550
|
};`;
|
|
4143
|
-
|
|
4551
|
+
/**
|
|
4552
|
+
* A consume-only stub never outranks a provider: when registering this container's
|
|
4553
|
+
* `import: false` share replaces an unloaded provider of the same version (#1311),
|
|
4554
|
+
* the `afterRegisterShare` hook restores the provider. Registered once per instance.
|
|
4555
|
+
*/
|
|
4556
|
+
function generateKeepProvidersOverStubsCode(runtimeVar) {
|
|
4557
|
+
return `if (!${runtimeVar}.__mfKeepAdoptedProviders) {
|
|
4558
|
+
${runtimeVar}.__mfKeepAdoptedProviders = true;
|
|
4559
|
+
${runtimeVar}.sharedHandler?.hooks?.lifecycle?.afterRegisterShare?.on?.((args) => {
|
|
4560
|
+
const { shared, previousShared, registeredShared } = args || {};
|
|
4561
|
+
if (
|
|
4562
|
+
shared?.shareConfig?.import !== false ||
|
|
4563
|
+
registeredShared !== shared ||
|
|
4564
|
+
!previousShared ||
|
|
4565
|
+
previousShared.shareConfig?.import === false
|
|
4566
|
+
) return;
|
|
4567
|
+
const versions = ${runtimeVar}.shareScopeMap?.[args.scope]?.[args.pkgName];
|
|
4568
|
+
if (versions && versions[shared.version] === shared) versions[shared.version] = previousShared;
|
|
4569
|
+
});
|
|
4570
|
+
}`;
|
|
4571
|
+
}
|
|
4572
|
+
function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "build") {
|
|
4144
4573
|
const seedBatches = getShareBatches(options, false);
|
|
4145
4574
|
const seedOrder = seedBatches.flat();
|
|
4146
4575
|
const seedIndex = new Map(seedOrder.map((pkg, index) => [pkg, index]));
|
|
@@ -4154,7 +4583,7 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
|
|
|
4154
4583
|
// import and set materialize. An import:false share has no local fallback
|
|
4155
4584
|
// though, so on a cold request (materialize not set yet) it must still be
|
|
4156
4585
|
// attempted here, or it is never seeded and its consumer reads it undefined.
|
|
4157
|
-
const __mfSeedKeys = __mfSeedOrder.filter((pkg) => usedShared[pkg] && (usedShared[pkg].materialize !== false || usedShared[pkg].shareConfig?.import === false));
|
|
4586
|
+
const __mfSeedKeys = __mfSeedOrder.filter((pkg) => usedShared[pkg] && (usedShared[pkg].materialize !== false || (usedShared[pkg].shareConfig?.import === false && !usedShared[pkg].lazy)));
|
|
4158
4587
|
__mfModuleCache.providerInit ||= new Map();
|
|
4159
4588
|
const __mfInitializeProviderOnce = (key, initialize) => {
|
|
4160
4589
|
const existing = __mfModuleCache.providerInit.get(key);
|
|
@@ -4187,6 +4616,16 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
|
|
|
4187
4616
|
);
|
|
4188
4617
|
return;
|
|
4189
4618
|
}
|
|
4619
|
+
${command === "serve" ? `// A pending webpack provider for this share, or for its package when this
|
|
4620
|
+
// is a subpath, is only bridged after init(). Seeding the local fallback now
|
|
4621
|
+
// would evaluate the package's dev proxy, which snapshots its exports, before
|
|
4622
|
+
// the bridge runs and pin a second copy. The proxy seeds itself on first import.
|
|
4623
|
+
if (
|
|
4624
|
+
typeof __mfGetPendingExternalSharedProvider === 'function' &&
|
|
4625
|
+
__mfGetPendingExternalSharedProvider(pkg, share)
|
|
4626
|
+
) {
|
|
4627
|
+
return;
|
|
4628
|
+
}` : ""}
|
|
4190
4629
|
const externalProvider = typeof __mfGetExternalSharedProvider === 'function'
|
|
4191
4630
|
? __mfGetExternalSharedProvider(pkg, share)
|
|
4192
4631
|
: undefined;
|
|
@@ -4215,6 +4654,12 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
|
|
|
4215
4654
|
const mod = typeof factory === "function" ? factory() : factory;
|
|
4216
4655
|
return Promise.resolve(mod);
|
|
4217
4656
|
});
|
|
4657
|
+
// The seeded local copy is what this container's consumers are bound to.
|
|
4658
|
+
// Flag the Runtime's provider as eager so a same-version sibling cannot
|
|
4659
|
+
// take over the share scope slot via the Runtime's name tie-break.
|
|
4660
|
+
for (const provider of initRes.options.shared?.[pkg] || []) {
|
|
4661
|
+
if (provider.get === share.get) provider.eager = true;
|
|
4662
|
+
}
|
|
4218
4663
|
${normalizeRuntimeShareCode}
|
|
4219
4664
|
const normalizedModule = __mfNormalizeRuntimeShare(resolved);
|
|
4220
4665
|
const exportModule = normalizedModule === resolved ? {...resolved} : normalizedModule;
|
|
@@ -4487,8 +4932,8 @@ function generateTreeShakingSnapshotPluginCode(enabled) {
|
|
|
4487
4932
|
},
|
|
4488
4933
|
});`;
|
|
4489
4934
|
}
|
|
4490
|
-
function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build", exportConditions) {
|
|
4491
|
-
const needsSharedProviderSelectionHelper =
|
|
4935
|
+
function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build", exportConditions, isSsrBuild = false) {
|
|
4936
|
+
const needsSharedProviderSelectionHelper = hasShared(options);
|
|
4492
4937
|
const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
|
|
4493
4938
|
const hasMultipleShareScopes = Array.isArray(options.shareScope);
|
|
4494
4939
|
const guardHostAutoInit = command === "build" && isRemoteContainer(options) && hasRemotes(options);
|
|
@@ -4499,7 +4944,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
4499
4944
|
...hasTreeShakingShared ? ["getRemoteEntry"] : []
|
|
4500
4945
|
].join(", ");
|
|
4501
4946
|
const runtimeHelperImports = [...hasTreeShakingShared ? ["global as runtimeGlobal"] : [], ...needsSharedProviderSelectionHelper ? ["share as runtimeShare"] : []];
|
|
4502
|
-
const pluginImportNames = options.runtimePlugins.map((p, i) => {
|
|
4947
|
+
const pluginImportNames = filterRuntimePluginsForTarget(options.runtimePlugins, SSR_ONLY_RUNTIME_PLUGINS, isSsrBuild).map((p, i) => {
|
|
4503
4948
|
if (typeof p === "string") return [
|
|
4504
4949
|
`$runtimePlugin_${i}`,
|
|
4505
4950
|
`import $runtimePlugin_${i} from "${p}";`,
|
|
@@ -4822,13 +5267,36 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
4822
5267
|
};
|
|
4823
5268
|
}
|
|
4824
5269
|
const runtimeResolveShareHook = initRes.sharedHandler.hooks.lifecycle.resolveShare;
|
|
5270
|
+
// Registering this container's shares lets its consume-only stub displace the parent's
|
|
5271
|
+
// unloaded same-version provider whenever this container's name sorts after the parent's
|
|
5272
|
+
// (the Runtime keeps the higher name). Nothing can be loaded from a stub, so put the
|
|
5273
|
+
// provider back; a share bridged later, e.g. from a lazy import(), still finds it.
|
|
5274
|
+
${generateKeepProvidersOverStubsCode("initRes")}
|
|
4825
5275
|
const __mfRuntimeProviderOrigins = new WeakMap();
|
|
4826
5276
|
runtimeResolveShareHook.on((args) => {
|
|
4827
5277
|
const loadId = args.shareInfo?.[__mfRuntimeShareLoadIdKey];
|
|
4828
5278
|
const resolver = args.resolver;
|
|
4829
5279
|
if (typeof resolver !== "function") return args;
|
|
4830
5280
|
const instrumentedResolver = (...resolverArgs) => {
|
|
4831
|
-
|
|
5281
|
+
let resolved = resolver(...resolverArgs);
|
|
5282
|
+
// A consume-only stub can never be loaded. The Runtime still settles on one when
|
|
5283
|
+
// it carries the highest version, e.g. a parent that registers its provider under
|
|
5284
|
+
// "0.0.0"; hand back the provider this container selects for itself instead.
|
|
5285
|
+
if (
|
|
5286
|
+
resolved?.shared?.shareConfig?.import === false &&
|
|
5287
|
+
typeof __mfSelectSharedProvider === "function" &&
|
|
5288
|
+
usedShared[args.pkgName]
|
|
5289
|
+
) {
|
|
5290
|
+
const provider = __mfSelectSharedProvider(
|
|
5291
|
+
args.shareScopeMap?.[args.scope]?.[args.pkgName],
|
|
5292
|
+
args.pkgName,
|
|
5293
|
+
usedShared[args.pkgName],
|
|
5294
|
+
'${options.shareStrategy}'
|
|
5295
|
+
);
|
|
5296
|
+
if (provider && provider.shareConfig?.import !== false) {
|
|
5297
|
+
resolved = { shared: provider, useTreesShaking: resolved.useTreesShaking };
|
|
5298
|
+
}
|
|
5299
|
+
}
|
|
4832
5300
|
const selectedProvider = resolved?.shared;
|
|
4833
5301
|
if (
|
|
4834
5302
|
selectedProvider &&
|
|
@@ -5241,7 +5709,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
5241
5709
|
);
|
|
5242
5710
|
}
|
|
5243
5711
|
}
|
|
5244
|
-
${generateRuntimeSharedCacheSeedCode(options.shareStrategy, options)}
|
|
5712
|
+
${generateRuntimeSharedCacheSeedCode(options.shareStrategy, options, command)}
|
|
5245
5713
|
${initializeSharingCode}
|
|
5246
5714
|
__mfRestoreForeignSharedProviders();
|
|
5247
5715
|
// Calling provider.get() marks a provider as loaded. Wait until the Runtime has
|
|
@@ -5259,9 +5727,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
5259
5727
|
);
|
|
5260
5728
|
}));
|
|
5261
5729
|
};
|
|
5262
|
-
await __mfBridgeSharedProviders();
|
|
5263
5730
|
if (__mfUsesWebpackShareScope) {
|
|
5731
|
+
// A webpack host's loadShare() awaits initializeSharing(), which awaits this
|
|
5732
|
+
// init(). Bridging here would call the host's provider.get() and re-enter
|
|
5733
|
+
// loadShare(), so both promises wait on each other forever (#1326).
|
|
5264
5734
|
__mfLateBridgeShared = __mfBridgeSharedProviders;
|
|
5735
|
+
} else {
|
|
5736
|
+
await __mfBridgeSharedProviders();
|
|
5265
5737
|
}
|
|
5266
5738
|
try {
|
|
5267
5739
|
const allInstances = globalThis.__FEDERATION__?.__SHARE__;
|
|
@@ -5415,6 +5887,29 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
5415
5887
|
(pkg) => !__mfBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
|
|
5416
5888
|
));
|
|
5417
5889
|
await __mfSeedLocalShared(__mfReadyDeferredSeedKeys);
|
|
5890
|
+
${command === "build" ? `// A consume-only share reached only through import() is bridged when that import runs
|
|
5891
|
+
// (see pluginLazyConsumeOnlyShares), through the same provider selection init() uses.
|
|
5892
|
+
const __mfLazyShareLoads = new Map();
|
|
5893
|
+
__mfResolveState.loadLazyShares = async (names) => {
|
|
5894
|
+
const requested = new Set(names);
|
|
5895
|
+
for (const batch of __mfMaterializedShareBatches) await Promise.all(batch.filter((pkg) => requested.has(pkg)).map((pkg) => {
|
|
5896
|
+
const share = usedShared[pkg];
|
|
5897
|
+
if (!share || !share.lazy || !__mfIsRuntimeOnlySharePending(pkg)) return;
|
|
5898
|
+
let load = __mfLazyShareLoads.get(pkg);
|
|
5899
|
+
if (!load) {
|
|
5900
|
+
load = __mfBridgeExternalSharedProvider(
|
|
5901
|
+
pkg,
|
|
5902
|
+
share,
|
|
5903
|
+
${hasMultipleShareScopes ? "getShareVersions(pkg, share)" : "shared[pkg]"},
|
|
5904
|
+
initialShared[pkg],
|
|
5905
|
+
undefined
|
|
5906
|
+
).then(() => __mfIsRuntimeOnlySharePending(pkg) ? __mfResolveImportFalseShared(pkg, share) : undefined);
|
|
5907
|
+
load.catch(() => __mfLazyShareLoads.delete(pkg));
|
|
5908
|
+
__mfLazyShareLoads.set(pkg, load);
|
|
5909
|
+
}
|
|
5910
|
+
return load;
|
|
5911
|
+
}));
|
|
5912
|
+
};` : ""}
|
|
5418
5913
|
initResolve(initRes)
|
|
5419
5914
|
return initRes
|
|
5420
5915
|
}
|
|
@@ -5431,8 +5926,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
5431
5926
|
${guardHostAutoInit ? `let __mfInitPromise;
|
|
5432
5927
|
function __mfGuardedInit(shared, initScope, remoteEntryInitOptions) {
|
|
5433
5928
|
if (shared === undefined && __mfInitPromise) return __mfInitPromise;
|
|
5434
|
-
|
|
5435
|
-
|
|
5929
|
+
// A call skipped by the circular-init guard resolves to undefined and must not
|
|
5930
|
+
// replace the cached result of the call that actually initialized the container.
|
|
5931
|
+
const prev = __mfInitPromise;
|
|
5932
|
+
const next = init(shared, initScope, remoteEntryInitOptions);
|
|
5933
|
+
__mfInitPromise = prev ? next.then((res) => (res === undefined ? prev : res)) : next;
|
|
5934
|
+
if (prev) __mfInitPromise.catch(() => {});
|
|
5935
|
+
return next;
|
|
5436
5936
|
}
|
|
5437
5937
|
export { __mfGuardedInit as init, getExposes as get }` : `export { init, getExposes as get }`}
|
|
5438
5938
|
`;
|
|
@@ -5468,7 +5968,28 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
|
|
|
5468
5968
|
const hostInitShareBatches = toSafeJsLiteral(getShareBatches(options, false));
|
|
5469
5969
|
const cacheOwner = toSafeJsLiteral(resolvedOptions.name);
|
|
5470
5970
|
const preferLocalVinextReact = hasPackageDependency("vinext") && (!exportConditions?.includes("browser") || exportConditions.includes("worker"));
|
|
5971
|
+
const hasConfiguredShared = hasShared(resolvedOptions);
|
|
5972
|
+
const hostInitSharedProviderHelperImport = shouldPreloadShares && hasConfiguredShared ? "import {share as runtimeShare} from \"@module-federation/runtime/helpers\";" : "";
|
|
5973
|
+
const hostInitSharedProviderHelperCode = shouldPreloadShares && hasConfiguredShared ? `
|
|
5974
|
+
${sharedProviderSelectionHelperCode}
|
|
5975
|
+
const __mfHasUsableProvider = (versions, pkg, share, scopeName) => {
|
|
5976
|
+
// Keep runtime singleton negotiation unchanged. A singleton already
|
|
5977
|
+
// registered in this scope is authoritative, even when runtime-core
|
|
5978
|
+
// reports a version mismatch.
|
|
5979
|
+
if (share.shareConfig?.singleton) {
|
|
5980
|
+
return Object.values(versions || {}).some(
|
|
5981
|
+
(provider) => provider?.shareConfig?.import !== false
|
|
5982
|
+
);
|
|
5983
|
+
}
|
|
5984
|
+
return Boolean(__mfSelectSharedProvider(
|
|
5985
|
+
versions,
|
|
5986
|
+
pkg,
|
|
5987
|
+
{ ...share, scope: [scopeName] },
|
|
5988
|
+
${toSafeJsLiteral(resolvedOptions.shareStrategy)}
|
|
5989
|
+
));
|
|
5990
|
+
};` : "";
|
|
5471
5991
|
return `
|
|
5992
|
+
${hostInitSharedProviderHelperImport}
|
|
5472
5993
|
${getRuntimeModuleCacheBootstrapCode(exportConditions)}
|
|
5473
5994
|
let hostInitPromise;
|
|
5474
5995
|
async function initHost() {
|
|
@@ -5482,16 +6003,18 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
|
|
|
5482
6003
|
${normalizeRuntimeShareCode}
|
|
5483
6004
|
${shouldPreloadShares ? `
|
|
5484
6005
|
const __mfHasAlternativeSharedVersion = (pkg, share) =>
|
|
5485
|
-
(
|
|
6006
|
+
__mfGetShareScopeNames(share).some(
|
|
5486
6007
|
(scopeName) => Object.keys(runtime.shareScopeMap?.[scopeName]?.[pkg] || {}).some(
|
|
5487
6008
|
(version) => version !== share.version
|
|
5488
6009
|
)
|
|
5489
6010
|
);
|
|
5490
6011
|
const __mfHostInitShareBatches = ${hostInitShareBatches};
|
|
6012
|
+
${hostInitSharedProviderHelperCode}
|
|
5491
6013
|
for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
|
|
5492
6014
|
await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
|
|
5493
6015
|
const share = usedShared[pkg];
|
|
5494
|
-
|
|
6016
|
+
// A standalone container has no dynamic-import boundary to load a lazy share behind.
|
|
6017
|
+
if (!share || (share.materialize === false && !share.lazy)) return;
|
|
5495
6018
|
// remoteEntry.init resolves tree-enabled shares into the
|
|
5496
6019
|
// coverage-aware cache. Never republish that selected partial under
|
|
5497
6020
|
// a generic full-module key here.
|
|
@@ -5505,18 +6028,44 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
|
|
|
5505
6028
|
)`}
|
|
5506
6029
|
) return;
|
|
5507
6030
|
// An import:false share has nothing to load until a foreign provider
|
|
5508
|
-
// registers: its own stub getter throws by construction.
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
6031
|
+
// registers: its own stub getter throws by construction. A standalone
|
|
6032
|
+
// container initialized on the same page keeps its providers in its
|
|
6033
|
+
// own runtime scope (#1307), so adopt those before giving up.
|
|
6034
|
+
if (share.shareConfig?.import === false) {
|
|
6035
|
+
const __mfScopeNames = __mfGetShareScopeNames(share);
|
|
6036
|
+
const __mfNeedsSiblingProvider = (scopeName) =>
|
|
6037
|
+
!__mfHasUsableProvider(
|
|
6038
|
+
runtime.shareScopeMap?.[scopeName]?.[pkg],
|
|
6039
|
+
pkg,
|
|
6040
|
+
share,
|
|
6041
|
+
scopeName
|
|
6042
|
+
);
|
|
6043
|
+
if (__mfScopeNames.some(__mfNeedsSiblingProvider)) {
|
|
6044
|
+
// loadShare() re-runs initializeSharing(), which re-registers this
|
|
6045
|
+
// container's own stub and lets it displace an unloaded adopted
|
|
6046
|
+
// provider whenever this container's name sorts after the provider's
|
|
6047
|
+
// (#1311). Put the provider back: a stub never outranks a provider.
|
|
6048
|
+
${generateKeepProvidersOverStubsCode("runtime")}
|
|
6049
|
+
for (const instance of globalThis.__FEDERATION__?.__INSTANCES__ || []) {
|
|
6050
|
+
for (const scopeName of __mfScopeNames) {
|
|
6051
|
+
const versions = instance?.shareScopeMap?.[scopeName]?.[pkg];
|
|
6052
|
+
if (!__mfHasUsableProvider(versions, pkg, share, scopeName)) continue;
|
|
6053
|
+
if (!__mfNeedsSiblingProvider(scopeName)) continue;
|
|
6054
|
+
const target = (runtime.shareScopeMap[scopeName] ||= {})[pkg] ||= {};
|
|
6055
|
+
for (const [version, provider] of Object.entries(versions)) {
|
|
6056
|
+
if (provider?.shareConfig?.import === false) continue;
|
|
6057
|
+
if (target[version] && target[version].shareConfig?.import !== false) continue;
|
|
6058
|
+
target[version] = provider;
|
|
6059
|
+
}
|
|
6060
|
+
}
|
|
6061
|
+
}
|
|
6062
|
+
}
|
|
6063
|
+
if (__mfScopeNames.every(__mfNeedsSiblingProvider)) return;
|
|
6064
|
+
}
|
|
5517
6065
|
await runtime.loadShare(pkg, {
|
|
5518
6066
|
customShareInfo: { shareConfig: share.shareConfig }
|
|
5519
6067
|
}).then(async (factory) => {
|
|
6068
|
+
if (factory === false) return;
|
|
5520
6069
|
const mod = typeof factory === "function" ? factory() : factory;
|
|
5521
6070
|
let resolved = __mfNormalizeRuntimeShare(await Promise.resolve(mod));
|
|
5522
6071
|
${preferLocalVinextReact ? `if (
|
|
@@ -5596,22 +6145,32 @@ function getPendingSharesState(options) {
|
|
|
5596
6145
|
}
|
|
5597
6146
|
function generatePendingSharesCode(command = "build", options) {
|
|
5598
6147
|
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
5599
|
-
const
|
|
6148
|
+
const pendingSharePkgs = command === "build" ? getMaterializedShares(options).filter((pkg) => {
|
|
5600
6149
|
const shareItem = getShareItemForPreload(pkg, resolvedOptions);
|
|
5601
6150
|
if (!shareItem || pkg.endsWith("/")) return false;
|
|
5602
6151
|
if (shareItem.shareConfig.eager) return false;
|
|
5603
6152
|
return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
|
|
5604
|
-
})
|
|
6153
|
+
}) : [];
|
|
6154
|
+
if (command === "build" && shouldPreloadEntryDeferredReactDomClient(resolvedOptions) && !pendingSharePkgs.includes("react-dom/client")) pendingSharePkgs.push(REACT_DOM_CLIENT_SHARE);
|
|
6155
|
+
const pendingShareImports = pendingSharePkgs.map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`);
|
|
5605
6156
|
return `
|
|
5606
6157
|
${getRuntimeModuleCacheBootstrapCode()}
|
|
5607
6158
|
${sharedCacheHelperCode}
|
|
5608
6159
|
const __mfPendingShareImports = [${pendingShareImports.join(", ")}];
|
|
5609
6160
|
export async function preloadPendingShares() {
|
|
5610
6161
|
if (__mfPendingShareImports.length === 0) return;
|
|
6162
|
+
const __mfRendererShare = ${toSafeJsLiteral(REACT_DOM_CLIENT_SHARE)};
|
|
6163
|
+
const __mfRendererParent = ${toSafeJsLiteral(getPackageName(REACT_DOM_CLIENT_SHARE))};
|
|
5611
6164
|
const {usedShared} = await import("${getLocalSharedImportMapPath(options)}");
|
|
5612
6165
|
await Promise.all(__mfPendingShareImports.map(async ([pkg, load]) => {
|
|
5613
|
-
const
|
|
5614
|
-
|
|
6166
|
+
const exactShare = usedShared[pkg];
|
|
6167
|
+
const share = exactShare ?? (pkg === __mfRendererShare ? usedShared[__mfRendererParent] : undefined);
|
|
6168
|
+
if (!share || share.treeShaking || share.shareConfig?.import === false) return;
|
|
6169
|
+
// The collapsed parent does not mark the renderer subpath materialized until the entry
|
|
6170
|
+
// imports it, and that import map can be emitted first. The deferred renderer wrapper
|
|
6171
|
+
// still has to run before a standalone entry reads createRoot. A cache hit (the host
|
|
6172
|
+
// renderer) skips load(), so a nested leaf does not import its own client.
|
|
6173
|
+
if (exactShare && exactShare.materialize === false && pkg !== __mfRendererShare) return;
|
|
5615
6174
|
const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
|
|
5616
6175
|
if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) return;
|
|
5617
6176
|
await load().catch((err) => console.warn("[module-federation] shared preload failed:", pkg, err));
|
|
@@ -6100,9 +6659,6 @@ if (typeof document !== 'undefined' && document.head) {
|
|
|
6100
6659
|
function getFirstHtmlEntryFile(entryFiles) {
|
|
6101
6660
|
return entryFiles.find((file) => file.endsWith(".html"));
|
|
6102
6661
|
}
|
|
6103
|
-
function stripQueryAndHash$1(file) {
|
|
6104
|
-
return file.split(/[?#]/)[0];
|
|
6105
|
-
}
|
|
6106
6662
|
function isReactRouterClientRouteInput(file) {
|
|
6107
6663
|
return /[?&]__react-router-build-client-route(?:[=&]|$)/.test(file);
|
|
6108
6664
|
}
|
|
@@ -6153,6 +6709,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
6153
6709
|
let emitFileId;
|
|
6154
6710
|
let pendingSharesEmitId;
|
|
6155
6711
|
let viteConfig;
|
|
6712
|
+
let devServer;
|
|
6156
6713
|
let skipHtmlDevFallback = forceClientInjected ?? false;
|
|
6157
6714
|
let clientInjected = false;
|
|
6158
6715
|
let emittedFileName;
|
|
@@ -6229,6 +6786,28 @@ const __mfCurrentScript = document.currentScript;
|
|
|
6229
6786
|
return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) && !/\.json(?:[?#]|$)/i.test(registration.entry) ? [registration.entry] : [];
|
|
6230
6787
|
})));
|
|
6231
6788
|
}
|
|
6789
|
+
async function warmupDevEntryGraph(entryUrl) {
|
|
6790
|
+
const server = devServer;
|
|
6791
|
+
if (!server) return;
|
|
6792
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6793
|
+
const cacheDir = normalizePathForImport(server.config?.cacheDir ?? "").replace(/\/$/, "") + "/";
|
|
6794
|
+
const visit = async (url) => {
|
|
6795
|
+
if (seen.has(url)) return;
|
|
6796
|
+
seen.add(url);
|
|
6797
|
+
try {
|
|
6798
|
+
await server.transformRequest(url);
|
|
6799
|
+
} catch {
|
|
6800
|
+
return;
|
|
6801
|
+
}
|
|
6802
|
+
const deps = [...(await server.moduleGraph.getModuleByUrl(url))?.importedModules ?? []].filter((dep) => {
|
|
6803
|
+
if (!dep.file || dep.type !== "js" || !path$1.isAbsolute(dep.file)) return false;
|
|
6804
|
+
const file = normalizePathForImport(dep.file);
|
|
6805
|
+
return !file.includes("/node_modules/") && !file.startsWith(cacheDir);
|
|
6806
|
+
});
|
|
6807
|
+
await Promise.all(deps.map((dep) => visit(dep.url)));
|
|
6808
|
+
};
|
|
6809
|
+
await visit(entryUrl).catch(() => {});
|
|
6810
|
+
}
|
|
6232
6811
|
function getBootstrapSource(initSrc, entrySrc, useSystemImportFallback = false, options) {
|
|
6233
6812
|
const importHelper = useSystemImportFallback ? `const __mfImport = (src) =>
|
|
6234
6813
|
globalThis.System && typeof globalThis.System.import === 'function'
|
|
@@ -6255,7 +6834,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6255
6834
|
}
|
|
6256
6835
|
` : "";
|
|
6257
6836
|
const sharedPreloadSources = _command === "serve" && waitsForInit && isRemoteOnlyContainer(normalizedOptions) && federationOptions ? Array.from(getUsedShares(federationOptions)).filter((pkg) => !pkg.endsWith("/")).filter((pkg) => {
|
|
6258
|
-
const shareItem =
|
|
6837
|
+
const shareItem = getNormalizeShareItem(pkg, federationOptions);
|
|
6259
6838
|
const isExplicitShare = Object.hasOwn(federationOptions.shared, pkg);
|
|
6260
6839
|
return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
|
|
6261
6840
|
}).map((pkg) => toViteEncodedId(getLoadShareModulePath(pkg, false, federationOptions))) : [];
|
|
@@ -6345,7 +6924,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6345
6924
|
function isWorkspaceSourceId(id) {
|
|
6346
6925
|
const normalized = normalizeModuleId(decodeViteId(id));
|
|
6347
6926
|
if (normalized.startsWith("\0") || normalized.startsWith("virtual:")) return false;
|
|
6348
|
-
const filePath = stripQueryAndHash
|
|
6927
|
+
const filePath = stripQueryAndHash(normalized);
|
|
6349
6928
|
if (filePath.startsWith("/@fs/")) return true;
|
|
6350
6929
|
if (!path$1.isAbsolute(filePath)) return false;
|
|
6351
6930
|
const root = normalizePathForImport(path$1.resolve(viteConfig.root));
|
|
@@ -6367,7 +6946,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6367
6946
|
ignoredHtmlScriptSources.add(match[1]);
|
|
6368
6947
|
continue;
|
|
6369
6948
|
}
|
|
6370
|
-
const scriptSrc = stripQueryAndHash
|
|
6949
|
+
const scriptSrc = stripQueryAndHash(match[1]);
|
|
6371
6950
|
if (/^(?:[a-z]+:)?\/\//i.test(scriptSrc)) continue;
|
|
6372
6951
|
addEntryFile(scriptSrc);
|
|
6373
6952
|
addEntryFile(scriptSrc.startsWith("/") ? path$1.resolve(viteConfig.root, scriptSrc.slice(1)) : path$1.resolve(path$1.dirname(htmlPath), scriptSrc));
|
|
@@ -6375,7 +6954,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6375
6954
|
}
|
|
6376
6955
|
function addEntryRemoteImports(entrySrc) {
|
|
6377
6956
|
if (!federationOptions || /^(?:[a-z]+:)?\/\//i.test(entrySrc)) return;
|
|
6378
|
-
const file = path$1.resolve(viteConfig.root, stripQueryAndHash
|
|
6957
|
+
const file = path$1.resolve(viteConfig.root, stripQueryAndHash(entrySrc).replace(/^\//, ""));
|
|
6379
6958
|
if (!fs$2.existsSync(file)) return;
|
|
6380
6959
|
const code = fs$2.readFileSync(file, "utf-8");
|
|
6381
6960
|
for (const source of findModuleImportSources(code)) {
|
|
@@ -6402,6 +6981,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6402
6981
|
skipTransformIds = new Set(skipTransformFor.map(resolveProjectId));
|
|
6403
6982
|
},
|
|
6404
6983
|
configureServer(server) {
|
|
6984
|
+
devServer = server;
|
|
6405
6985
|
server.middlewares.use((req, res, next) => {
|
|
6406
6986
|
const rawUrl = req.url?.split("#")[0] ?? "";
|
|
6407
6987
|
if (normalizeDevHtmlProxyId(rawUrl.split("?")[0]) === DEV_HTML_PROXY_PREFIX.slice(0, -1)) {
|
|
@@ -6411,9 +6991,12 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6411
6991
|
const entrySrc = params.get("entry");
|
|
6412
6992
|
if (initSrc && entrySrc) {
|
|
6413
6993
|
const withBase = (src) => viteConfig.base + src.replace(/^\//, "");
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6994
|
+
const source = getBootstrapSource(withBase(initSrc), withBase(entrySrc));
|
|
6995
|
+
warmupDevEntryGraph(entrySrc).finally(() => {
|
|
6996
|
+
res.statusCode = 200;
|
|
6997
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
6998
|
+
res.end(source);
|
|
6999
|
+
});
|
|
6417
7000
|
return;
|
|
6418
7001
|
}
|
|
6419
7002
|
}
|
|
@@ -6461,7 +7044,8 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6461
7044
|
const initSrc = params.get("init");
|
|
6462
7045
|
const entrySrc = params.get("entry");
|
|
6463
7046
|
if (!initSrc || !entrySrc) return;
|
|
6464
|
-
|
|
7047
|
+
const source = getBootstrapSource(initSrc, entrySrc);
|
|
7048
|
+
return warmupDevEntryGraph(entrySrc).then(() => source);
|
|
6465
7049
|
},
|
|
6466
7050
|
transform(code, id) {
|
|
6467
7051
|
if (id.includes("node_modules") || inject !== "html" || htmlFilePath) return;
|
|
@@ -6679,17 +7263,20 @@ function checkAliasConflicts(options) {
|
|
|
6679
7263
|
}
|
|
6680
7264
|
return false;
|
|
6681
7265
|
};
|
|
6682
|
-
for (const sharedKey of sharedKeys)
|
|
6683
|
-
const
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
if (
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
7266
|
+
for (const sharedKey of sharedKeys) {
|
|
7267
|
+
const request = getSharedRequest(sharedKey, shared[sharedKey]);
|
|
7268
|
+
for (const aliasEntry of userAliases) {
|
|
7269
|
+
const replacement = aliasEntry.replacement;
|
|
7270
|
+
if (!matchesSharedKey(aliasEntry, request)) continue;
|
|
7271
|
+
if (replacement === "$1") break;
|
|
7272
|
+
if (typeof replacement === "string") {
|
|
7273
|
+
if (getPackageNameFromNodeModulePath(replacement) === (request.endsWith("/") ? request.slice(0, -1) : request)) continue;
|
|
7274
|
+
conflicts.push({
|
|
7275
|
+
sharedModule: sharedKey,
|
|
7276
|
+
alias: String(aliasEntry.find),
|
|
7277
|
+
target: replacement
|
|
7278
|
+
});
|
|
7279
|
+
}
|
|
6693
7280
|
}
|
|
6694
7281
|
}
|
|
6695
7282
|
if (conflicts.length > 0) {
|
|
@@ -7404,9 +7991,6 @@ function pluginExternalRuntimeCore() {
|
|
|
7404
7991
|
};
|
|
7405
7992
|
}
|
|
7406
7993
|
//#endregion
|
|
7407
|
-
//#region package.json
|
|
7408
|
-
var version$1 = "1.22.0";
|
|
7409
|
-
//#endregion
|
|
7410
7994
|
//#region src/virtualModules/index.ts
|
|
7411
7995
|
function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
|
|
7412
7996
|
writeLocalSharedImportMap(options);
|
|
@@ -7424,6 +8008,11 @@ const JS_EXTENSIONS = [
|
|
|
7424
8008
|
".mjs",
|
|
7425
8009
|
".cjs"
|
|
7426
8010
|
];
|
|
8011
|
+
/** A module path without its JS extension, so `./src/App` matches `/root/src/App.tsx`. */
|
|
8012
|
+
const stripKnownJsExtension = (file) => {
|
|
8013
|
+
const ext = path$1.extname(file);
|
|
8014
|
+
return JS_EXTENSIONS.includes(ext) ? path$1.join(path$1.dirname(file), path$1.basename(file, ext)) : file;
|
|
8015
|
+
};
|
|
7427
8016
|
/**
|
|
7428
8017
|
* Creates an empty asset map structure for tracking JS and CSS assets
|
|
7429
8018
|
* @returns Initialized asset map with sync/async arrays for JS and CSS
|
|
@@ -7494,16 +8083,31 @@ const collectStaticChunks = (bundle, roots) => {
|
|
|
7494
8083
|
};
|
|
7495
8084
|
/**
|
|
7496
8085
|
* Analyzes assets associated with a chunk without mutating the output map.
|
|
7497
|
-
*
|
|
8086
|
+
* Dynamic imports are collected transitively (a lazy route nested behind another
|
|
8087
|
+
* lazy route is still reachable), following both static and dynamic edges.
|
|
8088
|
+
* The traversal is cycle-safe and ignores missing bundle entries.
|
|
7498
8089
|
*/
|
|
7499
8090
|
const analyzeChunkAssets = (bundle, fileName, chunk) => {
|
|
7500
8091
|
const dynamicAssets = [];
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
8092
|
+
const visited = /* @__PURE__ */ new Set([fileName]);
|
|
8093
|
+
const queue = [fileName];
|
|
8094
|
+
const enqueue = (imported) => {
|
|
8095
|
+
if (visited.has(imported)) return;
|
|
8096
|
+
visited.add(imported);
|
|
8097
|
+
queue.push(imported);
|
|
8098
|
+
};
|
|
8099
|
+
for (let queueIndex = 0; queueIndex < queue.length; queueIndex++) {
|
|
8100
|
+
const currentChunk = bundle[queue[queueIndex]];
|
|
8101
|
+
if (!currentChunk || currentChunk.type !== "chunk") continue;
|
|
8102
|
+
for (const imported of currentChunk.imports ?? []) enqueue(imported);
|
|
8103
|
+
for (const dynamicImport of currentChunk.dynamicImports ?? []) {
|
|
8104
|
+
if (!bundle[dynamicImport]) continue;
|
|
8105
|
+
dynamicAssets.push({
|
|
8106
|
+
fileName: dynamicImport,
|
|
8107
|
+
type: isCSSFile(dynamicImport) ? "css" : "js"
|
|
8108
|
+
});
|
|
8109
|
+
enqueue(dynamicImport);
|
|
8110
|
+
}
|
|
7507
8111
|
}
|
|
7508
8112
|
return {
|
|
7509
8113
|
importedCss: Array.from(chunk.viteMetadata?.importedCss ?? []),
|
|
@@ -7527,8 +8131,8 @@ const processModuleAssets = (bundle, filesMap, moduleMatcher, options = {}) => {
|
|
|
7527
8131
|
const comparableModulePath = options.root ? path$1.resolve(options.root, modulePath) : modulePath;
|
|
7528
8132
|
const comparableModulePaths = [comparableModulePath];
|
|
7529
8133
|
if (options.stripKnownJsExtensions) {
|
|
7530
|
-
const
|
|
7531
|
-
if (
|
|
8134
|
+
const stripped = stripKnownJsExtension(comparableModulePath);
|
|
8135
|
+
if (stripped !== comparableModulePath) comparableModulePaths.push(stripped);
|
|
7532
8136
|
}
|
|
7533
8137
|
const matchKey = comparableModulePaths.map(moduleMatcher).find(Boolean);
|
|
7534
8138
|
if (!matchKey) continue;
|
|
@@ -7589,6 +8193,118 @@ const buildFileToShareKeyMap = async (shareKeys, resolveFn, options) => {
|
|
|
7589
8193
|
return fileToShareKey;
|
|
7590
8194
|
};
|
|
7591
8195
|
//#endregion
|
|
8196
|
+
//#region src/plugins/pluginLazyConsumeOnlyShares.ts
|
|
8197
|
+
const chunkModuleIds = (chunk) => [...chunk.facadeModuleId ? [chunk.facadeModuleId] : [], ...chunk.moduleIds ?? Object.keys(chunk.modules ?? {})];
|
|
8198
|
+
function buildLazyShareGraph(chunks, wrapperShares, exposeModules) {
|
|
8199
|
+
const sharesInChunk = /* @__PURE__ */ new Map();
|
|
8200
|
+
const startupRoots = [];
|
|
8201
|
+
for (const [fileName, chunk] of Object.entries(chunks)) {
|
|
8202
|
+
if (chunk.type !== "chunk") continue;
|
|
8203
|
+
const moduleIds = chunkModuleIds(chunk);
|
|
8204
|
+
sharesInChunk.set(fileName, new Set(moduleIds.map((id) => wrapperShares.get(normalizeVirtualModuleId(id))).filter((share) => share !== void 0)));
|
|
8205
|
+
if (chunk.isEntry || moduleIds.some((id) => exposeModules.has(stripKnownJsExtension(id)))) startupRoots.push(fileName);
|
|
8206
|
+
}
|
|
8207
|
+
const sharesInClosure = (roots) => new Set(collectStaticChunks(chunks, roots).flatMap((chunk) => [...sharesInChunk.get(chunk.fileName) ?? []]));
|
|
8208
|
+
const lazyShares = new Set([...sharesInChunk.values()].flatMap((shares) => [...shares]));
|
|
8209
|
+
for (const share of sharesInClosure(startupRoots)) lazyShares.delete(share);
|
|
8210
|
+
const sharesByChunk = /* @__PURE__ */ new Map();
|
|
8211
|
+
if (lazyShares.size > 0) for (const fileName of sharesInChunk.keys()) {
|
|
8212
|
+
const shares = [...sharesInClosure([fileName])].filter((share) => lazyShares.has(share));
|
|
8213
|
+
if (shares.length > 0) sharesByChunk.set(fileName, shares.sort());
|
|
8214
|
+
}
|
|
8215
|
+
return {
|
|
8216
|
+
lazyShares,
|
|
8217
|
+
sharesByChunk
|
|
8218
|
+
};
|
|
8219
|
+
}
|
|
8220
|
+
const COMMENTS = String.raw`(?:\s|\/\*[\s\S]*?\*\/|\/\/[^\n]*\n)*`;
|
|
8221
|
+
const DYNAMIC_IMPORT_REGEX = new RegExp(String.raw`\bimport\(${COMMENTS}(["'` + "`" + String.raw`])([^"'` + "`" + String.raw`\n]+)\1${COMMENTS}\)`, "g");
|
|
8222
|
+
const QUOTES = [
|
|
8223
|
+
"\"",
|
|
8224
|
+
"'",
|
|
8225
|
+
"`"
|
|
8226
|
+
];
|
|
8227
|
+
/**
|
|
8228
|
+
* A consume-only (`import: false`) share that only a dynamic `import()` reaches is
|
|
8229
|
+
* left out of `init()` and bridged when that import runs: the import expression is
|
|
8230
|
+
* wrapped so the share is in the cache before the chunk evaluates. There is no
|
|
8231
|
+
* other async boundary in an ESM graph without top-level await, so a wrapper
|
|
8232
|
+
* reached statically from an entry or an expose keeps loading during `init()`.
|
|
8233
|
+
*/
|
|
8234
|
+
function pluginLazyConsumeOnlyShares(options) {
|
|
8235
|
+
let viteConfig;
|
|
8236
|
+
const graphs = /* @__PURE__ */ new WeakMap();
|
|
8237
|
+
const helperName = `__mfLoadLazyShares_${options.internalName.replace(/[^A-Za-z0-9_$]/g, "_")}`;
|
|
8238
|
+
return {
|
|
8239
|
+
name: "module-federation:lazy-consume-only-shares",
|
|
8240
|
+
apply: "build",
|
|
8241
|
+
configResolved(config) {
|
|
8242
|
+
viteConfig = config;
|
|
8243
|
+
},
|
|
8244
|
+
renderChunk(code, chunk, _outputOptions, meta) {
|
|
8245
|
+
const renderedChunk = chunk;
|
|
8246
|
+
const chunks = meta?.chunks;
|
|
8247
|
+
if (!chunks || Object.keys(options.exposes).length === 0) return null;
|
|
8248
|
+
if (isServerBuildContext(this, viteConfig)) return null;
|
|
8249
|
+
let graph = graphs.get(chunks);
|
|
8250
|
+
if (!graph) {
|
|
8251
|
+
const isRolldown = getIsRolldown(this);
|
|
8252
|
+
const wrapperShares = /* @__PURE__ */ new Map();
|
|
8253
|
+
for (const shareKey of getUsedShares(options)) {
|
|
8254
|
+
const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
|
|
8255
|
+
if (shareConfig?.import !== false || shareConfig.eager || shareConfig.treeShaking) continue;
|
|
8256
|
+
wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)), shareKey);
|
|
8257
|
+
}
|
|
8258
|
+
const root = viteConfig?.root ?? process.cwd();
|
|
8259
|
+
graph = buildLazyShareGraph(chunks, wrapperShares, new Set(Object.values(options.exposes).map((expose) => stripKnownJsExtension(path$1.resolve(root, expose.import)))));
|
|
8260
|
+
graphs.set(chunks, graph);
|
|
8261
|
+
}
|
|
8262
|
+
if (graph.lazyShares.size === 0) return null;
|
|
8263
|
+
const rewriter = new CodeRewriter(code);
|
|
8264
|
+
let edited = false;
|
|
8265
|
+
const importMapId = normalizeVirtualModuleId(getLocalSharedImportMapPath(options));
|
|
8266
|
+
if (chunkModuleIds(renderedChunk).some((id) => normalizeVirtualModuleId(id) === importMapId)) for (const quote of QUOTES) {
|
|
8267
|
+
const literal = `${quote}${LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER}${quote}`;
|
|
8268
|
+
const start = code.indexOf(literal);
|
|
8269
|
+
if (start === -1) continue;
|
|
8270
|
+
rewriter.overwrite(start, start + literal.length, JSON.stringify([...graph.lazyShares].sort()));
|
|
8271
|
+
edited = true;
|
|
8272
|
+
break;
|
|
8273
|
+
}
|
|
8274
|
+
const chunkDir = path$1.posix.dirname(renderedChunk.fileName);
|
|
8275
|
+
const codePositions = createCodePositionMap(code);
|
|
8276
|
+
let usesHelper = false;
|
|
8277
|
+
for (const match of code.matchAll(DYNAMIC_IMPORT_REGEX)) {
|
|
8278
|
+
const [expression, , specifier] = match;
|
|
8279
|
+
const start = match.index;
|
|
8280
|
+
if (!codePositions[start]) continue;
|
|
8281
|
+
const target = path$1.posix.normalize(path$1.posix.join(chunkDir, specifier));
|
|
8282
|
+
const shares = graph.sharesByChunk.get(target);
|
|
8283
|
+
if (!shares || !renderedChunk.dynamicImports.includes(target)) continue;
|
|
8284
|
+
rewriter.overwrite(start, start + expression.length, `${helperName}(${JSON.stringify(shares)}).then(() => ${expression})`);
|
|
8285
|
+
usesHelper = edited = true;
|
|
8286
|
+
}
|
|
8287
|
+
if (!edited) return null;
|
|
8288
|
+
if (usesHelper) {
|
|
8289
|
+
const stateKey = JSON.stringify(getRuntimeInitGlobalKey(getRuntimeInitStatusImportId(options)));
|
|
8290
|
+
rewriter.overwrite(code.length, code.length, `
|
|
8291
|
+
function ${helperName}(names) {
|
|
8292
|
+
const state = globalThis[${stateKey}];
|
|
8293
|
+
return state ? state.initPromise.then(() => (typeof state.loadLazyShares === "function" ? state.loadLazyShares(names) : undefined)) : Promise.resolve();
|
|
8294
|
+
}
|
|
8295
|
+
`);
|
|
8296
|
+
}
|
|
8297
|
+
return {
|
|
8298
|
+
code: rewriter.toString(),
|
|
8299
|
+
map: rewriter.generateMap(renderedChunk.fileName)
|
|
8300
|
+
};
|
|
8301
|
+
}
|
|
8302
|
+
};
|
|
8303
|
+
}
|
|
8304
|
+
//#endregion
|
|
8305
|
+
//#region package.json
|
|
8306
|
+
var version$1 = "1.23.0";
|
|
8307
|
+
//#endregion
|
|
7592
8308
|
//#region src/virtualModules/virtualExposesSSR.ts
|
|
7593
8309
|
/**
|
|
7594
8310
|
* Virtual module ID for the SSR exposes map.
|
|
@@ -7643,7 +8359,8 @@ function getSsrFileNameParts(browserFilename) {
|
|
|
7643
8359
|
ext
|
|
7644
8360
|
};
|
|
7645
8361
|
}
|
|
7646
|
-
function getSsrRemoteEntryFileName(browserFilename) {
|
|
8362
|
+
function getSsrRemoteEntryFileName(options, browserFilename = options.filename) {
|
|
8363
|
+
if (options.ssrFilename) return options.ssrFilename;
|
|
7647
8364
|
const { base, ext } = getSsrFileNameParts(browserFilename);
|
|
7648
8365
|
return `${base}.ssr${ext ?? ".js"}`;
|
|
7649
8366
|
}
|
|
@@ -7657,14 +8374,15 @@ function getSsrSharedSingletons(options) {
|
|
|
7657
8374
|
const result = {};
|
|
7658
8375
|
for (const [pkg, share] of Object.entries(options.shared)) {
|
|
7659
8376
|
if (!share.shareConfig.singleton) continue;
|
|
7660
|
-
|
|
7661
|
-
|
|
8377
|
+
const request = getSharedRequest(pkg, share);
|
|
8378
|
+
if (request.endsWith("/")) {
|
|
8379
|
+
for (const concrete of expandSharedPrefixKey(request, used)) result[getSharedRuntimeKey(concrete, share)] = {
|
|
7662
8380
|
...share,
|
|
7663
8381
|
name: concrete
|
|
7664
8382
|
};
|
|
7665
8383
|
continue;
|
|
7666
8384
|
}
|
|
7667
|
-
result[pkg] = share;
|
|
8385
|
+
result[getSharedRuntimeKey(pkg, share)] = share;
|
|
7668
8386
|
}
|
|
7669
8387
|
return result;
|
|
7670
8388
|
}
|
|
@@ -8009,7 +8727,7 @@ const Manifest = (providedOptions) => {
|
|
|
8009
8727
|
type: "module"
|
|
8010
8728
|
},
|
|
8011
8729
|
ssrRemoteEntry: {
|
|
8012
|
-
name: getSsrRemoteEntryFileName(devRemoteEntryFile),
|
|
8730
|
+
name: getSsrRemoteEntryFileName(mfOptions, devRemoteEntryFile),
|
|
8013
8731
|
path: "/__mf_ssr__/",
|
|
8014
8732
|
type: "module"
|
|
8015
8733
|
},
|
|
@@ -8052,6 +8770,33 @@ const Manifest = (providedOptions) => {
|
|
|
8052
8770
|
publicPath = mfOptions.publicPath === "auto" ? "auto" : resolvePublicPath(mfOptions, base, _originalConfigBase);
|
|
8053
8771
|
},
|
|
8054
8772
|
/**
|
|
8773
|
+
* A standalone `vite build --ssr` may run with its own `filename`, e.g.
|
|
8774
|
+
* `defineConfig(({ isSsrBuild }) => ...)`. The manifest written by the
|
|
8775
|
+
* earlier client build then advertises an SSR entry derived from the
|
|
8776
|
+
* browser filename, which is not the file this build emitted. Point the
|
|
8777
|
+
* manifest and stats on disk at the emitted SSR entry.
|
|
8778
|
+
*/
|
|
8779
|
+
writeBundle(outputOptions) {
|
|
8780
|
+
if (!mfManifestName || _command !== "build" || isConsumerProject) return;
|
|
8781
|
+
const environment = this.environment;
|
|
8782
|
+
if (!(environment ? environment.name === "ssr" : Boolean(viteConfig?.build?.ssr))) return;
|
|
8783
|
+
const ssrEntryName = getSsrRemoteEntryFileName(mfOptions);
|
|
8784
|
+
const outDirs = [...new Set([outputOptions.dir, viteConfig?.environments?.client?.build?.outDir].filter((dir) => typeof dir === "string").map((dir) => path$1.resolve(root, dir)))];
|
|
8785
|
+
if (!outDirs.some((dir) => fs$1.existsSync(path$1.resolve(dir, ssrEntryName)))) return;
|
|
8786
|
+
for (const dir of outDirs) for (const fileName of [mfManifestName, mfManifestStatsName]) {
|
|
8787
|
+
if (!fileName) continue;
|
|
8788
|
+
const file = path$1.resolve(dir, fileName);
|
|
8789
|
+
if (!fs$1.existsSync(file)) continue;
|
|
8790
|
+
try {
|
|
8791
|
+
const data = JSON.parse(fs$1.readFileSync(file, "utf8"));
|
|
8792
|
+
const entry = data?.metaData?.ssrRemoteEntry;
|
|
8793
|
+
if (!entry || typeof entry !== "object" || entry.name === ssrEntryName) continue;
|
|
8794
|
+
entry.name = ssrEntryName;
|
|
8795
|
+
fs$1.writeFileSync(file, JSON.stringify(data));
|
|
8796
|
+
} catch {}
|
|
8797
|
+
}
|
|
8798
|
+
},
|
|
8799
|
+
/**
|
|
8055
8800
|
* Generates the module federation manifest file
|
|
8056
8801
|
* @param options - Rollup output options
|
|
8057
8802
|
* @param bundle - Generated bundle assets
|
|
@@ -8061,10 +8806,10 @@ const Manifest = (providedOptions) => {
|
|
|
8061
8806
|
if (this.environment?.name === "ssr") return;
|
|
8062
8807
|
let filesMap = {};
|
|
8063
8808
|
const foundRemoteEntryFile = findRemoteEntryFile(mfOptions.filename, bundle);
|
|
8064
|
-
const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions
|
|
8809
|
+
const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions);
|
|
8065
8810
|
const foundSsrRemoteEntryFile = Object.values(bundle).find((file) => file.fileName === expectedSsrRemoteEntryFile)?.fileName;
|
|
8066
8811
|
if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
|
|
8067
|
-
ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(resolveHashPlaceholderFileName(mfOptions.filename)) : expectedSsrRemoteEntryFile);
|
|
8812
|
+
ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(mfOptions, resolveHashPlaceholderFileName(mfOptions.filename)) : expectedSsrRemoteEntryFile);
|
|
8068
8813
|
const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
|
|
8069
8814
|
if (allCssAssets.size > 0) {
|
|
8070
8815
|
const secondaryCss = /* @__PURE__ */ new Set();
|
|
@@ -8089,14 +8834,25 @@ const Manifest = (providedOptions) => {
|
|
|
8089
8834
|
expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions, getIsRolldown(this));
|
|
8090
8835
|
const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(mfOptions), this.resolve.bind(this), mfOptions);
|
|
8091
8836
|
processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
|
|
8837
|
+
const deferredSharedAssets = {
|
|
8838
|
+
js: /* @__PURE__ */ new Set(),
|
|
8839
|
+
css: /* @__PURE__ */ new Set()
|
|
8840
|
+
};
|
|
8092
8841
|
for (const shareKey of getUsedShares(mfOptions)) {
|
|
8093
8842
|
const shareItem = getNormalizeShareItem(shareKey, mfOptions);
|
|
8094
8843
|
const assets = filesMap[shareKey];
|
|
8095
8844
|
if (!assets || shareItem?.shareConfig.eager === true) continue;
|
|
8096
|
-
|
|
8097
|
-
|
|
8845
|
+
for (const type of ASSET_TYPES) {
|
|
8846
|
+
assets[type].async.push(...assets[type].sync.splice(0));
|
|
8847
|
+
for (const asset of assets[type].async) deferredSharedAssets[type].add(asset);
|
|
8848
|
+
}
|
|
8098
8849
|
}
|
|
8099
8850
|
if (mfOptions.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
|
|
8851
|
+
for (const exposeModule of exposesModules) {
|
|
8852
|
+
const assets = filesMap[exposeModule];
|
|
8853
|
+
if (!assets) continue;
|
|
8854
|
+
for (const type of ASSET_TYPES) for (const timing of LOAD_TIMINGS) assets[type][timing] = assets[type][timing].filter((asset) => !deferredSharedAssets[type].has(asset));
|
|
8855
|
+
}
|
|
8100
8856
|
filesMap = deduplicateAssets(filesMap);
|
|
8101
8857
|
}
|
|
8102
8858
|
const manifest = await applyManifestAdditionalData(generateMFManifest(filesMap, disableAssetsAnalyze), void 0);
|
|
@@ -8130,7 +8886,7 @@ const Manifest = (providedOptions) => {
|
|
|
8130
8886
|
type: "module"
|
|
8131
8887
|
};
|
|
8132
8888
|
const ssrRemoteEntry = {
|
|
8133
|
-
name: ssrRemoteEntryFile || getSsrRemoteEntryFileName(_command === "serve" ? resolveHashPlaceholderFileName(filename) : filename),
|
|
8889
|
+
name: ssrRemoteEntryFile || getSsrRemoteEntryFileName(mfOptions, _command === "serve" ? resolveHashPlaceholderFileName(filename) : filename),
|
|
8134
8890
|
path: _command === "serve" ? "/__mf_ssr__/" : "",
|
|
8135
8891
|
type: "module"
|
|
8136
8892
|
};
|
|
@@ -8447,6 +9203,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
8447
9203
|
return cleanId.includes(getHostAutoInitPath(options)) || cleanId.includes(getHostAutoInitPath());
|
|
8448
9204
|
};
|
|
8449
9205
|
const getEnvironmentConditions = (context) => context.environment?.config?.resolve?.conditions;
|
|
9206
|
+
const isSsrBuild = (context) => isServerBuildContext(context, viteConfig);
|
|
8450
9207
|
function isRemoteImport(source) {
|
|
8451
9208
|
return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
|
|
8452
9209
|
}
|
|
@@ -8550,7 +9307,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
8550
9307
|
}
|
|
8551
9308
|
},
|
|
8552
9309
|
async load(id) {
|
|
8553
|
-
if (id === remoteEntryId) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this)));
|
|
9310
|
+
if (id === remoteEntryId) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
|
|
8554
9311
|
if (id === virtualExposesId) {
|
|
8555
9312
|
await refreshExposeRemoteDependencies(this);
|
|
8556
9313
|
return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
|
|
@@ -8560,7 +9317,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
8560
9317
|
async transform(code, id) {
|
|
8561
9318
|
return mapCodeToCodeWithSourcemap(await (async () => {
|
|
8562
9319
|
if (!filterId(id)) return;
|
|
8563
|
-
if (id.includes(remoteEntryId)) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this)));
|
|
9320
|
+
if (id.includes(remoteEntryId)) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
|
|
8564
9321
|
if (id === virtualExposesId) {
|
|
8565
9322
|
await refreshExposeRemoteDependencies(this);
|
|
8566
9323
|
return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
|
|
@@ -8658,7 +9415,7 @@ function pluginProxyRemotes_default(options) {
|
|
|
8658
9415
|
const remoteModule = getRemoteVirtualModule(source, command, enableSsrInit, consumer, options);
|
|
8659
9416
|
addUsedRemote(remoteName, source, options);
|
|
8660
9417
|
refreshHostAutoInit(options);
|
|
8661
|
-
return remoteModule.
|
|
9418
|
+
return remoteModule.getResolvedId();
|
|
8662
9419
|
}
|
|
8663
9420
|
return {
|
|
8664
9421
|
name: "proxyRemotes",
|
|
@@ -8678,7 +9435,7 @@ function pluginProxyRemotes_default(options) {
|
|
|
8678
9435
|
},
|
|
8679
9436
|
configResolved(config) {
|
|
8680
9437
|
hasMultiEnvironment = Boolean(config.environments?.ssr);
|
|
8681
|
-
enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, Object.keys(remotes).length > 0).enableSsrInitBootstrap;
|
|
9438
|
+
enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, Object.keys(remotes).length > 0, isSsrConfig(config)).enableSsrInitBootstrap;
|
|
8682
9439
|
},
|
|
8683
9440
|
resolveId(source, importer) {
|
|
8684
9441
|
const resolvedIslandConsumerId = resolveReactIslandConsumerId(source);
|
|
@@ -8702,6 +9459,96 @@ function pluginProxyRemotes_default(options) {
|
|
|
8702
9459
|
};
|
|
8703
9460
|
}
|
|
8704
9461
|
//#endregion
|
|
9462
|
+
//#region src/utils/sharedSource.ts
|
|
9463
|
+
const pendingEntryLookups = /* @__PURE__ */ new Map();
|
|
9464
|
+
const getEntryLookupKey = (source, importer) => `${source}\0${importer}`;
|
|
9465
|
+
/** Whether a resolveId call is one of the shared source resolver's own entry lookups. */
|
|
9466
|
+
function isSharedEntryLookup(source, importer, options) {
|
|
9467
|
+
return options.custom?.__mfSharedEntryLookup === true || pendingEntryLookups.has(getEntryLookupKey(source, importer));
|
|
9468
|
+
}
|
|
9469
|
+
/** Identify shared entries through Vite, with a cache scoped to this federation instance. */
|
|
9470
|
+
function createSharedSourceResolver(shared, getResolutionConfig) {
|
|
9471
|
+
const caches = /* @__PURE__ */ new Map();
|
|
9472
|
+
async function matchEntry(source, suffix, resolveEntry) {
|
|
9473
|
+
const packageName = getPackageNameFromNodeModulePath(source);
|
|
9474
|
+
if (!packageName) return;
|
|
9475
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
9476
|
+
if (findSharedKey(packageName, shared)) candidates.add(packageName);
|
|
9477
|
+
if (findSharedKey(suffix, shared)) candidates.add(suffix);
|
|
9478
|
+
for (const key of Object.keys(shared)) {
|
|
9479
|
+
const request = getSharedRequest(key, shared[key]);
|
|
9480
|
+
if (getPackageName(request) !== packageName) continue;
|
|
9481
|
+
if (!request.endsWith("/")) candidates.add(request);
|
|
9482
|
+
for (const subpath of getCommonSharedSubpaths(request)) if (findSharedKey(subpath, shared)) candidates.add(subpath);
|
|
9483
|
+
}
|
|
9484
|
+
if (candidates.size === 0) return;
|
|
9485
|
+
const resolvedSource = await resolveEntry(source);
|
|
9486
|
+
if (!resolvedSource) return;
|
|
9487
|
+
for (const candidate of candidates) {
|
|
9488
|
+
const entry = await resolveEntry(candidate);
|
|
9489
|
+
if (!entry) continue;
|
|
9490
|
+
const allowNodeModulesSuffixMatch = shared[findSharedKey(candidate, shared) ?? candidate]?.shareConfig?.allowNodeModulesSuffixMatch === true;
|
|
9491
|
+
if (normalizeNodeModulePath(entry) === normalizeNodeModulePath(resolvedSource) || allowNodeModulesSuffixMatch && getNodeModulesSuffix(entry) === suffix) return candidate;
|
|
9492
|
+
}
|
|
9493
|
+
}
|
|
9494
|
+
return {
|
|
9495
|
+
clear() {
|
|
9496
|
+
caches.clear();
|
|
9497
|
+
},
|
|
9498
|
+
async resolve(context, source, options = {}) {
|
|
9499
|
+
if (source.startsWith("\0") || source.includes("#")) return;
|
|
9500
|
+
const queryIndex = source.indexOf("?");
|
|
9501
|
+
const query = queryIndex === -1 ? "" : source.slice(queryIndex + 1);
|
|
9502
|
+
if (query && [...new URLSearchParams(query).keys()].some((key) => ![
|
|
9503
|
+
"v",
|
|
9504
|
+
"t",
|
|
9505
|
+
"import"
|
|
9506
|
+
].includes(key))) return;
|
|
9507
|
+
if (findSharedKey(source, shared)) return source;
|
|
9508
|
+
const suffix = getNodeModulesSuffix(source);
|
|
9509
|
+
if (!suffix) return;
|
|
9510
|
+
const normalizedSource = stripViteFsPrefix(normalizeNodeModulePath(source));
|
|
9511
|
+
const environment = context.environment ?? !!options.ssr;
|
|
9512
|
+
const cacheable = !options.isEntry && !options.scan && (!options.kind || options.kind === "import-statement") && Object.keys(options.attributes ?? {}).length === 0 && Object.keys(options.custom ?? {}).length === 0;
|
|
9513
|
+
let cache = cacheable ? caches.get(environment) : void 0;
|
|
9514
|
+
if (cacheable && !cache) {
|
|
9515
|
+
cache = /* @__PURE__ */ new Map();
|
|
9516
|
+
caches.set(environment, cache);
|
|
9517
|
+
}
|
|
9518
|
+
if (cache?.has(normalizedSource)) return cache.get(normalizedSource);
|
|
9519
|
+
const { root, conditions } = getResolutionConfig(context, options);
|
|
9520
|
+
const result = await matchEntry(normalizedSource, suffix, async (request) => {
|
|
9521
|
+
if (!path$1.isAbsolute(request) && !isPackageExportAvailable(request, {
|
|
9522
|
+
cwd: root,
|
|
9523
|
+
conditions
|
|
9524
|
+
})) return void 0;
|
|
9525
|
+
const importer = path$1.join(root, "package.json");
|
|
9526
|
+
const lookupKey = getEntryLookupKey(request, importer);
|
|
9527
|
+
pendingEntryLookups.set(lookupKey, (pendingEntryLookups.get(lookupKey) ?? 0) + 1);
|
|
9528
|
+
try {
|
|
9529
|
+
const resolved = await context.resolve(request, importer, {
|
|
9530
|
+
...options,
|
|
9531
|
+
skipSelf: true,
|
|
9532
|
+
custom: {
|
|
9533
|
+
...options.custom,
|
|
9534
|
+
__mfSharedEntryLookup: true
|
|
9535
|
+
}
|
|
9536
|
+
});
|
|
9537
|
+
return resolved && !resolved.external ? resolved.id : void 0;
|
|
9538
|
+
} catch {
|
|
9539
|
+
return;
|
|
9540
|
+
} finally {
|
|
9541
|
+
const remaining = pendingEntryLookups.get(lookupKey) - 1;
|
|
9542
|
+
if (remaining) pendingEntryLookups.set(lookupKey, remaining);
|
|
9543
|
+
else pendingEntryLookups.delete(lookupKey);
|
|
9544
|
+
}
|
|
9545
|
+
});
|
|
9546
|
+
cache?.set(normalizedSource, result);
|
|
9547
|
+
return result;
|
|
9548
|
+
}
|
|
9549
|
+
};
|
|
9550
|
+
}
|
|
9551
|
+
//#endregion
|
|
8705
9552
|
//#region src/utils/PromiseStore.ts
|
|
8706
9553
|
/**
|
|
8707
9554
|
* example:
|
|
@@ -8742,7 +9589,7 @@ function tryResolveFromProjectRoot(source) {
|
|
|
8742
9589
|
const browserEntry = getInstalledPackageEntry(source, { cwd: getPackageDetectionCwd() });
|
|
8743
9590
|
if (browserEntry) return browserEntry;
|
|
8744
9591
|
try {
|
|
8745
|
-
return
|
|
9592
|
+
return resolveModulePath(source, path$1.join(getPackageDetectionCwd(), "package.json"));
|
|
8746
9593
|
} catch {
|
|
8747
9594
|
return;
|
|
8748
9595
|
}
|
|
@@ -8751,23 +9598,6 @@ function isBuildConfigImporter(importer) {
|
|
|
8751
9598
|
if (!importer) return false;
|
|
8752
9599
|
return /(^|\/)(?:nuxt|vite|vitest|webpack|rollup|rspack)\.config\.[cm]?[jt]sx?$/.test(importer.replace(/\\/g, "/"));
|
|
8753
9600
|
}
|
|
8754
|
-
function findSharedKeyForSource(source, shared) {
|
|
8755
|
-
const key = findSharedKey(source, shared);
|
|
8756
|
-
if (key) return key;
|
|
8757
|
-
const explicitSharedSubpathKeys = Object.keys(shared || {}).filter((sharedKey) => getPackageName(sharedKey) !== sharedKey && !sharedKey.endsWith("/"));
|
|
8758
|
-
if (isNodeModulePath(source)) {
|
|
8759
|
-
const explicitSubpathKey = getMatchingNodeModuleSubpath(source, explicitSharedSubpathKeys);
|
|
8760
|
-
if (explicitSubpathKey) return explicitSubpathKey;
|
|
8761
|
-
const normalizedSource = normalizeNodeModulePath(source);
|
|
8762
|
-
const explicitSubpathEntryKey = explicitSharedSubpathKeys.find((sharedKey) => {
|
|
8763
|
-
const entry = getInstalledPackageEntry(sharedKey, { cwd: getPackageDetectionCwd() });
|
|
8764
|
-
return entry ? normalizeNodeModulePath(entry) === normalizedSource : false;
|
|
8765
|
-
});
|
|
8766
|
-
if (explicitSubpathEntryKey) return explicitSubpathEntryKey;
|
|
8767
|
-
}
|
|
8768
|
-
const packageName = getPackageNameFromNodeModulePath(source);
|
|
8769
|
-
return packageName ? findSharedKey(packageName, shared) : void 0;
|
|
8770
|
-
}
|
|
8771
9601
|
/**
|
|
8772
9602
|
* Reads the dependencies of an installed package from its package.json.
|
|
8773
9603
|
*/
|
|
@@ -8785,9 +9615,13 @@ function getPackageDependencies(pkg) {
|
|
|
8785
9615
|
*/
|
|
8786
9616
|
function excludeSharedSubDependencies(shared) {
|
|
8787
9617
|
const sharedKeys = new Set(Object.keys(shared));
|
|
8788
|
-
const
|
|
9618
|
+
const requestBase = (key) => {
|
|
9619
|
+
const request = getSharedRequest(key, shared[key]);
|
|
9620
|
+
return request.endsWith("/") ? request.slice(0, -1) : request;
|
|
9621
|
+
};
|
|
9622
|
+
const sharedKeyByBase = new Map(Object.keys(shared).map((key) => [requestBase(key), key]));
|
|
8789
9623
|
for (const parentKey of sharedKeys) {
|
|
8790
|
-
const deps = getPackageDependencies(parentKey);
|
|
9624
|
+
const deps = getPackageDependencies(requestBase(parentKey));
|
|
8791
9625
|
for (const dep of deps) {
|
|
8792
9626
|
const depKey = sharedKeyByBase.get(dep);
|
|
8793
9627
|
if (depKey && depKey !== parentKey) {
|
|
@@ -9114,6 +9948,7 @@ function isSharedPackageRuntimeDependency(sharedKey, dependency, conditions) {
|
|
|
9114
9948
|
function proxySharedModule(options) {
|
|
9115
9949
|
const { shared = {}, federationOptions, getParsePromise = () => Promise.resolve() } = options;
|
|
9116
9950
|
let _config;
|
|
9951
|
+
const getBuildImportAnalysis = (environment) => getImportAnalysis(environment ?? _config ?? options);
|
|
9117
9952
|
let _command = "serve";
|
|
9118
9953
|
let useDirectReactImport = false;
|
|
9119
9954
|
let useRolldown = false;
|
|
@@ -9131,7 +9966,7 @@ function proxySharedModule(options) {
|
|
|
9131
9966
|
const getRuntimeDependencyConditions = (context, resolveOptions) => {
|
|
9132
9967
|
const environment = context.environment;
|
|
9133
9968
|
const environmentConfig = environment?.config;
|
|
9134
|
-
const isSsr = resolveOptions.ssr === true || Boolean(_config?.build?.ssr) ||
|
|
9969
|
+
const isSsr = resolveOptions.ssr === true || Boolean(_config?.build?.ssr) || isServerEnvironment(environment?.name, environmentConfig);
|
|
9135
9970
|
return getSharedExportConditions({
|
|
9136
9971
|
environmentConditions: environmentConfig?.resolve?.conditions,
|
|
9137
9972
|
isProduction: environmentConfig?.isProduction ?? isProduction,
|
|
@@ -9141,6 +9976,10 @@ function proxySharedModule(options) {
|
|
|
9141
9976
|
ssrTarget
|
|
9142
9977
|
});
|
|
9143
9978
|
};
|
|
9979
|
+
const sharedSourceResolver = createSharedSourceResolver(shared, (context, resolveOptions) => ({
|
|
9980
|
+
root: _config?.root || getPackageDetectionCwd(),
|
|
9981
|
+
conditions: getRuntimeDependencyConditions(context, resolveOptions)
|
|
9982
|
+
}));
|
|
9144
9983
|
const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command, getIsRolldown(context), getEnvironmentConditions(context));
|
|
9145
9984
|
const normalizeTreeShakingOutputPath = (value) => {
|
|
9146
9985
|
const normalized = normalizePathForImport(value);
|
|
@@ -9183,14 +10022,15 @@ function proxySharedModule(options) {
|
|
|
9183
10022
|
}, federationOptions);
|
|
9184
10023
|
},
|
|
9185
10024
|
resolveId(source) {
|
|
9186
|
-
|
|
10025
|
+
const resolvedId = getResolvedLocalSharedImportMapId(federationOptions);
|
|
10026
|
+
if (source === getLocalSharedImportMapPath(federationOptions) || source === resolvedId) return resolvedId;
|
|
9187
10027
|
},
|
|
9188
10028
|
load(id) {
|
|
9189
10029
|
if (id === getResolvedLocalSharedImportMapId(federationOptions)) return getParsePromise().then((_) => {
|
|
9190
10030
|
refreshTreeShakingForEnvironment(this);
|
|
9191
|
-
const providerPackages = /* @__PURE__ */ new Set([...Object.keys(shared).filter((pkg) => !pkg.endsWith("/")), ...getUsedShares(federationOptions)]);
|
|
10031
|
+
const providerPackages = /* @__PURE__ */ new Set([...Object.keys(shared).filter((pkg) => !getSharedRequest(pkg, shared[pkg]).endsWith("/")), ...getUsedShares(federationOptions)]);
|
|
9192
10032
|
for (const pkg of providerPackages) {
|
|
9193
|
-
const sharedKey =
|
|
10033
|
+
const sharedKey = findSharedKey(pkg, shared);
|
|
9194
10034
|
const shareItem = shared[pkg] || (sharedKey ? shared[sharedKey] : void 0);
|
|
9195
10035
|
if (shareItem) emitTreeShakingProvider(this, pkg, shareItem);
|
|
9196
10036
|
}
|
|
@@ -9210,6 +10050,7 @@ function proxySharedModule(options) {
|
|
|
9210
10050
|
setTreeShakingBuildMode(command === "build", federationOptions);
|
|
9211
10051
|
resetTreeShakingExports(federationOptions);
|
|
9212
10052
|
emittedTreeShakingProviders.clear();
|
|
10053
|
+
sharedSourceResolver.clear();
|
|
9213
10054
|
sharedDependencyCache.clear();
|
|
9214
10055
|
dependencyManifestCache.clear();
|
|
9215
10056
|
sharedRuntimeDependencyCache.clear();
|
|
@@ -9232,30 +10073,42 @@ function proxySharedModule(options) {
|
|
|
9232
10073
|
const resolvedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
|
|
9233
10074
|
const registerConfiguredShare = _command === "build" && Object.keys(resolvedOptions.exposes).length > 0 ? addUsedShares : addConfiguredShare;
|
|
9234
10075
|
Object.keys(shared).forEach((key) => {
|
|
9235
|
-
if (key.endsWith("/")) return;
|
|
9236
|
-
|
|
9237
|
-
|
|
10076
|
+
if (key.endsWith("/") || getSharedRequest(key, shared[key]).endsWith("/")) return;
|
|
10077
|
+
const runtimeKey = getSharedRuntimeKey(key, shared[key]);
|
|
10078
|
+
if (useDirectReactImport && runtimeKey === "react") {
|
|
10079
|
+
registerConfiguredShare(runtimeKey, federationOptions);
|
|
9238
10080
|
return;
|
|
9239
10081
|
}
|
|
9240
|
-
writeLoadShareModule(
|
|
9241
|
-
if (shared[key].shareConfig.import !== false) writePreBuildLibPath(
|
|
9242
|
-
registerConfiguredShare(
|
|
10082
|
+
writeLoadShareModule(runtimeKey, shared[key], _command, isRolldown, federationOptions);
|
|
10083
|
+
if (shared[key].shareConfig.import !== false) writePreBuildLibPath(runtimeKey, shared[key], federationOptions);
|
|
10084
|
+
registerConfiguredShare(runtimeKey, federationOptions);
|
|
9243
10085
|
});
|
|
9244
10086
|
writeLocalSharedImportMap(federationOptions);
|
|
9245
10087
|
refreshHostAutoInit(federationOptions);
|
|
9246
10088
|
},
|
|
10089
|
+
watchChange() {
|
|
10090
|
+
sharedSourceResolver.clear();
|
|
10091
|
+
},
|
|
9247
10092
|
buildStart() {
|
|
10093
|
+
sharedSourceResolver.clear();
|
|
9248
10094
|
if (_command !== "build") return;
|
|
10095
|
+
if (hasAnalyzableShares) getBuildImportAnalysis(this.environment).clear();
|
|
9249
10096
|
resetTreeShakingExports(federationOptions);
|
|
9250
10097
|
emittedTreeShakingProviders.clear();
|
|
9251
10098
|
refreshTreeShakingForEnvironment(this);
|
|
9252
10099
|
},
|
|
10100
|
+
buildEnd() {
|
|
10101
|
+
if (_command === "build" && hasAnalyzableShares) getBuildImportAnalysis(this.environment).clear();
|
|
10102
|
+
},
|
|
9253
10103
|
shouldTransformCachedModule() {
|
|
9254
10104
|
return _command === "build" && hasAnalyzableShares;
|
|
9255
10105
|
},
|
|
9256
|
-
transform(code, id) {
|
|
10106
|
+
async transform(code, id, transformOptions) {
|
|
9257
10107
|
if (_command !== "build" || !hasAnalyzableShares) return;
|
|
9258
|
-
collectTreeShakingImports(code, id, shared,
|
|
10108
|
+
await collectTreeShakingImports(code, id, shared, async (source, shares) => {
|
|
10109
|
+
const request = await sharedSourceResolver.resolve(this, source, transformOptions);
|
|
10110
|
+
return request ? findSharedKey(request, shares) : void 0;
|
|
10111
|
+
}, (sharedKey, exports, request) => recordTreeShakingExports(sharedKey, exports, request, federationOptions), (sharedKey, request) => markTreeShakingPackageUnsafe(sharedKey, request, federationOptions), getBuildImportAnalysis(this.environment));
|
|
9259
10112
|
refreshTreeShakingForEnvironment(this);
|
|
9260
10113
|
}
|
|
9261
10114
|
},
|
|
@@ -9264,6 +10117,7 @@ function proxySharedModule(options) {
|
|
|
9264
10117
|
enforce: "pre",
|
|
9265
10118
|
apply: "build",
|
|
9266
10119
|
async resolveId(source, importer, resolveOptions) {
|
|
10120
|
+
if (isSharedEntryLookup(source, importer, resolveOptions)) return;
|
|
9267
10121
|
const sourceToken = getTreeShakingGraphToken(source);
|
|
9268
10122
|
const importerToken = getTreeShakingGraphToken(importer);
|
|
9269
10123
|
const token = sourceToken || importerToken;
|
|
@@ -9271,7 +10125,8 @@ function proxySharedModule(options) {
|
|
|
9271
10125
|
const cleanSource = normalizePathForImport(stripTreeShakingGraphQuery(source));
|
|
9272
10126
|
const cleanImporter = importer ? normalizePathForImport(stripTreeShakingGraphQuery(importer)) : void 0;
|
|
9273
10127
|
if (!sourceToken && importerToken) {
|
|
9274
|
-
const
|
|
10128
|
+
const request = await sharedSourceResolver.resolve(this, cleanSource, resolveOptions);
|
|
10129
|
+
const nestedSharedKey = request ? findSharedKey(request, shared) : void 0;
|
|
9275
10130
|
if (nestedSharedKey && getPackageName(nestedSharedKey) !== getPackageName(importerToken)) return this.resolve(cleanSource, cleanImporter, {
|
|
9276
10131
|
...resolveOptions,
|
|
9277
10132
|
skipSelf: true
|
|
@@ -9298,21 +10153,24 @@ function proxySharedModule(options) {
|
|
|
9298
10153
|
name: "proxyPreBuildShared:resolve-shared-loadShare",
|
|
9299
10154
|
enforce: "pre",
|
|
9300
10155
|
async resolveId(source, importer, resolveOptions) {
|
|
9301
|
-
if (resolveOptions.custom?.__mfTreeShakingGraph) return;
|
|
9302
|
-
|
|
10156
|
+
if (isSharedEntryLookup(source, importer, resolveOptions) || resolveOptions.custom?.__mfTreeShakingGraph) return;
|
|
10157
|
+
const sharedSource = await sharedSourceResolver.resolve(this, source, resolveOptions);
|
|
10158
|
+
if (!sharedSource) return;
|
|
10159
|
+
const key = findSharedKey(sharedSource, shared);
|
|
10160
|
+
if (!key) return;
|
|
10161
|
+
const shouldSkipTaggedImporterProxy = (sharedKey, tag) => {
|
|
9303
10162
|
if (!importer?.includes(tag)) return false;
|
|
9304
10163
|
const taggedModule = VirtualModule.findModule(tag, importer);
|
|
9305
10164
|
if (!taggedModule) return true;
|
|
9306
|
-
return taggedModule.name === sharedKey || matchesSharedSource(
|
|
9307
|
-
}
|
|
9308
|
-
const key = findSharedKeyForSource(source, shared);
|
|
9309
|
-
if (!key) return;
|
|
10165
|
+
return taggedModule.name === sharedKey || matchesSharedSource(sharedSource, taggedModule.name);
|
|
10166
|
+
};
|
|
9310
10167
|
const importerPackage = getSharedPackageFromFile(importer, shared);
|
|
9311
10168
|
if (importerPackage === getPackageName(key)) return;
|
|
9312
10169
|
if (importerPackage && shared[key].shareConfig.import !== false) {
|
|
9313
10170
|
const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
|
|
9314
|
-
const
|
|
9315
|
-
|
|
10171
|
+
const request = getSharedRequest(key, shared[key]);
|
|
10172
|
+
const runtimeDependencyRequest = request.endsWith("/") && matchesSharedSource(sharedSource, key, shared[key]) ? sharedSource : request;
|
|
10173
|
+
if (importerIsUnsharedWorkspacePackage ? isSharedPackageRuntimeDependency(runtimeDependencyRequest, importerPackage, getRuntimeDependencyConditions(this, resolveOptions)) : isSharedPackageDependency(request, importerPackage)) return;
|
|
9316
10174
|
}
|
|
9317
10175
|
if (useDirectReactImport && key === "react") return;
|
|
9318
10176
|
if (isAssetLikeImport(source)) return;
|
|
@@ -9322,8 +10180,8 @@ function proxySharedModule(options) {
|
|
|
9322
10180
|
if (importer && (importer.includes("hostAutoInit") || importer.includes("__H_A_I__"))) return;
|
|
9323
10181
|
if (shouldSkipTaggedImporterProxy(key, "__loadShare__")) return;
|
|
9324
10182
|
if (shouldSkipTaggedImporterProxy(key, "__prebuild__")) return;
|
|
9325
|
-
const shareSource = key === "vue" &&
|
|
9326
|
-
if (shouldKeepSharedImportLocal(
|
|
10183
|
+
const shareSource = key === "vue" && sharedSource.startsWith("vue/dist/") ? key : sharedSource;
|
|
10184
|
+
if (shouldKeepSharedImportLocal(sharedSource, importer, key, shared, importerPackage)) {
|
|
9327
10185
|
const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
|
|
9328
10186
|
return tryResolveFromProjectRoot(localSource) || localSource;
|
|
9329
10187
|
}
|
|
@@ -9613,17 +10471,21 @@ function collectFromRegex(code, isRemoteImport) {
|
|
|
9613
10471
|
}
|
|
9614
10472
|
function pluginRemoteNamedExports(options) {
|
|
9615
10473
|
const remoteNames = Object.keys(options.remotes);
|
|
10474
|
+
let root = process.cwd();
|
|
9616
10475
|
const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
|
|
9617
10476
|
function isRemoteImport(source, importerId) {
|
|
9618
10477
|
return remoteNames.some((name) => {
|
|
9619
10478
|
if (source.startsWith(name + "/")) return true;
|
|
9620
10479
|
if (source !== name) return false;
|
|
9621
|
-
return !isNodeModulesId(importerId);
|
|
10480
|
+
return !isNodeModulesId(importerId) || !getInstalledPackageEntry(source, { cwd: root });
|
|
9622
10481
|
}) || source.includes("__loadRemote__");
|
|
9623
10482
|
}
|
|
9624
10483
|
return {
|
|
9625
10484
|
name: "module-federation-remote-named-exports",
|
|
9626
10485
|
enforce: "post",
|
|
10486
|
+
configResolved(config) {
|
|
10487
|
+
root = config.root || process.cwd();
|
|
10488
|
+
},
|
|
9627
10489
|
async transform(code, id) {
|
|
9628
10490
|
if (remoteNames.length === 0) return;
|
|
9629
10491
|
if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
|
|
@@ -9649,7 +10511,6 @@ function pluginRemoteNamedExports(options) {
|
|
|
9649
10511
|
const MAX_RUNNER_BODY_BYTES = 1024 * 1024;
|
|
9650
10512
|
const MAX_RUNNER_START_OFFSET = 1024 * 1024;
|
|
9651
10513
|
const ALLOWED_RUNNER_INVOKE_NAMES = /* @__PURE__ */ new Set(["fetchModule", "getBuiltins"]);
|
|
9652
|
-
const VITE_FS_PREFIX = "/@fs/";
|
|
9653
10514
|
function isPlainObject(value) {
|
|
9654
10515
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
9655
10516
|
}
|
|
@@ -9668,12 +10529,6 @@ function isSafeRunnerFetchModuleOptions(value) {
|
|
|
9668
10529
|
}
|
|
9669
10530
|
return true;
|
|
9670
10531
|
}
|
|
9671
|
-
function stripQueryAndHash(id) {
|
|
9672
|
-
const queryIndex = id.indexOf("?");
|
|
9673
|
-
const hashIndex = id.indexOf("#");
|
|
9674
|
-
const endIndex = queryIndex === -1 ? hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
|
|
9675
|
-
return endIndex === -1 ? id : id.slice(0, endIndex);
|
|
9676
|
-
}
|
|
9677
10532
|
function decodeRunnerFilePath(filePath) {
|
|
9678
10533
|
try {
|
|
9679
10534
|
return decodeURIComponent(filePath);
|
|
@@ -9717,8 +10572,8 @@ function isSafeRunnerFetchModuleId(id, config) {
|
|
|
9717
10572
|
const cleanId = decodeRunnerFilePath(stripQueryAndHash(decoded));
|
|
9718
10573
|
if (!cleanId || hasRelativeTraversal(cleanId)) return false;
|
|
9719
10574
|
const allowedDirectories = getRunnerAllowedDirectories(config);
|
|
9720
|
-
if (cleanId.startsWith(
|
|
9721
|
-
const fsPath =
|
|
10575
|
+
if (cleanId.startsWith("/@fs/")) {
|
|
10576
|
+
const fsPath = stripViteFsPrefix(cleanId);
|
|
9722
10577
|
return path$1.isAbsolute(fsPath) && isPathWithinAllowedDirectories(fsPath, allowedDirectories);
|
|
9723
10578
|
}
|
|
9724
10579
|
if (path$1.isAbsolute(cleanId)) {
|
|
@@ -9782,18 +10637,25 @@ function pluginSSRRemoteEntry(options) {
|
|
|
9782
10637
|
const remoteEntrySSRId = getRemoteEntrySSRId(options);
|
|
9783
10638
|
const virtualExposesSSRId = getVirtualExposesSSRId(options);
|
|
9784
10639
|
let cachedSsrRemoteEntrySource;
|
|
9785
|
-
const ssrOutputFilename = getSsrRemoteEntryFileName(options
|
|
10640
|
+
const ssrOutputFilename = getSsrRemoteEntryFileName(options);
|
|
9786
10641
|
const ssrExposesFileName = getSsrExposesFileName(options.filename);
|
|
9787
10642
|
let ssrOutputFiles = /* @__PURE__ */ new Set();
|
|
9788
10643
|
let ssrOutputDir = "";
|
|
9789
10644
|
let clientOutputDir = "";
|
|
9790
|
-
const
|
|
10645
|
+
const mfRuntimePackages = [
|
|
9791
10646
|
"@module-federation/runtime",
|
|
9792
10647
|
"@module-federation/runtime-core",
|
|
9793
|
-
"@module-federation/sdk"
|
|
9794
|
-
...options.ssrExternals ?? []
|
|
10648
|
+
"@module-federation/sdk"
|
|
9795
10649
|
];
|
|
10650
|
+
const ssrOnlyExternals = [...mfRuntimePackages, ...options.ssrExternals ?? []];
|
|
9796
10651
|
const ssrOnlyExternalPattern = new RegExp(`^(${ssrOnlyExternals.map((e) => e.replace(/[/\\^$*+?.()|[\]{}]/g, "\\$&")).join("|")})(\\/.*)?$`);
|
|
10652
|
+
let noExternal;
|
|
10653
|
+
const isNoExternal = (id) => {
|
|
10654
|
+
const pkg = ssrOnlyExternalPattern.exec(id)?.[1] ?? id;
|
|
10655
|
+
if (!noExternal || !mfRuntimePackages.includes(pkg)) return false;
|
|
10656
|
+
if (noExternal === true) return true;
|
|
10657
|
+
return (Array.isArray(noExternal) ? noExternal : [noExternal]).some((rule) => typeof rule === "string" ? rule === pkg : rule.test(pkg));
|
|
10658
|
+
};
|
|
9797
10659
|
const ssrModuleIds = /* @__PURE__ */ new Set([remoteEntrySSRId, virtualExposesSSRId]);
|
|
9798
10660
|
const resolvedAbsToPackage = /* @__PURE__ */ new Map();
|
|
9799
10661
|
let isServe = false;
|
|
@@ -9824,7 +10686,9 @@ function pluginSSRRemoteEntry(options) {
|
|
|
9824
10686
|
enforce: "pre",
|
|
9825
10687
|
configResolved(config) {
|
|
9826
10688
|
isServe = config.command === "serve";
|
|
10689
|
+
noExternal = config.environments?.ssr?.resolve?.noExternal ?? config.ssr?.noExternal;
|
|
9827
10690
|
for (const pkg of ssrOnlyExternals) {
|
|
10691
|
+
if (isNoExternal(pkg)) continue;
|
|
9828
10692
|
const aliasEntry = (config.resolve?.alias)?.find((a) => a.find === pkg || a.find instanceof RegExp && a.find.test(pkg));
|
|
9829
10693
|
if (aliasEntry?.replacement) resolvedAbsToPackage.set(aliasEntry.replacement, pkg);
|
|
9830
10694
|
}
|
|
@@ -9833,7 +10697,7 @@ function pluginSSRRemoteEntry(options) {
|
|
|
9833
10697
|
if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
|
|
9834
10698
|
if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
|
|
9835
10699
|
if (!importer || !ssrModuleIds.has(importer)) return;
|
|
9836
|
-
if (ssrOnlyExternalPattern.test(id)) return {
|
|
10700
|
+
if (ssrOnlyExternalPattern.test(id) && !isNoExternal(id)) return {
|
|
9837
10701
|
id,
|
|
9838
10702
|
external: true
|
|
9839
10703
|
};
|
|
@@ -9858,7 +10722,7 @@ function pluginSSRRemoteEntry(options) {
|
|
|
9858
10722
|
configureServer(server) {
|
|
9859
10723
|
const base = "/__mf_ssr__";
|
|
9860
10724
|
const basePath = getBasePath$1(viteConfig?.base);
|
|
9861
|
-
const ssrEntryFileName = getSsrRemoteEntryFileName(options
|
|
10725
|
+
const ssrEntryFileName = getSsrRemoteEntryFileName(options);
|
|
9862
10726
|
if (isNuxtProject || isNuxtClientBase(basePath)) server.middlewares.use((req, _res, next) => {
|
|
9863
10727
|
if (req.url?.replace(/\?.*/, "") === `${basePath}/${ssrEntryFileName}`) req.url = `${basePath}/__mf_ssr__/${ssrEntryFileName}`;
|
|
9864
10728
|
next();
|
|
@@ -9927,7 +10791,7 @@ function pluginSSRRemoteEntry(options) {
|
|
|
9927
10791
|
resolveId(id) {
|
|
9928
10792
|
if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
|
|
9929
10793
|
if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
|
|
9930
|
-
if (id === `/__mf_ssr__/${getSsrRemoteEntryFileName(options
|
|
10794
|
+
if (id === `/__mf_ssr__/${getSsrRemoteEntryFileName(options)}`) return remoteEntrySSRId;
|
|
9931
10795
|
if (id === `/__mf_ssr__/${ssrExposesFileName}`) return virtualExposesSSRId;
|
|
9932
10796
|
},
|
|
9933
10797
|
load(id) {
|
|
@@ -10132,6 +10996,85 @@ var aliasToArrayPlugin_default = {
|
|
|
10132
10996
|
}
|
|
10133
10997
|
};
|
|
10134
10998
|
//#endregion
|
|
10999
|
+
//#region src/utils/deferredPrebuildHelper.ts
|
|
11000
|
+
function isExportAllHelper(code, exportName) {
|
|
11001
|
+
try {
|
|
11002
|
+
const ast = parseAst(code);
|
|
11003
|
+
let localName;
|
|
11004
|
+
for (const node of ast.body) {
|
|
11005
|
+
if (node.type !== "ExportNamedDeclaration") continue;
|
|
11006
|
+
for (const specifier of node.specifiers) if (specifier.type === "ExportSpecifier" && specifier.exported.type === "Identifier" && specifier.exported.name === exportName && specifier.local.type === "Identifier") localName = specifier.local.name;
|
|
11007
|
+
}
|
|
11008
|
+
if (!localName) return false;
|
|
11009
|
+
for (const node of ast.body) {
|
|
11010
|
+
if (node.type !== "VariableDeclaration") continue;
|
|
11011
|
+
for (const declaration of node.declarations) {
|
|
11012
|
+
if (declaration.id.type !== "Identifier" || declaration.id.name !== localName) continue;
|
|
11013
|
+
const initializer = declaration.init;
|
|
11014
|
+
if (!initializer) return false;
|
|
11015
|
+
const source = code.slice(initializer.start, initializer.end);
|
|
11016
|
+
return source.includes("Symbol.toStringTag") && source.includes("Module");
|
|
11017
|
+
}
|
|
11018
|
+
}
|
|
11019
|
+
} catch {}
|
|
11020
|
+
return false;
|
|
11021
|
+
}
|
|
11022
|
+
/**
|
|
11023
|
+
* Rolldown sometimes places its shared namespace helper in a local prebuild
|
|
11024
|
+
* chunk. A loadShare wrapper then imports that helper statically, evaluating the
|
|
11025
|
+
* fallback even when a host provider is already in the cache. Inline only the
|
|
11026
|
+
* recognized Rolldown helper; leave every other prebuild import untouched.
|
|
11027
|
+
*/
|
|
11028
|
+
function inlineDeferredPrebuildNamespaceHelper(bundle) {
|
|
11029
|
+
for (const chunk of Object.values(bundle)) {
|
|
11030
|
+
if (chunk.type !== "chunk" || !chunk.fileName.includes("__loadShare__")) continue;
|
|
11031
|
+
let ast;
|
|
11032
|
+
try {
|
|
11033
|
+
ast = parseAst(chunk.code);
|
|
11034
|
+
} catch {
|
|
11035
|
+
continue;
|
|
11036
|
+
}
|
|
11037
|
+
const edits = [];
|
|
11038
|
+
const deferredSources = /* @__PURE__ */ new Set();
|
|
11039
|
+
forEachAstNode(ast, (node) => {
|
|
11040
|
+
if (node.type !== "ImportExpression") return;
|
|
11041
|
+
const source = getModuleSource(node.source);
|
|
11042
|
+
if (source) deferredSources.add(source);
|
|
11043
|
+
});
|
|
11044
|
+
const retainedImports = /* @__PURE__ */ new Set();
|
|
11045
|
+
const removedImports = /* @__PURE__ */ new Set();
|
|
11046
|
+
for (const node of ast.body) {
|
|
11047
|
+
if (node.type !== "ImportDeclaration") continue;
|
|
11048
|
+
const source = getModuleSource(node.source);
|
|
11049
|
+
if (!source) continue;
|
|
11050
|
+
const targetName = path.posix.normalize(path.posix.join(path.posix.dirname(chunk.fileName), source));
|
|
11051
|
+
const [specifier] = node.specifiers;
|
|
11052
|
+
const exported = specifier?.type === "ImportSpecifier" && specifier.imported;
|
|
11053
|
+
const target = bundle[targetName];
|
|
11054
|
+
if (!source.includes("__prebuild__") || node.specifiers.length !== 1 || !exported || exported.type !== "Identifier" || target?.type !== "chunk" || !deferredSources.has(source) || !Object.keys(target.modules ?? {}).some((id) => id.includes("rolldown/runtime.js")) || !isExportAllHelper(target.code, exported.name)) {
|
|
11055
|
+
retainedImports.add(targetName);
|
|
11056
|
+
continue;
|
|
11057
|
+
}
|
|
11058
|
+
removedImports.add(targetName);
|
|
11059
|
+
edits.push({
|
|
11060
|
+
start: node.start,
|
|
11061
|
+
end: node.end,
|
|
11062
|
+
replacement: `const ${specifier.local.name} = (all, noSymbols) => {
|
|
11063
|
+
const namespace = {};
|
|
11064
|
+
for (const name in all) Object.defineProperty(namespace, name, {
|
|
11065
|
+
get: all[name], enumerable: true,
|
|
11066
|
+
});
|
|
11067
|
+
if (!noSymbols) Object.defineProperty(namespace, Symbol.toStringTag, { value: 'Module' });
|
|
11068
|
+
return namespace;
|
|
11069
|
+
};`
|
|
11070
|
+
});
|
|
11071
|
+
}
|
|
11072
|
+
if (edits.length === 0) continue;
|
|
11073
|
+
for (const edit of edits.reverse()) chunk.code = chunk.code.slice(0, edit.start) + edit.replacement + chunk.code.slice(edit.end);
|
|
11074
|
+
if (chunk.imports) chunk.imports = chunk.imports.filter((imported) => !removedImports.has(imported) || retainedImports.has(imported));
|
|
11075
|
+
}
|
|
11076
|
+
}
|
|
11077
|
+
//#endregion
|
|
10135
11078
|
//#region src/utils/controlChunkSanitizer.ts
|
|
10136
11079
|
const FEDERATION_CONTROL_CHUNK_HINTS = ["hostInit", "localSharedImportMap"];
|
|
10137
11080
|
function stripEmptyPreloadCalls(code) {
|
|
@@ -10253,7 +11196,7 @@ function applyRuntimeCapabilityDefines(define, options, { defaultDisableSnapshot
|
|
|
10253
11196
|
function getRuntimeCapabilityConfigurationWarnings(options) {
|
|
10254
11197
|
const warnings = [];
|
|
10255
11198
|
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.");
|
|
10256
|
-
if (options.disableShared &&
|
|
11199
|
+
if (options.disableShared && hasShared(options)) warnings.push("disableShared is true, but shared dependencies are configured. Shared dependency loading will be unavailable at runtime.");
|
|
10257
11200
|
return warnings;
|
|
10258
11201
|
}
|
|
10259
11202
|
//#endregion
|
|
@@ -10349,7 +11292,7 @@ function isFederationHtmlPreloadDependency(dep, includeSharedRuntime = false) {
|
|
|
10349
11292
|
}
|
|
10350
11293
|
function canResolveSharedSubpath(subpath, projectRoot) {
|
|
10351
11294
|
try {
|
|
10352
|
-
return isViteOptimizableEntry(
|
|
11295
|
+
return isViteOptimizableEntry(resolveModulePath(subpath, path$1.join(projectRoot, "package.json")));
|
|
10353
11296
|
} catch (error) {
|
|
10354
11297
|
if (error?.code === "ERR_PACKAGE_PATH_NOT_EXPORTED" && !isBarePackageSubpath(subpath)) {
|
|
10355
11298
|
const entry = resolveViteImportPackageEntry(subpath, projectRoot);
|
|
@@ -10564,6 +11507,7 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
10564
11507
|
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));
|
|
10565
11508
|
resetConcreteSharedImportSourceCache();
|
|
10566
11509
|
setPackageDetectionCwd(root);
|
|
11510
|
+
resolveSharedVersions(shared, root);
|
|
10567
11511
|
const isVinext = hasPackageDependency("vinext");
|
|
10568
11512
|
initVirtualModules(_command, getRemoteEntryId(options), false, options);
|
|
10569
11513
|
const isRolldown = getIsRolldown(this);
|
|
@@ -10576,21 +11520,31 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
10576
11520
|
config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
|
|
10577
11521
|
}
|
|
10578
11522
|
}
|
|
10579
|
-
if (!config.build?.ssr && (
|
|
11523
|
+
if (!config.build?.ssr && (hasShared(options) || hasRemotes(options))) {
|
|
10580
11524
|
const hasJsxSource = registerEntryImports(options, root, _command === "serve", resolvedConfiguredEntryFiles);
|
|
10581
11525
|
if (_command === "serve") hasClientJsxSource = hasJsxSource;
|
|
10582
11526
|
}
|
|
10583
|
-
if (
|
|
11527
|
+
if (hasShared(options)) {
|
|
10584
11528
|
if (_command === "serve") {
|
|
10585
11529
|
excludeSharedSubDependencies(shared);
|
|
10586
11530
|
config.optimizeDeps = config.optimizeDeps || {};
|
|
10587
11531
|
config.optimizeDeps.include = config.optimizeDeps.include || [];
|
|
10588
11532
|
const optimizeDeps = config.optimizeDeps;
|
|
11533
|
+
const preparedShares = /* @__PURE__ */ new Map();
|
|
11534
|
+
const writeSharedModules = (source, shareItem) => {
|
|
11535
|
+
if (preparedShares.get(source) === shareItem) return;
|
|
11536
|
+
writeLoadShareModule(source, shareItem, _command, isRolldown, options);
|
|
11537
|
+
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
|
|
11538
|
+
preparedShares.set(source, shareItem);
|
|
11539
|
+
};
|
|
10589
11540
|
if (isRolldown) {
|
|
10590
11541
|
optimizeDeps.rolldownOptions ??= {};
|
|
10591
11542
|
optimizeDeps.rolldownOptions.plugins ??= [];
|
|
10592
11543
|
optimizeDeps.rolldownOptions.plugins.push({
|
|
10593
11544
|
name: "module-federation:optimize-shared-resolver",
|
|
11545
|
+
buildStart() {
|
|
11546
|
+
preparedShares.clear();
|
|
11547
|
+
},
|
|
10594
11548
|
load(id) {
|
|
10595
11549
|
if (!id.startsWith("module-federation:optimized-require-")) return;
|
|
10596
11550
|
const sourcePackage = id.slice(36);
|
|
@@ -10618,13 +11572,11 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
10618
11572
|
if (isCommonJsImporter(importer) && !isReactSingleton && !isReactDomRequire) return;
|
|
10619
11573
|
if (resolveOptions?.kind !== "entry-point") addUsedShares(source, options);
|
|
10620
11574
|
if (isReactRequire || isReactDomRequire) {
|
|
10621
|
-
|
|
10622
|
-
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
|
|
11575
|
+
writeSharedModules(source, shareItem);
|
|
10623
11576
|
return { id: `module-federation:optimized-require-${source}` };
|
|
10624
11577
|
}
|
|
10625
11578
|
const loadSharePath = getLoadShareModulePath(source, isRolldown, options);
|
|
10626
|
-
|
|
10627
|
-
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
|
|
11579
|
+
writeSharedModules(source, shareItem);
|
|
10628
11580
|
return {
|
|
10629
11581
|
id: loadSharePath,
|
|
10630
11582
|
external: true
|
|
@@ -10637,6 +11589,9 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
10637
11589
|
optimizeDeps.esbuildOptions.plugins.push({
|
|
10638
11590
|
name: "module-federation:optimize-shared-proxy",
|
|
10639
11591
|
setup(build) {
|
|
11592
|
+
build.onStart(() => {
|
|
11593
|
+
preparedShares.clear();
|
|
11594
|
+
});
|
|
10640
11595
|
build.onResolve({ filter: createViteEncodedIdPrefixRegExp("virtual:mf:") }, (args) => ({
|
|
10641
11596
|
path: args.path,
|
|
10642
11597
|
external: true
|
|
@@ -10654,8 +11609,7 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
10654
11609
|
if (args.kind === "import-statement" || args.kind === "dynamic-import") {
|
|
10655
11610
|
const shareItem = shared[key];
|
|
10656
11611
|
const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
|
|
10657
|
-
|
|
10658
|
-
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(args.path, shareItem, options);
|
|
11612
|
+
writeSharedModules(args.path, shareItem);
|
|
10659
11613
|
return {
|
|
10660
11614
|
path: loadSharePath,
|
|
10661
11615
|
external: true
|
|
@@ -10674,8 +11628,7 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
10674
11628
|
if (!key) return;
|
|
10675
11629
|
const shareItem = shared[key];
|
|
10676
11630
|
const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
|
|
10677
|
-
|
|
10678
|
-
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(args.path, shareItem, options);
|
|
11631
|
+
writeSharedModules(args.path, shareItem);
|
|
10679
11632
|
return {
|
|
10680
11633
|
loader: "js",
|
|
10681
11634
|
resolveDir: root,
|
|
@@ -10690,12 +11643,14 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
10690
11643
|
}
|
|
10691
11644
|
for (const key of Object.keys(shared)) {
|
|
10692
11645
|
const shareItem = shared[key];
|
|
10693
|
-
|
|
11646
|
+
const request = getSharedRequest(key, shareItem);
|
|
11647
|
+
const runtimeKey = getSharedRuntimeKey(key, shareItem);
|
|
11648
|
+
if (key.endsWith("/") || request.endsWith("/") || runtimeKey.endsWith("/")) {
|
|
10694
11649
|
if (_command === "serve" && shareItem.shareConfig?.import !== false) {
|
|
10695
11650
|
const optimizeDeps = config.optimizeDeps ??= {};
|
|
10696
11651
|
optimizeDeps.include ??= [];
|
|
10697
11652
|
optimizeDeps.exclude ??= [];
|
|
10698
|
-
for (const subpath of getCommonSharedSubpaths(
|
|
11653
|
+
for (const subpath of getCommonSharedSubpaths(request)) {
|
|
10699
11654
|
writePreBuildLibPath(subpath, shareItem, options);
|
|
10700
11655
|
if (canResolveSharedSubpath(subpath, root)) optimizeDeps.include.push(subpath);
|
|
10701
11656
|
else optimizeDeps.exclude.push(subpath);
|
|
@@ -10703,23 +11658,24 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
10703
11658
|
}
|
|
10704
11659
|
continue;
|
|
10705
11660
|
}
|
|
10706
|
-
if (isVinext &&
|
|
10707
|
-
addConfiguredShare(
|
|
11661
|
+
if (isVinext && runtimeKey === "react") {
|
|
11662
|
+
addConfiguredShare(runtimeKey, options);
|
|
10708
11663
|
continue;
|
|
10709
11664
|
}
|
|
10710
|
-
getLoadShareModulePath(
|
|
10711
|
-
writeLoadShareModule(
|
|
10712
|
-
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(
|
|
10713
|
-
addConfiguredShare(
|
|
11665
|
+
getLoadShareModulePath(runtimeKey, isRolldown, options);
|
|
11666
|
+
writeLoadShareModule(runtimeKey, shareItem, _command, isRolldown, options);
|
|
11667
|
+
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(runtimeKey, shareItem, options);
|
|
11668
|
+
addConfiguredShare(runtimeKey, options);
|
|
10714
11669
|
if (_command === "serve" && shareItem.shareConfig?.import !== false) {
|
|
10715
11670
|
const optimizeDeps = config.optimizeDeps ??= {};
|
|
10716
11671
|
optimizeDeps.include ??= [];
|
|
10717
11672
|
optimizeDeps.exclude ??= [];
|
|
10718
|
-
const shouldBypassOptimizeDep = isLitShare(
|
|
10719
|
-
if (optimizeDeps.include.includes(
|
|
10720
|
-
else if (shouldBypassOptimizeDep || optimizeDeps.exclude.includes(
|
|
10721
|
-
else optimizeDeps.include.push(
|
|
10722
|
-
|
|
11673
|
+
const shouldBypassOptimizeDep = isLitShare(runtimeKey) || !canResolveSharedSubpath(runtimeKey, root);
|
|
11674
|
+
if (optimizeDeps.include.includes(runtimeKey)) optimizeDeps.exclude = optimizeDeps.exclude.filter((dep) => dep !== runtimeKey);
|
|
11675
|
+
else if (shouldBypassOptimizeDep || optimizeDeps.exclude.includes(runtimeKey)) optimizeDeps.exclude.push(runtimeKey);
|
|
11676
|
+
else optimizeDeps.include.push(runtimeKey);
|
|
11677
|
+
const commonSubpaths = shareItem.shareConfig.request === void 0 && shareItem.shareConfig.shareKey === void 0 ? getCommonSharedSubpaths(runtimeKey) : [];
|
|
11678
|
+
for (const subpath of commonSubpaths) {
|
|
10723
11679
|
const canResolveSubpath = canResolveSharedSubpath(subpath, root);
|
|
10724
11680
|
if ([
|
|
10725
11681
|
"react/compiler-runtime",
|
|
@@ -10735,7 +11691,7 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
10735
11691
|
addConfiguredShare(subpath, options);
|
|
10736
11692
|
if (canResolveSubpath) {
|
|
10737
11693
|
optimizeDeps.include.push(subpath);
|
|
10738
|
-
if (
|
|
11694
|
+
if (runtimeKey === "react-dom") optimizeDeps.include.push(`${runtimeKey} > ${subpath}`);
|
|
10739
11695
|
} else optimizeDeps.exclude.push(subpath);
|
|
10740
11696
|
}
|
|
10741
11697
|
}
|
|
@@ -10753,10 +11709,8 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
10753
11709
|
const automaticJsxRuntime = getAutomaticJsxRuntime(config);
|
|
10754
11710
|
if (automaticJsxRuntime && materializeAutomaticJsxRuntime(options, automaticJsxRuntime)) writeLocalSharedImportMap(options);
|
|
10755
11711
|
}
|
|
10756
|
-
if (!getSsrCapabilities(parseInt(version, 10), config.command, hasRemotes(options)).injectSsrEntryLoader) return;
|
|
10757
|
-
if (options.runtimePlugins.some((p) =>
|
|
10758
|
-
return (typeof p === "string" ? p : p[0]) === "@module-federation/vite/ssrEntryLoader";
|
|
10759
|
-
})) return;
|
|
11712
|
+
if (!getSsrCapabilities(parseInt(version, 10), config.command, hasRemotes(options), isSsrConfig(config)).injectSsrEntryLoader) return;
|
|
11713
|
+
if (options.runtimePlugins.some((p) => getRuntimePluginSpecifier(p) === "@module-federation/vite/ssrEntryLoader")) return;
|
|
10760
11714
|
const projectRequire = createRequire$1(pathToFileURL(path$1.join(config.root, "package.json")));
|
|
10761
11715
|
const sharedKeys = Object.keys(options.shared ?? {});
|
|
10762
11716
|
const commonSharedPkgs = [
|
|
@@ -10799,16 +11753,14 @@ function applyBuildTimeRuntimeDefines(define, options, { target, isAstro, defaul
|
|
|
10799
11753
|
}
|
|
10800
11754
|
function loadPluginDts(options) {
|
|
10801
11755
|
if (options.dts === false) return [];
|
|
10802
|
-
return [import("./pluginDts-
|
|
11756
|
+
return [import("./pluginDts-VSLhAx6d.js").then(({ default: pluginDts }) => pluginDts(options))];
|
|
10803
11757
|
}
|
|
10804
11758
|
const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
|
|
10805
11759
|
function isInjectExternalRuntimeCorePlugin(specifier) {
|
|
10806
11760
|
return specifier === INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN || specifier.includes("injectExternalRuntimeCorePlugin") || specifier.includes("inject-external-runtime-core-plugin");
|
|
10807
11761
|
}
|
|
10808
11762
|
function hasInjectExternalRuntimeCorePlugin(runtimePlugins) {
|
|
10809
|
-
return runtimePlugins.some((plugin) =>
|
|
10810
|
-
return isInjectExternalRuntimeCorePlugin(typeof plugin === "string" ? plugin : plugin[0]);
|
|
10811
|
-
});
|
|
11763
|
+
return runtimePlugins.some((plugin) => isInjectExternalRuntimeCorePlugin(getRuntimePluginSpecifier(plugin)));
|
|
10812
11764
|
}
|
|
10813
11765
|
function resolveInjectExternalRuntimeCorePlugin() {
|
|
10814
11766
|
try {
|
|
@@ -10855,7 +11807,7 @@ function federation(mfUserOptions) {
|
|
|
10855
11807
|
const emittedRuntimeCapabilityWarnings = /* @__PURE__ */ new Set();
|
|
10856
11808
|
const getLoadHookExportConditions = (context, loadOptions) => {
|
|
10857
11809
|
const environment = context.environment;
|
|
10858
|
-
const isSsr = loadOptions?.ssr === true || isSsrBuild || environment?.
|
|
11810
|
+
const isSsr = loadOptions?.ssr === true || isSsrBuild || isServerEnvironment(environment?.name, environment?.config);
|
|
10859
11811
|
return getSharedExportConditions({
|
|
10860
11812
|
environmentConditions: environment?.config?.resolve?.conditions,
|
|
10861
11813
|
isProduction: environment?.config?.isProduction ?? isProduction,
|
|
@@ -10979,7 +11931,8 @@ function federation(mfUserOptions) {
|
|
|
10979
11931
|
ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
|
|
10980
11932
|
ssrTarget = config.ssr?.target ?? "node";
|
|
10981
11933
|
isProduction = config.isProduction;
|
|
10982
|
-
const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, Object.keys(options.remotes).length > 0);
|
|
11934
|
+
const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, Object.keys(options.remotes).length > 0, isSsrConfig(config));
|
|
11935
|
+
resolveSharedVersions(shared, config.root);
|
|
10983
11936
|
initVirtualModules(command, remoteEntryId, ssrCapabilities.enableSsrInitBootstrap, options);
|
|
10984
11937
|
}
|
|
10985
11938
|
},
|
|
@@ -11028,6 +11981,7 @@ function federation(mfUserOptions) {
|
|
|
11028
11981
|
federationOptions: options,
|
|
11029
11982
|
getParsePromise: () => moduleParseController.parsePromise
|
|
11030
11983
|
}),
|
|
11984
|
+
pluginLazyConsumeOnlyShares(options),
|
|
11031
11985
|
{
|
|
11032
11986
|
name: "module-federation-esm-shims",
|
|
11033
11987
|
enforce: "pre",
|
|
@@ -11079,6 +12033,7 @@ function federation(mfUserOptions) {
|
|
|
11079
12033
|
priority: USER_GROUP_MAX_PRIORITY
|
|
11080
12034
|
};
|
|
11081
12035
|
};
|
|
12036
|
+
const federationGroupDebugName = supportsCodeSplittingGroupDebugName(this) ? { debugName: "module-federation" } : {};
|
|
11082
12037
|
let warnedAboutManualChunks = false;
|
|
11083
12038
|
let warnedAboutObjectManualChunks = false;
|
|
11084
12039
|
const applyManualChunks = (output, useCodeSplitting) => {
|
|
@@ -11086,11 +12041,13 @@ function federation(mfUserOptions) {
|
|
|
11086
12041
|
const isPatchedByPlugin = typeof output.manualChunks === "function" && patchedManualChunks.has(output.manualChunks);
|
|
11087
12042
|
const mfChunkName = function(id) {
|
|
11088
12043
|
if (id.includes(runtimeInitId) || id.includes("__mf_v__runtimeInit__mf_v__")) return "runtimeInit";
|
|
12044
|
+
if (isSharedCacheHelpersId(id)) return getSharedChunkName(id);
|
|
11089
12045
|
if (id.includes("__loadShare__")) {
|
|
11090
12046
|
const pkg = getCachedLoadSharePkg(id);
|
|
11091
12047
|
const key = pkg && findSharedKey(pkg, shared);
|
|
11092
|
-
if (
|
|
12048
|
+
if (key && shared[key].shareConfig.eager === true) return "loadShare-eager";
|
|
11093
12049
|
if (key && shared[key].shareConfig.import === false) return null;
|
|
12050
|
+
if (pkg && !id.includes("commonjs-proxy") && isCoalescableLoadShareWrapper(pkg, options, id)) return getSharedChunkName(id);
|
|
11094
12051
|
const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
|
|
11095
12052
|
return match ? match[1] : "loadShare";
|
|
11096
12053
|
}
|
|
@@ -11127,7 +12084,8 @@ function federation(mfUserOptions) {
|
|
|
11127
12084
|
};
|
|
11128
12085
|
const mfNameGroup = {
|
|
11129
12086
|
name: mfChunkName,
|
|
11130
|
-
priority: MF_GROUP_PRIORITY
|
|
12087
|
+
priority: MF_GROUP_PRIORITY,
|
|
12088
|
+
...federationGroupDebugName
|
|
11131
12089
|
};
|
|
11132
12090
|
federationGroups.add(mfPreloadGroup);
|
|
11133
12091
|
federationGroups.add(mfNameGroup);
|
|
@@ -11200,7 +12158,14 @@ function federation(mfUserOptions) {
|
|
|
11200
12158
|
if (!virtualModule?.code) return null;
|
|
11201
12159
|
let code = virtualModule.code;
|
|
11202
12160
|
const consumerTarget = resolveEnvironmentConsumerTarget(this);
|
|
11203
|
-
if (consumerTarget === "server" || !consumerTarget && isSsrBuild)
|
|
12161
|
+
if (consumerTarget === "server" || !consumerTarget && isSsrBuild) {
|
|
12162
|
+
const withSsrImport = prependWorkspaceSingletonSsrImport(code);
|
|
12163
|
+
if (withSsrImport !== code) {
|
|
12164
|
+
const pkg = getCachedLoadSharePkg(id);
|
|
12165
|
+
if (pkg) markLoadShareWrapperNotCoalescable(pkg, options, id);
|
|
12166
|
+
code = withSsrImport;
|
|
12167
|
+
}
|
|
12168
|
+
}
|
|
11204
12169
|
code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
11205
12170
|
code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
11206
12171
|
if (!(/\b(?:var|let|const)\s+__moduleExports\b/.test(code) || /\bexport\s+const\s+__moduleExports\b/.test(code) || /\bexport\s*\{[^}]*__moduleExports/.test(code))) {
|
|
@@ -11218,6 +12183,9 @@ function federation(mfUserOptions) {
|
|
|
11218
12183
|
return loadVirtualModule();
|
|
11219
12184
|
},
|
|
11220
12185
|
generateBundle(_outputOptions, bundle, _isWrite) {
|
|
12186
|
+
inlineDeferredPrebuildNamespaceHelper(bundle);
|
|
12187
|
+
for (const [fileName, fallbacks] of findEagerFallbacksInSharedChunk(bundle)) mfWarn(`A shared-dependency fallback was merged into the loadShare chunk ${fileName}: ${fallbacks.join(", ")}.\n That fallback is no longer lazy, so consumers download their local copy even when a peer provides the share, and the container can deadlock.
|
|
12188
|
+
Stop the shared module from statically importing another share.`);
|
|
11221
12189
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
11222
12190
|
if (!isOutputChunk(chunk)) continue;
|
|
11223
12191
|
if (!isFederationControlChunk(fileName, filename)) continue;
|
|
@@ -11266,7 +12234,7 @@ function federation(mfUserOptions) {
|
|
|
11266
12234
|
config(config, { command: _command }) {
|
|
11267
12235
|
const isRolldown = getIsRolldown(this);
|
|
11268
12236
|
isSsrBuild = _command === "build" && Boolean(config.build?.ssr);
|
|
11269
|
-
const needsRuntimeHelpers =
|
|
12237
|
+
const needsRuntimeHelpers = hasShared(options);
|
|
11270
12238
|
if (needsRuntimeHelpers) appendResolveAlias(config, {
|
|
11271
12239
|
find: /^@module-federation\/runtime\/helpers$/,
|
|
11272
12240
|
replacement: getRuntimeHelpersImplementation(options.implementation)
|
|
@@ -11283,7 +12251,7 @@ function federation(mfUserOptions) {
|
|
|
11283
12251
|
config.optimizeDeps.include.push("@module-federation/runtime");
|
|
11284
12252
|
if (needsRuntimeHelpers) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
|
|
11285
12253
|
options.runtimePlugins.forEach((p) => {
|
|
11286
|
-
const pluginPath =
|
|
12254
|
+
const pluginPath = getRuntimePluginSpecifier(p);
|
|
11287
12255
|
if (SSR_ONLY_RUNTIME_PLUGINS.has(pluginPath)) return;
|
|
11288
12256
|
if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) {
|
|
11289
12257
|
let optimizeDep = pluginPath;
|
|
@@ -11319,7 +12287,7 @@ function federation(mfUserOptions) {
|
|
|
11319
12287
|
if (prematureExit) prematureExit.closeBundle = void 0;
|
|
11320
12288
|
},
|
|
11321
12289
|
configEnvironment(name, config) {
|
|
11322
|
-
if (!(
|
|
12290
|
+
if (!isServerEnvironment(name, config)) return;
|
|
11323
12291
|
const isAstro = hasPackageDependency("astro");
|
|
11324
12292
|
config.define = { ...config.define ?? {} };
|
|
11325
12293
|
applyBuildTimeRuntimeDefines(config.define, options, {
|