@module-federation/vite 1.23.5 → 1.23.7
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 +22 -1
- package/lib/{dtsConstants-BQdFpgKb.js → dtsConstants-CDuC8Bb7.js} +84 -24
- package/lib/index.js +1464 -1240
- package/lib/{logger-DOwfTlw5.js → logger-D67aJYOe.js} +110 -16
- package/lib/{pluginDts-DShMdjzR.js → pluginDts-rZMRTCTz.js} +5 -9
- package/lib/{sharedKeyMatcher-CHp4QRNq.js → sharedKeyMatcher-C04bVN1q.js} +8 -1
- package/lib/{ssrEntryLoader-CHdWk8Yg.js → ssrEntryLoader-DKpOrW8D.js} +152 -31
- package/lib/{ssrVmStrategy-BkyvcG4s.js → ssrVmStrategy-D1cSKUV-.js} +5 -13
- package/lib/utils/ssrEntryLoader.d.ts +7 -1
- package/lib/utils/ssrEntryLoader.js +2 -2
- package/package.json +4 -4
|
@@ -39,6 +39,9 @@ function normalizePathForImport(path) {
|
|
|
39
39
|
return path.replace(/\\/g, "/");
|
|
40
40
|
}
|
|
41
41
|
const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
|
|
42
|
+
function isHttpUrl(value) {
|
|
43
|
+
return value.startsWith("http://") || value.startsWith("https://");
|
|
44
|
+
}
|
|
42
45
|
function isAbsoluteUrl(src) {
|
|
43
46
|
if (/^[a-z]:[\\/]/i.test(src)) return false;
|
|
44
47
|
return EXTERNAL_URL_RE.test(src);
|
|
@@ -205,28 +208,91 @@ const REGEX_PREFIX_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
205
208
|
"void",
|
|
206
209
|
"yield"
|
|
207
210
|
]);
|
|
211
|
+
const CONTROL_PAREN_KEYWORDS = /* @__PURE__ */ new Set([
|
|
212
|
+
"if",
|
|
213
|
+
"while",
|
|
214
|
+
"for",
|
|
215
|
+
"with",
|
|
216
|
+
"switch",
|
|
217
|
+
"catch"
|
|
218
|
+
]);
|
|
219
|
+
function isWhitespace(char) {
|
|
220
|
+
if (char === void 0) return false;
|
|
221
|
+
const code = char.charCodeAt(0);
|
|
222
|
+
if (code < 128) return code === 32 || code >= 9 && code <= 13;
|
|
223
|
+
return /\s/.test(char);
|
|
224
|
+
}
|
|
225
|
+
function isAsciiLetter(code) {
|
|
226
|
+
return code >= 97 && code <= 122 || code >= 65 && code <= 90;
|
|
227
|
+
}
|
|
228
|
+
function isAsciiDigit(code) {
|
|
229
|
+
return code >= 48 && code <= 57;
|
|
230
|
+
}
|
|
231
|
+
function isIdentifierStart(char) {
|
|
232
|
+
const code = char.charCodeAt(0);
|
|
233
|
+
if (code < 128) return isAsciiLetter(code) || code === 36 || code === 95;
|
|
234
|
+
return /[$_\p{ID_Start}]/u.test(char);
|
|
235
|
+
}
|
|
236
|
+
function isIdentifierPart(char) {
|
|
237
|
+
if (char === void 0) return false;
|
|
238
|
+
const code = char.charCodeAt(0);
|
|
239
|
+
if (code < 128) return isAsciiLetter(code) || isAsciiDigit(code) || code === 36 || code === 95;
|
|
240
|
+
return /[$_\u200C\u200D\p{ID_Continue}]/u.test(char);
|
|
241
|
+
}
|
|
242
|
+
function isRegexFlag(char) {
|
|
243
|
+
if (char === void 0) return false;
|
|
244
|
+
const code = char.charCodeAt(0);
|
|
245
|
+
if (code < 128) return isAsciiLetter(code) || isAsciiDigit(code) || code === 36 || code === 95;
|
|
246
|
+
return /[$_\p{ID_Continue}]/u.test(char);
|
|
247
|
+
}
|
|
248
|
+
function isNumberPart(char) {
|
|
249
|
+
if (char === void 0) return false;
|
|
250
|
+
const code = char.charCodeAt(0);
|
|
251
|
+
return isAsciiLetter(code) || isAsciiDigit(code) || code === 95 || code === 46;
|
|
252
|
+
}
|
|
208
253
|
function isJsxClosingTagSlash(code, slashIndex) {
|
|
209
254
|
if (code[slashIndex - 1] !== "<") return false;
|
|
210
255
|
let cursor = slashIndex + 1;
|
|
211
|
-
while (
|
|
256
|
+
while (isWhitespace(code[cursor])) cursor++;
|
|
212
257
|
if (code[cursor] === ">") return true;
|
|
213
258
|
const tagStart = cursor;
|
|
214
259
|
while (/[-:.$_\u200C\u200D\p{ID_Continue}]/u.test(code[cursor] || "")) cursor++;
|
|
215
260
|
if (cursor === tagStart) return false;
|
|
216
|
-
while (
|
|
261
|
+
while (isWhitespace(code[cursor])) cursor++;
|
|
217
262
|
return code[cursor] === ">";
|
|
218
263
|
}
|
|
219
264
|
/** Mark comments, string/template literals, and regular expressions as non-code. */
|
|
220
265
|
function createCodePositionMap(code, onComment) {
|
|
221
|
-
const positions =
|
|
266
|
+
const positions = new Uint8Array(code.length).fill(1);
|
|
222
267
|
const mask = (start, end) => {
|
|
223
|
-
|
|
268
|
+
positions.fill(0, start, end);
|
|
224
269
|
};
|
|
225
270
|
let canStartRegex = true;
|
|
271
|
+
let pendingControlParen;
|
|
272
|
+
const controlParens = [];
|
|
273
|
+
let templateStart;
|
|
274
|
+
const templateExpressions = [];
|
|
226
275
|
for (let index = 0; index < code.length;) {
|
|
227
276
|
const char = code[index];
|
|
228
277
|
const next = code[index + 1];
|
|
229
|
-
if (
|
|
278
|
+
if (templateStart !== void 0) {
|
|
279
|
+
if (char === "\\") index += 2;
|
|
280
|
+
else if (char === "`") {
|
|
281
|
+
mask(templateStart, ++index);
|
|
282
|
+
templateStart = void 0;
|
|
283
|
+
canStartRegex = false;
|
|
284
|
+
} else if (char === "$" && next === "{") {
|
|
285
|
+
templateExpressions.push({
|
|
286
|
+
start: templateStart,
|
|
287
|
+
braceDepth: 0
|
|
288
|
+
});
|
|
289
|
+
templateStart = void 0;
|
|
290
|
+
canStartRegex = true;
|
|
291
|
+
index += 2;
|
|
292
|
+
} else index++;
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if (isWhitespace(char)) {
|
|
230
296
|
index++;
|
|
231
297
|
continue;
|
|
232
298
|
}
|
|
@@ -247,7 +313,13 @@ function createCodePositionMap(code, onComment) {
|
|
|
247
313
|
onComment?.(start, index);
|
|
248
314
|
continue;
|
|
249
315
|
}
|
|
250
|
-
|
|
316
|
+
const controlKeyword = pendingControlParen;
|
|
317
|
+
pendingControlParen = void 0;
|
|
318
|
+
if (char === "`") {
|
|
319
|
+
templateStart = index++;
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
if (char === "\"" || char === "'") {
|
|
251
323
|
const quote = char;
|
|
252
324
|
const start = index++;
|
|
253
325
|
while (index < code.length) {
|
|
@@ -265,8 +337,7 @@ function createCodePositionMap(code, onComment) {
|
|
|
265
337
|
canStartRegex = false;
|
|
266
338
|
continue;
|
|
267
339
|
}
|
|
268
|
-
|
|
269
|
-
if (char === "/" && canStartRegex && !closesJsxTag) {
|
|
340
|
+
if (char === "/" && canStartRegex && !isJsxClosingTagSlash(code, index)) {
|
|
270
341
|
const start = index;
|
|
271
342
|
let cursor = index + 1;
|
|
272
343
|
let escaped = false;
|
|
@@ -293,7 +364,7 @@ function createCodePositionMap(code, onComment) {
|
|
|
293
364
|
}
|
|
294
365
|
if (regexChar === "/" && !inCharacterClass) {
|
|
295
366
|
cursor++;
|
|
296
|
-
while (
|
|
367
|
+
while (isRegexFlag(code[cursor])) cursor++;
|
|
297
368
|
closed = true;
|
|
298
369
|
break;
|
|
299
370
|
}
|
|
@@ -305,15 +376,21 @@ function createCodePositionMap(code, onComment) {
|
|
|
305
376
|
continue;
|
|
306
377
|
}
|
|
307
378
|
}
|
|
308
|
-
if (
|
|
379
|
+
if (isIdentifierStart(char)) {
|
|
309
380
|
const start = index++;
|
|
310
|
-
while (
|
|
311
|
-
|
|
381
|
+
while (isIdentifierPart(code[index])) index++;
|
|
382
|
+
const word = code.slice(start, index);
|
|
383
|
+
if (CONTROL_PAREN_KEYWORDS.has(word)) {
|
|
384
|
+
let previous = start - 1;
|
|
385
|
+
while (previous >= 0 && (isWhitespace(code[previous]) || !positions[previous])) previous--;
|
|
386
|
+
if (code[previous] !== ".") pendingControlParen = word;
|
|
387
|
+
} else if (word === "await" && controlKeyword === "for") pendingControlParen = controlKeyword;
|
|
388
|
+
canStartRegex = REGEX_PREFIX_KEYWORDS.has(word);
|
|
312
389
|
continue;
|
|
313
390
|
}
|
|
314
|
-
if (
|
|
391
|
+
if (isAsciiDigit(char.charCodeAt(0))) {
|
|
315
392
|
index++;
|
|
316
|
-
while (
|
|
393
|
+
while (isNumberPart(code[index])) index++;
|
|
317
394
|
canStartRegex = false;
|
|
318
395
|
continue;
|
|
319
396
|
}
|
|
@@ -325,10 +402,27 @@ function createCodePositionMap(code, onComment) {
|
|
|
325
402
|
index++;
|
|
326
403
|
continue;
|
|
327
404
|
}
|
|
328
|
-
|
|
405
|
+
const expression = templateExpressions.at(-1);
|
|
406
|
+
if (expression && char === "{") expression.braceDepth++;
|
|
407
|
+
else if (expression && char === "}") {
|
|
408
|
+
if (expression.braceDepth === 0) {
|
|
409
|
+
templateStart = expression.start;
|
|
410
|
+
templateExpressions.pop();
|
|
411
|
+
index++;
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
expression.braceDepth--;
|
|
415
|
+
}
|
|
416
|
+
if (char === "(") {
|
|
417
|
+
controlParens.push(controlKeyword !== void 0);
|
|
418
|
+
canStartRegex = true;
|
|
419
|
+
} else if (char === ")") canStartRegex = controlParens.pop() === true;
|
|
420
|
+
else if (char === "]" || char === "}") canStartRegex = false;
|
|
329
421
|
else if (char !== ".") canStartRegex = true;
|
|
330
422
|
index++;
|
|
331
423
|
}
|
|
424
|
+
const unfinishedTemplateStart = templateExpressions[0]?.start ?? templateStart;
|
|
425
|
+
if (unfinishedTemplateStart !== void 0) mask(unfinishedTemplateStart, code.length);
|
|
332
426
|
return positions;
|
|
333
427
|
}
|
|
334
428
|
//#endregion
|
|
@@ -363,4 +457,4 @@ const moduleFederationConsole = {
|
|
|
363
457
|
const mfWarn = moduleFederationConsole.warn;
|
|
364
458
|
const mfError = moduleFederationConsole.error;
|
|
365
459
|
//#endregion
|
|
366
|
-
export { CodeRewriter as a, isAbsoluteUrl as c,
|
|
460
|
+
export { CodeRewriter as a, isAbsoluteUrl as c, rebaseImport as d, resolveHashPlaceholderFileName as f, createCodePositionMap as i, isHttpUrl as l, mfError as n, createSourceMap as o, mfWarn as r, EXTERNAL_URL_RE as s, createModuleFederationError as t, normalizePathForImport as u };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as
|
|
2
|
-
import {
|
|
1
|
+
import { l as isHttpUrl, n as mfError, t as createModuleFederationError, u as normalizePathForImport } from "./logger-D67aJYOe.js";
|
|
2
|
+
import { p as hasPackageDependency, r as watchFileEvents, y as resolveImportPath } from "./dtsConstants-CDuC8Bb7.js";
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
5
5
|
import { normalizeOptions } from "@module-federation/sdk";
|
|
@@ -113,7 +113,7 @@ const resolveDtsPluginOptions = (dts, options, context) => {
|
|
|
113
113
|
};
|
|
114
114
|
};
|
|
115
115
|
const getBasePath = (base) => {
|
|
116
|
-
if (
|
|
116
|
+
if (isHttpUrl(base)) return new URL(base).pathname.replace(/\/$/, "") || "/";
|
|
117
117
|
return base.replace(/\/$/, "") || "/";
|
|
118
118
|
};
|
|
119
119
|
const joinBaseAndAsset = (base, assetFileName) => {
|
|
@@ -262,15 +262,11 @@ function pluginDts(options) {
|
|
|
262
262
|
clearTimeout(updateTimer);
|
|
263
263
|
updateTimer = setTimeout(() => devWorker?.update(), UPDATE_DEBOUNCE_MS);
|
|
264
264
|
};
|
|
265
|
-
server.watcher
|
|
266
|
-
server.watcher.on("add", update);
|
|
267
|
-
server.watcher.on("unlink", update);
|
|
265
|
+
const stopWatching = watchFileEvents(server.watcher, update);
|
|
268
266
|
server.httpServer?.once("close", () => {
|
|
269
267
|
clearTimeout(updateTimer);
|
|
270
268
|
devWorker?.exit();
|
|
271
|
-
|
|
272
|
-
server.watcher.off("add", update);
|
|
273
|
-
server.watcher.off("unlink", update);
|
|
269
|
+
stopWatching();
|
|
274
270
|
});
|
|
275
271
|
};
|
|
276
272
|
startDevWorker().catch((error) => {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { u as normalizePathForImport } from "./logger-D67aJYOe.js";
|
|
2
|
+
import * as path$1 from "node:path";
|
|
1
3
|
//#region src/utils/pathNormalization.ts
|
|
2
4
|
const COMMON_SHARED_SUBPATHS = {
|
|
3
5
|
react: [
|
|
@@ -127,6 +129,11 @@ function resolvePublicPath(options, viteBase, originalBase) {
|
|
|
127
129
|
}
|
|
128
130
|
return "auto";
|
|
129
131
|
}
|
|
132
|
+
/** Relative `./`-prefixed import specifier from `fromFile` to `targetFile`. */
|
|
133
|
+
function toRelativeImport(fromFile, targetFile) {
|
|
134
|
+
const relative = normalizePathForImport(path$1.relative(path$1.dirname(fromFile), targetFile));
|
|
135
|
+
return relative.startsWith(".") ? relative : `./${relative}`;
|
|
136
|
+
}
|
|
130
137
|
//#endregion
|
|
131
138
|
//#region src/utils/sharedKeyMatcher.ts
|
|
132
139
|
function getSharedRequest(key, shareItem) {
|
|
@@ -218,4 +225,4 @@ function getSharedKeyMatcher(shared) {
|
|
|
218
225
|
return matcher;
|
|
219
226
|
}
|
|
220
227
|
//#endregion
|
|
221
|
-
export { removeTrailingSlash as _, matchesSharedSource as a, stripViteFsPrefix as b, filterId as c, getNodeModulesSuffix as d, isAssetLikeImport as f, normalizeNodeModulePath as g, isViteOptimizableEntry as h, invalidateSharedKeyMatcher as i, getBasePath as l, isNuxtClientBase as m, getSharedRequest as n, VITE_FS_PREFIX as o, isNodeModulePath as p, getSharedRuntimeKey as r, ensureTrailingSlash as s, findSharedKey as t, getCommonSharedSubpaths as u, resolvePublicPath as v, stripQueryAndHash as y };
|
|
228
|
+
export { removeTrailingSlash as _, matchesSharedSource as a, stripViteFsPrefix as b, filterId as c, getNodeModulesSuffix as d, isAssetLikeImport as f, normalizeNodeModulePath as g, isViteOptimizableEntry as h, invalidateSharedKeyMatcher as i, getBasePath as l, isNuxtClientBase as m, getSharedRequest as n, VITE_FS_PREFIX as o, isNodeModulePath as p, getSharedRuntimeKey as r, ensureTrailingSlash as s, findSharedKey as t, getCommonSharedSubpaths as u, resolvePublicPath as v, toRelativeImport as x, stripQueryAndHash as y };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as CodeRewriter, i as createCodePositionMap, r as mfWarn, s as EXTERNAL_URL_RE } from "./logger-
|
|
1
|
+
import { a as CodeRewriter, i as createCodePositionMap, l as isHttpUrl, r as mfWarn, s as EXTERNAL_URL_RE } from "./logger-D67aJYOe.js";
|
|
2
2
|
import { simpleJoinRemoteEntry } from "@module-federation/sdk";
|
|
3
3
|
//#region src/utils/fetchWithTimeout.ts
|
|
4
4
|
const DEFAULT_SSR_FETCH_TIMEOUT_MS = 1e4;
|
|
@@ -57,6 +57,10 @@ var SsrFetchBodyTooLargeError = class extends Error {
|
|
|
57
57
|
function isSsrFetchBodyTooLargeError(error) {
|
|
58
58
|
return error instanceof SsrFetchBodyTooLargeError;
|
|
59
59
|
}
|
|
60
|
+
/** A short single-line excerpt of a response body for error messages. */
|
|
61
|
+
function getBodyPreview(body) {
|
|
62
|
+
return body.slice(0, 240).replace(/\s+/g, " ").trim();
|
|
63
|
+
}
|
|
60
64
|
/**
|
|
61
65
|
* Read a response body as text, rejecting when it exceeds `maxBytes`.
|
|
62
66
|
* Set `maxBytes` to 0 (or a non-finite value) to disable the limit.
|
|
@@ -99,15 +103,6 @@ async function readResponseTextBounded(res, maxBytes = DEFAULT_SSR_FETCH_MAX_BYT
|
|
|
99
103
|
return new TextDecoder().decode(merged);
|
|
100
104
|
}
|
|
101
105
|
//#endregion
|
|
102
|
-
//#region src/utils/url.ts
|
|
103
|
-
function getUrlOrigin(value) {
|
|
104
|
-
try {
|
|
105
|
-
return new URL(value).origin;
|
|
106
|
-
} catch {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
//#endregion
|
|
111
106
|
//#region src/utils/ssrEntryLoader.ts
|
|
112
107
|
/**
|
|
113
108
|
* MF runtime plugin that intercepts the `loadEntry` lifecycle hook on the
|
|
@@ -198,9 +193,62 @@ function getRunnerCacheKey(remoteOrigin, resolvedShared, fetchTimeoutMs, fetchMa
|
|
|
198
193
|
getSortedRecordEntries(resolvedShared)
|
|
199
194
|
]);
|
|
200
195
|
}
|
|
201
|
-
|
|
196
|
+
function findResolvedSharedKey(id, resolvedShared) {
|
|
197
|
+
if (resolvedShared[id]) return id;
|
|
198
|
+
let matchedKey;
|
|
199
|
+
for (const key of Object.keys(resolvedShared)) {
|
|
200
|
+
if (!key.endsWith("/")) continue;
|
|
201
|
+
const base = key.slice(0, -1);
|
|
202
|
+
if (id !== base && !id.startsWith(`${base}/`)) continue;
|
|
203
|
+
if (!matchedKey || key.length > matchedKey.length) matchedKey = key;
|
|
204
|
+
}
|
|
205
|
+
return matchedKey;
|
|
206
|
+
}
|
|
207
|
+
function getEsmExportTarget(target) {
|
|
208
|
+
if (typeof target === "string") return target;
|
|
209
|
+
if (!target || typeof target !== "object" || Array.isArray(target)) return void 0;
|
|
210
|
+
for (const [condition, value] of Object.entries(target)) {
|
|
211
|
+
if (condition !== "node" && condition !== "import" && condition !== "default") continue;
|
|
212
|
+
const resolved = getEsmExportTarget(value);
|
|
213
|
+
if (resolved) return resolved;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async function resolveEsmSubpath(id, base) {
|
|
217
|
+
const { dirname, join } = await _path();
|
|
218
|
+
const { existsSync, readFileSync } = await _fs();
|
|
219
|
+
const segments = id.split("/");
|
|
220
|
+
const nameLength = id.startsWith("@") ? 2 : 1;
|
|
221
|
+
const name = segments.slice(0, nameLength).join("/");
|
|
222
|
+
const subpath = [".", ...segments.slice(nameLength)].join("/");
|
|
223
|
+
for (let dir = dirname(base); dirname(dir) !== dir; dir = dirname(dir)) {
|
|
224
|
+
const packageJson = join(dir, "node_modules", name, "package.json");
|
|
225
|
+
if (!existsSync(packageJson)) continue;
|
|
226
|
+
const { exports } = JSON.parse(readFileSync(packageJson, "utf8"));
|
|
227
|
+
const target = getEsmExportTarget(exports?.[subpath]);
|
|
228
|
+
return target && join(dirname(packageJson), target);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Resolve a shared request from the exact or wildcard build-time map.
|
|
233
|
+
* Wildcard entries point at the package entry, so concrete subpaths need a
|
|
234
|
+
* second Node resolution step to preserve package exports and conditions.
|
|
235
|
+
*/
|
|
236
|
+
async function resolveSharedPath(id, resolvedShared) {
|
|
202
237
|
if (typeof id !== "string") return null;
|
|
203
|
-
const
|
|
238
|
+
const matchedKey = findResolvedSharedKey(id, resolvedShared);
|
|
239
|
+
if (!matchedKey) return null;
|
|
240
|
+
const resolved = resolvedShared[matchedKey];
|
|
241
|
+
if (!resolved) return null;
|
|
242
|
+
if (matchedKey === id || EXTERNAL_URL_RE.test(resolved)) return resolved;
|
|
243
|
+
const { createRequire } = await _module();
|
|
244
|
+
const { join } = await _path();
|
|
245
|
+
for (const base of [resolved, join(process.cwd(), "noop.js")]) try {
|
|
246
|
+
return await resolveEsmSubpath(id, base).catch(() => void 0) ?? createRequire(base).resolve(id);
|
|
247
|
+
} catch {}
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
async function resolveSharedExternal(id, resolvedShared) {
|
|
251
|
+
const resolved = await resolveSharedPath(id, resolvedShared);
|
|
204
252
|
if (!resolved) return null;
|
|
205
253
|
if (EXTERNAL_URL_RE.test(resolved)) return {
|
|
206
254
|
externalize: resolved,
|
|
@@ -230,8 +278,9 @@ async function getOrCreateRunner(remoteOrigin, resolvedShared, fetchTimeoutMs, f
|
|
|
230
278
|
headers: { "Content-Type": "application/json" },
|
|
231
279
|
body: JSON.stringify(payload)
|
|
232
280
|
}, fetchTimeoutMs), fetchMaxBytes, runnerEndpoint);
|
|
233
|
-
const
|
|
234
|
-
|
|
281
|
+
const data = JSON.parse(text);
|
|
282
|
+
const result = parseRunnerInvokeResult(data);
|
|
283
|
+
if (("error" in result || isPlainObject(data) && data.shared === true) && payload.data.name === "fetchModule") {
|
|
235
284
|
const sharedExternal = await resolveSharedExternal(payload.data.data[0], resolvedShared);
|
|
236
285
|
if (sharedExternal) return { result: sharedExternal };
|
|
237
286
|
}
|
|
@@ -326,9 +375,6 @@ var SsrEntryHttpError = class extends Error {
|
|
|
326
375
|
this.name = "SsrEntryHttpError";
|
|
327
376
|
}
|
|
328
377
|
};
|
|
329
|
-
function getBodyPreview(body) {
|
|
330
|
-
return body.slice(0, 240).replace(/\s+/g, " ").trim();
|
|
331
|
-
}
|
|
332
378
|
function isSsrEntryHttpError(error) {
|
|
333
379
|
return error instanceof SsrEntryHttpError;
|
|
334
380
|
}
|
|
@@ -540,9 +586,10 @@ function scheduleVmCacheCleanup(remoteEntryUrl) {
|
|
|
540
586
|
*/
|
|
541
587
|
async function clearRunnerCaches(remoteEntryUrl) {
|
|
542
588
|
let remoteOrigin;
|
|
543
|
-
if (remoteEntryUrl) {
|
|
544
|
-
remoteOrigin =
|
|
545
|
-
|
|
589
|
+
if (remoteEntryUrl) try {
|
|
590
|
+
remoteOrigin = new URL(remoteEntryUrl).origin;
|
|
591
|
+
} catch {
|
|
592
|
+
return;
|
|
546
593
|
}
|
|
547
594
|
await Promise.all([...runnerCache.values()].filter((cached) => !remoteOrigin || cached.remoteOrigin === remoteOrigin).map(async (cached) => {
|
|
548
595
|
try {
|
|
@@ -751,13 +798,22 @@ function transformSsrCode(code, base, specifiers, sharedPkgMap, requireShimUrl,
|
|
|
751
798
|
}
|
|
752
799
|
const resolvedShared = sharedPkgMap?.get(value);
|
|
753
800
|
const relativeUrl = isRelativeSpecifier(value) ? new URL(value, base).href : void 0;
|
|
754
|
-
const absoluteHttpUrl =
|
|
801
|
+
const absoluteHttpUrl = isHttpUrl(value) ? value : void 0;
|
|
755
802
|
const httpUrl = relativeUrl ?? absoluteHttpUrl;
|
|
756
803
|
const replacement = (httpUrl ? tempFileUrlMap?.get(httpUrl) : void 0) ?? relativeUrl ?? (resolvedShared && `file://${resolvedShared}`);
|
|
757
804
|
if (replacement) rewriter.overwrite(start, end, `"${replacement}"`);
|
|
758
805
|
}
|
|
759
806
|
return neutralizeBrowserPreloadHelpers(rewriter.toString());
|
|
760
807
|
}
|
|
808
|
+
async function materializeSharedSubpaths(specifiers, sharedPkgMap) {
|
|
809
|
+
const uniqueSpecifiers = new Set(specifiers.map(({ value }) => value));
|
|
810
|
+
const resolvedShared = Object.fromEntries(sharedPkgMap);
|
|
811
|
+
for (const specifier of uniqueSpecifiers) {
|
|
812
|
+
if (sharedPkgMap.has(specifier)) continue;
|
|
813
|
+
const resolved = await resolveSharedPath(specifier, resolvedShared);
|
|
814
|
+
if (resolved) sharedPkgMap.set(specifier, resolved);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
761
817
|
function isVitePreloadHelperSpecifier(specifier) {
|
|
762
818
|
return specifier.includes("preload-helper");
|
|
763
819
|
}
|
|
@@ -773,7 +829,8 @@ function getTempFileImportUrl(filePath, versionKey) {
|
|
|
773
829
|
* a remote redeploy (new manifest → new key) produces new files and bypasses
|
|
774
830
|
* Node's ESM module cache instead of serving the stale build.
|
|
775
831
|
*/
|
|
776
|
-
async function fetchEsmToTempFile(url,
|
|
832
|
+
async function fetchEsmToTempFile(url, graph) {
|
|
833
|
+
const { tmpDir, visited, pending, sharedPkgMap, versionKey, fetchTimeoutMs, contextKey, fetchMaxBytes, extension, owner } = graph;
|
|
777
834
|
const cacheKey = JSON.stringify([
|
|
778
835
|
fetchTimeoutMs,
|
|
779
836
|
fetchMaxBytes,
|
|
@@ -795,7 +852,8 @@ async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, v
|
|
|
795
852
|
const tmpFilePromise = (async () => {
|
|
796
853
|
const { createHash } = await _crypto();
|
|
797
854
|
const { join } = await _path();
|
|
798
|
-
|
|
855
|
+
const hash = createHash("sha1").update(cacheKey).digest("hex").slice(0, 12);
|
|
856
|
+
return join(tmpDir, `${hash}${extension}`);
|
|
799
857
|
})();
|
|
800
858
|
tempFilePathCache.set(cacheKey, tmpFilePromise);
|
|
801
859
|
const promise = (async () => {
|
|
@@ -808,10 +866,11 @@ async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, v
|
|
|
808
866
|
const specifiers = findSsrModuleSpecifiers(code);
|
|
809
867
|
const relImports = specifiers.map(({ value }) => value).filter((value) => isRelativeSpecifier(value) && !isVitePreloadHelperSpecifier(value)).map((value) => new URL(value, base).href);
|
|
810
868
|
const subMap = /* @__PURE__ */ new Map();
|
|
811
|
-
await Promise.all([...new Set(relImports)].filter(
|
|
812
|
-
const tmpPath = await fetchEsmToTempFile(u,
|
|
869
|
+
await Promise.all([...new Set(relImports)].filter(isHttpUrl).map(async (u) => {
|
|
870
|
+
const tmpPath = await fetchEsmToTempFile(u, graph);
|
|
813
871
|
subMap.set(u, getTempFileImportUrl(tmpPath, versionKey));
|
|
814
872
|
}));
|
|
873
|
+
if (sharedPkgMap) await materializeSharedSubpaths(specifiers, sharedPkgMap);
|
|
815
874
|
const requireShimUrl = sharedPkgMap?.size && specifiers.some(({ value }) => isNodeModuleSpecifier(value)) ? await getRequireShimUrl(tmpDir, sharedPkgMap, contextKey) : void 0;
|
|
816
875
|
code = transformSsrCode(code, base, specifiers, sharedPkgMap, requireShimUrl, subMap);
|
|
817
876
|
const { writeFileSync } = await _fs();
|
|
@@ -834,9 +893,18 @@ async function fetchEsmToTempFile(url, tmpDir, visited, pending, sharedPkgMap, v
|
|
|
834
893
|
});
|
|
835
894
|
return promise;
|
|
836
895
|
}
|
|
837
|
-
async function fetchEsmGraphToTempFile(url,
|
|
896
|
+
async function fetchEsmGraphToTempFile(url, { versionKey = UNVERSIONED, fetchTimeoutMs = DEFAULT_SSR_FETCH_TIMEOUT_MS, contextKey = "default", fetchMaxBytes = DEFAULT_SSR_FETCH_MAX_BYTES, extension = ".mjs", ...rest }) {
|
|
838
897
|
const pending = /* @__PURE__ */ new Set();
|
|
839
|
-
const rootFile = await fetchEsmToTempFile(url,
|
|
898
|
+
const rootFile = await fetchEsmToTempFile(url, {
|
|
899
|
+
...rest,
|
|
900
|
+
versionKey,
|
|
901
|
+
fetchTimeoutMs,
|
|
902
|
+
contextKey,
|
|
903
|
+
fetchMaxBytes,
|
|
904
|
+
extension,
|
|
905
|
+
visited: /* @__PURE__ */ new Map(),
|
|
906
|
+
pending
|
|
907
|
+
});
|
|
840
908
|
await Promise.all(pending);
|
|
841
909
|
return rootFile;
|
|
842
910
|
}
|
|
@@ -848,7 +916,7 @@ async function importTempModule(filePath, versionKey) {
|
|
|
848
916
|
}
|
|
849
917
|
let warnedVmUnavailable = false;
|
|
850
918
|
function getVmStrategyModule() {
|
|
851
|
-
if (!loaderState.vmStrategyModulePromise) loaderState.vmStrategyModulePromise = import("./ssrVmStrategy-
|
|
919
|
+
if (!loaderState.vmStrategyModulePromise) loaderState.vmStrategyModulePromise = import("./ssrVmStrategy-D1cSKUV-.js");
|
|
852
920
|
return loaderState.vmStrategyModulePromise;
|
|
853
921
|
}
|
|
854
922
|
/**
|
|
@@ -889,7 +957,7 @@ async function loadSSRRemoteEntry(ssrEntry, options, rootEntryUrl) {
|
|
|
889
957
|
return req(url);
|
|
890
958
|
} catch {}
|
|
891
959
|
}
|
|
892
|
-
if (
|
|
960
|
+
if (isHttpUrl(url)) {
|
|
893
961
|
const urlObj = new URL(url);
|
|
894
962
|
if (urlObj.pathname.includes("/__mf_ssr__/")) {
|
|
895
963
|
const remoteOrigin = urlObj.origin;
|
|
@@ -919,7 +987,16 @@ async function loadSSRRemoteEntry(ssrEntry, options, rootEntryUrl) {
|
|
|
919
987
|
const isCommonJs = type === "commonjs-module" || type === "commonjs";
|
|
920
988
|
const extension = isCommonJs ? ".cjs" : ".mjs";
|
|
921
989
|
try {
|
|
922
|
-
const tmpFile = await fetchEsmGraphToTempFile(url,
|
|
990
|
+
const tmpFile = await fetchEsmGraphToTempFile(url, {
|
|
991
|
+
tmpDir: cacheDir,
|
|
992
|
+
sharedPkgMap,
|
|
993
|
+
versionKey,
|
|
994
|
+
fetchTimeoutMs: options.fetchTimeoutMs,
|
|
995
|
+
contextKey: getSsrTransformContextKey(resolvedShared, options.shareScopeName),
|
|
996
|
+
fetchMaxBytes: options.fetchMaxBytes,
|
|
997
|
+
extension,
|
|
998
|
+
owner: rootEntryUrl
|
|
999
|
+
});
|
|
923
1000
|
if (isCommonJs) return (await _module()).createRequire(import.meta.url)(tmpFile);
|
|
924
1001
|
return await importTempModule(tmpFile, versionKey);
|
|
925
1002
|
} catch (error) {
|
|
@@ -937,6 +1014,43 @@ async function loadSSRRemoteEntry(ssrEntry, options, rootEntryUrl) {
|
|
|
937
1014
|
return null;
|
|
938
1015
|
}
|
|
939
1016
|
}
|
|
1017
|
+
/**
|
|
1018
|
+
* Build-time `resolvedShared` paths point into the build machine's
|
|
1019
|
+
* node_modules. A traced or relocated server output imports shared packages
|
|
1020
|
+
* from its own copy, so pinning remotes to the build paths loads a second
|
|
1021
|
+
* instance (two Reacts: invalid hook call) or, once the build directory is
|
|
1022
|
+
* gone, nothing at all (ERR_MODULE_NOT_FOUND).
|
|
1023
|
+
*
|
|
1024
|
+
* Each specifier takes the first hit of a fixed order, independent of import
|
|
1025
|
+
* order or timing:
|
|
1026
|
+
* 1. resolved from the real path of the server entry (`process.argv[1]`),
|
|
1027
|
+
* which is where Node resolves the host's own bare imports from, unless
|
|
1028
|
+
* it is a CLI inside node_modules (e.g. `vite preview`);
|
|
1029
|
+
* 2. resolved from `process.cwd()`, for launchers whose `argv[1]` is not the
|
|
1030
|
+
* server entry or is missing;
|
|
1031
|
+
* 3. the build-time path.
|
|
1032
|
+
*/
|
|
1033
|
+
async function rebaseResolvedShared(resolvedShared) {
|
|
1034
|
+
const { createRequire } = await _module();
|
|
1035
|
+
const { realpathSync } = await _fs();
|
|
1036
|
+
const { join } = await _path();
|
|
1037
|
+
const requires = [];
|
|
1038
|
+
try {
|
|
1039
|
+
const entry = process.argv[1] && realpathSync(process.argv[1]);
|
|
1040
|
+
if (entry && !/[\\/]node_modules[\\/]/.test(entry)) requires.push(createRequire(entry));
|
|
1041
|
+
} catch {}
|
|
1042
|
+
requires.push(createRequire(join(process.cwd(), "noop.js")));
|
|
1043
|
+
const rebased = {};
|
|
1044
|
+
for (const [specifier, buildPath] of Object.entries(resolvedShared)) {
|
|
1045
|
+
rebased[specifier] = buildPath;
|
|
1046
|
+
const resolutionSpecifier = specifier.endsWith("/") ? specifier.slice(0, -1) : specifier;
|
|
1047
|
+
for (const require of requires) try {
|
|
1048
|
+
rebased[specifier] = require.resolve(resolutionSpecifier);
|
|
1049
|
+
break;
|
|
1050
|
+
} catch {}
|
|
1051
|
+
}
|
|
1052
|
+
return rebased;
|
|
1053
|
+
}
|
|
940
1054
|
function ssrEntryLoaderPlugin(options = {}) {
|
|
941
1055
|
const resolved = {
|
|
942
1056
|
resolvedShared: options.resolvedShared ?? {},
|
|
@@ -947,10 +1061,17 @@ function ssrEntryLoaderPlugin(options = {}) {
|
|
|
947
1061
|
fetchMaxBytes: options.fetchMaxBytes ?? 10485760,
|
|
948
1062
|
cacheContext: {}
|
|
949
1063
|
};
|
|
1064
|
+
let rebased;
|
|
950
1065
|
return {
|
|
951
1066
|
name: "mf-vite:ssr-entry-loader",
|
|
952
1067
|
async loadEntry({ remoteInfo, origin }) {
|
|
953
1068
|
if (!isNodeServer()) return;
|
|
1069
|
+
if (options.rebaseSharedAtRuntime) {
|
|
1070
|
+
rebased ??= rebaseResolvedShared(resolved.resolvedShared).then((map) => {
|
|
1071
|
+
resolved.resolvedShared = map;
|
|
1072
|
+
}, () => {});
|
|
1073
|
+
await rebased;
|
|
1074
|
+
}
|
|
954
1075
|
const loadOptions = origin ? {
|
|
955
1076
|
...resolved,
|
|
956
1077
|
cacheContext: origin,
|
|
@@ -968,4 +1089,4 @@ function ssrEntryLoaderPlugin(options = {}) {
|
|
|
968
1089
|
};
|
|
969
1090
|
}
|
|
970
1091
|
//#endregion
|
|
971
|
-
export {
|
|
1092
|
+
export { revalidate as a, DEFAULT_SSR_FETCH_TIMEOUT_MS as c, readResponseTextBounded as d, resolveSharedPath as i, fetchWithTimeout as l, SsrEntryHttpError as n, ssrEntryLoaderPlugin as o, neutralizeBrowserPreloadHelpers as r, DEFAULT_SSR_FETCH_MAX_BYTES as s, SSR_ENTRY_LOADER_STATE_KEY as t, getBodyPreview as u };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { l as isHttpUrl, s as EXTERNAL_URL_RE } from "./logger-D67aJYOe.js";
|
|
2
|
+
import { t as findSharedKey } from "./sharedKeyMatcher-C04bVN1q.js";
|
|
3
|
+
import { d as readResponseTextBounded, i as resolveSharedPath, l as fetchWithTimeout, n as SsrEntryHttpError, r as neutralizeBrowserPreloadHelpers, u as getBodyPreview } from "./ssrEntryLoader-DKpOrW8D.js";
|
|
3
4
|
//#region src/utils/ssrVmStrategy.ts
|
|
4
5
|
/**
|
|
5
6
|
* vm.SourceTextModule strategy for loading remote SSR entries.
|
|
@@ -68,11 +69,8 @@ async function loadBareModule(specifier, options) {
|
|
|
68
69
|
}
|
|
69
70
|
} catch {}
|
|
70
71
|
}
|
|
71
|
-
const resolvedPath = options.resolvedShared
|
|
72
|
-
if (resolvedPath) return import(
|
|
73
|
-
/* @vite-ignore */
|
|
74
|
-
`file://${resolvedPath}`
|
|
75
|
-
);
|
|
72
|
+
const resolvedPath = await resolveSharedPath(specifier, options.resolvedShared);
|
|
73
|
+
if (resolvedPath) return EXTERNAL_URL_RE.test(resolvedPath) ? import(resolvedPath) : import(`file://${resolvedPath}`);
|
|
76
74
|
const namespace = await import(
|
|
77
75
|
/* @vite-ignore */
|
|
78
76
|
specifier
|
|
@@ -163,18 +161,12 @@ function clearVmStrategyCaches(remoteEntryUrl) {
|
|
|
163
161
|
clearOwnedVmCache(httpModuleCache, httpModuleCacheOwners, remoteEntryUrl);
|
|
164
162
|
clearOwnedVmCache(namespaceCache, namespaceCacheOwners, remoteEntryUrl);
|
|
165
163
|
}
|
|
166
|
-
function getBodyPreview(body) {
|
|
167
|
-
return body.slice(0, 240).replace(/\s+/g, " ").trim();
|
|
168
|
-
}
|
|
169
164
|
async function fetchModuleSource(url, fetchTimeoutMs, fetchMaxBytes) {
|
|
170
165
|
const res = await fetchWithTimeout(url, {}, fetchTimeoutMs);
|
|
171
166
|
const text = await readResponseTextBounded(res, fetchMaxBytes ?? 10485760, url);
|
|
172
167
|
if (!res.ok) throw new SsrEntryHttpError(url, res.status, res.statusText, getBodyPreview(text));
|
|
173
168
|
return neutralizeBrowserPreloadHelpers(text);
|
|
174
169
|
}
|
|
175
|
-
function isHttpUrl(value) {
|
|
176
|
-
return value.startsWith("http://") || value.startsWith("https://");
|
|
177
|
-
}
|
|
178
170
|
/** Resolve a specifier against the referencing module's URL; null for bare specifiers. */
|
|
179
171
|
function resolveSpecifierUrl(specifier, referencerUrl) {
|
|
180
172
|
if (isHttpUrl(specifier)) return specifier;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { i as SsrEntryLoaderConfig } from "../normalizeModuleFederationOptions-DNUlv-AL.js";
|
|
2
2
|
//#region src/utils/ssrEntryLoader.d.ts
|
|
3
3
|
declare const SSR_ENTRY_LOADER_STATE_KEY: unique symbol;
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a shared request from the exact or wildcard build-time map.
|
|
6
|
+
* Wildcard entries point at the package entry, so concrete subpaths need a
|
|
7
|
+
* second Node resolution step to preserve package exports and conditions.
|
|
8
|
+
*/
|
|
9
|
+
declare function resolveSharedPath(id: unknown, resolvedShared: Record<string, string>): Promise<string | null>;
|
|
4
10
|
interface RemoteInfo {
|
|
5
11
|
name: string;
|
|
6
12
|
entry: string;
|
|
@@ -65,4 +71,4 @@ declare function ssrEntryLoaderPlugin(options?: SsrEntryLoaderOptions): {
|
|
|
65
71
|
} | undefined>;
|
|
66
72
|
};
|
|
67
73
|
//#endregion
|
|
68
|
-
export { SSR_ENTRY_LOADER_STATE_KEY, SsrEntryHttpError, ssrEntryLoaderPlugin as default, neutralizeBrowserPreloadHelpers, revalidate };
|
|
74
|
+
export { SSR_ENTRY_LOADER_STATE_KEY, SsrEntryHttpError, ssrEntryLoaderPlugin as default, neutralizeBrowserPreloadHelpers, resolveSharedPath, revalidate };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { SSR_ENTRY_LOADER_STATE_KEY, SsrEntryHttpError, ssrEntryLoaderPlugin as default, neutralizeBrowserPreloadHelpers, revalidate };
|
|
1
|
+
import { a as revalidate, i as resolveSharedPath, n as SsrEntryHttpError, o as ssrEntryLoaderPlugin, r as neutralizeBrowserPreloadHelpers, t as SSR_ENTRY_LOADER_STATE_KEY } from "../ssrEntryLoader-DKpOrW8D.js";
|
|
2
|
+
export { SSR_ENTRY_LOADER_STATE_KEY, SsrEntryHttpError, ssrEntryLoaderPlugin as default, neutralizeBrowserPreloadHelpers, resolveSharedPath, revalidate };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/vite",
|
|
3
|
-
"version": "1.23.
|
|
3
|
+
"version": "1.23.7",
|
|
4
4
|
"description": "Vite plugin for Module Federation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"homepage": "https://github.com/module-federation/vite#readme",
|
|
75
75
|
"packageManager": "pnpm@10.28.2",
|
|
76
76
|
"peerDependencies": {
|
|
77
|
-
"vite": "^5.
|
|
77
|
+
"vite": "^5.1.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"@module-federation/dts-plugin": "2.9.2",
|
|
@@ -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.2.
|
|
94
|
-
"vitest": "4.1.
|
|
93
|
+
"vite": "8.2.4",
|
|
94
|
+
"vitest": "4.1.12"
|
|
95
95
|
}
|
|
96
96
|
}
|