@module-federation/vite 1.20.1 → 1.20.3
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/lib/buildPaths-BkaQHrd2.js +47 -0
- package/lib/index.js +372 -307
- package/lib/pathNormalization-CLDIcf9-.js +119 -0
- package/lib/{ssrEntryLoader-Bw423jj_.js → ssrEntryLoader-7v0Do_g5.js} +47 -16
- package/lib/{ssrVmStrategy-7HAPa-Vc.js → ssrVmStrategy-BkEp3YIv.js} +23 -4
- package/lib/utils/ssrEntryLoader.d.ts +4 -5
- package/lib/utils/ssrEntryLoader.js +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
//#region src/utils/pathNormalization.ts
|
|
2
|
+
const COMMON_SHARED_SUBPATHS = {
|
|
3
|
+
react: [
|
|
4
|
+
"react/jsx-runtime",
|
|
5
|
+
"react/jsx-dev-runtime",
|
|
6
|
+
"react/compiler-runtime"
|
|
7
|
+
],
|
|
8
|
+
"react-dom": [
|
|
9
|
+
"react-dom/client",
|
|
10
|
+
"react-dom/server",
|
|
11
|
+
"react-dom/server.browser"
|
|
12
|
+
],
|
|
13
|
+
"solid-js": [
|
|
14
|
+
"solid-js/web",
|
|
15
|
+
"solid-js/store",
|
|
16
|
+
"solid-js/html",
|
|
17
|
+
"solid-js/h"
|
|
18
|
+
],
|
|
19
|
+
zustand: ["zustand/vanilla", "zustand/react"]
|
|
20
|
+
};
|
|
21
|
+
const VITE_DEFAULT_ASSET_TYPES = [
|
|
22
|
+
"apng",
|
|
23
|
+
"bmp",
|
|
24
|
+
"png",
|
|
25
|
+
"jpe?g",
|
|
26
|
+
"jfif",
|
|
27
|
+
"pjpeg",
|
|
28
|
+
"pjp",
|
|
29
|
+
"gif",
|
|
30
|
+
"svg",
|
|
31
|
+
"ico",
|
|
32
|
+
"webp",
|
|
33
|
+
"avif",
|
|
34
|
+
"cur",
|
|
35
|
+
"jxl",
|
|
36
|
+
"mp4",
|
|
37
|
+
"webm",
|
|
38
|
+
"ogg",
|
|
39
|
+
"mp3",
|
|
40
|
+
"wav",
|
|
41
|
+
"flac",
|
|
42
|
+
"aac",
|
|
43
|
+
"opus",
|
|
44
|
+
"mov",
|
|
45
|
+
"m4a",
|
|
46
|
+
"vtt",
|
|
47
|
+
"woff2?",
|
|
48
|
+
"eot",
|
|
49
|
+
"ttf",
|
|
50
|
+
"otf",
|
|
51
|
+
"webmanifest",
|
|
52
|
+
"pdf",
|
|
53
|
+
"txt"
|
|
54
|
+
];
|
|
55
|
+
const ASSET_LIKE_IMPORT_RE = new RegExp(`\\.(${[...[
|
|
56
|
+
"css",
|
|
57
|
+
"scss",
|
|
58
|
+
"sass",
|
|
59
|
+
"less",
|
|
60
|
+
"styl",
|
|
61
|
+
"stylus"
|
|
62
|
+
], ...VITE_DEFAULT_ASSET_TYPES].join("|")})(?:[?#].*)?$`, "i");
|
|
63
|
+
function isAssetLikeImport(source) {
|
|
64
|
+
return ASSET_LIKE_IMPORT_RE.test(source);
|
|
65
|
+
}
|
|
66
|
+
const VITE_OPTIMIZABLE_ENTRY_RE = /\.[cm]?[jt]s$/;
|
|
67
|
+
function isViteOptimizableEntry(resolvedPath) {
|
|
68
|
+
return VITE_OPTIMIZABLE_ENTRY_RE.test(resolvedPath);
|
|
69
|
+
}
|
|
70
|
+
function removeTrailingSlash(value) {
|
|
71
|
+
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
72
|
+
}
|
|
73
|
+
function ensureTrailingSlash(value) {
|
|
74
|
+
return `${removeTrailingSlash(value)}/`;
|
|
75
|
+
}
|
|
76
|
+
function getBasePath(base) {
|
|
77
|
+
return removeTrailingSlash(base || "/");
|
|
78
|
+
}
|
|
79
|
+
function isNuxtClientBase(base) {
|
|
80
|
+
return getBasePath(base).endsWith("/_nuxt");
|
|
81
|
+
}
|
|
82
|
+
function normalizeNodeModulePath(source) {
|
|
83
|
+
const queryIndex = source.indexOf("?");
|
|
84
|
+
return (queryIndex === -1 ? source : source.slice(0, queryIndex)).replace(/\\/g, "/");
|
|
85
|
+
}
|
|
86
|
+
function isNodeModulePath(source) {
|
|
87
|
+
return source.includes("/node_modules/") || source.includes("\\node_modules\\");
|
|
88
|
+
}
|
|
89
|
+
function filterId(id) {
|
|
90
|
+
return typeof id === "string" && !id.includes("\0");
|
|
91
|
+
}
|
|
92
|
+
function getMatchingNodeModuleSubpath(source, candidates) {
|
|
93
|
+
const normalized = normalizeNodeModulePath(source);
|
|
94
|
+
return [...candidates].sort((a, b) => b.length - a.length).find((candidate) => normalized.includes(`/node_modules/${candidate}/`) || normalized.includes(`/node_modules/${candidate}.`));
|
|
95
|
+
}
|
|
96
|
+
function getCommonSharedSubpaths(sharedKey) {
|
|
97
|
+
return COMMON_SHARED_SUBPATHS[removeTrailingSlash(sharedKey)] || [];
|
|
98
|
+
}
|
|
99
|
+
function getCommonSharedSubpathFromNodeModulePath(source, sharedKey) {
|
|
100
|
+
return getMatchingNodeModuleSubpath(source, getCommonSharedSubpaths(removeTrailingSlash(sharedKey)));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Resolves the public path for remote entries
|
|
104
|
+
* @param options - Module Federation options
|
|
105
|
+
* @param viteBase - Vite's base config value
|
|
106
|
+
* @param originalBase - Original base config before any transformations
|
|
107
|
+
* @returns The resolved public path
|
|
108
|
+
*/
|
|
109
|
+
function resolvePublicPath(options, viteBase, originalBase) {
|
|
110
|
+
if (options.publicPath && options.publicPath !== "auto") return options.publicPath;
|
|
111
|
+
if (!originalBase) return "auto";
|
|
112
|
+
if (viteBase) {
|
|
113
|
+
if (viteBase === "./") return "auto";
|
|
114
|
+
return ensureTrailingSlash(viteBase);
|
|
115
|
+
}
|
|
116
|
+
return "auto";
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
export { getMatchingNodeModuleSubpath as a, isNuxtClientBase as c, resolvePublicPath as d, getCommonSharedSubpaths as i, isViteOptimizableEntry as l, getBasePath as n, isAssetLikeImport as o, getCommonSharedSubpathFromNodeModulePath as r, isNodeModulePath as s, filterId as t, normalizeNodeModulePath as u };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t as EXTERNAL_URL_RE } from "./buildPaths-BkaQHrd2.js";
|
|
1
2
|
//#region src/utils/fetchWithTimeout.ts
|
|
2
3
|
const DEFAULT_SSR_FETCH_TIMEOUT_MS = 1e4;
|
|
3
4
|
const DEFAULT_SSR_FETCH_MAX_BYTES = 10 * 1024 * 1024;
|
|
@@ -116,11 +117,10 @@ async function readResponseTextBounded(res, maxBytes = DEFAULT_SSR_FETCH_MAX_BYT
|
|
|
116
117
|
* module source through Vite's plugin pipeline, avoiding serialisation which
|
|
117
118
|
* cannot faithfully represent React components or closures.
|
|
118
119
|
*
|
|
119
|
-
* Dev mode on Vite < 8 is NOT supported
|
|
120
|
-
* `
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* from `pluginSSRRemoteEntry.configureServer`.
|
|
120
|
+
* Dev mode on Vite < 8 is NOT supported by this integration because the
|
|
121
|
+
* cross-process `fetchModule` proxy uses Vite 8's environment APIs.
|
|
122
|
+
* `ModuleRunner` itself is available in earlier Vite versions, but an older
|
|
123
|
+
* remote needs a different transport and server endpoint.
|
|
124
124
|
*
|
|
125
125
|
* Exported as a plain factory function so it can be serialised into the
|
|
126
126
|
* generated runtimePlugins list in virtualRemotes.ts.
|
|
@@ -135,17 +135,21 @@ async function nodeImport(id) {
|
|
|
135
135
|
}
|
|
136
136
|
const isNodeServer = () => typeof globalThis.process?.versions?.node === "string";
|
|
137
137
|
const runnerCache = /* @__PURE__ */ new Map();
|
|
138
|
+
function getSortedRecordEntries(record) {
|
|
139
|
+
return Object.entries(record).sort(([left], [right]) => left.localeCompare(right));
|
|
140
|
+
}
|
|
138
141
|
/**
|
|
139
|
-
* Load `vite/module-runner`. Returns null
|
|
140
|
-
*
|
|
142
|
+
* Load `vite/module-runner`. Returns null when the installed Vite does not
|
|
143
|
+
* expose the module-runner entry point.
|
|
141
144
|
*/
|
|
142
145
|
async function getModuleRunnerModule() {
|
|
146
|
+
const moduleRunnerId = ["vite", "module-runner"].join("/");
|
|
143
147
|
try {
|
|
144
148
|
const { createRequire } = await nodeImport("module");
|
|
145
|
-
return createRequire(import.meta.url)(
|
|
149
|
+
return createRequire(import.meta.url)(moduleRunnerId);
|
|
146
150
|
} catch {}
|
|
147
151
|
try {
|
|
148
|
-
return await
|
|
152
|
+
return await nodeImport(moduleRunnerId);
|
|
149
153
|
} catch {
|
|
150
154
|
return null;
|
|
151
155
|
}
|
|
@@ -155,11 +159,33 @@ async function getModuleRunnerModule() {
|
|
|
155
159
|
* `/__mf_runner__` endpoint. Each HTTP POST carries a `fetchModule` invoke
|
|
156
160
|
* payload; the remote responds with the transformed module source as JSON.
|
|
157
161
|
*
|
|
158
|
-
*
|
|
159
|
-
* the `/__mf_runner__` proxy
|
|
162
|
+
* The cross-process transport is Vite 8+ only because older versions do not
|
|
163
|
+
* expose the `/__mf_runner__` environment proxy used here.
|
|
160
164
|
*/
|
|
161
|
-
|
|
162
|
-
|
|
165
|
+
function getRunnerCacheKey(remoteOrigin, resolvedShared, fetchTimeoutMs, fetchMaxBytes) {
|
|
166
|
+
return JSON.stringify([
|
|
167
|
+
remoteOrigin,
|
|
168
|
+
fetchTimeoutMs,
|
|
169
|
+
fetchMaxBytes,
|
|
170
|
+
getSortedRecordEntries(resolvedShared)
|
|
171
|
+
]);
|
|
172
|
+
}
|
|
173
|
+
async function resolveSharedExternal(id, resolvedShared) {
|
|
174
|
+
if (typeof id !== "string") return null;
|
|
175
|
+
const resolved = resolvedShared[id];
|
|
176
|
+
if (!resolved) return null;
|
|
177
|
+
if (EXTERNAL_URL_RE.test(resolved)) return {
|
|
178
|
+
externalize: resolved,
|
|
179
|
+
type: "module"
|
|
180
|
+
};
|
|
181
|
+
const { pathToFileURL } = await _url();
|
|
182
|
+
return {
|
|
183
|
+
externalize: pathToFileURL(resolved).href,
|
|
184
|
+
type: "module"
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
async function getOrCreateRunner(remoteOrigin, resolvedShared, fetchTimeoutMs, fetchMaxBytes) {
|
|
188
|
+
const cacheKey = getRunnerCacheKey(remoteOrigin, resolvedShared, fetchTimeoutMs, fetchMaxBytes);
|
|
163
189
|
if (runnerCache.has(cacheKey)) return runnerCache.get(cacheKey);
|
|
164
190
|
const promise = (async () => {
|
|
165
191
|
const viteRunner = await getModuleRunnerModule();
|
|
@@ -170,6 +196,10 @@ async function getOrCreateRunner(remoteOrigin, fetchTimeoutMs, fetchMaxBytes) {
|
|
|
170
196
|
return new ModuleRunner({
|
|
171
197
|
hmr: false,
|
|
172
198
|
transport: { async invoke(payload) {
|
|
199
|
+
if (payload.data.name === "fetchModule") {
|
|
200
|
+
const sharedExternal = await resolveSharedExternal(payload.data.data[0], resolvedShared);
|
|
201
|
+
if (sharedExternal) return { result: sharedExternal };
|
|
202
|
+
}
|
|
173
203
|
const text = await readResponseTextBounded(await fetchWithTimeout(runnerEndpoint, {
|
|
174
204
|
method: "POST",
|
|
175
205
|
headers: { "Content-Type": "application/json" },
|
|
@@ -189,6 +219,7 @@ const _path = () => nodeImport("path");
|
|
|
189
219
|
const _fs = () => nodeImport("fs");
|
|
190
220
|
const _crypto = () => nodeImport("crypto");
|
|
191
221
|
const _module = () => nodeImport("module");
|
|
222
|
+
const _url = () => nodeImport("url");
|
|
192
223
|
/**
|
|
193
224
|
* Version key for a resolved SSR entry. Derived from the remote's manifest
|
|
194
225
|
* content so a redeploy at the same URL produces a different key, which in
|
|
@@ -448,7 +479,7 @@ function revalidate(remoteEntryUrl) {
|
|
|
448
479
|
const tempFileCache = /* @__PURE__ */ new Map();
|
|
449
480
|
const tempFilePathCache = /* @__PURE__ */ new Map();
|
|
450
481
|
function getSsrTransformContextKey(resolvedShared, shareScopeName) {
|
|
451
|
-
return JSON.stringify([shareScopeName,
|
|
482
|
+
return JSON.stringify([shareScopeName, getSortedRecordEntries(resolvedShared)]);
|
|
452
483
|
}
|
|
453
484
|
let ssrCacheDirPromise;
|
|
454
485
|
async function getSSRCacheDir() {
|
|
@@ -572,7 +603,7 @@ async function importTempModule(filePath, versionKey) {
|
|
|
572
603
|
}
|
|
573
604
|
let warnedVmUnavailable = false;
|
|
574
605
|
async function tryVmStrategy(ssrEntry, options) {
|
|
575
|
-
const { loadViaVmStrategy, isVmStrategyAvailable } = await import("./ssrVmStrategy-
|
|
606
|
+
const { loadViaVmStrategy, isVmStrategyAvailable } = await import("./ssrVmStrategy-BkEp3YIv.js");
|
|
576
607
|
if (!await isVmStrategyAvailable()) {
|
|
577
608
|
if (!warnedVmUnavailable) {
|
|
578
609
|
warnedVmUnavailable = true;
|
|
@@ -604,7 +635,7 @@ async function loadSSRRemoteEntry(ssrEntry, options) {
|
|
|
604
635
|
const urlObj = new URL(url);
|
|
605
636
|
if (urlObj.pathname.includes("/__mf_ssr__/")) {
|
|
606
637
|
const remoteOrigin = urlObj.origin;
|
|
607
|
-
const runner = await getOrCreateRunner(remoteOrigin, options.fetchTimeoutMs, options.fetchMaxBytes);
|
|
638
|
+
const runner = await getOrCreateRunner(remoteOrigin, resolvedShared, options.fetchTimeoutMs, options.fetchMaxBytes);
|
|
608
639
|
if (!runner) {
|
|
609
640
|
if (process.env.NODE_ENV !== "production") return null;
|
|
610
641
|
} else try {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as getCommonSharedSubpaths } from "./pathNormalization-CLDIcf9-.js";
|
|
2
|
+
import { c as readResponseTextBounded, n as neutralizeBrowserPreloadHelpers, s as fetchWithTimeout, t as SsrEntryHttpError } from "./ssrEntryLoader-7v0Do_g5.js";
|
|
2
3
|
//#region src/utils/ssrVmStrategy.ts
|
|
3
4
|
/**
|
|
4
5
|
* vm.SourceTextModule strategy for loading remote SSR entries.
|
|
@@ -39,6 +40,22 @@ async function getVmApi() {
|
|
|
39
40
|
async function isVmStrategyAvailable() {
|
|
40
41
|
return await getVmApi() !== null;
|
|
41
42
|
}
|
|
43
|
+
function findVmSharedKey(specifier, shared) {
|
|
44
|
+
if (!shared) return;
|
|
45
|
+
const keys = Object.keys(shared);
|
|
46
|
+
if (Object.prototype.hasOwnProperty.call(shared, specifier)) return specifier;
|
|
47
|
+
const vueKey = keys.find((key) => key.endsWith("/") ? key.slice(0, -1) === "vue" : key === "vue");
|
|
48
|
+
if (vueKey && (specifier === "vue/dist/vue.esm-bundler.js" || specifier === "vue/dist/vue.runtime.esm-bundler.js")) return vueKey;
|
|
49
|
+
const commonSubpathKey = keys.find((key) => {
|
|
50
|
+
return getCommonSharedSubpaths(key.endsWith("/") ? key.slice(0, -1) : key).includes(specifier);
|
|
51
|
+
});
|
|
52
|
+
if (commonSubpathKey) return commonSubpathKey;
|
|
53
|
+
return keys.find((key) => {
|
|
54
|
+
if (!key.endsWith("/")) return false;
|
|
55
|
+
const keyBase = key.slice(0, -1);
|
|
56
|
+
return specifier === keyBase || specifier.startsWith(`${keyBase}/`);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
42
59
|
function getFederationInstances() {
|
|
43
60
|
return globalThis.__FEDERATION__?.__INSTANCES__ ?? [];
|
|
44
61
|
}
|
|
@@ -51,9 +68,11 @@ async function loadBareModule(specifier, options) {
|
|
|
51
68
|
const instances = owner ? [owner] : getFederationInstances();
|
|
52
69
|
for (const instance of instances) {
|
|
53
70
|
if (typeof instance?.loadShare !== "function") continue;
|
|
54
|
-
const shared = instance.options?.shared
|
|
55
|
-
|
|
56
|
-
|
|
71
|
+
const shared = instance.options?.shared;
|
|
72
|
+
const sharedKey = findVmSharedKey(specifier, shared);
|
|
73
|
+
const shareConfig = sharedKey ? shared?.[sharedKey] : void 0;
|
|
74
|
+
if (!shareConfig) continue;
|
|
75
|
+
if (!(Array.isArray(shareConfig.scope) ? shareConfig.scope : [shareConfig.scope ?? "default"]).includes(options.shareScopeName)) continue;
|
|
57
76
|
try {
|
|
58
77
|
const factory = await instance.loadShare(specifier);
|
|
59
78
|
if (typeof factory === "function") {
|
|
@@ -17,11 +17,10 @@
|
|
|
17
17
|
* module source through Vite's plugin pipeline, avoiding serialisation which
|
|
18
18
|
* cannot faithfully represent React components or closures.
|
|
19
19
|
*
|
|
20
|
-
* Dev mode on Vite < 8 is NOT supported
|
|
21
|
-
* `
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* from `pluginSSRRemoteEntry.configureServer`.
|
|
20
|
+
* Dev mode on Vite < 8 is NOT supported by this integration because the
|
|
21
|
+
* cross-process `fetchModule` proxy uses Vite 8's environment APIs.
|
|
22
|
+
* `ModuleRunner` itself is available in earlier Vite versions, but an older
|
|
23
|
+
* remote needs a different transport and server endpoint.
|
|
25
24
|
*
|
|
26
25
|
* Exported as a plain factory function so it can be serialised into the
|
|
27
26
|
* generated runtimePlugins list in virtualRemotes.ts.
|
|
@@ -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-7v0Do_g5.js";
|
|
2
2
|
export { SsrEntryHttpError, ssrEntryLoaderPlugin as default, neutralizeBrowserPreloadHelpers, revalidate };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/vite",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.3",
|
|
4
4
|
"description": "Vite plugin for Module Federation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"rollup": "4.62.3",
|
|
91
91
|
"tsdown": "0.22.14",
|
|
92
92
|
"typescript": "7.0.2",
|
|
93
|
-
"vite": "8.
|
|
94
|
-
"vitest": "4.
|
|
93
|
+
"vite": "8.2.0",
|
|
94
|
+
"vitest": "4.1.10"
|
|
95
95
|
}
|
|
96
|
-
}
|
|
96
|
+
}
|