@module-federation/vite 1.17.1 → 1.18.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 +1 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +168 -56
- package/lib/{ssrEntryLoader-D_sUES94.js → ssrEntryLoader-DgsCQOqq.js} +60 -21
- package/lib/{ssrVmStrategy-By_N71Dl.js → ssrVmStrategy-ChF8MB7l.js} +26 -4
- package/lib/utils/ssrEntryLoader.d.ts +3 -1
- package/lib/utils/ssrEntryLoader.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ Examples live in [`gioboa/module-federation-vite-examples`](https://github.com/g
|
|
|
31
31
|
| ---------------------------------------------------------------------------------------- | --------------- | ----------------- | --------------------------- |
|
|
32
32
|
| [Alpine](https://github.com/gioboa/module-federation-vite-examples/tree/main/alpine) | `alpine-host` | `alpine-remote` | Alpine.js |
|
|
33
33
|
| [Angular](https://github.com/gioboa/module-federation-vite-examples/tree/main/angular) | `angular-host` | `angular-remote` | Angular |
|
|
34
|
+
| [Ember](https://github.com/gioboa/module-federation-vite-examples/tree/main/ember) | `ember-host` | `ember-remote` | Ember 7 |
|
|
34
35
|
| [Lit](https://github.com/gioboa/module-federation-vite-examples/tree/main/lit) | `lit-host` | `lit-remote` | Lit |
|
|
35
36
|
| [Nuxt](https://github.com/gioboa/module-federation-vite-examples/tree/main/nuxt) | `nuxt-host` | `nuxt-remote` | Nuxt 4 |
|
|
36
37
|
| [Nx](https://github.com/gioboa/react-nx-microfrontend-demo) | `host` | `remote` | React + Nx |
|
package/lib/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ interface RemoteObjectConfig {
|
|
|
8
8
|
internalName?: string;
|
|
9
9
|
entry: string;
|
|
10
10
|
entryGlobalName?: string;
|
|
11
|
-
shareScope?: string;
|
|
11
|
+
shareScope?: string | string[];
|
|
12
12
|
}
|
|
13
13
|
interface TreeShakingConfig {
|
|
14
14
|
mode: 'server-calc' | 'runtime-infer';
|
|
@@ -36,7 +36,7 @@ type ModuleFederationOptions = {
|
|
|
36
36
|
name: string;
|
|
37
37
|
remotes?: Record<string, string | RemoteObjectConfig> | undefined;
|
|
38
38
|
runtime?: any;
|
|
39
|
-
shareScope?: string;
|
|
39
|
+
shareScope?: string | string[];
|
|
40
40
|
/**
|
|
41
41
|
* Override the public path used for remote entries
|
|
42
42
|
* Defaults to Vite's base config or "auto" if base is empty
|
package/lib/index.js
CHANGED
|
@@ -639,7 +639,7 @@ var VirtualModule = class VirtualModule {
|
|
|
639
639
|
//#endregion
|
|
640
640
|
//#region src/utils/ssrCapabilities.ts
|
|
641
641
|
/** A browser-safe generated expression that is true only in Node.js. */
|
|
642
|
-
const SERVER_ENV_GUARD = "
|
|
642
|
+
const SERVER_ENV_GUARD = "import.meta.env.SSR";
|
|
643
643
|
/**
|
|
644
644
|
* Single source of truth for SSR-related feature gates.
|
|
645
645
|
*
|
|
@@ -1854,6 +1854,7 @@ function getDependencyNames(packageJson) {
|
|
|
1854
1854
|
}
|
|
1855
1855
|
function isSharedSingletonConsumedByPeer(pkg) {
|
|
1856
1856
|
const shared = getNormalizeModuleFederationOptions()?.shared || {};
|
|
1857
|
+
if (Object.entries(shared).some(([key, item]) => key !== pkg && key.startsWith(`${pkg}/`) && item.shareConfig.singleton === true)) return true;
|
|
1857
1858
|
const sharedKeyByPackageName = /* @__PURE__ */ new Map();
|
|
1858
1859
|
Object.entries(shared).filter(([, item]) => item.shareConfig.singleton === true).forEach(([key]) => {
|
|
1859
1860
|
const packageName = getPackageName(key);
|
|
@@ -2144,13 +2145,14 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
|
|
|
2144
2145
|
__mfApplyEagerShareExports(exportModule);
|
|
2145
2146
|
export { __mf_default as default };${namedExportLine}`;
|
|
2146
2147
|
}
|
|
2147
|
-
function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer) {
|
|
2148
|
+
function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, serveLocalFallback = false) {
|
|
2148
2149
|
const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
|
|
2149
2150
|
const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
|
|
2150
2151
|
const assignments = namedExports.length > 0 ? [...namedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = mod.default ?? mod;"].join("\n ") : "__mf_default = mod.default ?? mod;";
|
|
2151
2152
|
const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
|
|
2152
2153
|
const applyLocalFallback = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
2153
|
-
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner})
|
|
2154
|
+
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
|
|
2155
|
+
__mfApplyLazyShareExports(exportModule);`;
|
|
2154
2156
|
return `${declarations}
|
|
2155
2157
|
const __mfApplyLazyShareExports = (mod) => {
|
|
2156
2158
|
${assignments}
|
|
@@ -2158,7 +2160,7 @@ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cache
|
|
|
2158
2160
|
__mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyLazyShareExports);
|
|
2159
2161
|
let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
|
|
2160
2162
|
if (exportModule === undefined) {
|
|
2161
|
-
if (import.meta.env.SSR) {
|
|
2163
|
+
if (import.meta.env.SSR${serveLocalFallback ? " || (import.meta.env.DEV && typeof __mfLocalShare !== 'undefined')" : ""}) {
|
|
2162
2164
|
${applyLocalFallback}
|
|
2163
2165
|
} else {
|
|
2164
2166
|
(__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
|
|
@@ -2183,7 +2185,7 @@ function prependWorkspaceSingletonSsrImport(code) {
|
|
|
2183
2185
|
if (!code.includes("if (import.meta.env.SSR)")) return code;
|
|
2184
2186
|
if (!code.includes(WORKSPACE_SINGLETON_SSR_LOCAL_SHARE)) return code;
|
|
2185
2187
|
if (code.includes("import * as __mfLocalShare")) return code;
|
|
2186
|
-
const importMatch = code.match(/initPromise\.then\(\(\)\s*=>\s*\{[\s\S]*?\breturn import\((["'])(.+?)\1\)\.then\(\(mod\)\s*=>\s*\{[\s\S]*?__mfApplyLazyShareExports/) ?? code.match(/initPromise\.then\(\(\)\s*=>\s*\n\s*import\((["'])(.+?)\1\)\.then\(\(mod\)\s*=>\s*\{[\s\S]*?__mfApplyLazyShareExports/);
|
|
2188
|
+
const importMatch = code.match(/initPromise\.then\(\(\)\s*=>\s*\{[\s\S]*?\breturn import\((["'])(.+?)\1\)\.then\(\(mod\)\s*=>\s*\{[\s\S]*?__mfApplyLazyShareExports/) ?? code.match(/initPromise\.then\(\(\)\s*=>\s*\n\s*import\((["'])(.+?)\1\)\.then\(\(mod\)\s*=>\s*\{[\s\S]*?__mfApplyLazyShareExports/) ?? code.match(/import\((["'])(.+?)\1\)/);
|
|
2187
2189
|
if (!importMatch) return code;
|
|
2188
2190
|
const quote = importMatch[1];
|
|
2189
2191
|
return `import * as __mfLocalShare from ${quote}${importMatch[2]}${quote};\n${code}`;
|
|
@@ -2223,10 +2225,15 @@ function generateShareModuleUnwrapCode({ source, preserveNamedExports, stopWithR
|
|
|
2223
2225
|
return current;`;
|
|
2224
2226
|
}
|
|
2225
2227
|
const normalizeLocalShareModuleCode = `const __mfNormalizeShareModule = (mod) => {
|
|
2226
|
-
|
|
2228
|
+
const normalized = (() => {
|
|
2229
|
+
${generateShareModuleUnwrapCode({
|
|
2227
2230
|
source: "mod",
|
|
2228
2231
|
preserveNamedExports: true
|
|
2229
2232
|
})}
|
|
2233
|
+
})();
|
|
2234
|
+
return normalized && Object.getPrototypeOf(normalized) === null
|
|
2235
|
+
? Object.assign({}, normalized)
|
|
2236
|
+
: normalized;
|
|
2230
2237
|
};`;
|
|
2231
2238
|
function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
2232
2239
|
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".js");
|
|
@@ -2265,6 +2272,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
|
2265
2272
|
const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
|
|
2266
2273
|
const isDefaultShareScope = shareItem.scope === void 0 || shareItem.scope === "default" || Array.isArray(shareItem.scope) && shareItem.scope[0] === "default";
|
|
2267
2274
|
const usesDeferredSingletonFallback = hasCompleteExportCoverage && (isWorkspaceSingleton || command !== "build" && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && !isDefaultShareScope);
|
|
2275
|
+
const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true;
|
|
2268
2276
|
const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg);
|
|
2269
2277
|
const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && command !== "build" && !isWorkspaceSingleton && isRemoteOnlyContainer() && shareItem.shareConfig.singleton === true && getNormalizeModuleFederationOptions().hostInitInjectLocation === "entry" && isConsumedByPeerSingleton;
|
|
2270
2278
|
const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && isConsumedByPeerSingleton;
|
|
@@ -2273,11 +2281,11 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
|
2273
2281
|
let initBlock = "";
|
|
2274
2282
|
if (usesDeferredTreeShakingFallback) {
|
|
2275
2283
|
importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
|
|
2276
|
-
exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer);
|
|
2284
|
+
exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && (isWorkspaceSingleton || isWorkspacePackage || servesRemoteSingletonFallback));
|
|
2277
2285
|
} else if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer);
|
|
2278
2286
|
else if (usesDeferredSingletonFallback) {
|
|
2279
2287
|
importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
|
|
2280
|
-
exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer);
|
|
2288
|
+
exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && (isWorkspaceSingleton || isWorkspacePackage || servesRemoteSingletonFallback));
|
|
2281
2289
|
} else if (detectedNamedExports === void 0) {
|
|
2282
2290
|
exportLine = `const __mfDefaultExport = (() => {
|
|
2283
2291
|
${generateShareModuleUnwrapCode({
|
|
@@ -2339,7 +2347,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
|
2339
2347
|
initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
2340
2348
|
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
|
|
2341
2349
|
}
|
|
2342
|
-
const prebuildImportLine = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
|
|
2350
|
+
const prebuildImportLine = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? servesRemoteSingletonFallback || usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(lazyLocalFallbackSource)};` : "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
|
|
2343
2351
|
const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
2344
2352
|
const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? `
|
|
2345
2353
|
${prebuildImportLine}
|
|
@@ -2454,10 +2462,12 @@ function generateLocalSharedImportMap() {
|
|
|
2454
2462
|
? (res?.default ?? res)
|
|
2455
2463
|
: {...res}
|
|
2456
2464
|
// All npm packages pre-built by vite will be converted to esm
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2465
|
+
if (exportModule.__esModule !== true) {
|
|
2466
|
+
Object.defineProperty(exportModule, "__esModule", {
|
|
2467
|
+
value: true,
|
|
2468
|
+
enumerable: false
|
|
2469
|
+
})
|
|
2470
|
+
}
|
|
2461
2471
|
return function () {
|
|
2462
2472
|
return exportModule
|
|
2463
2473
|
}
|
|
@@ -2550,7 +2560,17 @@ function orderSharedDependenciesFirst(sharedPackages) {
|
|
|
2550
2560
|
const sharedDependency = sharedKeyByPackageName.get(dependency);
|
|
2551
2561
|
if (sharedDependency) visit(sharedDependency);
|
|
2552
2562
|
});
|
|
2553
|
-
if (pkg === packageName)
|
|
2563
|
+
if (pkg === packageName) {
|
|
2564
|
+
const subpaths = subpathKeysByPackageName.get(packageName) || [];
|
|
2565
|
+
if (packageName === "react" || packageName === "react-dom") {
|
|
2566
|
+
visiting.delete(pkg);
|
|
2567
|
+
visited.add(pkg);
|
|
2568
|
+
ordered.push(pkg);
|
|
2569
|
+
subpaths.forEach(visit);
|
|
2570
|
+
return;
|
|
2571
|
+
}
|
|
2572
|
+
subpaths.forEach(visit);
|
|
2573
|
+
}
|
|
2554
2574
|
visiting.delete(pkg);
|
|
2555
2575
|
visited.add(pkg);
|
|
2556
2576
|
ordered.push(pkg);
|
|
@@ -2572,7 +2592,7 @@ function generateSharedCacheSeedItem(pkg, shareItem, importPath) {
|
|
|
2572
2592
|
${normalizeRuntimeShareCode}
|
|
2573
2593
|
const normalizedModule = __mfNormalizeRuntimeShare(mod);
|
|
2574
2594
|
const exportModule = normalizedModule === mod ? {...mod} : normalizedModule;
|
|
2575
|
-
Object.defineProperty(exportModule, "__esModule", {
|
|
2595
|
+
if (exportModule.__esModule !== true) Object.defineProperty(exportModule, "__esModule", {
|
|
2576
2596
|
value: true,
|
|
2577
2597
|
enumerable: false
|
|
2578
2598
|
});
|
|
@@ -2789,7 +2809,7 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy) {
|
|
|
2789
2809
|
${normalizeRuntimeShareCode}
|
|
2790
2810
|
const normalizedModule = __mfNormalizeRuntimeShare(resolved);
|
|
2791
2811
|
const exportModule = normalizedModule === resolved ? {...resolved} : normalizedModule;
|
|
2792
|
-
Object.defineProperty(exportModule, "__esModule", {
|
|
2812
|
+
if (exportModule.__esModule !== true) Object.defineProperty(exportModule, "__esModule", {
|
|
2793
2813
|
value: true,
|
|
2794
2814
|
enumerable: false
|
|
2795
2815
|
});
|
|
@@ -3047,6 +3067,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3047
3067
|
const needsSharedProviderSelectionHelper = Object.keys(options.shared ?? {}).length > 0;
|
|
3048
3068
|
const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
|
|
3049
3069
|
const hasEagerShared = Object.values(options.shared ?? {}).some((share) => share?.shareConfig.eager === true && share.shareConfig.import !== false);
|
|
3070
|
+
const hasMultipleShareScopes = Array.isArray(options.shareScope);
|
|
3050
3071
|
const runtimeImports = [
|
|
3051
3072
|
"init as runtimeInit",
|
|
3052
3073
|
"loadRemote",
|
|
@@ -3065,7 +3086,19 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3065
3086
|
serializeRuntimeOptions(p[1])
|
|
3066
3087
|
];
|
|
3067
3088
|
});
|
|
3068
|
-
const initializeSharingCode = `
|
|
3089
|
+
const initializeSharingCode = hasMultipleShareScopes ? `for (const shareScopeName of shareScopeNamesToInitialize) {
|
|
3090
|
+
try {
|
|
3091
|
+
await retrySharedInit(async () => {
|
|
3092
|
+
await Promise.all(await initRes.initializeSharing(shareScopeName, {
|
|
3093
|
+
strategy: '${options.shareStrategy}',
|
|
3094
|
+
from: "build",
|
|
3095
|
+
initScope
|
|
3096
|
+
}));
|
|
3097
|
+
});
|
|
3098
|
+
} catch (e) {
|
|
3099
|
+
console.error('[Module Federation]', e)
|
|
3100
|
+
}
|
|
3101
|
+
}` : `try {
|
|
3069
3102
|
await retrySharedInit(async () => {
|
|
3070
3103
|
await Promise.all(await initRes.initializeSharing('${options.shareScope}', {
|
|
3071
3104
|
strategy: '${options.shareStrategy}',
|
|
@@ -3092,7 +3125,8 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3092
3125
|
${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
|
|
3093
3126
|
${getRuntimeModuleCacheBootstrapCode()}
|
|
3094
3127
|
const initTokens = {}
|
|
3095
|
-
const
|
|
3128
|
+
const shareScopeNames = Array.isArray(${JSON.stringify(options.shareScope)}) ? ${JSON.stringify(options.shareScope)} : [${JSON.stringify(options.shareScope)}]
|
|
3129
|
+
const shareScopeName = ${JSON.stringify(hasMultipleShareScopes ? options.shareScope[0] : options.shareScope)}
|
|
3096
3130
|
const mfName = ${JSON.stringify(options.name)}
|
|
3097
3131
|
let localSharedImportMapPromise
|
|
3098
3132
|
let exposesMapPromise
|
|
@@ -3139,31 +3173,66 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3139
3173
|
|
|
3140
3174
|
async function init(shared = {}, initScope = []) {
|
|
3141
3175
|
${sharedCacheHelperCode}
|
|
3176
|
+
const getShareScope = (scopeName) => ${hasMultipleShareScopes} ? (shared?.[scopeName] || {}) : shared;
|
|
3177
|
+
const getShareScopeNames = (share) => {
|
|
3178
|
+
const configuredScopes = Array.isArray(share?.scope) ? share.scope : [share?.scope || shareScopeName];
|
|
3179
|
+
if (!${hasMultipleShareScopes}) return configuredScopes;
|
|
3180
|
+
return [...new Set([...configuredScopes, ...shareScopeNames])];
|
|
3181
|
+
};
|
|
3182
|
+
const getShareScopeName = (pkg, share) => {
|
|
3183
|
+
for (const scopeName of getShareScopeNames(share)) {
|
|
3184
|
+
if (getShareScope(scopeName)?.[pkg]) return scopeName;
|
|
3185
|
+
}
|
|
3186
|
+
return shareScopeName;
|
|
3187
|
+
};
|
|
3188
|
+
const getShareVersions = (pkg, share) => {
|
|
3189
|
+
for (const scopeName of getShareScopeNames(share)) {
|
|
3190
|
+
const versions = getShareScope(scopeName)?.[pkg];
|
|
3191
|
+
if (versions) return versions;
|
|
3192
|
+
}
|
|
3193
|
+
return getShareScope(shareScopeName)?.[pkg];
|
|
3194
|
+
};
|
|
3142
3195
|
const federationInstances = globalThis.__FEDERATION__?.__INSTANCES__ || [];
|
|
3143
3196
|
const initRootName = initScope.find((token) => token?.from)?.from;
|
|
3144
3197
|
const scopeRoot = federationInstances.find((instance) =>
|
|
3145
3198
|
instance?.options?.name === initRootName &&
|
|
3146
|
-
instance?.shareScopeMap?.['${options.shareScope}'] === shared
|
|
3199
|
+
${hasMultipleShareScopes ? "shareScopeNames.some((scopeName) => instance?.shareScopeMap?.[scopeName] === getShareScope(scopeName))" : `instance?.shareScopeMap?.['${options.shareScope}'] === shared`}
|
|
3147
3200
|
) || federationInstances.find((instance) =>
|
|
3148
3201
|
instance?.options?.name !== mfName &&
|
|
3149
|
-
instance?.shareScopeMap?.['${options.shareScope}'] === shared
|
|
3202
|
+
${hasMultipleShareScopes ? "shareScopeNames.some((scopeName) => instance?.shareScopeMap?.[scopeName] === getShareScope(scopeName))" : `instance?.shareScopeMap?.['${options.shareScope}'] === shared`}
|
|
3150
3203
|
);
|
|
3151
3204
|
const initialShared = Object.create(null);
|
|
3152
|
-
for (const
|
|
3205
|
+
${hasMultipleShareScopes ? `for (const scopeName of shareScopeNames) {
|
|
3206
|
+
for (const [pkg, versions] of Object.entries(getShareScope(scopeName))) {
|
|
3207
|
+
if (initialShared[pkg]) continue;
|
|
3208
|
+
const initialVersions = initialShared[pkg] = Object.create(null);
|
|
3209
|
+
for (const [version, provider] of Object.entries(versions)) {
|
|
3210
|
+
initialVersions[version] = Object.assign({}, provider);
|
|
3211
|
+
}
|
|
3212
|
+
}
|
|
3213
|
+
}` : `for (const [pkg, versions] of Object.entries(shared)) {
|
|
3153
3214
|
const initialVersions = initialShared[pkg] = Object.create(null);
|
|
3154
3215
|
for (const [version, provider] of Object.entries(versions)) {
|
|
3155
3216
|
// Runtime registration mutates provider records in-place, notably their origin.
|
|
3156
3217
|
// Preserve the parent-visible provider and its original provenance.
|
|
3157
3218
|
initialVersions[version] = Object.assign({}, provider);
|
|
3158
3219
|
}
|
|
3159
|
-
}
|
|
3220
|
+
}`}
|
|
3160
3221
|
const {usedShared, usedRemotes} = await getLocalSharedImportMap()
|
|
3161
3222
|
// handling circular init calls before an external provider can re-enter this container
|
|
3162
|
-
|
|
3223
|
+
${hasMultipleShareScopes ? `const shareScopeNamesToInitialize = [];
|
|
3224
|
+
for (const shareScopeName of shareScopeNames) {
|
|
3225
|
+
let initToken = initTokens[shareScopeName];
|
|
3226
|
+
if (!initToken) initToken = initTokens[shareScopeName] = { from: mfName };
|
|
3227
|
+
if (initScope.indexOf(initToken) >= 0) continue;
|
|
3228
|
+
initScope.push(initToken);
|
|
3229
|
+
shareScopeNamesToInitialize.push(shareScopeName);
|
|
3230
|
+
}
|
|
3231
|
+
if (shareScopeNamesToInitialize.length === 0) return;` : `var initToken = initTokens[shareScopeName];
|
|
3163
3232
|
if (!initToken)
|
|
3164
3233
|
initToken = initTokens[shareScopeName] = { from: mfName };
|
|
3165
3234
|
if (initScope.indexOf(initToken) >= 0) return;
|
|
3166
|
-
initScope.push(initToken)
|
|
3235
|
+
initScope.push(initToken);`}
|
|
3167
3236
|
${normalizeRuntimeShareCode}
|
|
3168
3237
|
const __browserPlugins = [${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => `${item[0]}(${item[2]})`).join(", ")}];
|
|
3169
3238
|
const __ssrPlugins = typeof globalThis.window === 'undefined'
|
|
@@ -3184,7 +3253,10 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3184
3253
|
plugins: [__mfSharePinLifecyclePlugin(), ${hasTreeShakingShared ? "__mfTreeShakingSnapshotPlugin()," : ""} ...__browserPlugins, ...__ssrPlugins],
|
|
3185
3254
|
${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
|
|
3186
3255
|
});
|
|
3187
|
-
|
|
3256
|
+
${hasMultipleShareScopes ? `for (const shareScopeName of shareScopeNamesToInitialize) {
|
|
3257
|
+
const scopeShare = getShareScope(shareScopeName);
|
|
3258
|
+
initRes.initShareScopeMap(shareScopeName, scopeShare);
|
|
3259
|
+
}` : `initRes.initShareScopeMap('${options.shareScope}', shared);`}
|
|
3188
3260
|
function __mfSharePinLifecyclePlugin() {
|
|
3189
3261
|
return {
|
|
3190
3262
|
name: "vite-share-pin-lifecycle-plugin",
|
|
@@ -3232,7 +3304,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3232
3304
|
if (!versionMap || versionMap[version] !== currentProvider) return undefined;
|
|
3233
3305
|
const pinnedProvider = Object.assign({}, provider, {
|
|
3234
3306
|
version: provider.version ?? version,
|
|
3235
|
-
scope: provider.scope ?? currentProvider?.scope ??
|
|
3307
|
+
scope: provider.scope ?? currentProvider?.scope ?? ${JSON.stringify(hasMultipleShareScopes ? options.shareScope : [options.shareScope])},
|
|
3236
3308
|
strategy: 'loaded-first'
|
|
3237
3309
|
});
|
|
3238
3310
|
const providerFrom = provider.from;
|
|
@@ -3440,7 +3512,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3440
3512
|
usedShare.scope
|
|
3441
3513
|
);
|
|
3442
3514
|
if (__mfReadSharedCache(__mfModuleCache.share, usedCacheDescriptor) !== undefined) return;
|
|
3443
|
-
const liveVersionMap = shared[pkg];
|
|
3515
|
+
const liveVersionMap = ${hasMultipleShareScopes ? "getShareVersions(pkg, usedShare)" : "shared[pkg]"};
|
|
3444
3516
|
const liveProvider = liveVersionMap?.[version];
|
|
3445
3517
|
if (providerEntry.registered && !__mfMatchesSharedProvider(liveProvider, provider)) return;
|
|
3446
3518
|
let loadedShare;
|
|
@@ -3526,8 +3598,8 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3526
3598
|
const resolvedExternalProvider = __mfResolveExternalSharedProvider(
|
|
3527
3599
|
federationInstances,
|
|
3528
3600
|
scopeRoot,
|
|
3529
|
-
shared,
|
|
3530
|
-
'${options.shareScope}',
|
|
3601
|
+
${hasMultipleShareScopes ? "getShareScope(getShareScopeName(pkg, usedShare))" : "shared"},
|
|
3602
|
+
${hasMultipleShareScopes ? "getShareScopeName(pkg, usedShare)" : `'${options.shareScope}'`},
|
|
3531
3603
|
pkg,
|
|
3532
3604
|
providerEntry,
|
|
3533
3605
|
selectedExternalProvider,
|
|
@@ -3549,7 +3621,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3549
3621
|
if (cachedShare !== undefined && cachedShareOwner !== mfName) return;
|
|
3550
3622
|
// Registration can replace an unloaded same-version root provider in-place.
|
|
3551
3623
|
// Pin the chosen provider while loadShare() runs its implicit registration.
|
|
3552
|
-
const liveVersionMap = shared[pkg];
|
|
3624
|
+
const liveVersionMap = ${hasMultipleShareScopes ? "getShareVersions(pkg, usedShare)" : "shared[pkg]"};
|
|
3553
3625
|
const liveProvider = liveVersionMap?.[version];
|
|
3554
3626
|
if (
|
|
3555
3627
|
providerEntry.registered &&
|
|
@@ -3631,7 +3703,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3631
3703
|
await __mfBridgeExternalSharedProvider(
|
|
3632
3704
|
pkg,
|
|
3633
3705
|
usedShare,
|
|
3634
|
-
shared[pkg],
|
|
3706
|
+
${hasMultipleShareScopes ? "getShareVersions(pkg, usedShare)" : "shared[pkg]"},
|
|
3635
3707
|
initialShared[pkg],
|
|
3636
3708
|
undefined
|
|
3637
3709
|
);
|
|
@@ -3641,9 +3713,10 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3641
3713
|
const globalVersionsByPackage = Object.create(null);
|
|
3642
3714
|
if (allInstances) {
|
|
3643
3715
|
for (const [, scopes] of Object.entries(allInstances)) {
|
|
3644
|
-
const
|
|
3645
|
-
|
|
3646
|
-
|
|
3716
|
+
for (const scopeName of shareScopeNames) {
|
|
3717
|
+
const scopeShare = scopes?.[scopeName];
|
|
3718
|
+
if (!scopeShare) continue;
|
|
3719
|
+
for (const [pkg, versionMap] of Object.entries(scopeShare)) {
|
|
3647
3720
|
const usedShare = usedShared?.[pkg];
|
|
3648
3721
|
const passedVersions = initialShared[pkg];
|
|
3649
3722
|
const bridgeSelection = bridgeSelections.get(pkg);
|
|
@@ -3664,6 +3737,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3664
3737
|
if (provider === usedShare || (usedShare.from && provider.from === usedShare.from)) continue;
|
|
3665
3738
|
if (globalVersions[version] === undefined) globalVersions[version] = provider;
|
|
3666
3739
|
}
|
|
3740
|
+
}
|
|
3667
3741
|
}
|
|
3668
3742
|
}
|
|
3669
3743
|
}
|
|
@@ -3687,7 +3761,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
3687
3761
|
: __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor);
|
|
3688
3762
|
if (share.shareConfig?.import !== false || cachedShare !== undefined) return;
|
|
3689
3763
|
${normalizeRuntimeShareCode}
|
|
3690
|
-
const versionMap = shared?.[pkg];
|
|
3764
|
+
const versionMap = ${hasMultipleShareScopes ? "getShareVersions(pkg, share)" : "shared?.[pkg]"};
|
|
3691
3765
|
const provider = __mfSelectSharedProvider(
|
|
3692
3766
|
versionMap,
|
|
3693
3767
|
pkg,
|
|
@@ -3861,7 +3935,7 @@ function getRemoteVirtualModule(remote, command, enableSsrInit = false, consumer
|
|
|
3861
3935
|
const { shareStrategy } = getNormalizeModuleFederationOptions();
|
|
3862
3936
|
const cacheKey = `${remote}__${command}__${shareStrategy}__${consumer}__${enableSsrInit ? "ssr-init" : "no-ssr-init"}`;
|
|
3863
3937
|
if (!cacheRemoteMap[cacheKey]) {
|
|
3864
|
-
cacheRemoteMap[cacheKey] = new VirtualModule(remote
|
|
3938
|
+
cacheRemoteMap[cacheKey] = new VirtualModule(consumer === "unified" ? remote : `${remote}__mf_consumer__${consumer}`, LOAD_REMOTE_TAG, ".js");
|
|
3865
3939
|
cacheRemoteMap[cacheKey].writeSync(generateRemotes(remote, command, enableSsrInit, consumer));
|
|
3866
3940
|
}
|
|
3867
3941
|
return cacheRemoteMap[cacheKey];
|
|
@@ -3904,9 +3978,24 @@ function shouldIncludeDeferredProxy(initMode, consumer, eagerLoadClientRemote, d
|
|
|
3904
3978
|
function getRemoteModuleRuntimeHelpers() {
|
|
3905
3979
|
return `
|
|
3906
3980
|
function __mfUnwrapRemoteDefault(mod) {
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3981
|
+
let value = mod;
|
|
3982
|
+
// A federated expose can pass through more than one ESM/CJS namespace
|
|
3983
|
+
// wrapper (notably with React/Preact lazy imports). Keep unwrapping
|
|
3984
|
+
// explicit default namespaces until the actual component is reached.
|
|
3985
|
+
const seen = new Set();
|
|
3986
|
+
while (value != null && typeof value === "object" && !seen.has(value)) {
|
|
3987
|
+
seen.add(value);
|
|
3988
|
+
if (value.__esModule && value.default != null) {
|
|
3989
|
+
value = value.default;
|
|
3990
|
+
continue;
|
|
3991
|
+
}
|
|
3992
|
+
if (!value.__esModule && value.default != null) {
|
|
3993
|
+
value = value.default;
|
|
3994
|
+
continue;
|
|
3995
|
+
}
|
|
3996
|
+
break;
|
|
3997
|
+
}
|
|
3998
|
+
return value;
|
|
3910
3999
|
}
|
|
3911
4000
|
let __mfDefaultExport;
|
|
3912
4001
|
function __mfSyncDefaultExport() {
|
|
@@ -4210,9 +4299,10 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
4210
4299
|
const blockEnd = body.lastIndexOf("}");
|
|
4211
4300
|
if (blockStart === -1 || blockEnd <= blockStart) return scriptTag;
|
|
4212
4301
|
return `<script>${body.slice(0, blockStart + 1) + `
|
|
4302
|
+
const __mfCurrentScript = document.currentScript;
|
|
4213
4303
|
(async () => {
|
|
4214
4304
|
await import(${JSON.stringify(initPath)}).then(({ initHost }) => initHost());
|
|
4215
|
-
` + body.slice(blockStart + 1, blockEnd) + `
|
|
4305
|
+
` + body.slice(blockStart + 1, blockEnd).replaceAll("document.currentScript", "__mfCurrentScript") + `
|
|
4216
4306
|
})();
|
|
4217
4307
|
` + body.slice(blockEnd)}<\/script>`;
|
|
4218
4308
|
});
|
|
@@ -5521,15 +5611,25 @@ function generateRemoteEntrySSR(options) {
|
|
|
5521
5611
|
const initToken = { from: ${JSON.stringify(options.name)} };
|
|
5522
5612
|
if (initScope.indexOf(initToken) >= 0) return;
|
|
5523
5613
|
initScope.push(initToken);
|
|
5524
|
-
|
|
5614
|
+
const shareScopeNames = Array.isArray(${JSON.stringify(options.shareScope)})
|
|
5615
|
+
? ${JSON.stringify(options.shareScope)}
|
|
5616
|
+
: [${JSON.stringify(options.shareScope)}];
|
|
5525
5617
|
try {
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5618
|
+
for (const scopeName of shareScopeNames) {
|
|
5619
|
+
try {
|
|
5620
|
+
const scopeShare = Array.isArray(${JSON.stringify(options.shareScope)}) ? (shared?.[scopeName] || {}) : shared;
|
|
5621
|
+
initRes.initShareScopeMap(scopeName, scopeShare);
|
|
5622
|
+
await Promise.all(
|
|
5623
|
+
await initRes.initializeSharing(scopeName, {
|
|
5624
|
+
strategy: ${JSON.stringify(options.shareStrategy ?? "version-first")},
|
|
5625
|
+
from: 'build',
|
|
5626
|
+
initScope,
|
|
5627
|
+
})
|
|
5628
|
+
);
|
|
5629
|
+
} catch (e) {
|
|
5630
|
+
console.error('[Module Federation SSR]', e);
|
|
5631
|
+
}
|
|
5632
|
+
}
|
|
5533
5633
|
} catch (e) {
|
|
5534
5634
|
console.error('[Module Federation SSR]', e);
|
|
5535
5635
|
}
|
|
@@ -6114,7 +6214,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
6114
6214
|
},
|
|
6115
6215
|
async buildStart() {
|
|
6116
6216
|
await refreshExposeRemoteDependencies(this);
|
|
6117
|
-
if (_command !== "build") return;
|
|
6217
|
+
if (_command !== "build" || hasPackageDependency("@tanstack/react-start", root)) return;
|
|
6118
6218
|
for (const expose of Object.values(options.exposes)) {
|
|
6119
6219
|
const resolved = await this.resolve(expose.import);
|
|
6120
6220
|
if (resolved) this.emitFile({
|
|
@@ -6966,15 +7066,22 @@ function isPathWithinAllowedDirectories(filePath, allowedDirectories) {
|
|
|
6966
7066
|
return allowedDirectories.some((directory) => isPathWithinDirectory(filePath, directory));
|
|
6967
7067
|
}
|
|
6968
7068
|
function isSafeRunnerFetchModuleId(id, config) {
|
|
6969
|
-
if (typeof id !== "string" || !id
|
|
6970
|
-
const
|
|
6971
|
-
|
|
6972
|
-
if (
|
|
7069
|
+
if (typeof id !== "string" || !id) return false;
|
|
7070
|
+
const rawDecoded = decodeViteId(id);
|
|
7071
|
+
const decoded = rawDecoded.replace(/^\0+/, "");
|
|
7072
|
+
if (!decoded || rawDecoded.startsWith("\0") || decoded.startsWith("virtual:")) return !!decoded;
|
|
7073
|
+
if (decoded.startsWith("file://")) try {
|
|
7074
|
+
const filePath = decodeURIComponent(new URL(decoded).pathname);
|
|
7075
|
+
return path$1.isAbsolute(filePath) && isPathWithinAllowedDirectories(filePath, getRunnerAllowedDirectories(config));
|
|
7076
|
+
} catch {
|
|
7077
|
+
return false;
|
|
7078
|
+
}
|
|
7079
|
+
if (/^(?:https?|data|blob|javascript):/i.test(decoded) || decoded.startsWith("//")) return false;
|
|
6973
7080
|
const cleanId = decodeRunnerFilePath(stripQueryAndHash(decoded));
|
|
6974
7081
|
if (!cleanId || hasRelativeTraversal(cleanId)) return false;
|
|
6975
7082
|
const allowedDirectories = getRunnerAllowedDirectories(config);
|
|
6976
7083
|
if (cleanId.startsWith(VITE_FS_PREFIX)) {
|
|
6977
|
-
const fsPath = cleanId.slice(5)
|
|
7084
|
+
const fsPath = `/${cleanId.slice(5)}`;
|
|
6978
7085
|
return path$1.isAbsolute(fsPath) && isPathWithinAllowedDirectories(fsPath, allowedDirectories);
|
|
6979
7086
|
}
|
|
6980
7087
|
if (path$1.isAbsolute(cleanId)) {
|
|
@@ -7591,8 +7698,8 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
7591
7698
|
name: "module-federation:optimize-shared-resolver",
|
|
7592
7699
|
load(id) {
|
|
7593
7700
|
if (id !== "module-federation:optimized-require-react") return;
|
|
7594
|
-
const
|
|
7595
|
-
const source = JSON.stringify(
|
|
7701
|
+
const loadSharePath = getLoadShareModulePath("react", isRolldown);
|
|
7702
|
+
const source = JSON.stringify(loadSharePath);
|
|
7596
7703
|
return "import * as __mfShared from " + source + ";\nexport * from " + source + ";\nexport default __mfShared.default ?? __mfShared;";
|
|
7597
7704
|
},
|
|
7598
7705
|
resolveId(source, importer, options) {
|
|
@@ -8105,6 +8212,11 @@ function federation(mfUserOptions) {
|
|
|
8105
8212
|
if (resolvedTarget === "node" && !("FEDERATION_OPTIMIZE_NO_SNAPSHOT_PLUGIN" in config.define)) config.define["FEDERATION_OPTIMIZE_NO_SNAPSHOT_PLUGIN"] = "true";
|
|
8106
8213
|
if (options.target && "ENV_TARGET" in config.define && config.define["ENV_TARGET"] !== JSON.stringify(options.target)) mfWarn(`ENV_TARGET define (${config.define["ENV_TARGET"]}) differs from target option ("${options.target}"). ENV_TARGET will not be overridden.`);
|
|
8107
8214
|
},
|
|
8215
|
+
configResolved(config) {
|
|
8216
|
+
if (!hasPackageDependency("nitro")) return;
|
|
8217
|
+
const prematureExit = config.plugins.find((plugin) => plugin.name === "tanstack-build-exit");
|
|
8218
|
+
if (prematureExit) prematureExit.closeBundle = void 0;
|
|
8219
|
+
},
|
|
8108
8220
|
configEnvironment(name, config) {
|
|
8109
8221
|
if (!(config.consumer === "server" || name === "ssr" || name === "server" || config.build?.ssr === true)) return;
|
|
8110
8222
|
const isAstro = hasPackageDependency("astro");
|
|
@@ -1,14 +1,38 @@
|
|
|
1
1
|
//#region src/utils/fetchWithTimeout.ts
|
|
2
2
|
const DEFAULT_SSR_FETCH_TIMEOUT_MS = 1e4;
|
|
3
|
+
function getFetchUrl(input) {
|
|
4
|
+
const raw = typeof input === "string" || input instanceof URL ? String(input) : input.url;
|
|
5
|
+
return new URL(raw);
|
|
6
|
+
}
|
|
7
|
+
function getSecureFetchUrl(input) {
|
|
8
|
+
const url = getFetchUrl(input);
|
|
9
|
+
const isLoopback = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
|
|
10
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && isLoopback)) throw new TypeError(`Refusing to fetch SSR resource over an insecure connection: ${url}`);
|
|
11
|
+
return url;
|
|
12
|
+
}
|
|
3
13
|
/** Fetch with a bounded wait. Set timeoutMs to 0 to disable the timeout. */
|
|
4
|
-
function fetchWithTimeout(input, init = {}, timeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS) {
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
async function fetchWithTimeout(input, init = {}, timeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS) {
|
|
15
|
+
const inputUrl = getSecureFetchUrl(input);
|
|
16
|
+
const request = (target) => {
|
|
17
|
+
const requestInit = {
|
|
18
|
+
...init,
|
|
19
|
+
redirect: "error"
|
|
20
|
+
};
|
|
21
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) return fetch(target.href, requestInit);
|
|
22
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
23
|
+
const signal = init.signal ? AbortSignal.any([init.signal, timeoutSignal]) : timeoutSignal;
|
|
24
|
+
return fetch(target.href, {
|
|
25
|
+
...requestInit,
|
|
26
|
+
signal
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
try {
|
|
30
|
+
return await request(inputUrl);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (inputUrl.hostname !== "localhost") throw error;
|
|
33
|
+
inputUrl.hostname = "[::1]";
|
|
34
|
+
return request(inputUrl);
|
|
35
|
+
}
|
|
12
36
|
}
|
|
13
37
|
//#endregion
|
|
14
38
|
//#region src/utils/ssrEntryLoader.ts
|
|
@@ -347,6 +371,9 @@ function revalidate(remoteEntryUrl) {
|
|
|
347
371
|
}
|
|
348
372
|
const tempFileCache = /* @__PURE__ */ new Map();
|
|
349
373
|
const tempFilePathCache = /* @__PURE__ */ new Map();
|
|
374
|
+
function getSsrTransformContextKey(resolvedShared, shareScopeName) {
|
|
375
|
+
return JSON.stringify([shareScopeName, Object.entries(resolvedShared).sort(([left], [right]) => left.localeCompare(right))]);
|
|
376
|
+
}
|
|
350
377
|
let ssrCacheDirPromise;
|
|
351
378
|
async function getSSRCacheDir() {
|
|
352
379
|
if (!ssrCacheDirPromise) ssrCacheDirPromise = (async () => {
|
|
@@ -402,11 +429,12 @@ function isVitePreloadHelperSpecifier(specifier) {
|
|
|
402
429
|
* a remote redeploy (new manifest → new key) produces new files and bypasses
|
|
403
430
|
* Node's ESM module cache instead of serving the stale build.
|
|
404
431
|
*/
|
|
405
|
-
async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, versionKey = UNVERSIONED, fetchTimeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS) {
|
|
432
|
+
async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, versionKey = UNVERSIONED, fetchTimeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS, contextKey = "default") {
|
|
406
433
|
const cacheKey = JSON.stringify([
|
|
407
434
|
fetchTimeoutMs,
|
|
408
435
|
versionKey,
|
|
409
|
-
url
|
|
436
|
+
url,
|
|
437
|
+
contextKey
|
|
410
438
|
]);
|
|
411
439
|
if (visited.has(url)) return visited.get(url);
|
|
412
440
|
const cached = tempFileCache.get(cacheKey);
|
|
@@ -435,7 +463,7 @@ async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, v
|
|
|
435
463
|
while ((m = relRegex.exec(code)) !== null) if ((m[1].startsWith("./") || m[1].startsWith("../")) && !isVitePreloadHelperSpecifier(m[1])) relImports.push(new URL(m[1], base).href);
|
|
436
464
|
const subMap = /* @__PURE__ */ new Map();
|
|
437
465
|
await Promise.all([...new Set(relImports)].filter((u) => u.startsWith("http://") || u.startsWith("https://")).map(async (u) => {
|
|
438
|
-
const tmpPath = await fetchEsmToTempFile(u, tmpDir, visited, pending, sharedPkgMap, versionKey, fetchTimeoutMs);
|
|
466
|
+
const tmpPath = await fetchEsmToTempFile(u, tmpDir, visited, pending, sharedPkgMap, versionKey, fetchTimeoutMs, contextKey);
|
|
439
467
|
subMap.set(u, `file://${tmpPath}`);
|
|
440
468
|
}));
|
|
441
469
|
code = transformSsrCode(code, base, sharedPkgMap);
|
|
@@ -452,18 +480,21 @@ async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, v
|
|
|
452
480
|
});
|
|
453
481
|
return promise;
|
|
454
482
|
}
|
|
455
|
-
async function fetchEsmGraphToTempFile(url, tmpDir, sharedPkgMap, versionKey = UNVERSIONED, fetchTimeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS) {
|
|
483
|
+
async function fetchEsmGraphToTempFile(url, tmpDir, sharedPkgMap, versionKey = UNVERSIONED, fetchTimeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS, contextKey = "default") {
|
|
456
484
|
const pending = /* @__PURE__ */ new Set();
|
|
457
|
-
const rootFile = await fetchEsmToTempFile(url, tmpDir, /* @__PURE__ */ new Map(), pending, sharedPkgMap, versionKey, fetchTimeoutMs);
|
|
485
|
+
const rootFile = await fetchEsmToTempFile(url, tmpDir, /* @__PURE__ */ new Map(), pending, sharedPkgMap, versionKey, fetchTimeoutMs, contextKey);
|
|
458
486
|
await Promise.all(pending);
|
|
459
487
|
return rootFile;
|
|
460
488
|
}
|
|
461
489
|
async function importTempModule(filePath, versionKey) {
|
|
462
|
-
return await import(
|
|
490
|
+
return await import(
|
|
491
|
+
/* @vite-ignore */
|
|
492
|
+
`${filePath}?v=${encodeURIComponent(versionKey)}`
|
|
493
|
+
);
|
|
463
494
|
}
|
|
464
495
|
let warnedVmUnavailable = false;
|
|
465
496
|
async function tryVmStrategy(ssrEntry, options) {
|
|
466
|
-
const { loadViaVmStrategy, isVmStrategyAvailable } = await import("./ssrVmStrategy-
|
|
497
|
+
const { loadViaVmStrategy, isVmStrategyAvailable } = await import("./ssrVmStrategy-ChF8MB7l.js");
|
|
467
498
|
if (!await isVmStrategyAvailable()) {
|
|
468
499
|
if (!warnedVmUnavailable) {
|
|
469
500
|
warnedVmUnavailable = true;
|
|
@@ -475,7 +506,9 @@ async function tryVmStrategy(ssrEntry, options) {
|
|
|
475
506
|
resolvedShared: options.resolvedShared,
|
|
476
507
|
shareScopeName: options.shareScopeName,
|
|
477
508
|
versionKey: ssrEntry.versionKey,
|
|
478
|
-
fetchTimeoutMs: options.fetchTimeoutMs
|
|
509
|
+
fetchTimeoutMs: options.fetchTimeoutMs,
|
|
510
|
+
cacheContext: options.cacheContext,
|
|
511
|
+
federationInstance: options.federationInstance
|
|
479
512
|
});
|
|
480
513
|
}
|
|
481
514
|
async function loadSSRRemoteEntry(ssrEntry, options) {
|
|
@@ -514,7 +547,7 @@ async function loadSSRRemoteEntry(ssrEntry, options) {
|
|
|
514
547
|
mkdirSync(cacheDir, { recursive: true });
|
|
515
548
|
const sharedPkgMap = new Map(Object.entries(resolvedShared));
|
|
516
549
|
try {
|
|
517
|
-
return await importTempModule(await fetchEsmGraphToTempFile(url, cacheDir, sharedPkgMap, versionKey, options.fetchTimeoutMs), versionKey);
|
|
550
|
+
return await importTempModule(await fetchEsmGraphToTempFile(url, cacheDir, sharedPkgMap, versionKey, options.fetchTimeoutMs, getSsrTransformContextKey(resolvedShared, options.shareScopeName)), versionKey);
|
|
518
551
|
} catch (error) {
|
|
519
552
|
if (isSsrEntryHttpError(error)) throw error;
|
|
520
553
|
return null;
|
|
@@ -535,15 +568,21 @@ function ssrEntryLoaderPlugin(options = {}) {
|
|
|
535
568
|
strategy: options.strategy ?? "temp-file",
|
|
536
569
|
shareScopeName: options.shareScopeName ?? "default",
|
|
537
570
|
maxAgeMs: options.maxAgeMs,
|
|
538
|
-
fetchTimeoutMs: options.fetchTimeoutMs ?? 1e4
|
|
571
|
+
fetchTimeoutMs: options.fetchTimeoutMs ?? 1e4,
|
|
572
|
+
cacheContext: {}
|
|
539
573
|
};
|
|
540
574
|
return {
|
|
541
575
|
name: "mf-vite:ssr-entry-loader",
|
|
542
|
-
async loadEntry({ remoteInfo }) {
|
|
576
|
+
async loadEntry({ remoteInfo, origin }) {
|
|
543
577
|
if (!isNodeServer()) return;
|
|
544
|
-
const
|
|
578
|
+
const loadOptions = origin ? {
|
|
579
|
+
...resolved,
|
|
580
|
+
cacheContext: origin,
|
|
581
|
+
federationInstance: origin
|
|
582
|
+
} : resolved;
|
|
583
|
+
const ssrEntry = await getSSREntry(remoteInfo.entry, loadOptions.maxAgeMs, loadOptions.fetchTimeoutMs);
|
|
545
584
|
if (!ssrEntry) return;
|
|
546
|
-
const mod = await loadSSRRemoteEntry(ssrEntry,
|
|
585
|
+
const mod = await loadSSRRemoteEntry(ssrEntry, loadOptions);
|
|
547
586
|
if (!mod) return;
|
|
548
587
|
return mod;
|
|
549
588
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as neutralizeBrowserPreloadHelpers, o as fetchWithTimeout, t as SsrEntryHttpError } from "./ssrEntryLoader-
|
|
1
|
+
import { n as neutralizeBrowserPreloadHelpers, o as fetchWithTimeout, t as SsrEntryHttpError } from "./ssrEntryLoader-DgsCQOqq.js";
|
|
2
2
|
//#region src/utils/ssrVmStrategy.ts
|
|
3
3
|
/**
|
|
4
4
|
* vm.SourceTextModule strategy for loading remote SSR entries.
|
|
@@ -47,9 +47,13 @@ function getFederationInstances() {
|
|
|
47
47
|
* build-time resolvedShared file map, then plain host import.
|
|
48
48
|
*/
|
|
49
49
|
async function loadBareModule(specifier, options) {
|
|
50
|
-
|
|
50
|
+
const owner = options.federationInstance;
|
|
51
|
+
const instances = owner ? [owner] : getFederationInstances();
|
|
52
|
+
for (const instance of instances) {
|
|
51
53
|
if (typeof instance?.loadShare !== "function") continue;
|
|
52
|
-
|
|
54
|
+
const shared = instance.options?.shared?.[specifier];
|
|
55
|
+
if (!shared) continue;
|
|
56
|
+
if (!(Array.isArray(shared.scope) ? shared.scope : [shared.scope ?? "default"]).includes(options.shareScopeName)) continue;
|
|
53
57
|
try {
|
|
54
58
|
const factory = await instance.loadShare(specifier);
|
|
55
59
|
if (typeof factory === "function") {
|
|
@@ -80,6 +84,23 @@ function createSyntheticModule(vm, specifier, namespace) {
|
|
|
80
84
|
}
|
|
81
85
|
const httpModuleCache = /* @__PURE__ */ new Map();
|
|
82
86
|
const namespaceCache = /* @__PURE__ */ new Map();
|
|
87
|
+
const contextIds = /* @__PURE__ */ new WeakMap();
|
|
88
|
+
let nextContextId = 1;
|
|
89
|
+
function getContextId(context) {
|
|
90
|
+
let id = contextIds.get(context);
|
|
91
|
+
if (id === void 0) {
|
|
92
|
+
id = nextContextId++;
|
|
93
|
+
contextIds.set(context, id);
|
|
94
|
+
}
|
|
95
|
+
return id;
|
|
96
|
+
}
|
|
97
|
+
function getVmCacheContextKey(options) {
|
|
98
|
+
return JSON.stringify([
|
|
99
|
+
getContextId(options.cacheContext),
|
|
100
|
+
options.shareScopeName,
|
|
101
|
+
Object.entries(options.resolvedShared).sort(([left], [right]) => left.localeCompare(right))
|
|
102
|
+
]);
|
|
103
|
+
}
|
|
83
104
|
function getBodyPreview(body) {
|
|
84
105
|
return body.slice(0, 240).replace(/\s+/g, " ").trim();
|
|
85
106
|
}
|
|
@@ -100,6 +121,7 @@ function resolveSpecifierUrl(specifier, referencerUrl) {
|
|
|
100
121
|
}
|
|
101
122
|
function getHttpModule(vm, url, options) {
|
|
102
123
|
const cacheKey = JSON.stringify([
|
|
124
|
+
getVmCacheContextKey(options),
|
|
103
125
|
options.fetchTimeoutMs ?? 1e4,
|
|
104
126
|
options.versionKey,
|
|
105
127
|
url
|
|
@@ -139,7 +161,7 @@ async function importDynamically(vm, specifier, referencingModule, options) {
|
|
|
139
161
|
async function loadViaVmStrategy(entryUrl, options) {
|
|
140
162
|
const vm = await getVmApi();
|
|
141
163
|
if (!vm) return null;
|
|
142
|
-
const cacheKey = `${options.versionKey}::${entryUrl}`;
|
|
164
|
+
const cacheKey = `${getVmCacheContextKey(options)}::${options.versionKey}::${entryUrl}`;
|
|
143
165
|
if (!namespaceCache.has(cacheKey)) namespaceCache.set(cacheKey, (async () => {
|
|
144
166
|
const entryModule = await getHttpModule(vm, entryUrl, options);
|
|
145
167
|
const linker = (specifier, referencingModule) => linkModule(vm, specifier, referencingModule, options);
|
|
@@ -109,9 +109,11 @@ interface SsrEntryLoaderOptions {
|
|
|
109
109
|
declare function ssrEntryLoaderPlugin(options?: SsrEntryLoaderOptions): {
|
|
110
110
|
name: string;
|
|
111
111
|
loadEntry({
|
|
112
|
-
remoteInfo
|
|
112
|
+
remoteInfo,
|
|
113
|
+
origin
|
|
113
114
|
}: {
|
|
114
115
|
remoteInfo: RemoteInfo;
|
|
116
|
+
origin?: object;
|
|
115
117
|
}): Promise<{
|
|
116
118
|
init: unknown;
|
|
117
119
|
get: unknown;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as ssrEntryLoaderPlugin, n as neutralizeBrowserPreloadHelpers, r as revalidate, t as SsrEntryHttpError } from "../ssrEntryLoader-
|
|
1
|
+
import { i as ssrEntryLoaderPlugin, n as neutralizeBrowserPreloadHelpers, r as revalidate, t as SsrEntryHttpError } from "../ssrEntryLoader-DgsCQOqq.js";
|
|
2
2
|
export { SsrEntryHttpError, ssrEntryLoaderPlugin as default, neutralizeBrowserPreloadHelpers, revalidate };
|