@module-federation/vite 1.18.1 → 1.19.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 +23 -0
- package/lib/index.d.ts +21 -0
- package/lib/index.js +632 -361
- package/lib/{pluginDts-CGDIZCsD.js → pluginDts-Cd2opGcZ.js} +8 -0
- package/lib/{ssrEntryLoader-DgsCQOqq.js → ssrEntryLoader-CuZVKlRm.js} +114 -40
- package/lib/{ssrVmStrategy-ChF8MB7l.js → ssrVmStrategy-Dpw20xiw.js} +5 -4
- package/lib/utils/ssrEntryLoader.d.ts +5 -0
- package/lib/utils/ssrEntryLoader.js +1 -1
- package/package.json +2 -2
|
@@ -102,6 +102,7 @@ let packageDetectionCwd;
|
|
|
102
102
|
function getDependencyCacheKey(cwd, dependencyName) {
|
|
103
103
|
return `${cwd}:${dependencyName}`;
|
|
104
104
|
}
|
|
105
|
+
const installedPackageJsonCache = /* @__PURE__ */ new Map();
|
|
105
106
|
function setPackageDetectionCwd(cwd) {
|
|
106
107
|
packageDetectionCwd = cwd;
|
|
107
108
|
}
|
|
@@ -398,6 +399,13 @@ const sharedCacheHelperCode = `const __mfGetSharedCacheDescriptor = (pkg, single
|
|
|
398
399
|
function getInstalledPackageJson(pkg, opts) {
|
|
399
400
|
const cwd = opts?.cwd || getPackageDetectionCwd();
|
|
400
401
|
const packageName = opts?.packageName || getPackageName(pkg);
|
|
402
|
+
const cacheKey = `${cwd}\0${pkg}\0${packageName}\0${opts?.fromResolvedEntry ?? ""}`;
|
|
403
|
+
if (installedPackageJsonCache.has(cacheKey)) return installedPackageJsonCache.get(cacheKey);
|
|
404
|
+
const result = resolveInstalledPackageJson(pkg, cwd, packageName, opts);
|
|
405
|
+
installedPackageJsonCache.set(cacheKey, result);
|
|
406
|
+
return result;
|
|
407
|
+
}
|
|
408
|
+
function resolveInstalledPackageJson(pkg, cwd, packageName, opts) {
|
|
401
409
|
const tryReadPackageJson = (packageJsonPath) => {
|
|
402
410
|
if (!existsSync(packageJsonPath)) return void 0;
|
|
403
411
|
try {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
//#region src/utils/fetchWithTimeout.ts
|
|
2
2
|
const DEFAULT_SSR_FETCH_TIMEOUT_MS = 1e4;
|
|
3
|
+
const DEFAULT_SSR_FETCH_MAX_BYTES = 10 * 1024 * 1024;
|
|
3
4
|
function getFetchUrl(input) {
|
|
4
5
|
const raw = typeof input === "string" || input instanceof URL ? String(input) : input.url;
|
|
5
6
|
return new URL(raw);
|
|
@@ -10,6 +11,11 @@ function getSecureFetchUrl(input) {
|
|
|
10
11
|
if (url.protocol !== "https:" && !(url.protocol === "http:" && isLoopback)) throw new TypeError(`Refusing to fetch SSR resource over an insecure connection: ${url}`);
|
|
11
12
|
return url;
|
|
12
13
|
}
|
|
14
|
+
function isAbortLikeError(error) {
|
|
15
|
+
if (!error || typeof error !== "object") return false;
|
|
16
|
+
const name = error.name;
|
|
17
|
+
return name === "AbortError" || name === "TimeoutError";
|
|
18
|
+
}
|
|
13
19
|
/** Fetch with a bounded wait. Set timeoutMs to 0 to disable the timeout. */
|
|
14
20
|
async function fetchWithTimeout(input, init = {}, timeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS) {
|
|
15
21
|
const inputUrl = getSecureFetchUrl(input);
|
|
@@ -29,11 +35,67 @@ async function fetchWithTimeout(input, init = {}, timeoutMs = DEFAULT_SSR_FETCH_
|
|
|
29
35
|
try {
|
|
30
36
|
return await request(inputUrl);
|
|
31
37
|
} catch (error) {
|
|
32
|
-
if (inputUrl.hostname !== "localhost") throw error;
|
|
38
|
+
if (inputUrl.hostname !== "localhost" || isAbortLikeError(error)) throw error;
|
|
33
39
|
inputUrl.hostname = "[::1]";
|
|
34
40
|
return request(inputUrl);
|
|
35
41
|
}
|
|
36
42
|
}
|
|
43
|
+
var SsrFetchBodyTooLargeError = class extends Error {
|
|
44
|
+
url;
|
|
45
|
+
maxBytes;
|
|
46
|
+
declaredBytes;
|
|
47
|
+
constructor(url, maxBytes, declaredBytes) {
|
|
48
|
+
super(declaredBytes != null ? `SSR response from ${url} declared ${declaredBytes} bytes which exceeds the ${maxBytes}-byte limit` : `SSR response from ${url} exceeded the ${maxBytes}-byte limit`);
|
|
49
|
+
this.name = "SsrFetchBodyTooLargeError";
|
|
50
|
+
this.url = url;
|
|
51
|
+
this.maxBytes = maxBytes;
|
|
52
|
+
this.declaredBytes = declaredBytes;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
function isSsrFetchBodyTooLargeError(error) {
|
|
56
|
+
return error instanceof SsrFetchBodyTooLargeError;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Read a response body as text, rejecting when it exceeds `maxBytes`.
|
|
60
|
+
* Set `maxBytes` to 0 (or a non-finite value) to disable the limit.
|
|
61
|
+
*/
|
|
62
|
+
async function readResponseTextBounded(res, maxBytes = DEFAULT_SSR_FETCH_MAX_BYTES, url = res.url || "unknown") {
|
|
63
|
+
if (!Number.isFinite(maxBytes) || maxBytes <= 0) return res.text();
|
|
64
|
+
const contentLengthHeader = res.headers?.get?.("content-length") ?? null;
|
|
65
|
+
if (contentLengthHeader != null) {
|
|
66
|
+
const declaredBytes = Number(contentLengthHeader);
|
|
67
|
+
if (Number.isFinite(declaredBytes) && declaredBytes > maxBytes) {
|
|
68
|
+
try {
|
|
69
|
+
await res.body?.cancel();
|
|
70
|
+
} catch {}
|
|
71
|
+
throw new SsrFetchBodyTooLargeError(url, maxBytes, declaredBytes);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (!res.body) return res.text();
|
|
75
|
+
const reader = res.body.getReader();
|
|
76
|
+
const chunks = [];
|
|
77
|
+
let total = 0;
|
|
78
|
+
while (true) {
|
|
79
|
+
const { done, value } = await reader.read();
|
|
80
|
+
if (done) break;
|
|
81
|
+
if (!value) continue;
|
|
82
|
+
total += value.byteLength;
|
|
83
|
+
if (total > maxBytes) {
|
|
84
|
+
try {
|
|
85
|
+
await reader.cancel();
|
|
86
|
+
} catch {}
|
|
87
|
+
throw new SsrFetchBodyTooLargeError(url, maxBytes);
|
|
88
|
+
}
|
|
89
|
+
chunks.push(value);
|
|
90
|
+
}
|
|
91
|
+
const merged = new Uint8Array(total);
|
|
92
|
+
let offset = 0;
|
|
93
|
+
for (const chunk of chunks) {
|
|
94
|
+
merged.set(chunk, offset);
|
|
95
|
+
offset += chunk.byteLength;
|
|
96
|
+
}
|
|
97
|
+
return new TextDecoder().decode(merged);
|
|
98
|
+
}
|
|
37
99
|
//#endregion
|
|
38
100
|
//#region src/utils/ssrEntryLoader.ts
|
|
39
101
|
/**
|
|
@@ -93,8 +155,8 @@ async function getModuleRunnerModule() {
|
|
|
93
155
|
* This is Vite 8+ only — older versions don't expose `vite/module-runner` or
|
|
94
156
|
* the `/__mf_runner__` proxy endpoint.
|
|
95
157
|
*/
|
|
96
|
-
async function getOrCreateRunner(remoteOrigin, fetchTimeoutMs) {
|
|
97
|
-
const cacheKey = `${fetchTimeoutMs}::${remoteOrigin}`;
|
|
158
|
+
async function getOrCreateRunner(remoteOrigin, fetchTimeoutMs, fetchMaxBytes) {
|
|
159
|
+
const cacheKey = `${fetchTimeoutMs}::${fetchMaxBytes}::${remoteOrigin}`;
|
|
98
160
|
if (runnerCache.has(cacheKey)) return runnerCache.get(cacheKey);
|
|
99
161
|
const promise = (async () => {
|
|
100
162
|
const viteRunner = await getModuleRunnerModule();
|
|
@@ -105,11 +167,12 @@ async function getOrCreateRunner(remoteOrigin, fetchTimeoutMs) {
|
|
|
105
167
|
return new ModuleRunner({
|
|
106
168
|
hmr: false,
|
|
107
169
|
transport: { async invoke(payload) {
|
|
108
|
-
|
|
170
|
+
const text = await readResponseTextBounded(await fetchWithTimeout(runnerEndpoint, {
|
|
109
171
|
method: "POST",
|
|
110
172
|
headers: { "Content-Type": "application/json" },
|
|
111
173
|
body: JSON.stringify(payload)
|
|
112
|
-
}, fetchTimeoutMs))
|
|
174
|
+
}, fetchTimeoutMs), fetchMaxBytes, runnerEndpoint);
|
|
175
|
+
return JSON.parse(text);
|
|
113
176
|
} }
|
|
114
177
|
}, new ESModulesEvaluator());
|
|
115
178
|
} catch {
|
|
@@ -146,8 +209,8 @@ function computeManifestVersionKey(manifest) {
|
|
|
146
209
|
}
|
|
147
210
|
const ssrEntryCache = /* @__PURE__ */ new Map();
|
|
148
211
|
const manifestFetchCache = /* @__PURE__ */ new Map();
|
|
149
|
-
function makeUrlCacheKey(url, fetchTimeoutMs) {
|
|
150
|
-
return `${fetchTimeoutMs}::${url}`;
|
|
212
|
+
function makeUrlCacheKey(url, fetchTimeoutMs, fetchMaxBytes) {
|
|
213
|
+
return `${fetchTimeoutMs}::${fetchMaxBytes}::${url}`;
|
|
151
214
|
}
|
|
152
215
|
var SsrEntryHttpError = class extends Error {
|
|
153
216
|
constructor(url, status, statusText, bodyPreview) {
|
|
@@ -165,22 +228,26 @@ function getBodyPreview(body) {
|
|
|
165
228
|
function isSsrEntryHttpError(error) {
|
|
166
229
|
return error instanceof SsrEntryHttpError;
|
|
167
230
|
}
|
|
168
|
-
async function fetchManifest(manifestUrl, fetchTimeoutMs) {
|
|
231
|
+
async function fetchManifest(manifestUrl, fetchTimeoutMs, fetchMaxBytes) {
|
|
169
232
|
try {
|
|
170
233
|
const res = await fetchWithTimeout(manifestUrl, {}, fetchTimeoutMs);
|
|
171
234
|
if (!res.ok) return null;
|
|
172
|
-
|
|
173
|
-
|
|
235
|
+
const text = await readResponseTextBounded(res, fetchMaxBytes, manifestUrl);
|
|
236
|
+
return JSON.parse(text);
|
|
237
|
+
} catch (error) {
|
|
238
|
+
if (isSsrFetchBodyTooLargeError(error)) throw error;
|
|
174
239
|
return null;
|
|
175
240
|
}
|
|
176
241
|
}
|
|
177
|
-
async function fetchManifestCached(manifestUrl, fetchTimeoutMs) {
|
|
178
|
-
const cacheKey = makeUrlCacheKey(manifestUrl, fetchTimeoutMs);
|
|
242
|
+
async function fetchManifestCached(manifestUrl, fetchTimeoutMs, fetchMaxBytes) {
|
|
243
|
+
const cacheKey = makeUrlCacheKey(manifestUrl, fetchTimeoutMs, fetchMaxBytes);
|
|
179
244
|
if (!manifestFetchCache.has(cacheKey)) {
|
|
180
|
-
const promise = fetchManifest(manifestUrl, fetchTimeoutMs);
|
|
245
|
+
const promise = fetchManifest(manifestUrl, fetchTimeoutMs, fetchMaxBytes);
|
|
181
246
|
manifestFetchCache.set(cacheKey, promise);
|
|
182
247
|
promise.then((manifest) => {
|
|
183
248
|
if (!manifest && manifestFetchCache.get(cacheKey) === promise) manifestFetchCache.delete(cacheKey);
|
|
249
|
+
}, () => {
|
|
250
|
+
if (manifestFetchCache.get(cacheKey) === promise) manifestFetchCache.delete(cacheKey);
|
|
184
251
|
});
|
|
185
252
|
}
|
|
186
253
|
return manifestFetchCache.get(cacheKey);
|
|
@@ -239,9 +306,9 @@ function resolveAssetBaseUrl(entryUrl, manifest, manifestUrl) {
|
|
|
239
306
|
if (!isManifestEntry(entryUrl)) return entryUrl;
|
|
240
307
|
return new URL("remoteEntry.js", manifestUrl.replace(/\/[^/]+$/, "/")).href;
|
|
241
308
|
}
|
|
242
|
-
async function buildEntryContext(entryUrl, fetchTimeoutMs) {
|
|
309
|
+
async function buildEntryContext(entryUrl, fetchTimeoutMs, fetchMaxBytes) {
|
|
243
310
|
const manifestUrl = getManifestUrl(entryUrl);
|
|
244
|
-
const manifest = await fetchManifestCached(manifestUrl, fetchTimeoutMs);
|
|
311
|
+
const manifest = await fetchManifestCached(manifestUrl, fetchTimeoutMs, fetchMaxBytes);
|
|
245
312
|
const assetBaseUrl = resolveAssetBaseUrl(entryUrl, manifest, manifestUrl);
|
|
246
313
|
return {
|
|
247
314
|
entryUrl,
|
|
@@ -279,7 +346,7 @@ async function resolveFirstReachableCandidate(candidates, fetchTimeoutMs) {
|
|
|
279
346
|
}
|
|
280
347
|
return null;
|
|
281
348
|
}
|
|
282
|
-
async function resolveSSREntryImpl(remoteEntryUrl, fetchTimeoutMs) {
|
|
349
|
+
async function resolveSSREntryImpl(remoteEntryUrl, fetchTimeoutMs, fetchMaxBytes) {
|
|
283
350
|
if (isSsrEntry(remoteEntryUrl)) return {
|
|
284
351
|
url: remoteEntryUrl,
|
|
285
352
|
type: "module",
|
|
@@ -294,33 +361,35 @@ async function resolveSSREntryImpl(remoteEntryUrl, fetchTimeoutMs) {
|
|
|
294
361
|
}, fetchTimeoutMs);
|
|
295
362
|
if (fromServerBuild) return fromServerBuild;
|
|
296
363
|
}
|
|
297
|
-
const ctx = await buildEntryContext(remoteEntryUrl, fetchTimeoutMs);
|
|
364
|
+
const ctx = await buildEntryContext(remoteEntryUrl, fetchTimeoutMs, fetchMaxBytes);
|
|
298
365
|
if (ctx.manifest) {
|
|
299
366
|
const fromManifest = resolveSSREntryUrl(ctx.manifest, ctx.manifestUrl);
|
|
300
367
|
if (fromManifest) return fromManifest;
|
|
301
368
|
}
|
|
302
369
|
return resolveFirstReachableCandidate(buildSsrEntryCandidates(ctx, { skipServerBuild: !isManifestEntry(remoteEntryUrl) }), fetchTimeoutMs);
|
|
303
370
|
}
|
|
304
|
-
function setSsrEntryCache(remoteEntryUrl, fetchTimeoutMs) {
|
|
305
|
-
const cacheKey = makeUrlCacheKey(remoteEntryUrl, fetchTimeoutMs);
|
|
371
|
+
function setSsrEntryCache(remoteEntryUrl, fetchTimeoutMs, fetchMaxBytes) {
|
|
372
|
+
const cacheKey = makeUrlCacheKey(remoteEntryUrl, fetchTimeoutMs, fetchMaxBytes);
|
|
306
373
|
const record = {
|
|
307
|
-
promise: resolveSSREntryImpl(remoteEntryUrl, fetchTimeoutMs),
|
|
374
|
+
promise: resolveSSREntryImpl(remoteEntryUrl, fetchTimeoutMs, fetchMaxBytes),
|
|
308
375
|
resolvedAt: Date.now()
|
|
309
376
|
};
|
|
310
377
|
ssrEntryCache.set(cacheKey, record);
|
|
311
378
|
record.promise.then((entry) => {
|
|
312
379
|
if (!entry && ssrEntryCache.get(cacheKey) === record) ssrEntryCache.delete(cacheKey);
|
|
380
|
+
}, () => {
|
|
381
|
+
if (ssrEntryCache.get(cacheKey) === record) ssrEntryCache.delete(cacheKey);
|
|
313
382
|
});
|
|
314
383
|
return record;
|
|
315
384
|
}
|
|
316
|
-
async function getSSREntry(remoteEntryUrl, maxAgeMs, fetchTimeoutMs) {
|
|
317
|
-
const cacheKey = makeUrlCacheKey(remoteEntryUrl, fetchTimeoutMs);
|
|
385
|
+
async function getSSREntry(remoteEntryUrl, maxAgeMs, fetchTimeoutMs, fetchMaxBytes) {
|
|
386
|
+
const cacheKey = makeUrlCacheKey(remoteEntryUrl, fetchTimeoutMs, fetchMaxBytes);
|
|
318
387
|
const cached = ssrEntryCache.get(cacheKey);
|
|
319
|
-
if (!cached) return setSsrEntryCache(remoteEntryUrl, fetchTimeoutMs).promise;
|
|
388
|
+
if (!cached) return setSsrEntryCache(remoteEntryUrl, fetchTimeoutMs, fetchMaxBytes).promise;
|
|
320
389
|
if (!(typeof maxAgeMs === "number" && maxAgeMs >= 0 && Date.now() - cached.resolvedAt >= maxAgeMs)) return cached.promise;
|
|
321
390
|
const previous = await cached.promise.catch(() => null);
|
|
322
|
-
manifestFetchCache.delete(makeUrlCacheKey(getManifestUrl(remoteEntryUrl), fetchTimeoutMs));
|
|
323
|
-
const record = setSsrEntryCache(remoteEntryUrl, fetchTimeoutMs);
|
|
391
|
+
manifestFetchCache.delete(makeUrlCacheKey(getManifestUrl(remoteEntryUrl), fetchTimeoutMs, fetchMaxBytes));
|
|
392
|
+
const record = setSsrEntryCache(remoteEntryUrl, fetchTimeoutMs, fetchMaxBytes);
|
|
324
393
|
const next = await record.promise.catch(() => null);
|
|
325
394
|
if (previous && next && previous.versionKey !== next.versionKey) dropRemoteCaches(remoteEntryUrl);
|
|
326
395
|
return record.promise;
|
|
@@ -337,7 +406,7 @@ function dropRemoteCaches(remoteEntryUrl) {
|
|
|
337
406
|
} catch {
|
|
338
407
|
return;
|
|
339
408
|
}
|
|
340
|
-
for (const [key] of tempFileCache) if (JSON.parse(key)
|
|
409
|
+
for (const [key] of tempFileCache) if (JSON.parse(key).find((part) => typeof part === "string" && /^https?:\/\//.test(part))?.startsWith(origin)) {
|
|
341
410
|
tempFileCache.delete(key);
|
|
342
411
|
tempFilePathCache.delete(key);
|
|
343
412
|
}
|
|
@@ -429,9 +498,10 @@ function isVitePreloadHelperSpecifier(specifier) {
|
|
|
429
498
|
* a remote redeploy (new manifest → new key) produces new files and bypasses
|
|
430
499
|
* Node's ESM module cache instead of serving the stale build.
|
|
431
500
|
*/
|
|
432
|
-
async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, versionKey = UNVERSIONED, fetchTimeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS, contextKey = "default") {
|
|
501
|
+
async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, versionKey = UNVERSIONED, fetchTimeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS, contextKey = "default", fetchMaxBytes = DEFAULT_SSR_FETCH_MAX_BYTES) {
|
|
433
502
|
const cacheKey = JSON.stringify([
|
|
434
503
|
fetchTimeoutMs,
|
|
504
|
+
fetchMaxBytes,
|
|
435
505
|
versionKey,
|
|
436
506
|
url,
|
|
437
507
|
contextKey
|
|
@@ -440,7 +510,8 @@ async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, v
|
|
|
440
510
|
const cached = tempFileCache.get(cacheKey);
|
|
441
511
|
if (cached) {
|
|
442
512
|
pending.add(cached);
|
|
443
|
-
const
|
|
513
|
+
const reserved = tempFilePathCache.get(cacheKey);
|
|
514
|
+
const tmpFile = reserved ? await reserved : await cached;
|
|
444
515
|
visited.set(url, tmpFile);
|
|
445
516
|
return tmpFile;
|
|
446
517
|
}
|
|
@@ -454,7 +525,7 @@ async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, v
|
|
|
454
525
|
const tmpFile = await tmpFilePromise;
|
|
455
526
|
visited.set(url, tmpFile);
|
|
456
527
|
const res = await fetchWithTimeout(url, {}, fetchTimeoutMs);
|
|
457
|
-
let code = await res
|
|
528
|
+
let code = await readResponseTextBounded(res, fetchMaxBytes, url);
|
|
458
529
|
if (!res.ok) throw new SsrEntryHttpError(url, res.status, res.statusText, getBodyPreview(code));
|
|
459
530
|
const base = url.replace(/\/[^/]*$/, "/");
|
|
460
531
|
const relImports = [];
|
|
@@ -463,7 +534,7 @@ async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, v
|
|
|
463
534
|
while ((m = relRegex.exec(code)) !== null) if ((m[1].startsWith("./") || m[1].startsWith("../")) && !isVitePreloadHelperSpecifier(m[1])) relImports.push(new URL(m[1], base).href);
|
|
464
535
|
const subMap = /* @__PURE__ */ new Map();
|
|
465
536
|
await Promise.all([...new Set(relImports)].filter((u) => u.startsWith("http://") || u.startsWith("https://")).map(async (u) => {
|
|
466
|
-
const tmpPath = await fetchEsmToTempFile(u, tmpDir, visited, pending, sharedPkgMap, versionKey, fetchTimeoutMs, contextKey);
|
|
537
|
+
const tmpPath = await fetchEsmToTempFile(u, tmpDir, visited, pending, sharedPkgMap, versionKey, fetchTimeoutMs, contextKey, fetchMaxBytes);
|
|
467
538
|
subMap.set(u, `file://${tmpPath}`);
|
|
468
539
|
}));
|
|
469
540
|
code = transformSsrCode(code, base, sharedPkgMap);
|
|
@@ -480,9 +551,9 @@ async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, v
|
|
|
480
551
|
});
|
|
481
552
|
return promise;
|
|
482
553
|
}
|
|
483
|
-
async function fetchEsmGraphToTempFile(url, tmpDir, sharedPkgMap, versionKey = UNVERSIONED, fetchTimeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS, contextKey = "default") {
|
|
554
|
+
async function fetchEsmGraphToTempFile(url, tmpDir, sharedPkgMap, versionKey = UNVERSIONED, fetchTimeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS, contextKey = "default", fetchMaxBytes = DEFAULT_SSR_FETCH_MAX_BYTES) {
|
|
484
555
|
const pending = /* @__PURE__ */ new Set();
|
|
485
|
-
const rootFile = await fetchEsmToTempFile(url, tmpDir, /* @__PURE__ */ new Map(), pending, sharedPkgMap, versionKey, fetchTimeoutMs, contextKey);
|
|
556
|
+
const rootFile = await fetchEsmToTempFile(url, tmpDir, /* @__PURE__ */ new Map(), pending, sharedPkgMap, versionKey, fetchTimeoutMs, contextKey, fetchMaxBytes);
|
|
486
557
|
await Promise.all(pending);
|
|
487
558
|
return rootFile;
|
|
488
559
|
}
|
|
@@ -494,7 +565,7 @@ async function importTempModule(filePath, versionKey) {
|
|
|
494
565
|
}
|
|
495
566
|
let warnedVmUnavailable = false;
|
|
496
567
|
async function tryVmStrategy(ssrEntry, options) {
|
|
497
|
-
const { loadViaVmStrategy, isVmStrategyAvailable } = await import("./ssrVmStrategy-
|
|
568
|
+
const { loadViaVmStrategy, isVmStrategyAvailable } = await import("./ssrVmStrategy-Dpw20xiw.js");
|
|
498
569
|
if (!await isVmStrategyAvailable()) {
|
|
499
570
|
if (!warnedVmUnavailable) {
|
|
500
571
|
warnedVmUnavailable = true;
|
|
@@ -507,6 +578,7 @@ async function tryVmStrategy(ssrEntry, options) {
|
|
|
507
578
|
shareScopeName: options.shareScopeName,
|
|
508
579
|
versionKey: ssrEntry.versionKey,
|
|
509
580
|
fetchTimeoutMs: options.fetchTimeoutMs,
|
|
581
|
+
fetchMaxBytes: options.fetchMaxBytes,
|
|
510
582
|
cacheContext: options.cacheContext,
|
|
511
583
|
federationInstance: options.federationInstance
|
|
512
584
|
});
|
|
@@ -525,14 +597,15 @@ async function loadSSRRemoteEntry(ssrEntry, options) {
|
|
|
525
597
|
const urlObj = new URL(url);
|
|
526
598
|
if (urlObj.pathname.includes("/__mf_ssr__/")) {
|
|
527
599
|
const remoteOrigin = urlObj.origin;
|
|
528
|
-
const runner = await getOrCreateRunner(remoteOrigin, options.fetchTimeoutMs);
|
|
600
|
+
const runner = await getOrCreateRunner(remoteOrigin, options.fetchTimeoutMs, options.fetchMaxBytes);
|
|
529
601
|
if (!runner) {
|
|
530
602
|
if (process.env.NODE_ENV !== "production") return null;
|
|
531
603
|
} else try {
|
|
532
604
|
const mod = await runner.import(urlObj.pathname);
|
|
533
605
|
if (mod && typeof mod === "object" && "init" in mod) return mod;
|
|
534
606
|
if (process.env.NODE_ENV !== "production") return null;
|
|
535
|
-
} catch {
|
|
607
|
+
} catch (error) {
|
|
608
|
+
if (isSsrFetchBodyTooLargeError(error)) throw error;
|
|
536
609
|
if (process.env.NODE_ENV !== "production") return null;
|
|
537
610
|
}
|
|
538
611
|
}
|
|
@@ -540,16 +613,16 @@ async function loadSSRRemoteEntry(ssrEntry, options) {
|
|
|
540
613
|
const fromVm = await tryVmStrategy(ssrEntry, options);
|
|
541
614
|
if (fromVm) return fromVm;
|
|
542
615
|
} catch (error) {
|
|
543
|
-
if (isSsrEntryHttpError(error)) throw error;
|
|
616
|
+
if (isSsrEntryHttpError(error) || isSsrFetchBodyTooLargeError(error)) throw error;
|
|
544
617
|
}
|
|
545
618
|
const { mkdirSync } = await _fs();
|
|
546
619
|
const cacheDir = await getSSRCacheDir();
|
|
547
620
|
mkdirSync(cacheDir, { recursive: true });
|
|
548
621
|
const sharedPkgMap = new Map(Object.entries(resolvedShared));
|
|
549
622
|
try {
|
|
550
|
-
return await importTempModule(await fetchEsmGraphToTempFile(url, cacheDir, sharedPkgMap, versionKey, options.fetchTimeoutMs, getSsrTransformContextKey(resolvedShared, options.shareScopeName)), versionKey);
|
|
623
|
+
return await importTempModule(await fetchEsmGraphToTempFile(url, cacheDir, sharedPkgMap, versionKey, options.fetchTimeoutMs, getSsrTransformContextKey(resolvedShared, options.shareScopeName), options.fetchMaxBytes), versionKey);
|
|
551
624
|
} catch (error) {
|
|
552
|
-
if (isSsrEntryHttpError(error)) throw error;
|
|
625
|
+
if (isSsrEntryHttpError(error) || isSsrFetchBodyTooLargeError(error)) throw error;
|
|
553
626
|
return null;
|
|
554
627
|
}
|
|
555
628
|
}
|
|
@@ -569,6 +642,7 @@ function ssrEntryLoaderPlugin(options = {}) {
|
|
|
569
642
|
shareScopeName: options.shareScopeName ?? "default",
|
|
570
643
|
maxAgeMs: options.maxAgeMs,
|
|
571
644
|
fetchTimeoutMs: options.fetchTimeoutMs ?? 1e4,
|
|
645
|
+
fetchMaxBytes: options.fetchMaxBytes ?? 10485760,
|
|
572
646
|
cacheContext: {}
|
|
573
647
|
};
|
|
574
648
|
return {
|
|
@@ -580,7 +654,7 @@ function ssrEntryLoaderPlugin(options = {}) {
|
|
|
580
654
|
cacheContext: origin,
|
|
581
655
|
federationInstance: origin
|
|
582
656
|
} : resolved;
|
|
583
|
-
const ssrEntry = await getSSREntry(remoteInfo.entry, loadOptions.maxAgeMs, loadOptions.fetchTimeoutMs);
|
|
657
|
+
const ssrEntry = await getSSREntry(remoteInfo.entry, loadOptions.maxAgeMs, loadOptions.fetchTimeoutMs, loadOptions.fetchMaxBytes);
|
|
584
658
|
if (!ssrEntry) return;
|
|
585
659
|
const mod = await loadSSRRemoteEntry(ssrEntry, loadOptions);
|
|
586
660
|
if (!mod) return;
|
|
@@ -589,4 +663,4 @@ function ssrEntryLoaderPlugin(options = {}) {
|
|
|
589
663
|
};
|
|
590
664
|
}
|
|
591
665
|
//#endregion
|
|
592
|
-
export {
|
|
666
|
+
export { DEFAULT_SSR_FETCH_MAX_BYTES as a, readResponseTextBounded as c, ssrEntryLoaderPlugin as i, neutralizeBrowserPreloadHelpers as n, DEFAULT_SSR_FETCH_TIMEOUT_MS as o, revalidate as r, fetchWithTimeout as s, SsrEntryHttpError as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as neutralizeBrowserPreloadHelpers,
|
|
1
|
+
import { c as readResponseTextBounded, n as neutralizeBrowserPreloadHelpers, s as fetchWithTimeout, t as SsrEntryHttpError } from "./ssrEntryLoader-CuZVKlRm.js";
|
|
2
2
|
//#region src/utils/ssrVmStrategy.ts
|
|
3
3
|
/**
|
|
4
4
|
* vm.SourceTextModule strategy for loading remote SSR entries.
|
|
@@ -104,9 +104,9 @@ function getVmCacheContextKey(options) {
|
|
|
104
104
|
function getBodyPreview(body) {
|
|
105
105
|
return body.slice(0, 240).replace(/\s+/g, " ").trim();
|
|
106
106
|
}
|
|
107
|
-
async function fetchModuleSource(url, fetchTimeoutMs) {
|
|
107
|
+
async function fetchModuleSource(url, fetchTimeoutMs, fetchMaxBytes) {
|
|
108
108
|
const res = await fetchWithTimeout(url, {}, fetchTimeoutMs);
|
|
109
|
-
const text = await res
|
|
109
|
+
const text = await readResponseTextBounded(res, fetchMaxBytes ?? 10485760, url);
|
|
110
110
|
if (!res.ok) throw new SsrEntryHttpError(url, res.status, res.statusText, getBodyPreview(text));
|
|
111
111
|
return neutralizeBrowserPreloadHelpers(text);
|
|
112
112
|
}
|
|
@@ -123,11 +123,12 @@ function getHttpModule(vm, url, options) {
|
|
|
123
123
|
const cacheKey = JSON.stringify([
|
|
124
124
|
getVmCacheContextKey(options),
|
|
125
125
|
options.fetchTimeoutMs ?? 1e4,
|
|
126
|
+
options.fetchMaxBytes ?? 10485760,
|
|
126
127
|
options.versionKey,
|
|
127
128
|
url
|
|
128
129
|
]);
|
|
129
130
|
if (!httpModuleCache.has(cacheKey)) httpModuleCache.set(cacheKey, (async () => {
|
|
130
|
-
const code = await fetchModuleSource(url, options.fetchTimeoutMs);
|
|
131
|
+
const code = await fetchModuleSource(url, options.fetchTimeoutMs, options.fetchMaxBytes);
|
|
131
132
|
return new vm.SourceTextModule(code, {
|
|
132
133
|
identifier: url,
|
|
133
134
|
initializeImportMeta(meta) {
|
|
@@ -105,6 +105,11 @@ interface SsrEntryLoaderOptions {
|
|
|
105
105
|
* 10 seconds. Set to `0` to disable the timeout.
|
|
106
106
|
*/
|
|
107
107
|
fetchTimeoutMs?: number;
|
|
108
|
+
/**
|
|
109
|
+
* Maximum response body size in bytes for each SSR network request. Defaults
|
|
110
|
+
* to 10 MiB. Set to `0` to disable the limit.
|
|
111
|
+
*/
|
|
112
|
+
fetchMaxBytes?: number;
|
|
108
113
|
}
|
|
109
114
|
declare function ssrEntryLoaderPlugin(options?: SsrEntryLoaderOptions): {
|
|
110
115
|
name: string;
|
|
@@ -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-CuZVKlRm.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.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "Vite plugin for Module Federation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -86,4 +86,4 @@
|
|
|
86
86
|
"vite": "8.1.0",
|
|
87
87
|
"vitest": "4.0.18"
|
|
88
88
|
}
|
|
89
|
-
}
|
|
89
|
+
}
|