@module-federation/vite 1.16.8 → 1.16.10
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 +8 -2
- package/lib/index.js +364 -118
- package/lib/{pluginDts-Cpmdbbr0.js → pluginDts-CrSsDUnT.js} +2 -1
- package/lib/utils/ssrEntryLoader.js +114 -40
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@module-federation/vite)
|
|
4
4
|
|
|
5
|
+
## Vite and VoidZero recommend this plugin
|
|
6
|
+
|
|
7
|
+
[Read the announcement](https://www.linkedin.com/posts/voidzero_github-module-federationvite-vite-plugin-activity-7449452398202241024-JyAL).
|
|
8
|
+
|
|
5
9
|
## Reason why 🤔
|
|
6
10
|
|
|
7
11
|
[Microservices](https://martinfowler.com/articles/microservices.html) nowadays is a well-known concept and maybe you are using it in your current company.
|
|
@@ -47,7 +51,7 @@ pnpm run multi-example
|
|
|
47
51
|
|
|
48
52
|
## Getting started 🚀
|
|
49
53
|
|
|
50
|
-
[https://module-federation.io/
|
|
54
|
+
[https://module-federation.io/integrations/build-tool/vite](https://module-federation.io/integrations/build-tool/vite)
|
|
51
55
|
|
|
52
56
|
With **@module-federation/vite**, the process becomes delightfully simple, you will only find the differences from a normal Vite configuration.
|
|
53
57
|
|
|
@@ -143,7 +147,9 @@ export default defineConfig({
|
|
|
143
147
|
// Optional parameter that controls where the host initialization script is injected.
|
|
144
148
|
// By default, it is injected into the index.html file.
|
|
145
149
|
// You can set this to "entry" to inject it into the entry script instead.
|
|
146
|
-
//
|
|
150
|
+
// Recommended for SSR hosts without index.html (Nitro, TanStack Start) so
|
|
151
|
+
// initHost() completes before hydrateRoot and @module-federation/bridge-react
|
|
152
|
+
// remotes render on first paint.
|
|
147
153
|
hostInitInjectLocation: "html", // or "entry"
|
|
148
154
|
// Controls whether all CSS assets from the bundle should be added to every exposed module.
|
|
149
155
|
// When false (default), the plugin will not process any CSS assets.
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as mfWarn, a as getIsRolldown, c as getPackageNameFromNodeModulePath, d as isNuxtProjectRoot, f as packageNameDecode, g as createModuleFederationError, h as setPackageDetectionCwd, i as getInstalledPackageJson, l as getSharedCacheKey, m as resolveImportPath, o as getPackageDetectionCwd, p as packageNameEncode, r as getInstalledPackageEntry, s as getPackageName, u as hasPackageDependency, v as normalizePathForImport, y as rebaseImport } from "./pluginDts-
|
|
1
|
+
import { _ as mfWarn, a as getIsRolldown, c as getPackageNameFromNodeModulePath, d as isNuxtProjectRoot, f as packageNameDecode, g as createModuleFederationError, h as setPackageDetectionCwd, i as getInstalledPackageJson, l as getSharedCacheKey, m as resolveImportPath, o as getPackageDetectionCwd, p as packageNameEncode, r as getInstalledPackageEntry, s as getPackageName, u as hasPackageDependency, v as normalizePathForImport, y as rebaseImport } from "./pluginDts-CrSsDUnT.js";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import * as fs$1 from "fs";
|
|
4
4
|
import { existsSync, readFileSync, realpathSync, statSync, writeFileSync } from "fs";
|
|
@@ -171,6 +171,71 @@ function injectEntryScript(html, initSrc) {
|
|
|
171
171
|
return html.replace("<head>", `<head><script type="module" src=${JSON.stringify(src)}><\/script>`);
|
|
172
172
|
}
|
|
173
173
|
//#endregion
|
|
174
|
+
//#region src/utils/pathNormalization.ts
|
|
175
|
+
const COMMON_SHARED_SUBPATHS = {
|
|
176
|
+
react: [
|
|
177
|
+
"react/jsx-runtime",
|
|
178
|
+
"react/jsx-dev-runtime",
|
|
179
|
+
"react/compiler-runtime"
|
|
180
|
+
],
|
|
181
|
+
"react-dom": [
|
|
182
|
+
"react-dom/client",
|
|
183
|
+
"react-dom/server",
|
|
184
|
+
"react-dom/server.browser"
|
|
185
|
+
],
|
|
186
|
+
"solid-js": [
|
|
187
|
+
"solid-js/web",
|
|
188
|
+
"solid-js/store",
|
|
189
|
+
"solid-js/html",
|
|
190
|
+
"solid-js/h"
|
|
191
|
+
],
|
|
192
|
+
zustand: ["zustand/vanilla", "zustand/react"]
|
|
193
|
+
};
|
|
194
|
+
function removeTrailingSlash(value) {
|
|
195
|
+
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
196
|
+
}
|
|
197
|
+
function ensureTrailingSlash(value) {
|
|
198
|
+
return `${removeTrailingSlash(value)}/`;
|
|
199
|
+
}
|
|
200
|
+
function getBasePath$1(base) {
|
|
201
|
+
return removeTrailingSlash(base || "/");
|
|
202
|
+
}
|
|
203
|
+
function isNuxtClientBase(base) {
|
|
204
|
+
return getBasePath$1(base).endsWith("/_nuxt");
|
|
205
|
+
}
|
|
206
|
+
function normalizeNodeModulePath(source) {
|
|
207
|
+
return source.replace(/\\/g, "/").replace(/\?.*$/, "");
|
|
208
|
+
}
|
|
209
|
+
function isNodeModulePath(source) {
|
|
210
|
+
return source.includes("/node_modules/") || source.includes("\\node_modules\\");
|
|
211
|
+
}
|
|
212
|
+
function filterId(id) {
|
|
213
|
+
return typeof id === "string" && !id.includes("\0");
|
|
214
|
+
}
|
|
215
|
+
function getMatchingNodeModuleSubpath(source, candidates) {
|
|
216
|
+
const normalized = normalizeNodeModulePath(source);
|
|
217
|
+
return [...candidates].sort((a, b) => b.length - a.length).find((candidate) => normalized.includes(`/node_modules/${candidate}/`) || normalized.includes(`/node_modules/${candidate}.`));
|
|
218
|
+
}
|
|
219
|
+
function getCommonSharedSubpaths(sharedKey) {
|
|
220
|
+
return COMMON_SHARED_SUBPATHS[removeTrailingSlash(sharedKey)] || [];
|
|
221
|
+
}
|
|
222
|
+
function getCommonSharedSubpathFromNodeModulePath(source, sharedKey) {
|
|
223
|
+
return getMatchingNodeModuleSubpath(source, getCommonSharedSubpaths(removeTrailingSlash(sharedKey)));
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Resolves the public path for remote entries
|
|
227
|
+
* @param options - Module Federation options
|
|
228
|
+
* @param viteBase - Vite's base config value
|
|
229
|
+
* @param originalBase - Original base config before any transformations
|
|
230
|
+
* @returns The resolved public path
|
|
231
|
+
*/
|
|
232
|
+
function resolvePublicPath(options, viteBase, originalBase) {
|
|
233
|
+
if (options.publicPath && options.publicPath !== "auto") return options.publicPath;
|
|
234
|
+
if (!originalBase) return "auto";
|
|
235
|
+
if (viteBase) return ensureTrailingSlash(viteBase);
|
|
236
|
+
return "auto";
|
|
237
|
+
}
|
|
238
|
+
//#endregion
|
|
174
239
|
//#region src/utils/normalizeModuleFederationOptions.ts
|
|
175
240
|
const INTERNAL_NAME_PREFIX = "__mfe_internal__";
|
|
176
241
|
function toInternalModuleFederationName(name) {
|
|
@@ -257,7 +322,9 @@ function getLitExportSubpathShares(sharedName) {
|
|
|
257
322
|
}
|
|
258
323
|
function normalizeShareItem(key, shareItem) {
|
|
259
324
|
const isImportFalse = typeof shareItem === "object" && shareItem.import === false;
|
|
260
|
-
const
|
|
325
|
+
const explicitVersion = typeof shareItem === "object" ? shareItem.version : void 0;
|
|
326
|
+
const inferredVersion = typeof shareItem === "object" ? inferVersionFromRequiredVersion(shareItem.requiredVersion) : void 0;
|
|
327
|
+
const version = explicitVersion || searchPackageVersion(key) || inferredVersion;
|
|
261
328
|
if (typeof shareItem === "string") return {
|
|
262
329
|
name: shareItem,
|
|
263
330
|
version,
|
|
@@ -282,6 +349,11 @@ function normalizeShareItem(key, shareItem) {
|
|
|
282
349
|
}
|
|
283
350
|
};
|
|
284
351
|
}
|
|
352
|
+
function normalizeSharedKey(key) {
|
|
353
|
+
if (!key.endsWith("/")) return key;
|
|
354
|
+
const baseKey = key.slice(0, -1);
|
|
355
|
+
return getCommonSharedSubpaths(baseKey).length > 0 ? baseKey : key;
|
|
356
|
+
}
|
|
285
357
|
function normalizeShared(shared) {
|
|
286
358
|
explicitSharedKeys = /* @__PURE__ */ new Set();
|
|
287
359
|
if (!shared) {
|
|
@@ -306,16 +378,18 @@ function normalizeShared(shared) {
|
|
|
306
378
|
const sourceEntries = [];
|
|
307
379
|
if (Array.isArray(shared)) shared.forEach((key) => {
|
|
308
380
|
if (isModuleFederationRuntimePackage(key)) return;
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
381
|
+
const normalizedKey = normalizeSharedKey(key);
|
|
382
|
+
result[normalizedKey] = normalizeShareItem(normalizedKey, normalizedKey);
|
|
383
|
+
explicitSharedKeys.add(normalizedKey);
|
|
384
|
+
sourceEntries.push([normalizedKey, normalizedKey]);
|
|
312
385
|
});
|
|
313
386
|
else if (typeof shared === "object") Object.keys(shared).forEach((key) => {
|
|
314
387
|
if (isModuleFederationRuntimePackage(key)) return;
|
|
388
|
+
const normalizedKey = normalizeSharedKey(key);
|
|
315
389
|
const value = shared[key];
|
|
316
|
-
result[
|
|
317
|
-
explicitSharedKeys.add(
|
|
318
|
-
sourceEntries.push([
|
|
390
|
+
result[normalizedKey] = normalizeShareItem(normalizedKey, value);
|
|
391
|
+
explicitSharedKeys.add(normalizedKey);
|
|
392
|
+
sourceEntries.push([normalizedKey, value]);
|
|
319
393
|
});
|
|
320
394
|
sourceEntries.forEach(([key, value]) => {
|
|
321
395
|
for (const subpathShare of getLitExportSubpathShares(key)) {
|
|
@@ -723,6 +797,19 @@ globalThis[__mfCacheGlobalKey] ||= { share: {}, remote: {} };
|
|
|
723
797
|
globalThis[__mfCacheGlobalKey].share ||= {};
|
|
724
798
|
globalThis[__mfCacheGlobalKey].remote ||= {};
|
|
725
799
|
const __mfModuleCache = globalThis[__mfCacheGlobalKey];
|
|
800
|
+
for (const __mfShareKey of Object.keys(__mfModuleCache.share)) {
|
|
801
|
+
if (__mfShareKey.startsWith("default:")) {
|
|
802
|
+
const __mfLegacyShareKey = __mfShareKey.slice("default:".length);
|
|
803
|
+
if (__mfModuleCache.share[__mfLegacyShareKey] === undefined) {
|
|
804
|
+
__mfModuleCache.share[__mfLegacyShareKey] = __mfModuleCache.share[__mfShareKey];
|
|
805
|
+
}
|
|
806
|
+
} else if (!__mfShareKey.includes(":")) {
|
|
807
|
+
const __mfDefaultShareKey = "default:" + __mfShareKey;
|
|
808
|
+
if (__mfModuleCache.share[__mfDefaultShareKey] === undefined) {
|
|
809
|
+
__mfModuleCache.share[__mfDefaultShareKey] = __mfModuleCache.share[__mfShareKey];
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
726
813
|
`;
|
|
727
814
|
}
|
|
728
815
|
function getRuntimeInitPromiseBootstrapCode(enableSsrInit = false) {
|
|
@@ -985,6 +1072,49 @@ function isWorkspacePackageEntry(pkg, resolved) {
|
|
|
985
1072
|
fromResolvedEntry: resolved
|
|
986
1073
|
});
|
|
987
1074
|
}
|
|
1075
|
+
function getWorkspacePackageJson(pkg) {
|
|
1076
|
+
const resolved = getLocalProviderImportPath(pkg) || getProjectResolvedImportPath(pkg);
|
|
1077
|
+
if (!isWorkspacePackageEntry(pkg, resolved)) return;
|
|
1078
|
+
return getInstalledPackageJson(pkg, {
|
|
1079
|
+
packageName: getPackageName(pkg),
|
|
1080
|
+
fromResolvedEntry: resolved
|
|
1081
|
+
})?.packageJson;
|
|
1082
|
+
}
|
|
1083
|
+
function getDependencyNames(packageJson) {
|
|
1084
|
+
if (!packageJson) return [];
|
|
1085
|
+
const names = /* @__PURE__ */ new Set();
|
|
1086
|
+
for (const field of [
|
|
1087
|
+
"dependencies",
|
|
1088
|
+
"peerDependencies",
|
|
1089
|
+
"optionalDependencies"
|
|
1090
|
+
]) {
|
|
1091
|
+
const deps = packageJson[field];
|
|
1092
|
+
if (!deps || typeof deps !== "object") continue;
|
|
1093
|
+
for (const dep of Object.keys(deps)) names.add(dep);
|
|
1094
|
+
}
|
|
1095
|
+
return Array.from(names);
|
|
1096
|
+
}
|
|
1097
|
+
function isWorkspaceSingletonConsumedByPeer(pkg) {
|
|
1098
|
+
const shared = getNormalizeModuleFederationOptions()?.shared || {};
|
|
1099
|
+
const sharedKeyByPackageName = /* @__PURE__ */ new Map();
|
|
1100
|
+
Object.entries(shared).filter(([, item]) => item.shareConfig.singleton === true).forEach(([key]) => {
|
|
1101
|
+
const packageName = getPackageName(key);
|
|
1102
|
+
if (!sharedKeyByPackageName.get(packageName) || key === packageName) sharedKeyByPackageName.set(packageName, key);
|
|
1103
|
+
});
|
|
1104
|
+
const reachesPkg = (current, seen) => {
|
|
1105
|
+
const packageJson = getWorkspacePackageJson(current);
|
|
1106
|
+
for (const dependency of getDependencyNames(packageJson)) {
|
|
1107
|
+
const sharedDependency = sharedKeyByPackageName.get(dependency);
|
|
1108
|
+
if (!sharedDependency) continue;
|
|
1109
|
+
if (sharedDependency === pkg) return true;
|
|
1110
|
+
if (seen.has(sharedDependency)) continue;
|
|
1111
|
+
seen.add(sharedDependency);
|
|
1112
|
+
if (reachesPkg(sharedDependency, seen)) return true;
|
|
1113
|
+
}
|
|
1114
|
+
return false;
|
|
1115
|
+
};
|
|
1116
|
+
return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && reachesPkg(sharedPkg, new Set([sharedPkg])));
|
|
1117
|
+
}
|
|
988
1118
|
function tryResolveImportFromPackageRoot(pkg, root) {
|
|
989
1119
|
try {
|
|
990
1120
|
return createRequire$1(pathToFileURL(path$1.join(root, "package.json"))).resolve(pkg);
|
|
@@ -1114,26 +1244,46 @@ function materializeCachedLoadShareModule(options) {
|
|
|
1114
1244
|
options.addUsedShares(pkg);
|
|
1115
1245
|
options.writeLocalSharedImportMap();
|
|
1116
1246
|
}
|
|
1247
|
+
function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheKey) {
|
|
1248
|
+
const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.join(", ")} } from ${escapeGeneratedStringLiteral(importSource)};` : "";
|
|
1249
|
+
return `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(importSource)};
|
|
1250
|
+
let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}];
|
|
1251
|
+
if (exportModule === undefined) {
|
|
1252
|
+
Promise.resolve().then(() => {
|
|
1253
|
+
if (__mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] === undefined) {
|
|
1254
|
+
__mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] = __mfNormalizeShareModule(__mfLocalShare);
|
|
1255
|
+
}
|
|
1256
|
+
});
|
|
1257
|
+
exportModule = __mfLocalShare;
|
|
1258
|
+
}
|
|
1259
|
+
const __mf_default = exportModule.default ?? exportModule;
|
|
1260
|
+
export { __mf_default as default };${namedExportLine}`;
|
|
1261
|
+
}
|
|
1117
1262
|
function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheKey, eagerLocalFallback) {
|
|
1118
1263
|
const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
|
|
1119
1264
|
const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
|
|
1120
1265
|
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;";
|
|
1121
1266
|
const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
|
|
1267
|
+
const applyLocalFallback = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
1268
|
+
__mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] = exportModule;
|
|
1269
|
+
__mfApplyLazyShareExports(exportModule);`;
|
|
1122
1270
|
const body = `${declarations}
|
|
1123
1271
|
const __mfApplyLazyShareExports = (mod) => {
|
|
1124
1272
|
${assignments}
|
|
1125
1273
|
};
|
|
1126
1274
|
let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}];
|
|
1127
1275
|
if (exportModule === undefined) {
|
|
1128
|
-
${eagerLocalFallback ? `
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1276
|
+
${eagerLocalFallback ? applyLocalFallback : `if (import.meta.env.SSR) {
|
|
1277
|
+
${applyLocalFallback}
|
|
1278
|
+
} else {
|
|
1279
|
+
initPromise.then(() =>
|
|
1280
|
+
import(${escapeGeneratedStringLiteral(importSource)}).then((mod) => {
|
|
1281
|
+
exportModule = __mfNormalizeShareModule(mod);
|
|
1282
|
+
__mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] = exportModule;
|
|
1283
|
+
__mfApplyLazyShareExports(exportModule);
|
|
1284
|
+
})
|
|
1285
|
+
);
|
|
1286
|
+
}`}
|
|
1137
1287
|
} else {
|
|
1138
1288
|
__mfApplyLazyShareExports(exportModule);
|
|
1139
1289
|
}
|
|
@@ -1141,6 +1291,16 @@ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cache
|
|
|
1141
1291
|
return eagerLocalFallback ? `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(importSource)};
|
|
1142
1292
|
${body}` : body;
|
|
1143
1293
|
}
|
|
1294
|
+
const WORKSPACE_SINGLETON_SSR_LOCAL_SHARE = "__mfNormalizeShareModule(__mfLocalShare)";
|
|
1295
|
+
function prependWorkspaceSingletonSsrImport(code) {
|
|
1296
|
+
if (!code.includes("if (import.meta.env.SSR)")) return code;
|
|
1297
|
+
if (!code.includes(WORKSPACE_SINGLETON_SSR_LOCAL_SHARE)) return code;
|
|
1298
|
+
if (code.includes("import * as __mfLocalShare")) return code;
|
|
1299
|
+
const importMatch = code.match(/initPromise\.then\(\(\)\s*=>\s*\n\s*import\((["'])(.+?)\1\)\.then\(\(mod\)\s*=>\s*\{[\s\S]*?__mfApplyLazyShareExports/);
|
|
1300
|
+
if (!importMatch) return code;
|
|
1301
|
+
const quote = importMatch[1];
|
|
1302
|
+
return `import * as __mfLocalShare from ${quote}${importMatch[2]}${quote};\n${code}`;
|
|
1303
|
+
}
|
|
1144
1304
|
function generateDeferredHostProvidedExports(namedExports, pkg, cacheKey) {
|
|
1145
1305
|
const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
|
|
1146
1306
|
const declarations = ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ");
|
|
@@ -1207,11 +1367,13 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
|
1207
1367
|
const isWorkspacePackage = isWorkspacePackageEntry(pkg, localProviderPath) || isWorkspacePackageEntry(pkg, concreteSharedImportSource);
|
|
1208
1368
|
const lazyLocalFallbackSource = concreteSharedImportSource || localProviderPath || sharedImportSource;
|
|
1209
1369
|
const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
|
|
1210
|
-
const
|
|
1370
|
+
const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
|
|
1371
|
+
const usesEagerWorkspaceFallback = isWorkspaceSingleton && isWorkspaceSingletonConsumedByPeer(pkg);
|
|
1211
1372
|
const namedExports = getSharedNamedExports(pkg, shareItem);
|
|
1212
1373
|
let exportLine;
|
|
1213
1374
|
let initBlock = "";
|
|
1214
|
-
if (
|
|
1375
|
+
if (usesEagerWorkspaceFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheKey);
|
|
1376
|
+
else if (isWorkspaceSingleton) {
|
|
1215
1377
|
importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
|
|
1216
1378
|
exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheKey, command !== "build");
|
|
1217
1379
|
} else if (namedExports.length > 0) {
|
|
@@ -1234,9 +1396,9 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
|
1234
1396
|
initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
1235
1397
|
__mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] = exportModule;`;
|
|
1236
1398
|
}
|
|
1237
|
-
const prebuildImportLine =
|
|
1399
|
+
const prebuildImportLine = isWorkspaceSingleton || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
|
|
1238
1400
|
const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
1239
|
-
const moduleBody =
|
|
1401
|
+
const moduleBody = isWorkspaceSingleton ? `
|
|
1240
1402
|
${prebuildImportLine}
|
|
1241
1403
|
${devDynamicImportLine}
|
|
1242
1404
|
${importLine}
|
|
@@ -1340,6 +1502,7 @@ function generateLocalSharedImportMap() {
|
|
|
1340
1502
|
shareConfig: {
|
|
1341
1503
|
singleton: ${shareItem.shareConfig.singleton},
|
|
1342
1504
|
requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
|
|
1505
|
+
strictVersion: ${shareItem.shareConfig.strictVersion},
|
|
1343
1506
|
${shareItem.shareConfig.import === false ? "import: false," : ""}
|
|
1344
1507
|
}
|
|
1345
1508
|
}
|
|
@@ -1372,9 +1535,12 @@ function generateUsedSharedPreloadConfig() {
|
|
|
1372
1535
|
const shareItem = getShareItemForPreload(pkg);
|
|
1373
1536
|
if (!shareItem) return null;
|
|
1374
1537
|
return `${JSON.stringify(pkg)}: {
|
|
1538
|
+
version: ${JSON.stringify(shareItem.version)},
|
|
1539
|
+
scope: ${JSON.stringify(shareItem.scope)},
|
|
1375
1540
|
shareConfig: {
|
|
1376
1541
|
singleton: ${shareItem.shareConfig.singleton},
|
|
1377
1542
|
requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
|
|
1543
|
+
strictVersion: ${shareItem.shareConfig.strictVersion},
|
|
1378
1544
|
${shareItem.shareConfig.import === false ? "import: false," : ""}
|
|
1379
1545
|
}
|
|
1380
1546
|
}`;
|
|
@@ -1394,7 +1560,11 @@ function getOrderedUsedShares() {
|
|
|
1394
1560
|
}));
|
|
1395
1561
|
}
|
|
1396
1562
|
function orderSharedDependenciesFirst(sharedPackages) {
|
|
1397
|
-
const sharedKeyByPackageName = new Map(
|
|
1563
|
+
const sharedKeyByPackageName = /* @__PURE__ */ new Map();
|
|
1564
|
+
sharedPackages.forEach((pkg) => {
|
|
1565
|
+
const packageName = getPackageName(pkg);
|
|
1566
|
+
if (!sharedKeyByPackageName.get(packageName) || pkg === packageName) sharedKeyByPackageName.set(packageName, pkg);
|
|
1567
|
+
});
|
|
1398
1568
|
const visiting = /* @__PURE__ */ new Set();
|
|
1399
1569
|
const visited = /* @__PURE__ */ new Set();
|
|
1400
1570
|
const ordered = [];
|
|
@@ -1439,6 +1609,11 @@ function generateSharedCacheSeedItem(pkg, shareItem, importPath) {
|
|
|
1439
1609
|
__mfModuleCache.share[${JSON.stringify(cacheKey)}] = exportModule;
|
|
1440
1610
|
}`;
|
|
1441
1611
|
}
|
|
1612
|
+
const sharedCacheKeyHelperCode = `const __mfGetSharedCacheKey = (pkg, singleton, version, scope) => {
|
|
1613
|
+
const normalizedScope = Array.isArray(scope) ? scope[0] : scope;
|
|
1614
|
+
const prefix = (normalizedScope || "default") + ":";
|
|
1615
|
+
return singleton || !version ? prefix + pkg : prefix + pkg + "@" + version;
|
|
1616
|
+
};`;
|
|
1442
1617
|
const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
|
|
1443
1618
|
let current = mod;
|
|
1444
1619
|
for (let i = 0; i < 5; i++) {
|
|
@@ -1450,6 +1625,40 @@ const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
|
|
|
1450
1625
|
}
|
|
1451
1626
|
return current;
|
|
1452
1627
|
};`;
|
|
1628
|
+
const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbol("mf.originalSharedProvider");
|
|
1629
|
+
const __mfResolveShareHook = { emit: (params) => params };
|
|
1630
|
+
const __mfCreateProviderSelectionVersions = (versions, strategy) => {
|
|
1631
|
+
if (strategy !== "version-first") return versions;
|
|
1632
|
+
const selectionVersions = {};
|
|
1633
|
+
for (const [version, provider] of Object.entries(versions)) {
|
|
1634
|
+
selectionVersions[version] = Object.assign({}, provider, {
|
|
1635
|
+
loaded: false,
|
|
1636
|
+
loading: undefined,
|
|
1637
|
+
lib: undefined,
|
|
1638
|
+
[__mfOriginalProviderKey]: provider
|
|
1639
|
+
});
|
|
1640
|
+
}
|
|
1641
|
+
return selectionVersions;
|
|
1642
|
+
};
|
|
1643
|
+
const __mfSelectSharedProvider = (versions, pkg, share, strategy) => {
|
|
1644
|
+
if (!versions || !share) return undefined;
|
|
1645
|
+
const scopes = Array.isArray(share.scope) ? share.scope : [share.scope || "default"];
|
|
1646
|
+
const selectionVersions = __mfCreateProviderSelectionVersions(versions, strategy);
|
|
1647
|
+
const shareScopeMap = {};
|
|
1648
|
+
for (const scope of scopes) {
|
|
1649
|
+
shareScopeMap[scope || "default"] = { [pkg]: selectionVersions };
|
|
1650
|
+
}
|
|
1651
|
+
const selected = runtimeShare.getRegisteredShare(
|
|
1652
|
+
shareScopeMap,
|
|
1653
|
+
pkg,
|
|
1654
|
+
{ ...share, scope: scopes, strategy },
|
|
1655
|
+
__mfResolveShareHook
|
|
1656
|
+
)?.shared;
|
|
1657
|
+
return selected?.[__mfOriginalProviderKey] || selected;
|
|
1658
|
+
};`;
|
|
1659
|
+
function hasImportFalseShared$1(options) {
|
|
1660
|
+
return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
|
|
1661
|
+
}
|
|
1453
1662
|
function generateDirectSharedCacheSeedCode(command = "build") {
|
|
1454
1663
|
return getOrderedUsedShares().map((pkg) => {
|
|
1455
1664
|
const shareItem = getShareItemForPreload(pkg);
|
|
@@ -1487,6 +1696,7 @@ const SSR_ONLY_PLUGIN_SPECIFIERS = new Set(["@module-federation/vite/ssrEntryLoa
|
|
|
1487
1696
|
const isSsrOnlyPlugin = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].some((s) => importStatement.includes(s));
|
|
1488
1697
|
const getSsrOnlyPluginSpecifier = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].find((s) => importStatement.includes(s));
|
|
1489
1698
|
function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
|
|
1699
|
+
const needsSharedProviderSelectionHelper = hasImportFalseShared$1(options);
|
|
1490
1700
|
const pluginImportNames = options.runtimePlugins.map((p, i) => {
|
|
1491
1701
|
if (typeof p === "string") return [
|
|
1492
1702
|
`$runtimePlugin_${i}`,
|
|
@@ -1509,6 +1719,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1509
1719
|
globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
|
|
1510
1720
|
}
|
|
1511
1721
|
import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
|
|
1722
|
+
${needsSharedProviderSelectionHelper ? "import {share as runtimeShare} from \"@module-federation/runtime/helpers\";" : ""}
|
|
1512
1723
|
${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
|
|
1513
1724
|
${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
|
|
1514
1725
|
${getRuntimeModuleCacheBootstrapCode()}
|
|
@@ -1536,6 +1747,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1536
1747
|
}
|
|
1537
1748
|
}
|
|
1538
1749
|
}
|
|
1750
|
+
${needsSharedProviderSelectionHelper ? sharedProviderSelectionHelperCode : ""}
|
|
1539
1751
|
|
|
1540
1752
|
async function getLocalSharedImportMap() {
|
|
1541
1753
|
if (!localSharedImportMapPromise) {
|
|
@@ -1555,6 +1767,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1555
1767
|
}
|
|
1556
1768
|
|
|
1557
1769
|
async function init(shared = {}, initScope = []) {
|
|
1770
|
+
${sharedCacheKeyHelperCode}
|
|
1558
1771
|
const {usedShared, usedRemotes} = await getLocalSharedImportMap()
|
|
1559
1772
|
try {
|
|
1560
1773
|
const allInstances = globalThis.__FEDERATION__?.__SHARE__;
|
|
@@ -1564,13 +1777,27 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1564
1777
|
const scopeShare = scopes?.['${options.shareScope}'];
|
|
1565
1778
|
if (!scopeShare) continue;
|
|
1566
1779
|
for (const [pkg, versionMap] of Object.entries(scopeShare)) {
|
|
1567
|
-
|
|
1780
|
+
const usedShare = usedShared?.[pkg];
|
|
1781
|
+
const selectedProvider = usedShare?.shareConfig?.import === false
|
|
1782
|
+
? __mfSelectSharedProvider(versionMap, pkg, usedShare, '${options.shareStrategy}')
|
|
1783
|
+
: undefined;
|
|
1784
|
+
const providerEntries = usedShare?.shareConfig?.import === false
|
|
1785
|
+
? Object.entries(versionMap).filter(([, provider]) => provider === selectedProvider)
|
|
1786
|
+
: Object.entries(versionMap);
|
|
1787
|
+
for (const [version, provider] of providerEntries) {
|
|
1568
1788
|
if (!provider.lib) continue;
|
|
1569
|
-
const cacheKey = provider.shareConfig?.singleton
|
|
1789
|
+
const cacheKey = __mfGetSharedCacheKey(pkg, provider.shareConfig?.singleton, version, ${JSON.stringify(options.shareScope)});
|
|
1570
1790
|
if (__mfModuleCache.share[cacheKey] !== undefined) continue;
|
|
1571
1791
|
const mod = typeof provider.lib === "function" ? provider.lib() : provider.lib;
|
|
1572
1792
|
const resolved = await Promise.resolve(mod);
|
|
1573
|
-
|
|
1793
|
+
const normalized = __mfNormalizeRuntimeShare(resolved);
|
|
1794
|
+
__mfModuleCache.share[cacheKey] = normalized;
|
|
1795
|
+
if (provider.shareConfig?.singleton && usedShare) {
|
|
1796
|
+
const usedCacheKey = __mfGetSharedCacheKey(pkg, usedShare.shareConfig?.singleton, usedShare.version, usedShare.scope);
|
|
1797
|
+
if (__mfModuleCache.share[usedCacheKey] === undefined) {
|
|
1798
|
+
__mfModuleCache.share[usedCacheKey] = normalized;
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1574
1801
|
}
|
|
1575
1802
|
}
|
|
1576
1803
|
}
|
|
@@ -1578,6 +1805,14 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1578
1805
|
} catch (e) {
|
|
1579
1806
|
console.error('[Module Federation] Failed to bridge external shared modules', e)
|
|
1580
1807
|
}
|
|
1808
|
+
for (const [pkg, share] of Object.entries(usedShared)) {
|
|
1809
|
+
const cacheKey = __mfGetSharedCacheKey(pkg, share.shareConfig?.singleton, share.version, share.scope);
|
|
1810
|
+
if (__mfModuleCache.share[cacheKey] !== undefined) continue;
|
|
1811
|
+
const singletonCacheKey = __mfGetSharedCacheKey(pkg, true, share.version, share.scope);
|
|
1812
|
+
if (__mfModuleCache.share[singletonCacheKey] !== undefined) {
|
|
1813
|
+
__mfModuleCache.share[cacheKey] = __mfModuleCache.share[singletonCacheKey];
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1581
1816
|
${generateDirectSharedCacheSeedCode(command)}
|
|
1582
1817
|
const __browserPlugins = [${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => `${item[0]}(${item[2]})`).join(", ")}];
|
|
1583
1818
|
const __ssrPlugins = typeof globalThis.window === 'undefined'
|
|
@@ -1614,11 +1849,11 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1614
1849
|
console.error('[Module Federation]', e)
|
|
1615
1850
|
}
|
|
1616
1851
|
for (const [pkg, share] of Object.entries(usedShared)) {
|
|
1617
|
-
const cacheKey = share.shareConfig?.singleton
|
|
1852
|
+
const cacheKey = __mfGetSharedCacheKey(pkg, share.shareConfig?.singleton, share.version, share.scope);
|
|
1618
1853
|
if (share.shareConfig?.import !== false || __mfModuleCache.share[cacheKey] !== undefined) continue;
|
|
1619
1854
|
${normalizeRuntimeShareCode}
|
|
1620
1855
|
const versions = shared?.[pkg];
|
|
1621
|
-
const provider = versions
|
|
1856
|
+
const provider = __mfSelectSharedProvider(versions, pkg, share, '${options.shareStrategy}');
|
|
1622
1857
|
if (!provider) continue;
|
|
1623
1858
|
const factory = provider.lib || (provider.loading ? await provider.loading : await provider.get?.());
|
|
1624
1859
|
const mod = typeof factory === "function" ? factory() : factory;
|
|
@@ -1654,10 +1889,11 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
|
|
|
1654
1889
|
const remoteEntry = await import(${remoteEntryImport});
|
|
1655
1890
|
const runtime = await remoteEntry.init();
|
|
1656
1891
|
const usedShared = ${generateUsedSharedPreloadConfig()};
|
|
1892
|
+
${sharedCacheKeyHelperCode}
|
|
1657
1893
|
${normalizeRuntimeShareCode}
|
|
1658
1894
|
${shouldPreloadShares ? `
|
|
1659
1895
|
for (const [pkg, share] of Object.entries(usedShared)) {
|
|
1660
|
-
const cacheKey = share.shareConfig?.singleton
|
|
1896
|
+
const cacheKey = __mfGetSharedCacheKey(pkg, share.shareConfig?.singleton, share.version, share.scope);
|
|
1661
1897
|
if (__mfModuleCache.share[cacheKey] !== undefined) {
|
|
1662
1898
|
continue;
|
|
1663
1899
|
}
|
|
@@ -1866,7 +2102,7 @@ function getRemoteExportBlock(command, deferRemoteLoad, consumer) {
|
|
|
1866
2102
|
if (command !== "serve" && command !== "build") return `__mfSyncDefaultExport();
|
|
1867
2103
|
export { __mfDefaultExport as default };`;
|
|
1868
2104
|
return `__mfSyncDefaultExport();
|
|
1869
|
-
__mfRemotePending?.then(__mfSyncDefaultExport);
|
|
2105
|
+
__mfRemotePending?.then(__mfSyncDefaultExport, () => {});
|
|
1870
2106
|
export { exportModule as __moduleExports };
|
|
1871
2107
|
${deferRemoteLoad ? getLazyRemotePendingExport() : getEagerRemotePendingExport()}
|
|
1872
2108
|
${command === "serve" && consumer === "server" ? getServerThenExport() : ""}
|
|
@@ -1897,8 +2133,9 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
|
|
|
1897
2133
|
const remoteLoadFailureHandler = command === "build" ? `.catch((error) => {
|
|
1898
2134
|
delete __mfModuleCache.remote[pendingKey];
|
|
1899
2135
|
throw error;
|
|
1900
|
-
})` : `.catch(() => {
|
|
2136
|
+
})` : `.catch((error) => {
|
|
1901
2137
|
delete __mfModuleCache.remote[pendingKey];
|
|
2138
|
+
throw error;
|
|
1902
2139
|
})`;
|
|
1903
2140
|
const remoteLoadCode = `
|
|
1904
2141
|
function __mfStartRemoteLoad() {
|
|
@@ -2024,9 +2261,11 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
2024
2261
|
let _command;
|
|
2025
2262
|
let emitFileId;
|
|
2026
2263
|
let viteConfig;
|
|
2027
|
-
let
|
|
2264
|
+
let skipHtmlDevFallback = forceClientInjected ?? false;
|
|
2265
|
+
let clientInjected = false;
|
|
2028
2266
|
let emittedFileName;
|
|
2029
2267
|
let skipTransformIds = /* @__PURE__ */ new Set();
|
|
2268
|
+
let injectedTransformIds = /* @__PURE__ */ new Set();
|
|
2030
2269
|
let bootstrapDir = "";
|
|
2031
2270
|
function skipSvelteKitSsrBuild() {
|
|
2032
2271
|
return (_command === "build" || viteConfig?.command === "build") && viteConfig?.build?.ssr && hasPackageDependency("@sveltejs/kit");
|
|
@@ -2148,6 +2387,10 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
2148
2387
|
if (id.startsWith("\0") || id.startsWith("virtual:")) return normalizeModuleId(id);
|
|
2149
2388
|
return normalizeModuleId(path$1.isAbsolute(id) ? id : path$1.resolve(viteConfig.root, id));
|
|
2150
2389
|
}
|
|
2390
|
+
function isFederationInternalVirtualId(id) {
|
|
2391
|
+
const normalized = decodeViteId(id).replace(/^\0+/, "");
|
|
2392
|
+
return normalized.includes("virtual:mf:") || /__(?:loadShare|prebuild|loadRemote)__/.test(normalized);
|
|
2393
|
+
}
|
|
2151
2394
|
function addEntryFile(file) {
|
|
2152
2395
|
const normalized = normalizeModuleId(file);
|
|
2153
2396
|
if (!entryFiles.includes(normalized)) entryFiles.push(normalized);
|
|
@@ -2255,9 +2498,9 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
2255
2498
|
if (envName?.name && envName.name !== "client") return;
|
|
2256
2499
|
const inputOptions = getBuildInput(config);
|
|
2257
2500
|
if (!inputOptions) htmlFilePath = path$1.resolve(config.root, "index.html");
|
|
2258
|
-
else if (typeof inputOptions === "string") entryFiles = [
|
|
2259
|
-
else if (Array.isArray(inputOptions)) entryFiles = inputOptions.map(
|
|
2260
|
-
else if (typeof inputOptions === "object") entryFiles = Object.values(inputOptions).map((input) =>
|
|
2501
|
+
else if (typeof inputOptions === "string") entryFiles = [resolveProjectId(inputOptions)];
|
|
2502
|
+
else if (Array.isArray(inputOptions)) entryFiles = inputOptions.map(resolveProjectId);
|
|
2503
|
+
else if (typeof inputOptions === "object") entryFiles = Object.values(inputOptions).map((input) => resolveProjectId(String(input)));
|
|
2261
2504
|
if (entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles);
|
|
2262
2505
|
if (htmlFilePath) addHtmlScriptEntries(htmlFilePath);
|
|
2263
2506
|
},
|
|
@@ -2357,7 +2600,8 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
2357
2600
|
if (isSvelteKitServerModule(id)) return;
|
|
2358
2601
|
if (hasEntryBootstrapParam(id)) return;
|
|
2359
2602
|
if (normalizeModuleId(id).endsWith(".html")) return;
|
|
2360
|
-
|
|
2603
|
+
const projectId = resolveProjectId(id);
|
|
2604
|
+
if (skipTransformIds.has(projectId)) return;
|
|
2361
2605
|
const transformCtx = this;
|
|
2362
2606
|
const transformEnv = transformCtx != null && typeof transformCtx === "object" ? transformCtx["environment"] : void 0;
|
|
2363
2607
|
if (transformEnv?.name && transformEnv.name !== "client") return;
|
|
@@ -2382,12 +2626,13 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
2382
2626
|
const injection = `await import(${JSON.stringify(getEntryPath())}).then(({ initHost }) => initHost());\n `;
|
|
2383
2627
|
return mapCodeToCodeWithSourcemap(code.replace("vueApp.mount(vueAppRootContainer);", `${injection}vueApp.mount(vueAppRootContainer);`));
|
|
2384
2628
|
}
|
|
2385
|
-
const isHydrationEntryFallback = inject === "entry" && entryFiles.length === 0 && (!htmlFilePath || !fs$1.existsSync(htmlFilePath)) && !clientInjected && !id.includes("node_modules") && (id.startsWith("\0") || /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id)) && /hydrateRoot|createRoot|ReactDOM\.render/.test(code);
|
|
2629
|
+
const isHydrationEntryFallback = inject === "entry" && entryFiles.length === 0 && (!htmlFilePath || !fs$1.existsSync(htmlFilePath)) && !clientInjected && !isFederationInternalVirtualId(id) && !id.includes("node_modules") && (id.startsWith("\0") || /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id)) && (/hydrateRoot|createRoot|ReactDOM\.render/.test(code) || /\.mount\s*\(\s*['"#]/.test(code) || /\.mount\s*\(/.test(code) && /createSSRApp|createApp/.test(code));
|
|
2386
2630
|
const isNuxtEntryAsyncModule = /(?:^|\/)nuxt\/dist\/app\/entry\.async\.js(?:\?|$)/.test(id) && code.includes("entry();");
|
|
2387
|
-
const isNuxtClientEntryFallback = _command === "serve" && inject === "entry" && (!htmlFilePath || !fs$1.existsSync(htmlFilePath)) && !clientInjected && !hasEntryBootstrapParam(id) && !id.includes("node_modules/.vite") && isNuxtEntryAsyncModule && !entryFiles.some((file) =>
|
|
2388
|
-
if (!(_command === "serve" && isNuxtEntryAsyncModule) && (injectEntry() && entryFiles.some((file) =>
|
|
2631
|
+
const isNuxtClientEntryFallback = _command === "serve" && inject === "entry" && (!htmlFilePath || !fs$1.existsSync(htmlFilePath)) && !clientInjected && !hasEntryBootstrapParam(id) && !id.includes("node_modules/.vite") && isNuxtEntryAsyncModule && !entryFiles.some((file) => projectId === file);
|
|
2632
|
+
if (!(_command === "serve" && isNuxtEntryAsyncModule) && (injectedTransformIds.has(projectId) || injectEntry() && entryFiles.some((file) => projectId === file) || _command === "serve" && inject === "html" && !isVinext && !clientInjected && !skipHtmlDevFallback && !id.startsWith("\0") && !id.includes("node_modules") && /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id) || isHydrationEntryFallback || isNuxtClientEntryFallback)) {
|
|
2389
2633
|
clientInjected = true;
|
|
2390
|
-
|
|
2634
|
+
injectedTransformIds.add(projectId);
|
|
2635
|
+
if (!waitsForInit) return mapCodeToCodeWithSourcemap(`import ${JSON.stringify(getEntryPath())};\n` + code);
|
|
2391
2636
|
const entrySrc = id.includes("?") ? `${id}&${ENTRY_BOOTSTRAP_QUERY.slice(1)}` : `${id}${ENTRY_BOOTSTRAP_QUERY}`;
|
|
2392
2637
|
return mapCodeToCodeWithSourcemap(getBootstrapSource(getEntryPath(), entrySrc, false, { skipRemotePreload: _command === "serve" && isNuxtEntryAsyncModule }));
|
|
2393
2638
|
}
|
|
@@ -2592,7 +2837,7 @@ const REMOTE_HMR_ENDPOINT = "__mf_hmr";
|
|
|
2592
2837
|
const REMOTE_HMR_EVENT = "mf:remote-update";
|
|
2593
2838
|
const REMOTE_HMR_CONNECT_RETRY_DELAY_MS = 1e3;
|
|
2594
2839
|
const REMOTE_HMR_CONNECT_MAX_RETRIES = 10;
|
|
2595
|
-
function getBasePath
|
|
2840
|
+
function getBasePath(base) {
|
|
2596
2841
|
if (!base) return "/";
|
|
2597
2842
|
if (base.startsWith("http://") || base.startsWith("https://")) try {
|
|
2598
2843
|
return new URL(base).pathname || "/";
|
|
@@ -2602,11 +2847,11 @@ function getBasePath$1(base) {
|
|
|
2602
2847
|
return base;
|
|
2603
2848
|
}
|
|
2604
2849
|
function getRemoteHmrPath(base) {
|
|
2605
|
-
return `${getBasePath
|
|
2850
|
+
return `${getBasePath(base).replace(/\/?$/, "/")}${REMOTE_HMR_ENDPOINT}`.replace(/\/{2,}/g, "/");
|
|
2606
2851
|
}
|
|
2607
2852
|
function getHmrWsPath(base, hmrPath) {
|
|
2608
|
-
const normalizedBase = getBasePath
|
|
2609
|
-
const normalizedPath = getBasePath
|
|
2853
|
+
const normalizedBase = getBasePath(base);
|
|
2854
|
+
const normalizedPath = getBasePath(hmrPath || "");
|
|
2610
2855
|
if (!normalizedPath || normalizedPath === "/") return normalizedBase;
|
|
2611
2856
|
return `${normalizedBase.endsWith("/") ? normalizedBase.slice(0, -1) : normalizedBase}/${normalizedPath.startsWith("/") ? normalizedPath.slice(1) : normalizedPath}`;
|
|
2612
2857
|
}
|
|
@@ -3255,70 +3500,6 @@ const buildFileToShareKeyMap = async (shareKeys, resolveFn) => {
|
|
|
3255
3500
|
return fileToShareKey;
|
|
3256
3501
|
};
|
|
3257
3502
|
//#endregion
|
|
3258
|
-
//#region src/utils/pathNormalization.ts
|
|
3259
|
-
const COMMON_SHARED_SUBPATHS = {
|
|
3260
|
-
react: [
|
|
3261
|
-
"react/jsx-runtime",
|
|
3262
|
-
"react/jsx-dev-runtime",
|
|
3263
|
-
"react/compiler-runtime"
|
|
3264
|
-
],
|
|
3265
|
-
"react-dom": [
|
|
3266
|
-
"react-dom/client",
|
|
3267
|
-
"react-dom/server",
|
|
3268
|
-
"react-dom/server.browser"
|
|
3269
|
-
],
|
|
3270
|
-
"solid-js": [
|
|
3271
|
-
"solid-js/web",
|
|
3272
|
-
"solid-js/store",
|
|
3273
|
-
"solid-js/html",
|
|
3274
|
-
"solid-js/h"
|
|
3275
|
-
]
|
|
3276
|
-
};
|
|
3277
|
-
function removeTrailingSlash(value) {
|
|
3278
|
-
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
3279
|
-
}
|
|
3280
|
-
function ensureTrailingSlash(value) {
|
|
3281
|
-
return `${removeTrailingSlash(value)}/`;
|
|
3282
|
-
}
|
|
3283
|
-
function getBasePath(base) {
|
|
3284
|
-
return removeTrailingSlash(base || "/");
|
|
3285
|
-
}
|
|
3286
|
-
function isNuxtClientBase(base) {
|
|
3287
|
-
return getBasePath(base).endsWith("/_nuxt");
|
|
3288
|
-
}
|
|
3289
|
-
function normalizeNodeModulePath(source) {
|
|
3290
|
-
return source.replace(/\\/g, "/").replace(/\?.*$/, "");
|
|
3291
|
-
}
|
|
3292
|
-
function isNodeModulePath(source) {
|
|
3293
|
-
return source.includes("/node_modules/") || source.includes("\\node_modules\\");
|
|
3294
|
-
}
|
|
3295
|
-
function filterId(id) {
|
|
3296
|
-
return typeof id === "string" && !id.includes("\0");
|
|
3297
|
-
}
|
|
3298
|
-
function getMatchingNodeModuleSubpath(source, candidates) {
|
|
3299
|
-
const normalized = normalizeNodeModulePath(source);
|
|
3300
|
-
return [...candidates].sort((a, b) => b.length - a.length).find((candidate) => normalized.includes(`/node_modules/${candidate}/`) || normalized.includes(`/node_modules/${candidate}.`));
|
|
3301
|
-
}
|
|
3302
|
-
function getCommonSharedSubpaths(sharedKey) {
|
|
3303
|
-
return COMMON_SHARED_SUBPATHS[removeTrailingSlash(sharedKey)] || [];
|
|
3304
|
-
}
|
|
3305
|
-
function getCommonSharedSubpathFromNodeModulePath(source, sharedKey) {
|
|
3306
|
-
return getMatchingNodeModuleSubpath(source, getCommonSharedSubpaths(removeTrailingSlash(sharedKey)));
|
|
3307
|
-
}
|
|
3308
|
-
/**
|
|
3309
|
-
* Resolves the public path for remote entries
|
|
3310
|
-
* @param options - Module Federation options
|
|
3311
|
-
* @param viteBase - Vite's base config value
|
|
3312
|
-
* @param originalBase - Original base config before any transformations
|
|
3313
|
-
* @returns The resolved public path
|
|
3314
|
-
*/
|
|
3315
|
-
function resolvePublicPath(options, viteBase, originalBase) {
|
|
3316
|
-
if (options.publicPath && options.publicPath !== "auto") return options.publicPath;
|
|
3317
|
-
if (!originalBase) return "auto";
|
|
3318
|
-
if (viteBase) return ensureTrailingSlash(viteBase);
|
|
3319
|
-
return "auto";
|
|
3320
|
-
}
|
|
3321
|
-
//#endregion
|
|
3322
3503
|
//#region src/virtualModules/virtualExposesSSR.ts
|
|
3323
3504
|
/**
|
|
3324
3505
|
* Virtual module ID for the SSR exposes map.
|
|
@@ -3471,6 +3652,24 @@ function resolveTypesMeta(dts) {
|
|
|
3471
3652
|
api: `${typesFolder}.d.ts`
|
|
3472
3653
|
};
|
|
3473
3654
|
}
|
|
3655
|
+
function resolveDevRemoteEntryFileName(fileName) {
|
|
3656
|
+
if (!fileName.includes("[hash")) return fileName;
|
|
3657
|
+
const normalized = fileName.replace(/(?:[._-]?\[hash(?::\d+)?\])/g, "");
|
|
3658
|
+
const baseName = path$1.basename(normalized);
|
|
3659
|
+
return path$1.extname(baseName) ? normalized : `${normalized}.js`;
|
|
3660
|
+
}
|
|
3661
|
+
function createRemoteEntryAssetMap(fileName) {
|
|
3662
|
+
return {
|
|
3663
|
+
js: {
|
|
3664
|
+
async: [],
|
|
3665
|
+
sync: [fileName]
|
|
3666
|
+
},
|
|
3667
|
+
css: {
|
|
3668
|
+
async: [],
|
|
3669
|
+
sync: []
|
|
3670
|
+
}
|
|
3671
|
+
};
|
|
3672
|
+
}
|
|
3474
3673
|
const Manifest = () => {
|
|
3475
3674
|
const mfOptions = getNormalizeModuleFederationOptions();
|
|
3476
3675
|
const { name, filename, getPublicPath, manifest: manifestOptions, varFilename } = mfOptions;
|
|
@@ -3504,6 +3703,12 @@ const Manifest = () => {
|
|
|
3504
3703
|
next();
|
|
3505
3704
|
return;
|
|
3506
3705
|
}
|
|
3706
|
+
const devRemoteEntryFile = resolveDevRemoteEntryFileName(filename);
|
|
3707
|
+
if (devRemoteEntryFile !== filename && req.url?.startsWith((viteConfig.base + devRemoteEntryFile).replace(/^\/?/, "/"))) {
|
|
3708
|
+
req.url = req.url.replace(devRemoteEntryFile, filename);
|
|
3709
|
+
next();
|
|
3710
|
+
return;
|
|
3711
|
+
}
|
|
3507
3712
|
if (req.url?.replace(/\?.*/, "") === (viteConfig.base + mfManifestName).replace(/^\/?/, "/")) {
|
|
3508
3713
|
res.setHeader("Content-Type", "application/json");
|
|
3509
3714
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
@@ -3520,12 +3725,12 @@ const Manifest = () => {
|
|
|
3520
3725
|
buildName: name
|
|
3521
3726
|
},
|
|
3522
3727
|
remoteEntry: {
|
|
3523
|
-
name:
|
|
3728
|
+
name: devRemoteEntryFile,
|
|
3524
3729
|
path: "",
|
|
3525
3730
|
type: "module"
|
|
3526
3731
|
},
|
|
3527
3732
|
ssrRemoteEntry: {
|
|
3528
|
-
name: getSsrRemoteEntryFileName(
|
|
3733
|
+
name: getSsrRemoteEntryFileName(devRemoteEntryFile),
|
|
3529
3734
|
path: "/__mf_ssr__/",
|
|
3530
3735
|
type: "module"
|
|
3531
3736
|
},
|
|
@@ -3566,10 +3771,10 @@ const Manifest = () => {
|
|
|
3566
3771
|
if (!mfManifestName) return;
|
|
3567
3772
|
let filesMap = {};
|
|
3568
3773
|
const foundRemoteEntryFile = findRemoteEntryFile(mfOptions.filename, bundle);
|
|
3569
|
-
const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions.filename);
|
|
3774
|
+
const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(foundRemoteEntryFile || mfOptions.filename);
|
|
3570
3775
|
const foundSsrRemoteEntryFile = Object.values(bundle).find((file) => file.fileName === expectedSsrRemoteEntryFile)?.fileName;
|
|
3571
3776
|
if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
|
|
3572
|
-
ssrRemoteEntryFile = foundSsrRemoteEntryFile || expectedSsrRemoteEntryFile;
|
|
3777
|
+
ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(resolveDevRemoteEntryFileName(mfOptions.filename)) : expectedSsrRemoteEntryFile);
|
|
3573
3778
|
const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
|
|
3574
3779
|
if (!disableAssetsAnalyze) {
|
|
3575
3780
|
const exposesModules = Object.keys(mfOptions.exposes).map((item) => mfOptions.exposes[item].import);
|
|
@@ -3610,13 +3815,14 @@ const Manifest = () => {
|
|
|
3610
3815
|
function generateMFManifest(preloadMap, disableAssetsAnalyze = false) {
|
|
3611
3816
|
const options = getNormalizeModuleFederationOptions();
|
|
3612
3817
|
const { name, varFilename } = options;
|
|
3818
|
+
const resolvedRemoteEntryFile = _command === "serve" ? remoteEntryFile || resolveDevRemoteEntryFileName(filename) : remoteEntryFile;
|
|
3613
3819
|
const remoteEntry = {
|
|
3614
|
-
name:
|
|
3820
|
+
name: resolvedRemoteEntryFile,
|
|
3615
3821
|
path: "",
|
|
3616
3822
|
type: "module"
|
|
3617
3823
|
};
|
|
3618
3824
|
const ssrRemoteEntry = {
|
|
3619
|
-
name: ssrRemoteEntryFile || getSsrRemoteEntryFileName(filename),
|
|
3825
|
+
name: ssrRemoteEntryFile || getSsrRemoteEntryFileName(_command === "serve" ? resolveDevRemoteEntryFileName(filename) : filename),
|
|
3620
3826
|
path: _command === "serve" ? "/__mf_ssr__/" : "",
|
|
3621
3827
|
type: "module"
|
|
3622
3828
|
};
|
|
@@ -3634,7 +3840,7 @@ const Manifest = () => {
|
|
|
3634
3840
|
const shared = Array.from(getUsedShares()).flatMap((shareKey) => {
|
|
3635
3841
|
const shareItem = getNormalizeShareItem(shareKey);
|
|
3636
3842
|
if (!shareItem) return [];
|
|
3637
|
-
const assets = preloadMap[shareKey] || createEmptyAssetMap();
|
|
3843
|
+
const assets = preloadMap[shareKey] || (_command === "serve" && resolvedRemoteEntryFile ? createRemoteEntryAssetMap(resolvedRemoteEntryFile) : createEmptyAssetMap());
|
|
3638
3844
|
return [{
|
|
3639
3845
|
id: `${name}:${shareKey}`,
|
|
3640
3846
|
name: shareKey,
|
|
@@ -3655,7 +3861,7 @@ const Manifest = () => {
|
|
|
3655
3861
|
});
|
|
3656
3862
|
const exposes = Object.entries(options.exposes).map(([key, value]) => {
|
|
3657
3863
|
const formatKey = key.replace("./", "");
|
|
3658
|
-
const assets = preloadMap[value.import] || createEmptyAssetMap();
|
|
3864
|
+
const assets = preloadMap[value.import] || (_command === "serve" && resolvedRemoteEntryFile ? createRemoteEntryAssetMap(resolvedRemoteEntryFile) : createEmptyAssetMap());
|
|
3659
3865
|
return {
|
|
3660
3866
|
id: `${name}:${formatKey}`,
|
|
3661
3867
|
name: formatKey,
|
|
@@ -4651,7 +4857,7 @@ function pluginSSRRemoteEntry(options) {
|
|
|
4651
4857
|
},
|
|
4652
4858
|
configureServer(server) {
|
|
4653
4859
|
const base = "/__mf_ssr__";
|
|
4654
|
-
const basePath = getBasePath(viteConfig?.base);
|
|
4860
|
+
const basePath = getBasePath$1(viteConfig?.base);
|
|
4655
4861
|
const ssrEntryFileName = getSsrRemoteEntryFileName(options.filename);
|
|
4656
4862
|
if (isNuxtProject || isNuxtClientBase(basePath)) server.middlewares.use((req, _res, next) => {
|
|
4657
4863
|
if (req.url?.replace(/\?.*/, "") === `${basePath}/${ssrEntryFileName}`) req.url = `${basePath}/__mf_ssr__/${ssrEntryFileName}`;
|
|
@@ -4955,6 +5161,13 @@ var normalizeOptimizeDeps_default = {
|
|
|
4955
5161
|
if (!optimizeDeps.include) optimizeDeps.include = [];
|
|
4956
5162
|
if (!optimizeDeps.exclude) optimizeDeps.exclude = [];
|
|
4957
5163
|
if (!optimizeDeps.needsInterop) optimizeDeps.needsInterop = [];
|
|
5164
|
+
},
|
|
5165
|
+
configResolved: (config) => {
|
|
5166
|
+
const include = config.optimizeDeps?.include;
|
|
5167
|
+
const exclude = config.optimizeDeps?.exclude;
|
|
5168
|
+
if (!include?.length || !exclude?.length) return;
|
|
5169
|
+
const included = new Set(include);
|
|
5170
|
+
config.optimizeDeps.exclude = exclude.filter((dep) => !included.has(dep));
|
|
4958
5171
|
}
|
|
4959
5172
|
};
|
|
4960
5173
|
//#endregion
|
|
@@ -5005,6 +5218,17 @@ function appendResolveAlias(config, alias) {
|
|
|
5005
5218
|
replacement
|
|
5006
5219
|
})), alias];
|
|
5007
5220
|
}
|
|
5221
|
+
function hasImportFalseShared(options) {
|
|
5222
|
+
return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
|
|
5223
|
+
}
|
|
5224
|
+
function getRuntimeHelpersImplementation(runtimeImplementation) {
|
|
5225
|
+
const indexEntryMatch = runtimeImplementation.match(/^(.*[\\/])index(\.[cm]?js)$/);
|
|
5226
|
+
if (indexEntryMatch) return `${indexEntryMatch[1]}helpers${indexEntryMatch[2]}`;
|
|
5227
|
+
const extension = path$1.extname(runtimeImplementation);
|
|
5228
|
+
if (extension) return path$1.join(path$1.dirname(runtimeImplementation), `helpers${extension}`);
|
|
5229
|
+
if (path$1.isAbsolute(runtimeImplementation) || runtimeImplementation.startsWith(".")) return path$1.join(runtimeImplementation, "helpers");
|
|
5230
|
+
return `${runtimeImplementation.replace(/\/$/, "")}/helpers`;
|
|
5231
|
+
}
|
|
5008
5232
|
const UNSAFE_JS_SOURCE_CHAR_MAP = {
|
|
5009
5233
|
"<": "\\u003C",
|
|
5010
5234
|
">": "\\u003E",
|
|
@@ -5108,6 +5332,7 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
5108
5332
|
external: true
|
|
5109
5333
|
}));
|
|
5110
5334
|
build.onResolve({ filter: /.*/ }, (args) => {
|
|
5335
|
+
if (args.kind === "entry-point") return;
|
|
5111
5336
|
if (!args.importer || args.namespace === "mf-shared") return;
|
|
5112
5337
|
if (isSharedResolverInternalImporter(args.importer)) return;
|
|
5113
5338
|
if (!findSharedKey(args.path, shared) || args.path.endsWith(".css")) return;
|
|
@@ -5221,7 +5446,7 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
5221
5446
|
const SSR_ONLY_PLUGINS = new Set(["@module-federation/vite/ssrEntryLoader"]);
|
|
5222
5447
|
function loadPluginDts(options) {
|
|
5223
5448
|
if (options.dts === false) return [];
|
|
5224
|
-
return [import("./pluginDts-
|
|
5449
|
+
return [import("./pluginDts-CrSsDUnT.js").then((n) => n.n).then(({ default: pluginDts }) => pluginDts(options))];
|
|
5225
5450
|
}
|
|
5226
5451
|
function federation(mfUserOptions) {
|
|
5227
5452
|
if (isTestEnv()) return [];
|
|
@@ -5233,6 +5458,7 @@ function federation(mfUserOptions) {
|
|
|
5233
5458
|
const virtualExposesId = getVirtualExposesId(options);
|
|
5234
5459
|
let command;
|
|
5235
5460
|
let desiredRolldownOutput;
|
|
5461
|
+
let isSsrBuild = false;
|
|
5236
5462
|
return [
|
|
5237
5463
|
{
|
|
5238
5464
|
name: "vite:module-federation-virtual-modules",
|
|
@@ -5344,6 +5570,7 @@ function federation(mfUserOptions) {
|
|
|
5344
5570
|
enforce: "pre",
|
|
5345
5571
|
apply: "build",
|
|
5346
5572
|
config(config) {
|
|
5573
|
+
isSsrBuild = config.build?.ssr === true;
|
|
5347
5574
|
const runtimeInitId = virtualRuntimeInitStatus.getImportId();
|
|
5348
5575
|
config.build = config.build || {};
|
|
5349
5576
|
if (config.build.modulePreload !== false) {
|
|
@@ -5465,6 +5692,8 @@ function federation(mfUserOptions) {
|
|
|
5465
5692
|
load(id) {
|
|
5466
5693
|
if (id.includes("__loadShare__") || id.includes("__loadRemote__")) {
|
|
5467
5694
|
let code = VirtualModule.findById(id)?.code ?? readFileSync(id, "utf-8");
|
|
5695
|
+
const environmentName = this.environment?.name;
|
|
5696
|
+
if (environmentName && environmentName !== "client" || !environmentName && isSsrBuild) code = prependWorkspaceSingletonSsrImport(code);
|
|
5468
5697
|
code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
5469
5698
|
code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
5470
5699
|
if (!(/\b(?:var|let|const)\s+__moduleExports\b/.test(code) || /\bexport\s+const\s+__moduleExports\b/.test(code) || /\bexport\s*\{[^}]*__moduleExports/.test(code))) {
|
|
@@ -5526,8 +5755,14 @@ function federation(mfUserOptions) {
|
|
|
5526
5755
|
_options: options,
|
|
5527
5756
|
config(config, { command: _command }) {
|
|
5528
5757
|
const isRolldown = getIsRolldown(this);
|
|
5758
|
+
isSsrBuild = _command === "build" && config.build?.ssr === true;
|
|
5759
|
+
const needsSharedProviderSelectionHelper = hasImportFalseShared(options);
|
|
5760
|
+
if (needsSharedProviderSelectionHelper) appendResolveAlias(config, {
|
|
5761
|
+
find: /^@module-federation\/runtime\/helpers$/,
|
|
5762
|
+
replacement: getRuntimeHelpersImplementation(options.implementation)
|
|
5763
|
+
});
|
|
5529
5764
|
appendResolveAlias(config, {
|
|
5530
|
-
find:
|
|
5765
|
+
find: /^@module-federation\/runtime$/,
|
|
5531
5766
|
replacement: options.implementation
|
|
5532
5767
|
});
|
|
5533
5768
|
config.build ||= {};
|
|
@@ -5536,6 +5771,7 @@ function federation(mfUserOptions) {
|
|
|
5536
5771
|
config.optimizeDeps ||= {};
|
|
5537
5772
|
config.optimizeDeps.include ||= [];
|
|
5538
5773
|
config.optimizeDeps.include.push("@module-federation/runtime");
|
|
5774
|
+
if (needsSharedProviderSelectionHelper) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
|
|
5539
5775
|
options.runtimePlugins.forEach((p) => {
|
|
5540
5776
|
const pluginPath = typeof p === "string" ? p : p[0];
|
|
5541
5777
|
if (SSR_ONLY_PLUGINS.has(pluginPath)) return;
|
|
@@ -5550,7 +5786,17 @@ function federation(mfUserOptions) {
|
|
|
5550
5786
|
const envTargetDefineValue = !options.target && isAstro ? "undefined" : JSON.stringify(resolvedTarget);
|
|
5551
5787
|
if (!config.define) config.define = {};
|
|
5552
5788
|
if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] = envTargetDefineValue;
|
|
5789
|
+
if (resolvedTarget === "node" && !("FEDERATION_OPTIMIZE_NO_SNAPSHOT_PLUGIN" in config.define)) config.define["FEDERATION_OPTIMIZE_NO_SNAPSHOT_PLUGIN"] = "true";
|
|
5553
5790
|
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.`);
|
|
5791
|
+
},
|
|
5792
|
+
configEnvironment(name, config) {
|
|
5793
|
+
if (!(config.consumer === "server" || name === "ssr" || name === "server" || config.build?.ssr === true)) return;
|
|
5794
|
+
const isAstro = hasPackageDependency("astro");
|
|
5795
|
+
const envTargetDefineValue = !options.target && isAstro ? "undefined" : JSON.stringify(options.target ?? "node");
|
|
5796
|
+
config.define = { ...config.define ?? {} };
|
|
5797
|
+
if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] = envTargetDefineValue;
|
|
5798
|
+
if (!("FEDERATION_OPTIMIZE_NO_SNAPSHOT_PLUGIN" in config.define)) config.define["FEDERATION_OPTIMIZE_NO_SNAPSHOT_PLUGIN"] = "true";
|
|
5799
|
+
if (options.target && 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.`);
|
|
5554
5800
|
}
|
|
5555
5801
|
},
|
|
5556
5802
|
...Manifest(),
|
|
@@ -194,7 +194,8 @@ function getPackageNameFromNodeModulePath(source) {
|
|
|
194
194
|
return parts[0];
|
|
195
195
|
}
|
|
196
196
|
function getSharedCacheKey(pkg, shareItem) {
|
|
197
|
-
|
|
197
|
+
const prefix = `${shareItem.scope || "default"}:`;
|
|
198
|
+
return shareItem.shareConfig.singleton || !shareItem.version ? `${prefix}${pkg}` : `${prefix}${pkg}@${shareItem.version}`;
|
|
198
199
|
}
|
|
199
200
|
function getInstalledPackageJson(pkg, opts) {
|
|
200
201
|
const cwd = opts?.cwd || getPackageDetectionCwd();
|
|
@@ -87,7 +87,24 @@ const _path = () => nodeImport("path");
|
|
|
87
87
|
const _fs = () => nodeImport("fs");
|
|
88
88
|
const _crypto = () => nodeImport("crypto");
|
|
89
89
|
const _module = () => nodeImport("module");
|
|
90
|
-
const
|
|
90
|
+
const ssrEntryCache = /* @__PURE__ */ new Map();
|
|
91
|
+
const manifestFetchCache = /* @__PURE__ */ new Map();
|
|
92
|
+
var SsrEntryHttpError = class extends Error {
|
|
93
|
+
constructor(url, status, statusText, bodyPreview) {
|
|
94
|
+
super(`Failed to fetch SSR module "${url}": ${status} ${statusText}` + (bodyPreview ? `\npreview: ${bodyPreview}` : ""));
|
|
95
|
+
this.url = url;
|
|
96
|
+
this.status = status;
|
|
97
|
+
this.statusText = statusText;
|
|
98
|
+
this.bodyPreview = bodyPreview;
|
|
99
|
+
this.name = "SsrEntryHttpError";
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
function getBodyPreview(body) {
|
|
103
|
+
return body.slice(0, 240).replace(/\s+/g, " ").trim();
|
|
104
|
+
}
|
|
105
|
+
function isSsrEntryHttpError(error) {
|
|
106
|
+
return error instanceof SsrEntryHttpError;
|
|
107
|
+
}
|
|
91
108
|
async function fetchManifest(manifestUrl) {
|
|
92
109
|
try {
|
|
93
110
|
const res = await fetch(manifestUrl);
|
|
@@ -97,9 +114,33 @@ async function fetchManifest(manifestUrl) {
|
|
|
97
114
|
return null;
|
|
98
115
|
}
|
|
99
116
|
}
|
|
117
|
+
async function fetchManifestCached(manifestUrl) {
|
|
118
|
+
if (!manifestFetchCache.has(manifestUrl)) manifestFetchCache.set(manifestUrl, fetchManifest(manifestUrl));
|
|
119
|
+
return manifestFetchCache.get(manifestUrl);
|
|
120
|
+
}
|
|
121
|
+
/** True when the host configured a manifest URL as the remote entry (any .json name). */
|
|
122
|
+
function isManifestEntry(remoteEntryUrl) {
|
|
123
|
+
try {
|
|
124
|
+
const { pathname } = new URL(remoteEntryUrl);
|
|
125
|
+
return /\.json$/i.test(pathname);
|
|
126
|
+
} catch {
|
|
127
|
+
return /\.json(?:[?#]|$)/i.test(remoteEntryUrl);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function isSsrEntry(remoteEntryUrl) {
|
|
131
|
+
return /\.ssr\.js(?:[?#].*)?$/.test(remoteEntryUrl);
|
|
132
|
+
}
|
|
100
133
|
function getManifestUrl(remoteEntryUrl) {
|
|
134
|
+
if (isManifestEntry(remoteEntryUrl)) return remoteEntryUrl;
|
|
101
135
|
return remoteEntryUrl.replace(/\/[^/]+$/, "/mf-manifest.json");
|
|
102
136
|
}
|
|
137
|
+
function getEntryFilename(entryUrl) {
|
|
138
|
+
return entryUrl.split("/").pop()?.replace(/[?#].*$/, "").replace(/\.[^.]+$/, "") ?? "remoteEntry";
|
|
139
|
+
}
|
|
140
|
+
function resolveEntryAssetUrl(entry, manifestUrl) {
|
|
141
|
+
const base = manifestUrl.replace(/\/[^/]+$/, "/");
|
|
142
|
+
return new URL(`${entry.path || ""}${entry.name}`, base).href;
|
|
143
|
+
}
|
|
103
144
|
function resolveSSREntryUrl(manifest, manifestUrl) {
|
|
104
145
|
const meta = manifest?.metaData;
|
|
105
146
|
if (!meta?.ssrRemoteEntry?.name) return null;
|
|
@@ -124,48 +165,72 @@ async function headCheckSsrEntry(candidate) {
|
|
|
124
165
|
} catch {}
|
|
125
166
|
return null;
|
|
126
167
|
}
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
168
|
+
function resolveAssetBaseUrl(entryUrl, manifest, manifestUrl) {
|
|
169
|
+
const remoteEntry = manifest?.metaData?.remoteEntry;
|
|
170
|
+
if (remoteEntry?.name) return resolveEntryAssetUrl(remoteEntry, manifestUrl);
|
|
171
|
+
if (!isManifestEntry(entryUrl)) return entryUrl;
|
|
172
|
+
return new URL("remoteEntry.js", manifestUrl.replace(/\/[^/]+$/, "/")).href;
|
|
173
|
+
}
|
|
174
|
+
async function buildEntryContext(entryUrl) {
|
|
175
|
+
const manifestUrl = getManifestUrl(entryUrl);
|
|
176
|
+
const manifest = await fetchManifestCached(manifestUrl);
|
|
177
|
+
const assetBaseUrl = resolveAssetBaseUrl(entryUrl, manifest, manifestUrl);
|
|
178
|
+
return {
|
|
179
|
+
entryUrl,
|
|
180
|
+
manifestUrl,
|
|
181
|
+
manifest,
|
|
182
|
+
assetBaseUrl,
|
|
183
|
+
filename: getEntryFilename(assetBaseUrl),
|
|
184
|
+
remoteOrigin: assetBaseUrl.replace(/\/[^/]+$/, "")
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function buildSsrEntryCandidates(ctx, options = {}) {
|
|
188
|
+
const { assetBaseUrl, filename, remoteOrigin } = ctx;
|
|
189
|
+
const base = assetBaseUrl.replace(/\.[^.]+$/, "");
|
|
190
|
+
const candidates = [];
|
|
191
|
+
if (!options.skipServerBuild) candidates.push({
|
|
192
|
+
url: `${remoteOrigin}/__mf_server__/${filename}.ssr.js`,
|
|
193
|
+
type: "module"
|
|
194
|
+
});
|
|
195
|
+
candidates.push({
|
|
196
|
+
url: `${base}.ssr.js`,
|
|
197
|
+
type: "module"
|
|
198
|
+
}, {
|
|
199
|
+
url: `${remoteOrigin}/__mf_ssr__/${filename}.ssr.js`,
|
|
200
|
+
type: "module"
|
|
201
|
+
});
|
|
202
|
+
return candidates;
|
|
203
|
+
}
|
|
204
|
+
async function resolveFirstReachableCandidate(candidates) {
|
|
145
205
|
for (const candidate of candidates) {
|
|
146
206
|
const hit = await headCheckSsrEntry(candidate);
|
|
147
207
|
if (hit) return hit;
|
|
148
208
|
}
|
|
149
209
|
return null;
|
|
150
210
|
}
|
|
151
|
-
async function
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
211
|
+
async function resolveSSREntryImpl(remoteEntryUrl) {
|
|
212
|
+
if (isSsrEntry(remoteEntryUrl)) return {
|
|
213
|
+
url: remoteEntryUrl,
|
|
214
|
+
type: "module"
|
|
215
|
+
};
|
|
216
|
+
if (!isManifestEntry(remoteEntryUrl)) {
|
|
217
|
+
const filename = getEntryFilename(remoteEntryUrl);
|
|
156
218
|
const fromServerBuild = await headCheckSsrEntry({
|
|
157
|
-
url: `${
|
|
219
|
+
url: `${remoteEntryUrl.replace(/\/[^/]+$/, "")}/__mf_server__/${filename}.ssr.js`,
|
|
158
220
|
type: "module"
|
|
159
221
|
});
|
|
160
222
|
if (fromServerBuild) return fromServerBuild;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
})
|
|
168
|
-
|
|
223
|
+
}
|
|
224
|
+
const ctx = await buildEntryContext(remoteEntryUrl);
|
|
225
|
+
if (ctx.manifest) {
|
|
226
|
+
const fromManifest = resolveSSREntryUrl(ctx.manifest, ctx.manifestUrl);
|
|
227
|
+
if (fromManifest) return fromManifest;
|
|
228
|
+
}
|
|
229
|
+
return resolveFirstReachableCandidate(buildSsrEntryCandidates(ctx, { skipServerBuild: !isManifestEntry(remoteEntryUrl) }));
|
|
230
|
+
}
|
|
231
|
+
async function getSSREntry(remoteEntryUrl) {
|
|
232
|
+
if (!ssrEntryCache.has(remoteEntryUrl)) ssrEntryCache.set(remoteEntryUrl, resolveSSREntryImpl(remoteEntryUrl));
|
|
233
|
+
return ssrEntryCache.get(remoteEntryUrl);
|
|
169
234
|
}
|
|
170
235
|
const tempFileCache = /* @__PURE__ */ new Map();
|
|
171
236
|
let ssrCacheDirPromise;
|
|
@@ -204,6 +269,9 @@ function transformSsrCode(code, base, sharedPkgMap) {
|
|
|
204
269
|
code = code.replace(/\b([A-Za-z_$][\w$]*)\s*\(\s*\(\s*\)\s*=>\s*import\(([^)]*)\)\s*,\s*\[\]\s*\)/g, "import($2)");
|
|
205
270
|
return code;
|
|
206
271
|
}
|
|
272
|
+
function isVitePreloadHelperSpecifier(specifier) {
|
|
273
|
+
return specifier.includes("preload-helper");
|
|
274
|
+
}
|
|
207
275
|
/**
|
|
208
276
|
* Fetch an HTTP ESM module, transform it, write it to a temp .js file and
|
|
209
277
|
* return the file path. Recursively does the same for HTTP transitive imports
|
|
@@ -213,12 +281,14 @@ async function fetchEsmToTempFile(url, tmpDir, visited, sharedPkgMap) {
|
|
|
213
281
|
if (visited.has(url)) return visited.get(url);
|
|
214
282
|
if (tempFileCache.has(url)) return tempFileCache.get(url);
|
|
215
283
|
const promise = (async () => {
|
|
216
|
-
|
|
284
|
+
const res = await fetch(url);
|
|
285
|
+
let code = await res.text();
|
|
286
|
+
if (!res.ok) throw new SsrEntryHttpError(url, res.status, res.statusText, getBodyPreview(code));
|
|
217
287
|
const base = url.replace(/\/[^/]*$/, "/");
|
|
218
288
|
const relImports = [];
|
|
219
289
|
const relRegex = /(?:from|export\s*\*\s*from|import\s*(?:\(|\s))\s*["'`]([^"'`\s]+)["'`]/g;
|
|
220
290
|
let m;
|
|
221
|
-
while ((m = relRegex.exec(code)) !== null) if (m[1].startsWith("./") || m[1].startsWith("../")) relImports.push(new URL(m[1], base).href);
|
|
291
|
+
while ((m = relRegex.exec(code)) !== null) if ((m[1].startsWith("./") || m[1].startsWith("../")) && !isVitePreloadHelperSpecifier(m[1])) relImports.push(new URL(m[1], base).href);
|
|
222
292
|
const subMap = /* @__PURE__ */ new Map();
|
|
223
293
|
await Promise.all([...new Set(relImports)].filter((u) => u.startsWith("http://") || u.startsWith("https://")).map(async (u) => {
|
|
224
294
|
const tmpPath = await fetchEsmToTempFile(u, tmpDir, visited, sharedPkgMap);
|
|
@@ -257,11 +327,14 @@ async function loadSSRRemoteEntry(ssrEntry, resolvedShared = {}) {
|
|
|
257
327
|
if (urlObj.pathname.includes("/__mf_ssr__/")) {
|
|
258
328
|
const remoteOrigin = urlObj.origin;
|
|
259
329
|
const runner = await getOrCreateRunner(remoteOrigin);
|
|
260
|
-
if (!runner)
|
|
261
|
-
|
|
262
|
-
|
|
330
|
+
if (!runner) {
|
|
331
|
+
if (process.env.NODE_ENV !== "production") return null;
|
|
332
|
+
} else try {
|
|
333
|
+
const mod = await runner.import(urlObj.pathname);
|
|
334
|
+
if (mod && typeof mod === "object" && "init" in mod) return mod;
|
|
335
|
+
if (process.env.NODE_ENV !== "production") return null;
|
|
263
336
|
} catch {
|
|
264
|
-
return null;
|
|
337
|
+
if (process.env.NODE_ENV !== "production") return null;
|
|
265
338
|
}
|
|
266
339
|
}
|
|
267
340
|
const { mkdirSync } = await _fs();
|
|
@@ -270,7 +343,8 @@ async function loadSSRRemoteEntry(ssrEntry, resolvedShared = {}) {
|
|
|
270
343
|
const sharedPkgMap = new Map(Object.entries(resolvedShared));
|
|
271
344
|
try {
|
|
272
345
|
return await importTempModule(await fetchEsmToTempFile(url, cacheDir, /* @__PURE__ */ new Map(), sharedPkgMap));
|
|
273
|
-
} catch {
|
|
346
|
+
} catch (error) {
|
|
347
|
+
if (isSsrEntryHttpError(error)) throw error;
|
|
274
348
|
return null;
|
|
275
349
|
}
|
|
276
350
|
}
|