@module-federation/vite 1.23.0 → 1.23.2
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 +36 -0
- package/lib/{dtsConstants-DEMpRfBz.js → dtsConstants-r5OfegUr.js} +2 -32
- package/lib/index.d.ts +17 -0
- package/lib/index.js +605 -414
- package/lib/logger-DOwfTlw5.js +366 -0
- package/lib/{pluginDts-VSLhAx6d.js → pluginDts-DnEX3cp_.js} +3 -3
- package/lib/{ssrEntryLoader-BvAkpCyi.js → ssrEntryLoader-DEH3eV1e.js} +238 -54
- package/lib/{ssrVmStrategy-CDbcwMnf.js → ssrVmStrategy-COMHOCN2.js} +69 -5
- package/lib/utils/ssrEntryLoader.js +1 -1
- package/package.json +4 -4
- package/lib/buildPaths-BoaQTkxt.js +0 -66
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _ as resolvePublicPath, a as matchesSharedSource, c as filterId, d as getNodeModulesSuffix, f as isAssetLikeImport, g as normalizeNodeModulePath, h as isViteOptimizableEntry, i as invalidateSharedKeyMatcher, l as getBasePath$1, m as isNuxtClientBase, n as getSharedRequest, p as isNodeModulePath, r as getSharedRuntimeKey, s as ensureTrailingSlash, t as findSharedKey, u as getCommonSharedSubpaths, v as stripQueryAndHash, y as stripViteFsPrefix } from "./sharedKeyMatcher-Od_nYxJA.js";
|
|
2
|
-
import {
|
|
3
|
-
import { C as isReactCoreShare,
|
|
2
|
+
import { a as CodeRewriter, c as isAbsoluteUrl, d as resolveHashPlaceholderFileName, i as createCodePositionMap, l as normalizePathForImport, o as createSourceMap, r as mfWarn, t as createModuleFederationError, u as rebaseImport } from "./logger-DOwfTlw5.js";
|
|
3
|
+
import { C as isReactCoreShare, S as REACT_DOM_CLIENT_SHARE, _ as resolveModulePath, a as getIsRolldown, b as supportsCodeSplittingGroupDebugName, c as getPackageNameFromNodeModulePath, d as isNuxtProjectRoot, f as isPackageExportAvailable, g as resolveImportPath, h as packageNameEncode, i as getInstalledPackageJson, l as getSharedCacheDescriptor, m as packageNameDecode, n as getDependencyNames, o as getPackageDetectionCwd, p as isPackageInstalled, r as getInstalledPackageEntry, s as getPackageName, u as hasPackageDependency, v as setPackageDetectionCwd, x as REACT_CLIENT_INTERNALS_KEY, y as sharedCacheHelperCode } from "./dtsConstants-r5OfegUr.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import * as fs$2 from "fs";
|
|
6
6
|
import { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
|
|
@@ -15,6 +15,8 @@ import * as fs$1 from "node:fs";
|
|
|
15
15
|
import { existsSync as existsSync$1, readFileSync as readFileSync$1 } from "node:fs";
|
|
16
16
|
import { pathToFileURL as pathToFileURL$1 } from "node:url";
|
|
17
17
|
import { isIPv6 } from "node:net";
|
|
18
|
+
import { inferAutoPublicPath } from "@module-federation/sdk";
|
|
19
|
+
import { readFile } from "node:fs/promises";
|
|
18
20
|
//#region src/utils/regexEscape.ts
|
|
19
21
|
const REGEXP_SPECIAL_CHARS_RE = /[.*+?^${}()|[\]\\]/g;
|
|
20
22
|
/**
|
|
@@ -236,134 +238,6 @@ function findRemoteEntryFile(filename, bundle) {
|
|
|
236
238
|
return fallback;
|
|
237
239
|
}
|
|
238
240
|
//#endregion
|
|
239
|
-
//#region src/utils/codeRewriter.ts
|
|
240
|
-
const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
241
|
-
var CodeRewriter = class {
|
|
242
|
-
original;
|
|
243
|
-
replacements = [];
|
|
244
|
-
constructor(original) {
|
|
245
|
-
this.original = original;
|
|
246
|
-
}
|
|
247
|
-
overwrite(start, end, content) {
|
|
248
|
-
if (start < 0 || end < start || end > this.original.length) throw new Error(`Invalid overwrite range: ${start}-${end}`);
|
|
249
|
-
this.replacements.push({
|
|
250
|
-
start,
|
|
251
|
-
end,
|
|
252
|
-
content
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
toString() {
|
|
256
|
-
return applyReplacements(this.original, this.getSortedReplacements()).code;
|
|
257
|
-
}
|
|
258
|
-
generateMap(source = "") {
|
|
259
|
-
const { code, replacements } = applyReplacements(this.original, this.getSortedReplacements());
|
|
260
|
-
return {
|
|
261
|
-
version: 3,
|
|
262
|
-
sources: [source],
|
|
263
|
-
sourcesContent: [this.original],
|
|
264
|
-
names: [],
|
|
265
|
-
mappings: generateLineMappings(code, this.original, replacements)
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
getSortedReplacements() {
|
|
269
|
-
return [...this.replacements].sort((a, b) => a.start - b.start || a.end - b.end);
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
function createSourceMap(code, source = "") {
|
|
273
|
-
return {
|
|
274
|
-
version: 3,
|
|
275
|
-
sources: [source],
|
|
276
|
-
sourcesContent: [code],
|
|
277
|
-
names: [],
|
|
278
|
-
mappings: generateLineMappings(code, code, [])
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
function applyReplacements(original, replacements) {
|
|
282
|
-
let code = "";
|
|
283
|
-
let cursor = 0;
|
|
284
|
-
let delta = 0;
|
|
285
|
-
const applied = [];
|
|
286
|
-
for (const replacement of replacements) {
|
|
287
|
-
if (replacement.start < cursor) throw new Error("Overlapping overwrite ranges are not supported");
|
|
288
|
-
code += original.slice(cursor, replacement.start);
|
|
289
|
-
const generatedStart = replacement.start + delta;
|
|
290
|
-
code += replacement.content;
|
|
291
|
-
const generatedEnd = generatedStart + replacement.content.length;
|
|
292
|
-
applied.push({
|
|
293
|
-
...replacement,
|
|
294
|
-
generatedStart,
|
|
295
|
-
generatedEnd
|
|
296
|
-
});
|
|
297
|
-
cursor = replacement.end;
|
|
298
|
-
delta += replacement.content.length - (replacement.end - replacement.start);
|
|
299
|
-
}
|
|
300
|
-
code += original.slice(cursor);
|
|
301
|
-
return {
|
|
302
|
-
code,
|
|
303
|
-
replacements: applied
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
function generateLineMappings(generated, original, replacements) {
|
|
307
|
-
const generatedLineStarts = getLineStarts(generated);
|
|
308
|
-
const originalLineStarts = getLineStarts(original);
|
|
309
|
-
let previousOriginalLine = 0;
|
|
310
|
-
let previousOriginalColumn = 0;
|
|
311
|
-
let mappings = "";
|
|
312
|
-
generatedLineStarts.forEach((generatedOffset, lineIndex) => {
|
|
313
|
-
if (lineIndex > 0) mappings += ";";
|
|
314
|
-
const originalOffset = generatedOffsetToOriginalOffset(generatedOffset, replacements);
|
|
315
|
-
const originalLine = findLine(originalLineStarts, originalOffset);
|
|
316
|
-
const originalColumn = originalOffset - originalLineStarts[originalLine];
|
|
317
|
-
mappings += encodeSegment([
|
|
318
|
-
0,
|
|
319
|
-
0,
|
|
320
|
-
originalLine - previousOriginalLine,
|
|
321
|
-
originalColumn - previousOriginalColumn
|
|
322
|
-
]);
|
|
323
|
-
previousOriginalLine = originalLine;
|
|
324
|
-
previousOriginalColumn = originalColumn;
|
|
325
|
-
});
|
|
326
|
-
return mappings;
|
|
327
|
-
}
|
|
328
|
-
function generatedOffsetToOriginalOffset(offset, replacements) {
|
|
329
|
-
let delta = 0;
|
|
330
|
-
for (const replacement of replacements) {
|
|
331
|
-
if (offset < replacement.generatedStart) break;
|
|
332
|
-
if (offset < replacement.generatedEnd) return replacement.start;
|
|
333
|
-
delta += replacement.content.length - (replacement.end - replacement.start);
|
|
334
|
-
}
|
|
335
|
-
return offset - delta;
|
|
336
|
-
}
|
|
337
|
-
function getLineStarts(code) {
|
|
338
|
-
const starts = [0];
|
|
339
|
-
for (let i = 0; i < code.length; i++) if (code.charCodeAt(i) === 10) starts.push(i + 1);
|
|
340
|
-
return starts;
|
|
341
|
-
}
|
|
342
|
-
function findLine(lineStarts, offset) {
|
|
343
|
-
let low = 0;
|
|
344
|
-
let high = lineStarts.length - 1;
|
|
345
|
-
while (low <= high) {
|
|
346
|
-
const mid = low + high >> 1;
|
|
347
|
-
if (lineStarts[mid] <= offset) low = mid + 1;
|
|
348
|
-
else high = mid - 1;
|
|
349
|
-
}
|
|
350
|
-
return Math.max(0, high);
|
|
351
|
-
}
|
|
352
|
-
function encodeSegment(values) {
|
|
353
|
-
return values.map(encodeVlq).join("");
|
|
354
|
-
}
|
|
355
|
-
function encodeVlq(value) {
|
|
356
|
-
let vlq = value < 0 ? (-value << 1) + 1 : value << 1;
|
|
357
|
-
let encoded = "";
|
|
358
|
-
do {
|
|
359
|
-
let digit = vlq & 31;
|
|
360
|
-
vlq >>>= 5;
|
|
361
|
-
if (vlq > 0) digit |= 32;
|
|
362
|
-
encoded += BASE64_CHARS[digit];
|
|
363
|
-
} while (vlq > 0);
|
|
364
|
-
return encoded;
|
|
365
|
-
}
|
|
366
|
-
//#endregion
|
|
367
241
|
//#region src/utils/mapCodeToCodeWithSourcemap.ts
|
|
368
242
|
async function mapCodeToCodeWithSourcemap(code) {
|
|
369
243
|
const resolvedCode = await code;
|
|
@@ -416,147 +290,6 @@ function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
|
|
|
416
290
|
return resolveEnvironmentConsumerTarget(ctx) ?? "client";
|
|
417
291
|
}
|
|
418
292
|
//#endregion
|
|
419
|
-
//#region src/utils/codePositionMap.ts
|
|
420
|
-
const REGEX_PREFIX_KEYWORDS = /* @__PURE__ */ new Set([
|
|
421
|
-
"await",
|
|
422
|
-
"case",
|
|
423
|
-
"delete",
|
|
424
|
-
"in",
|
|
425
|
-
"instanceof",
|
|
426
|
-
"new",
|
|
427
|
-
"return",
|
|
428
|
-
"throw",
|
|
429
|
-
"typeof",
|
|
430
|
-
"void",
|
|
431
|
-
"yield"
|
|
432
|
-
]);
|
|
433
|
-
function isJsxClosingTagSlash(code, slashIndex) {
|
|
434
|
-
if (code[slashIndex - 1] !== "<") return false;
|
|
435
|
-
let cursor = slashIndex + 1;
|
|
436
|
-
while (/\s/.test(code[cursor] || "")) cursor++;
|
|
437
|
-
if (code[cursor] === ">") return true;
|
|
438
|
-
const tagStart = cursor;
|
|
439
|
-
while (/[-:.$_\u200C\u200D\p{ID_Continue}]/u.test(code[cursor] || "")) cursor++;
|
|
440
|
-
if (cursor === tagStart) return false;
|
|
441
|
-
while (/\s/.test(code[cursor] || "")) cursor++;
|
|
442
|
-
return code[cursor] === ">";
|
|
443
|
-
}
|
|
444
|
-
/** Mark comments, string/template literals, and regular expressions as non-code. */
|
|
445
|
-
function createCodePositionMap(code, onComment) {
|
|
446
|
-
const positions = Array(code.length).fill(true);
|
|
447
|
-
const mask = (start, end) => {
|
|
448
|
-
for (let index = start; index < end; index++) positions[index] = false;
|
|
449
|
-
};
|
|
450
|
-
let canStartRegex = true;
|
|
451
|
-
for (let index = 0; index < code.length;) {
|
|
452
|
-
const char = code[index];
|
|
453
|
-
const next = code[index + 1];
|
|
454
|
-
if (/\s/.test(char)) {
|
|
455
|
-
index++;
|
|
456
|
-
continue;
|
|
457
|
-
}
|
|
458
|
-
if (char === "/" && next === "/") {
|
|
459
|
-
const start = index;
|
|
460
|
-
index += 2;
|
|
461
|
-
while (index < code.length && code[index] !== "\n" && code[index] !== "\r") index++;
|
|
462
|
-
mask(start, index);
|
|
463
|
-
onComment?.(start, index);
|
|
464
|
-
continue;
|
|
465
|
-
}
|
|
466
|
-
if (char === "/" && next === "*") {
|
|
467
|
-
const start = index;
|
|
468
|
-
index += 2;
|
|
469
|
-
while (index < code.length && !(code[index] === "*" && code[index + 1] === "/")) index++;
|
|
470
|
-
index = Math.min(code.length, index + 2);
|
|
471
|
-
mask(start, index);
|
|
472
|
-
onComment?.(start, index);
|
|
473
|
-
continue;
|
|
474
|
-
}
|
|
475
|
-
if (char === "\"" || char === "'" || char === "`") {
|
|
476
|
-
const quote = char;
|
|
477
|
-
const start = index++;
|
|
478
|
-
while (index < code.length) {
|
|
479
|
-
if (code[index] === "\\") {
|
|
480
|
-
index += 2;
|
|
481
|
-
continue;
|
|
482
|
-
}
|
|
483
|
-
if (code[index] === quote) {
|
|
484
|
-
index++;
|
|
485
|
-
break;
|
|
486
|
-
}
|
|
487
|
-
index++;
|
|
488
|
-
}
|
|
489
|
-
mask(start, index);
|
|
490
|
-
canStartRegex = false;
|
|
491
|
-
continue;
|
|
492
|
-
}
|
|
493
|
-
const closesJsxTag = isJsxClosingTagSlash(code, index);
|
|
494
|
-
if (char === "/" && canStartRegex && !closesJsxTag) {
|
|
495
|
-
const start = index;
|
|
496
|
-
let cursor = index + 1;
|
|
497
|
-
let escaped = false;
|
|
498
|
-
let inCharacterClass = false;
|
|
499
|
-
let closed = false;
|
|
500
|
-
for (; cursor < code.length; cursor++) {
|
|
501
|
-
const regexChar = code[cursor];
|
|
502
|
-
if (regexChar === "\n" || regexChar === "\r") break;
|
|
503
|
-
if (escaped) {
|
|
504
|
-
escaped = false;
|
|
505
|
-
continue;
|
|
506
|
-
}
|
|
507
|
-
if (regexChar === "\\") {
|
|
508
|
-
escaped = true;
|
|
509
|
-
continue;
|
|
510
|
-
}
|
|
511
|
-
if (regexChar === "[") {
|
|
512
|
-
inCharacterClass = true;
|
|
513
|
-
continue;
|
|
514
|
-
}
|
|
515
|
-
if (regexChar === "]" && inCharacterClass) {
|
|
516
|
-
inCharacterClass = false;
|
|
517
|
-
continue;
|
|
518
|
-
}
|
|
519
|
-
if (regexChar === "/" && !inCharacterClass) {
|
|
520
|
-
cursor++;
|
|
521
|
-
while (/[$_\p{ID_Continue}]/u.test(code[cursor] || "")) cursor++;
|
|
522
|
-
closed = true;
|
|
523
|
-
break;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
if (closed) {
|
|
527
|
-
mask(start, cursor);
|
|
528
|
-
index = cursor;
|
|
529
|
-
canStartRegex = false;
|
|
530
|
-
continue;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
if (/[$_\p{ID_Start}]/u.test(char)) {
|
|
534
|
-
const start = index++;
|
|
535
|
-
while (/[$_\u200C\u200D\p{ID_Continue}]/u.test(code[index] || "")) index++;
|
|
536
|
-
canStartRegex = REGEX_PREFIX_KEYWORDS.has(code.slice(start, index));
|
|
537
|
-
continue;
|
|
538
|
-
}
|
|
539
|
-
if (/\d/.test(char)) {
|
|
540
|
-
index++;
|
|
541
|
-
while (/[\w.]/.test(code[index] || "")) index++;
|
|
542
|
-
canStartRegex = false;
|
|
543
|
-
continue;
|
|
544
|
-
}
|
|
545
|
-
if ((char === "+" || char === "-") && next === char) {
|
|
546
|
-
index += 2;
|
|
547
|
-
continue;
|
|
548
|
-
}
|
|
549
|
-
if (char === "!" && next !== "=") {
|
|
550
|
-
index++;
|
|
551
|
-
continue;
|
|
552
|
-
}
|
|
553
|
-
if (char === ")" || char === "]" || char === "}") canStartRegex = false;
|
|
554
|
-
else if (char !== ".") canStartRegex = true;
|
|
555
|
-
index++;
|
|
556
|
-
}
|
|
557
|
-
return positions;
|
|
558
|
-
}
|
|
559
|
-
//#endregion
|
|
560
293
|
//#region src/utils/htmlEntryUtils.ts
|
|
561
294
|
const IDENTIFIER = String.raw`[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*`;
|
|
562
295
|
const NAMED_SPECIFIERS = String.raw`\{[^{}]*\}`;
|
|
@@ -722,18 +455,18 @@ function normalizeExposes(exposes) {
|
|
|
722
455
|
});
|
|
723
456
|
return res;
|
|
724
457
|
}
|
|
725
|
-
function normalizeRemotes(remotes) {
|
|
458
|
+
function normalizeRemotes(remotes, defaultShareScope = "default") {
|
|
726
459
|
if (!remotes) return {};
|
|
727
460
|
const result = {};
|
|
728
461
|
if (typeof remotes === "object") Object.keys(remotes).forEach((key) => {
|
|
729
|
-
result[key] = normalizeRemoteItem(key, remotes[key]);
|
|
462
|
+
result[key] = normalizeRemoteItem(key, remotes[key], defaultShareScope);
|
|
730
463
|
});
|
|
731
464
|
return result;
|
|
732
465
|
}
|
|
733
466
|
function warnOmittedObjectRemoteType(remoteKey) {
|
|
734
467
|
mfWarn(`Remote "${remoteKey}" omits type and defaults to 'var'. Set type: 'module' for Vite ESM remotes, or type: 'var' explicitly to silence this warning.`);
|
|
735
468
|
}
|
|
736
|
-
function normalizeRemoteItem(key, remote) {
|
|
469
|
+
function normalizeRemoteItem(key, remote, defaultShareScope) {
|
|
737
470
|
warnOnReservedInternalNamePrefix(key, "remoteAlias");
|
|
738
471
|
if (typeof remote === "string") {
|
|
739
472
|
const separatorIndex = remote.startsWith("@") ? remote.indexOf("@", 1) : remote.indexOf("@");
|
|
@@ -752,7 +485,7 @@ function normalizeRemoteItem(key, remote) {
|
|
|
752
485
|
internalName: toInternalModuleFederationName(key),
|
|
753
486
|
entry,
|
|
754
487
|
entryGlobalName,
|
|
755
|
-
shareScope:
|
|
488
|
+
shareScope: defaultShareScope
|
|
756
489
|
};
|
|
757
490
|
}
|
|
758
491
|
const typeOmitted = remote.type === void 0 || remote.type === null || remote.type === "";
|
|
@@ -761,7 +494,7 @@ function normalizeRemoteItem(key, remote) {
|
|
|
761
494
|
type: "var",
|
|
762
495
|
name: key,
|
|
763
496
|
internalName: toInternalModuleFederationName(key),
|
|
764
|
-
shareScope:
|
|
497
|
+
shareScope: defaultShareScope,
|
|
765
498
|
entryGlobalName: key
|
|
766
499
|
}, {
|
|
767
500
|
...remote,
|
|
@@ -869,7 +602,7 @@ function resolveSharedVersions(shared, root) {
|
|
|
869
602
|
item.shareConfig.requiredVersion = requiredVersion;
|
|
870
603
|
}
|
|
871
604
|
}
|
|
872
|
-
function normalizeShareItem(key, shareItem) {
|
|
605
|
+
function normalizeShareItem(key, shareItem, defaultShareScope) {
|
|
873
606
|
const treeShaking = typeof shareItem === "object" ? shareItem.treeShaking : void 0;
|
|
874
607
|
if (treeShaking && treeShaking.mode !== "server-calc" && treeShaking.mode !== "runtime-infer") throw createModuleFederationError(`Invalid shared config for "${key}": treeShaking.mode must be either "server-calc" or "runtime-infer".`);
|
|
875
608
|
if (treeShaking && typeof shareItem === "object" && shareItem.eager) throw createModuleFederationError(`Invalid shared config for "${key}": cannot use both "eager: true" and "treeShaking.mode" simultaneously. Choose one strategy.`);
|
|
@@ -885,7 +618,7 @@ function normalizeShareItem(key, shareItem) {
|
|
|
885
618
|
const result = {
|
|
886
619
|
name: shareItem,
|
|
887
620
|
version,
|
|
888
|
-
scope:
|
|
621
|
+
scope: defaultShareScope,
|
|
889
622
|
from: "",
|
|
890
623
|
shareConfig: {
|
|
891
624
|
import: void 0,
|
|
@@ -901,7 +634,7 @@ function normalizeShareItem(key, shareItem) {
|
|
|
901
634
|
name: key,
|
|
902
635
|
from: "",
|
|
903
636
|
version,
|
|
904
|
-
scope: shareItem.shareScope ||
|
|
637
|
+
scope: shareItem.shareScope || defaultShareScope,
|
|
905
638
|
shareConfig: {
|
|
906
639
|
import: shareItem.import,
|
|
907
640
|
singleton: shareItem.singleton || false,
|
|
@@ -940,7 +673,7 @@ function normalizeSharedKey(key) {
|
|
|
940
673
|
if (baseKey === "react") return key;
|
|
941
674
|
return getCommonSharedSubpaths(baseKey).length > 0 ? baseKey : key;
|
|
942
675
|
}
|
|
943
|
-
function normalizeShared(shared) {
|
|
676
|
+
function normalizeShared(shared, defaultShareScope = "default") {
|
|
944
677
|
explicitSharedKeys = /* @__PURE__ */ new Set();
|
|
945
678
|
if (!shared) return {};
|
|
946
679
|
const result = {};
|
|
@@ -949,7 +682,7 @@ function normalizeShared(shared) {
|
|
|
949
682
|
if (isModuleFederationRuntimePackage(key)) return;
|
|
950
683
|
const normalizedKey = normalizeSharedKey(key);
|
|
951
684
|
const hadConfiguredPackageSubpath = (result[normalizedKey]?.shareConfig)?.__mfConfiguredPackageSubpath === true;
|
|
952
|
-
result[normalizedKey] = normalizeShareItem(normalizedKey, normalizedKey);
|
|
685
|
+
result[normalizedKey] = normalizeShareItem(normalizedKey, normalizedKey, defaultShareScope);
|
|
953
686
|
if (key.endsWith("/") || hadConfiguredPackageSubpath) result[normalizedKey].shareConfig.__mfConfiguredPackageSubpath = true;
|
|
954
687
|
explicitSharedKeys.add(normalizedKey);
|
|
955
688
|
sourceEntries.push([normalizedKey, normalizedKey]);
|
|
@@ -959,7 +692,7 @@ function normalizeShared(shared) {
|
|
|
959
692
|
const normalizedKey = normalizeSharedKey(key);
|
|
960
693
|
const value = shared[key];
|
|
961
694
|
const hadConfiguredPackageSubpath = (result[normalizedKey]?.shareConfig)?.__mfConfiguredPackageSubpath === true;
|
|
962
|
-
result[normalizedKey] = normalizeShareItem(normalizedKey, value);
|
|
695
|
+
result[normalizedKey] = normalizeShareItem(normalizedKey, value, defaultShareScope);
|
|
963
696
|
const requestIsPrefix = typeof value?.request === "string" && value.request.endsWith("/");
|
|
964
697
|
if (key.endsWith("/") || requestIsPrefix || hadConfiguredPackageSubpath) result[normalizedKey].shareConfig.__mfConfiguredPackageSubpath = true;
|
|
965
698
|
explicitSharedKeys.add(normalizedKey);
|
|
@@ -968,7 +701,7 @@ function normalizeShared(shared) {
|
|
|
968
701
|
sourceEntries.forEach(([key, value]) => {
|
|
969
702
|
for (const subpathShare of getLitExportSubpathShares(key)) {
|
|
970
703
|
if (result[subpathShare]) continue;
|
|
971
|
-
result[subpathShare] = normalizeShareItem(subpathShare, value);
|
|
704
|
+
result[subpathShare] = normalizeShareItem(subpathShare, value, defaultShareScope);
|
|
972
705
|
}
|
|
973
706
|
});
|
|
974
707
|
return result;
|
|
@@ -992,7 +725,8 @@ function normalizeExperiments(experiments) {
|
|
|
992
725
|
return {
|
|
993
726
|
externalRuntime: experiments?.externalRuntime === true,
|
|
994
727
|
provideExternalRuntime: experiments?.provideExternalRuntime === true,
|
|
995
|
-
ssrMode: experiments?.ssrMode === "ISLAND" ? "ISLAND" : void 0
|
|
728
|
+
ssrMode: experiments?.ssrMode === "ISLAND" ? "ISLAND" : void 0,
|
|
729
|
+
hostProvidesAllShared: experiments?.hostProvidesAllShared === true
|
|
996
730
|
};
|
|
997
731
|
}
|
|
998
732
|
function normalizeSsrEntryLoader(ssrEntryLoader) {
|
|
@@ -1048,6 +782,7 @@ function getNormalizeShareItem(key, options = getNormalizeModuleFederationOption
|
|
|
1048
782
|
function normalizeModuleFederationOptions(options) {
|
|
1049
783
|
warnOnReservedInternalNamePrefix(options.name, "containerName");
|
|
1050
784
|
if (options.virtualModuleDir && options.virtualModuleDir.includes("/")) throw createModuleFederationError(`Invalid virtualModuleDir: "${options.virtualModuleDir}". The virtualModuleDir option cannot contain slashes (/). Please use a single directory name like '__mf__virtual__your_app_name'.`);
|
|
785
|
+
const defaultShareScope = typeof options.shareScope === "string" ? options.shareScope : "default";
|
|
1051
786
|
const normalized = {
|
|
1052
787
|
exposes: normalizeExposes(options.exposes),
|
|
1053
788
|
filename: options.filename || "remoteEntry-[hash]",
|
|
@@ -1055,10 +790,10 @@ function normalizeModuleFederationOptions(options) {
|
|
|
1055
790
|
internalName: toInternalModuleFederationName(options.name),
|
|
1056
791
|
library: normalizeLibrary(options.library),
|
|
1057
792
|
name: options.name,
|
|
1058
|
-
remotes: normalizeRemotes(options.remotes),
|
|
793
|
+
remotes: normalizeRemotes(options.remotes, defaultShareScope),
|
|
1059
794
|
runtime: options.runtime,
|
|
1060
795
|
shareScope: options.shareScope || "default",
|
|
1061
|
-
shared: normalizeShared(options.shared),
|
|
796
|
+
shared: normalizeShared(options.shared, defaultShareScope),
|
|
1062
797
|
runtimePlugins: options.runtimePlugins || [],
|
|
1063
798
|
implementation: normalizePathForImport(options.implementation || resolveRuntimeImplementation()),
|
|
1064
799
|
manifest: normalizeManifest(options.manifest),
|
|
@@ -2671,6 +2406,11 @@ function resolveRelativeModule(filePath, specifier) {
|
|
|
2671
2406
|
const dir = path$1.dirname(filePath);
|
|
2672
2407
|
const exact = path$1.resolve(dir, specifier);
|
|
2673
2408
|
if (existsSync(exact) && !statSync(exact).isDirectory()) return exact;
|
|
2409
|
+
const sourceExtensions = specifier.endsWith(".mjs") ? [".mts"] : specifier.endsWith(".cjs") ? [".cts"] : /\.jsx?$/.test(specifier) ? [".ts", ".tsx"] : [];
|
|
2410
|
+
for (const ext of sourceExtensions) {
|
|
2411
|
+
const candidate = exact.replace(/\.[cm]?jsx?$/, ext);
|
|
2412
|
+
if (existsSync(candidate) && !statSync(candidate).isDirectory()) return candidate;
|
|
2413
|
+
}
|
|
2674
2414
|
const extensions = [
|
|
2675
2415
|
".ts",
|
|
2676
2416
|
".tsx",
|
|
@@ -4001,16 +3741,22 @@ function generateLocalSharedImportMap(options) {
|
|
|
4001
3741
|
const __mfGetCachedReactFamily = (keys, reactKeys, localVersion, requiredExport) => {
|
|
4002
3742
|
const cache = globalThis.__mf_module_cache__?.share;
|
|
4003
3743
|
const react = reactKeys.map((key) => cache?.[key]).find((value) => value !== undefined);
|
|
4004
|
-
const
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
3744
|
+
const isOlder = (version) => {
|
|
3745
|
+
const actual = String(version || '').split(/[^0-9]+/).map(Number);
|
|
3746
|
+
const expected = String(localVersion || '').split(/[^0-9]+/).map(Number);
|
|
3747
|
+
for (let index = 0; index < Math.max(actual.length, expected.length); index++) {
|
|
3748
|
+
if ((actual[index] || 0) < (expected[index] || 0)) return true;
|
|
3749
|
+
if ((actual[index] || 0) > (expected[index] || 0)) return false;
|
|
3750
|
+
}
|
|
3751
|
+
return false;
|
|
3752
|
+
};
|
|
3753
|
+
if (isOlder(react?.version ?? react?.default?.version)) return undefined;
|
|
4011
3754
|
for (const key of keys) {
|
|
4012
3755
|
const cached = cache?.[key];
|
|
4013
3756
|
if (cached === undefined) continue;
|
|
3757
|
+
// A host seed from an older React family is not coherent with the newer cached react
|
|
3758
|
+
const cachedVersion = cached?.version ?? cached?.default?.version;
|
|
3759
|
+
if (cachedVersion !== undefined && isOlder(cachedVersion)) continue;
|
|
4014
3760
|
if (!requiredExport || typeof cached?.[requiredExport] === 'function' || typeof cached?.default?.[requiredExport] === 'function') return cached;
|
|
4015
3761
|
}
|
|
4016
3762
|
return undefined;
|
|
@@ -4385,6 +4131,9 @@ const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
|
|
|
4385
4131
|
for (let i = 0; i < 5; i++) {
|
|
4386
4132
|
const defaultExport = current?.default;
|
|
4387
4133
|
if (!defaultExport || typeof defaultExport !== "object" || Object.keys(defaultExport).length === 0) break;
|
|
4134
|
+
// Only unwrap plain CJS namespaces; spreading a class instance would drop its prototype.
|
|
4135
|
+
const proto = Object.getPrototypeOf(defaultExport);
|
|
4136
|
+
if (proto !== null && proto !== Object.prototype) break;
|
|
4388
4137
|
const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
|
|
4389
4138
|
if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;
|
|
4390
4139
|
current = defaultExport;
|
|
@@ -4645,8 +4394,9 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
|
|
|
4645
4394
|
__mfNormalizeRuntimeShare(externalResolved),
|
|
4646
4395
|
externalProvider.from
|
|
4647
4396
|
);
|
|
4397
|
+
return;
|
|
4648
4398
|
}
|
|
4649
|
-
return;
|
|
4399
|
+
if (typeof isWebpackProvider === 'function' && isWebpackProvider(externalProvider)) return;
|
|
4650
4400
|
}
|
|
4651
4401
|
const providerKey = cacheDescriptor.canonical;
|
|
4652
4402
|
const resolved = await __mfInitializeProviderOnce(providerKey, async () => {
|
|
@@ -6089,6 +5839,22 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
|
|
|
6089
5839
|
}));
|
|
6090
5840
|
}
|
|
6091
5841
|
` : ""}
|
|
5842
|
+
// The seed called this container's get() directly, so the Runtime's
|
|
5843
|
+
// provider never learned it is in use and a remote could load its own
|
|
5844
|
+
// copy (#1396). Mark it once the host is bound to the local copy.
|
|
5845
|
+
for (const [pkg, share] of Object.entries(usedShared)) {
|
|
5846
|
+
if (!share.lib || share.treeShaking || share.shareConfig?.import === false) continue;
|
|
5847
|
+
const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
|
|
5848
|
+
if (__mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) !== ${cacheOwner}) continue;
|
|
5849
|
+
for (const scopeName of Array.isArray(share.scope) ? share.scope : [share.scope || "default"]) {
|
|
5850
|
+
const versions = runtime.shareScopeMap?.[scopeName]?.[pkg];
|
|
5851
|
+
const provider = versions?.[share.version];
|
|
5852
|
+
if (!provider || provider.get !== share.get || provider.lib) continue;
|
|
5853
|
+
if (Object.values(versions).some((other) => other !== provider && (other?.lib || other?.loaded))) continue;
|
|
5854
|
+
provider.lib = share.lib;
|
|
5855
|
+
provider.loaded = true;
|
|
5856
|
+
}
|
|
5857
|
+
}
|
|
6092
5858
|
return runtime;
|
|
6093
5859
|
})();
|
|
6094
5860
|
}
|
|
@@ -6967,6 +6733,19 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6967
6733
|
apply: "serve",
|
|
6968
6734
|
config(_config, { command }) {
|
|
6969
6735
|
_command = command;
|
|
6736
|
+
const isRemoteEntry = entryName === "remoteEntry" && federationOptions !== void 0 && isRemoteContainer(federationOptions);
|
|
6737
|
+
if (command === "serve" && _config.experimental?.bundledDev && isRemoteEntry) {
|
|
6738
|
+
_config.experimental = {
|
|
6739
|
+
..._config.experimental,
|
|
6740
|
+
bundledDev: false
|
|
6741
|
+
};
|
|
6742
|
+
_config.environments ??= {};
|
|
6743
|
+
_config.environments.client ??= {};
|
|
6744
|
+
if (_config.environments.client.isBundled !== false) {
|
|
6745
|
+
_config.environments.client.isBundled = false;
|
|
6746
|
+
mfWarn("Vite bundledDev is disabled for the client environment of a Module Federation remote container so its remoteEntry keeps the standard init/get contract.");
|
|
6747
|
+
}
|
|
6748
|
+
}
|
|
6970
6749
|
},
|
|
6971
6750
|
configResolved(config) {
|
|
6972
6751
|
viteConfig = config;
|
|
@@ -8263,7 +8042,8 @@ function pluginLazyConsumeOnlyShares(options) {
|
|
|
8263
8042
|
const rewriter = new CodeRewriter(code);
|
|
8264
8043
|
let edited = false;
|
|
8265
8044
|
const importMapId = normalizeVirtualModuleId(getLocalSharedImportMapPath(options));
|
|
8266
|
-
|
|
8045
|
+
const isImportMapChunk = chunkModuleIds(renderedChunk).some((id) => normalizeVirtualModuleId(id) === importMapId);
|
|
8046
|
+
if (isImportMapChunk) for (const quote of QUOTES) {
|
|
8267
8047
|
const literal = `${quote}${LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER}${quote}`;
|
|
8268
8048
|
const start = code.indexOf(literal);
|
|
8269
8049
|
if (start === -1) continue;
|
|
@@ -8274,7 +8054,7 @@ function pluginLazyConsumeOnlyShares(options) {
|
|
|
8274
8054
|
const chunkDir = path$1.posix.dirname(renderedChunk.fileName);
|
|
8275
8055
|
const codePositions = createCodePositionMap(code);
|
|
8276
8056
|
let usesHelper = false;
|
|
8277
|
-
for (const match of code.matchAll(DYNAMIC_IMPORT_REGEX)) {
|
|
8057
|
+
for (const match of isImportMapChunk ? [] : code.matchAll(DYNAMIC_IMPORT_REGEX)) {
|
|
8278
8058
|
const [expression, , specifier] = match;
|
|
8279
8059
|
const start = match.index;
|
|
8280
8060
|
if (!codePositions[start]) continue;
|
|
@@ -8303,7 +8083,7 @@ function ${helperName}(names) {
|
|
|
8303
8083
|
}
|
|
8304
8084
|
//#endregion
|
|
8305
8085
|
//#region package.json
|
|
8306
|
-
var version$1 = "1.23.
|
|
8086
|
+
var version$1 = "1.23.2";
|
|
8307
8087
|
//#endregion
|
|
8308
8088
|
//#region src/virtualModules/virtualExposesSSR.ts
|
|
8309
8089
|
/**
|
|
@@ -8405,6 +8185,8 @@ function generateRemoteEntrySSR(options) {
|
|
|
8405
8185
|
const sharedSingletons = ${JSON.stringify(sharedSingletons)};
|
|
8406
8186
|
const moduleCacheKey = Symbol.for(${JSON.stringify(MODULE_CACHE_SHARE_SCOPE_KEY)});
|
|
8407
8187
|
let exposesMapPromise;
|
|
8188
|
+
// One identity per container, so a re-entrant init with the same initScope finds it.
|
|
8189
|
+
const initToken = { from: ${JSON.stringify(options.name)} };
|
|
8408
8190
|
|
|
8409
8191
|
function createShareInitError(errors) {
|
|
8410
8192
|
const details = errors.map(({ scopeName, pkg, error }) => {
|
|
@@ -8433,7 +8215,6 @@ function generateRemoteEntrySSR(options) {
|
|
|
8433
8215
|
remotes: [],
|
|
8434
8216
|
shared: {},
|
|
8435
8217
|
});
|
|
8436
|
-
const initToken = { from: ${JSON.stringify(options.name)} };
|
|
8437
8218
|
if (initScope.indexOf(initToken) >= 0) return;
|
|
8438
8219
|
initScope.push(initToken);
|
|
8439
8220
|
const shareScopeNames = Array.isArray(${JSON.stringify(options.shareScope)})
|
|
@@ -8770,18 +8551,21 @@ const Manifest = (providedOptions) => {
|
|
|
8770
8551
|
publicPath = mfOptions.publicPath === "auto" ? "auto" : resolvePublicPath(mfOptions, base, _originalConfigBase);
|
|
8771
8552
|
},
|
|
8772
8553
|
/**
|
|
8773
|
-
*
|
|
8774
|
-
*
|
|
8775
|
-
*
|
|
8776
|
-
*
|
|
8777
|
-
*
|
|
8554
|
+
* The client manifest only advertises an SSR entry its own bundle
|
|
8555
|
+
* emitted. The SSR entry usually lands in a separate build: a standalone
|
|
8556
|
+
* `vite build --ssr` (possibly with its own `filename`, e.g.
|
|
8557
|
+
* `defineConfig(({ isSsrBuild }) => ...)`) or the `ssr` environment,
|
|
8558
|
+
* which the builder may run before or after `client`. Whichever build
|
|
8559
|
+
* finishes with the SSR entry on disk points the manifest and stats at it.
|
|
8778
8560
|
*/
|
|
8779
8561
|
writeBundle(outputOptions) {
|
|
8780
8562
|
if (!mfManifestName || _command !== "build" || isConsumerProject) return;
|
|
8781
|
-
const environment = this.environment;
|
|
8782
|
-
if (!(environment ? environment.name === "ssr" : Boolean(viteConfig?.build?.ssr))) return;
|
|
8783
8563
|
const ssrEntryName = getSsrRemoteEntryFileName(mfOptions);
|
|
8784
|
-
const outDirs = [...new Set([
|
|
8564
|
+
const outDirs = [...new Set([
|
|
8565
|
+
outputOptions.dir,
|
|
8566
|
+
viteConfig?.environments?.client?.build?.outDir,
|
|
8567
|
+
viteConfig?.environments?.ssr?.build?.outDir
|
|
8568
|
+
].filter((dir) => typeof dir === "string").map((dir) => path$1.resolve(root, dir)))];
|
|
8785
8569
|
if (!outDirs.some((dir) => fs$1.existsSync(path$1.resolve(dir, ssrEntryName)))) return;
|
|
8786
8570
|
for (const dir of outDirs) for (const fileName of [mfManifestName, mfManifestStatsName]) {
|
|
8787
8571
|
if (!fileName) continue;
|
|
@@ -8790,8 +8574,12 @@ const Manifest = (providedOptions) => {
|
|
|
8790
8574
|
try {
|
|
8791
8575
|
const data = JSON.parse(fs$1.readFileSync(file, "utf8"));
|
|
8792
8576
|
const entry = data?.metaData?.ssrRemoteEntry;
|
|
8793
|
-
if (!
|
|
8794
|
-
|
|
8577
|
+
if (!data?.metaData || entry?.name === ssrEntryName) continue;
|
|
8578
|
+
data.metaData.ssrRemoteEntry = Object.assign({
|
|
8579
|
+
name: ssrEntryName,
|
|
8580
|
+
path: "",
|
|
8581
|
+
type: "module"
|
|
8582
|
+
}, typeof entry === "object" ? entry : null, { name: ssrEntryName });
|
|
8795
8583
|
fs$1.writeFileSync(file, JSON.stringify(data));
|
|
8796
8584
|
} catch {}
|
|
8797
8585
|
}
|
|
@@ -8809,7 +8597,7 @@ const Manifest = (providedOptions) => {
|
|
|
8809
8597
|
const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions);
|
|
8810
8598
|
const foundSsrRemoteEntryFile = Object.values(bundle).find((file) => file.fileName === expectedSsrRemoteEntryFile)?.fileName;
|
|
8811
8599
|
if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
|
|
8812
|
-
ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(mfOptions, resolveHashPlaceholderFileName(mfOptions.filename)) :
|
|
8600
|
+
ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(mfOptions, resolveHashPlaceholderFileName(mfOptions.filename)) : void 0);
|
|
8813
8601
|
const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
|
|
8814
8602
|
if (allCssAssets.size > 0) {
|
|
8815
8603
|
const secondaryCss = /* @__PURE__ */ new Set();
|
|
@@ -8885,11 +8673,12 @@ const Manifest = (providedOptions) => {
|
|
|
8885
8673
|
path: "",
|
|
8886
8674
|
type: "module"
|
|
8887
8675
|
};
|
|
8888
|
-
const
|
|
8889
|
-
|
|
8676
|
+
const resolvedSsrRemoteEntryFile = _command === "serve" ? ssrRemoteEntryFile || getSsrRemoteEntryFileName(mfOptions, resolveHashPlaceholderFileName(filename)) : ssrRemoteEntryFile;
|
|
8677
|
+
const ssrRemoteEntry = resolvedSsrRemoteEntryFile ? {
|
|
8678
|
+
name: resolvedSsrRemoteEntryFile,
|
|
8890
8679
|
path: _command === "serve" ? "/__mf_ssr__/" : "",
|
|
8891
8680
|
type: "module"
|
|
8892
|
-
};
|
|
8681
|
+
} : void 0;
|
|
8893
8682
|
const varRemoteEntry = varFilename ? {
|
|
8894
8683
|
name: varFilename,
|
|
8895
8684
|
path: "",
|
|
@@ -9014,6 +8803,106 @@ function getStatsFileName(manifestFileName) {
|
|
|
9014
8803
|
return parsed.dir ? normalizePathForImport(path$1.join(parsed.dir, fileName)) : fileName;
|
|
9015
8804
|
}
|
|
9016
8805
|
//#endregion
|
|
8806
|
+
//#region src/utils/sharedSource.ts
|
|
8807
|
+
const pendingEntryLookups = /* @__PURE__ */ new Map();
|
|
8808
|
+
const getEntryLookupKey = (source, importer) => `${source}\0${importer}`;
|
|
8809
|
+
/** Whether a resolveId call is one of the shared source resolver's own entry lookups. */
|
|
8810
|
+
function isSharedEntryLookup(source, importer, options) {
|
|
8811
|
+
return options.custom?.__mfSharedEntryLookup === true || pendingEntryLookups.has(getEntryLookupKey(source, importer));
|
|
8812
|
+
}
|
|
8813
|
+
/**
|
|
8814
|
+
* Runs one of the plugin's own `this.resolve()` calls (a shared entry lookup, a
|
|
8815
|
+
* parse-barrier external probe), marked so `isSharedEntryLookup` recognizes it
|
|
8816
|
+
* and the share hooks neither proxy it nor register a used share for it.
|
|
8817
|
+
*/
|
|
8818
|
+
async function resolveInternally(context, source, importer, options = {}) {
|
|
8819
|
+
const lookupKey = getEntryLookupKey(source, importer);
|
|
8820
|
+
pendingEntryLookups.set(lookupKey, (pendingEntryLookups.get(lookupKey) ?? 0) + 1);
|
|
8821
|
+
try {
|
|
8822
|
+
return await context.resolve(source, importer, {
|
|
8823
|
+
...options,
|
|
8824
|
+
skipSelf: true,
|
|
8825
|
+
custom: {
|
|
8826
|
+
...options.custom,
|
|
8827
|
+
__mfSharedEntryLookup: true
|
|
8828
|
+
}
|
|
8829
|
+
});
|
|
8830
|
+
} finally {
|
|
8831
|
+
const remaining = pendingEntryLookups.get(lookupKey) - 1;
|
|
8832
|
+
if (remaining) pendingEntryLookups.set(lookupKey, remaining);
|
|
8833
|
+
else pendingEntryLookups.delete(lookupKey);
|
|
8834
|
+
}
|
|
8835
|
+
}
|
|
8836
|
+
/** Identify shared entries through Vite, with a cache scoped to this federation instance. */
|
|
8837
|
+
function createSharedSourceResolver(shared, getResolutionConfig) {
|
|
8838
|
+
const caches = /* @__PURE__ */ new Map();
|
|
8839
|
+
async function matchEntry(source, suffix, resolveEntry) {
|
|
8840
|
+
const packageName = getPackageNameFromNodeModulePath(source);
|
|
8841
|
+
if (!packageName) return;
|
|
8842
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
8843
|
+
if (findSharedKey(packageName, shared)) candidates.add(packageName);
|
|
8844
|
+
if (findSharedKey(suffix, shared)) candidates.add(suffix);
|
|
8845
|
+
for (const key of Object.keys(shared)) {
|
|
8846
|
+
const request = getSharedRequest(key, shared[key]);
|
|
8847
|
+
if (getPackageName(request) !== packageName) continue;
|
|
8848
|
+
if (!request.endsWith("/")) candidates.add(request);
|
|
8849
|
+
for (const subpath of getCommonSharedSubpaths(request)) if (findSharedKey(subpath, shared)) candidates.add(subpath);
|
|
8850
|
+
}
|
|
8851
|
+
if (candidates.size === 0) return;
|
|
8852
|
+
const resolvedSource = await resolveEntry(source);
|
|
8853
|
+
if (!resolvedSource) return;
|
|
8854
|
+
for (const candidate of candidates) {
|
|
8855
|
+
const entry = await resolveEntry(candidate);
|
|
8856
|
+
if (!entry) continue;
|
|
8857
|
+
const allowNodeModulesSuffixMatch = shared[findSharedKey(candidate, shared) ?? candidate]?.shareConfig?.allowNodeModulesSuffixMatch === true;
|
|
8858
|
+
if (normalizeNodeModulePath(entry) === normalizeNodeModulePath(resolvedSource) || allowNodeModulesSuffixMatch && getNodeModulesSuffix(entry) === suffix) return candidate;
|
|
8859
|
+
}
|
|
8860
|
+
}
|
|
8861
|
+
return {
|
|
8862
|
+
clear() {
|
|
8863
|
+
caches.clear();
|
|
8864
|
+
},
|
|
8865
|
+
async resolve(context, source, options = {}) {
|
|
8866
|
+
if (source.startsWith("\0") || source.includes("#")) return;
|
|
8867
|
+
const queryIndex = source.indexOf("?");
|
|
8868
|
+
const query = queryIndex === -1 ? "" : source.slice(queryIndex + 1);
|
|
8869
|
+
if (query && [...new URLSearchParams(query).keys()].some((key) => ![
|
|
8870
|
+
"v",
|
|
8871
|
+
"t",
|
|
8872
|
+
"import"
|
|
8873
|
+
].includes(key))) return;
|
|
8874
|
+
if (findSharedKey(source, shared)) return source;
|
|
8875
|
+
const suffix = getNodeModulesSuffix(source);
|
|
8876
|
+
if (!suffix) return;
|
|
8877
|
+
const normalizedSource = stripViteFsPrefix(normalizeNodeModulePath(source));
|
|
8878
|
+
const environment = context.environment ?? !!options.ssr;
|
|
8879
|
+
const cacheable = !options.isEntry && !options.scan && (!options.kind || options.kind === "import-statement") && Object.keys(options.attributes ?? {}).length === 0 && Object.keys(options.custom ?? {}).length === 0;
|
|
8880
|
+
let cache = cacheable ? caches.get(environment) : void 0;
|
|
8881
|
+
if (cacheable && !cache) {
|
|
8882
|
+
cache = /* @__PURE__ */ new Map();
|
|
8883
|
+
caches.set(environment, cache);
|
|
8884
|
+
}
|
|
8885
|
+
if (cache?.has(normalizedSource)) return cache.get(normalizedSource);
|
|
8886
|
+
const { root, conditions } = getResolutionConfig(context, options);
|
|
8887
|
+
const result = await matchEntry(normalizedSource, suffix, async (request) => {
|
|
8888
|
+
if (!path$1.isAbsolute(request) && !isPackageExportAvailable(request, {
|
|
8889
|
+
cwd: root,
|
|
8890
|
+
conditions
|
|
8891
|
+
})) return void 0;
|
|
8892
|
+
const importer = path$1.join(root, "package.json");
|
|
8893
|
+
try {
|
|
8894
|
+
const resolved = await resolveInternally(context, request, importer, options);
|
|
8895
|
+
return resolved && !resolved.external ? resolved.id : void 0;
|
|
8896
|
+
} catch {
|
|
8897
|
+
return;
|
|
8898
|
+
}
|
|
8899
|
+
});
|
|
8900
|
+
cache?.set(normalizedSource, result);
|
|
8901
|
+
return result;
|
|
8902
|
+
}
|
|
8903
|
+
};
|
|
8904
|
+
}
|
|
8905
|
+
//#endregion
|
|
9017
8906
|
//#region src/plugins/pluginModuleParseEnd.ts
|
|
9018
8907
|
function createModuleParseController() {
|
|
9019
8908
|
return {
|
|
@@ -9155,7 +9044,7 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
|
|
|
9155
9044
|
if (typeof this.resolve !== "function") return;
|
|
9156
9045
|
if (controller.resolutionProbed.has(pendingId)) return;
|
|
9157
9046
|
controller.resolutionProbed.add(pendingId);
|
|
9158
|
-
this
|
|
9047
|
+
resolveInternally(this, pendingId, id).then((resolved) => {
|
|
9159
9048
|
if (!resolved?.external) return;
|
|
9160
9049
|
controller.externalSet.add(pendingId);
|
|
9161
9050
|
controller.parseStartSet.delete(pendingId);
|
|
@@ -9164,7 +9053,7 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
|
|
|
9164
9053
|
};
|
|
9165
9054
|
const addPendingIds = (ids) => {
|
|
9166
9055
|
for (const pendingId of ids || []) {
|
|
9167
|
-
if (
|
|
9056
|
+
if (controller.externalSet.has(pendingId) || matchesExternal(configuredExternal, pendingId, id) || excludeFn(pendingId)) continue;
|
|
9168
9057
|
controller.parseStartSet.add(pendingId);
|
|
9169
9058
|
if (!controller.parseEndSet.has(pendingId)) probeExternal(pendingId);
|
|
9170
9059
|
}
|
|
@@ -9239,7 +9128,12 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
9239
9128
|
if (!dynamic) dependencies.add(source);
|
|
9240
9129
|
continue;
|
|
9241
9130
|
}
|
|
9242
|
-
|
|
9131
|
+
let resolved;
|
|
9132
|
+
try {
|
|
9133
|
+
resolved = await ctx.resolve(source, id);
|
|
9134
|
+
} catch {
|
|
9135
|
+
continue;
|
|
9136
|
+
}
|
|
9243
9137
|
if (!resolved?.id || !shouldScanResolvedImport(resolved.id)) continue;
|
|
9244
9138
|
for (const dependency of await collectRemoteDependencies(ctx, resolved.id, seen)) dependencies.add(dependency);
|
|
9245
9139
|
}
|
|
@@ -9459,96 +9353,6 @@ function pluginProxyRemotes_default(options) {
|
|
|
9459
9353
|
};
|
|
9460
9354
|
}
|
|
9461
9355
|
//#endregion
|
|
9462
|
-
//#region src/utils/sharedSource.ts
|
|
9463
|
-
const pendingEntryLookups = /* @__PURE__ */ new Map();
|
|
9464
|
-
const getEntryLookupKey = (source, importer) => `${source}\0${importer}`;
|
|
9465
|
-
/** Whether a resolveId call is one of the shared source resolver's own entry lookups. */
|
|
9466
|
-
function isSharedEntryLookup(source, importer, options) {
|
|
9467
|
-
return options.custom?.__mfSharedEntryLookup === true || pendingEntryLookups.has(getEntryLookupKey(source, importer));
|
|
9468
|
-
}
|
|
9469
|
-
/** Identify shared entries through Vite, with a cache scoped to this federation instance. */
|
|
9470
|
-
function createSharedSourceResolver(shared, getResolutionConfig) {
|
|
9471
|
-
const caches = /* @__PURE__ */ new Map();
|
|
9472
|
-
async function matchEntry(source, suffix, resolveEntry) {
|
|
9473
|
-
const packageName = getPackageNameFromNodeModulePath(source);
|
|
9474
|
-
if (!packageName) return;
|
|
9475
|
-
const candidates = /* @__PURE__ */ new Set();
|
|
9476
|
-
if (findSharedKey(packageName, shared)) candidates.add(packageName);
|
|
9477
|
-
if (findSharedKey(suffix, shared)) candidates.add(suffix);
|
|
9478
|
-
for (const key of Object.keys(shared)) {
|
|
9479
|
-
const request = getSharedRequest(key, shared[key]);
|
|
9480
|
-
if (getPackageName(request) !== packageName) continue;
|
|
9481
|
-
if (!request.endsWith("/")) candidates.add(request);
|
|
9482
|
-
for (const subpath of getCommonSharedSubpaths(request)) if (findSharedKey(subpath, shared)) candidates.add(subpath);
|
|
9483
|
-
}
|
|
9484
|
-
if (candidates.size === 0) return;
|
|
9485
|
-
const resolvedSource = await resolveEntry(source);
|
|
9486
|
-
if (!resolvedSource) return;
|
|
9487
|
-
for (const candidate of candidates) {
|
|
9488
|
-
const entry = await resolveEntry(candidate);
|
|
9489
|
-
if (!entry) continue;
|
|
9490
|
-
const allowNodeModulesSuffixMatch = shared[findSharedKey(candidate, shared) ?? candidate]?.shareConfig?.allowNodeModulesSuffixMatch === true;
|
|
9491
|
-
if (normalizeNodeModulePath(entry) === normalizeNodeModulePath(resolvedSource) || allowNodeModulesSuffixMatch && getNodeModulesSuffix(entry) === suffix) return candidate;
|
|
9492
|
-
}
|
|
9493
|
-
}
|
|
9494
|
-
return {
|
|
9495
|
-
clear() {
|
|
9496
|
-
caches.clear();
|
|
9497
|
-
},
|
|
9498
|
-
async resolve(context, source, options = {}) {
|
|
9499
|
-
if (source.startsWith("\0") || source.includes("#")) return;
|
|
9500
|
-
const queryIndex = source.indexOf("?");
|
|
9501
|
-
const query = queryIndex === -1 ? "" : source.slice(queryIndex + 1);
|
|
9502
|
-
if (query && [...new URLSearchParams(query).keys()].some((key) => ![
|
|
9503
|
-
"v",
|
|
9504
|
-
"t",
|
|
9505
|
-
"import"
|
|
9506
|
-
].includes(key))) return;
|
|
9507
|
-
if (findSharedKey(source, shared)) return source;
|
|
9508
|
-
const suffix = getNodeModulesSuffix(source);
|
|
9509
|
-
if (!suffix) return;
|
|
9510
|
-
const normalizedSource = stripViteFsPrefix(normalizeNodeModulePath(source));
|
|
9511
|
-
const environment = context.environment ?? !!options.ssr;
|
|
9512
|
-
const cacheable = !options.isEntry && !options.scan && (!options.kind || options.kind === "import-statement") && Object.keys(options.attributes ?? {}).length === 0 && Object.keys(options.custom ?? {}).length === 0;
|
|
9513
|
-
let cache = cacheable ? caches.get(environment) : void 0;
|
|
9514
|
-
if (cacheable && !cache) {
|
|
9515
|
-
cache = /* @__PURE__ */ new Map();
|
|
9516
|
-
caches.set(environment, cache);
|
|
9517
|
-
}
|
|
9518
|
-
if (cache?.has(normalizedSource)) return cache.get(normalizedSource);
|
|
9519
|
-
const { root, conditions } = getResolutionConfig(context, options);
|
|
9520
|
-
const result = await matchEntry(normalizedSource, suffix, async (request) => {
|
|
9521
|
-
if (!path$1.isAbsolute(request) && !isPackageExportAvailable(request, {
|
|
9522
|
-
cwd: root,
|
|
9523
|
-
conditions
|
|
9524
|
-
})) return void 0;
|
|
9525
|
-
const importer = path$1.join(root, "package.json");
|
|
9526
|
-
const lookupKey = getEntryLookupKey(request, importer);
|
|
9527
|
-
pendingEntryLookups.set(lookupKey, (pendingEntryLookups.get(lookupKey) ?? 0) + 1);
|
|
9528
|
-
try {
|
|
9529
|
-
const resolved = await context.resolve(request, importer, {
|
|
9530
|
-
...options,
|
|
9531
|
-
skipSelf: true,
|
|
9532
|
-
custom: {
|
|
9533
|
-
...options.custom,
|
|
9534
|
-
__mfSharedEntryLookup: true
|
|
9535
|
-
}
|
|
9536
|
-
});
|
|
9537
|
-
return resolved && !resolved.external ? resolved.id : void 0;
|
|
9538
|
-
} catch {
|
|
9539
|
-
return;
|
|
9540
|
-
} finally {
|
|
9541
|
-
const remaining = pendingEntryLookups.get(lookupKey) - 1;
|
|
9542
|
-
if (remaining) pendingEntryLookups.set(lookupKey, remaining);
|
|
9543
|
-
else pendingEntryLookups.delete(lookupKey);
|
|
9544
|
-
}
|
|
9545
|
-
});
|
|
9546
|
-
cache?.set(normalizedSource, result);
|
|
9547
|
-
return result;
|
|
9548
|
-
}
|
|
9549
|
-
};
|
|
9550
|
-
}
|
|
9551
|
-
//#endregion
|
|
9552
9356
|
//#region src/utils/PromiseStore.ts
|
|
9553
9357
|
/**
|
|
9554
9358
|
* example:
|
|
@@ -9762,8 +9566,9 @@ function isSharedPackageDependency(sharedKey, dependency) {
|
|
|
9762
9566
|
function isConfiguredSharedPackage(pkg, shared) {
|
|
9763
9567
|
return Object.keys(shared).some((key) => getPackageName(key) === pkg);
|
|
9764
9568
|
}
|
|
9765
|
-
function shouldKeepSharedImportLocal(source, importer, sharedKey, shared, importerPackage) {
|
|
9569
|
+
function shouldKeepSharedImportLocal(source, importer, sharedKey, shared, importerPackage, federationOptions) {
|
|
9766
9570
|
if (!importer || shared[sharedKey]?.shareConfig.import === false) return false;
|
|
9571
|
+
if (hasRemotes(federationOptions)) return false;
|
|
9767
9572
|
const prebuildImporter = importer.includes("__prebuild__") ? VirtualModule.findModule(PREBUILD_TAG, importer) : void 0;
|
|
9768
9573
|
const fallbackPackage = prebuildImporter ? getPackageName(prebuildImporter.name) : importerPackage;
|
|
9769
9574
|
if (!fallbackPackage || !isConfiguredSharedPackage(fallbackPackage, shared)) return false;
|
|
@@ -10181,7 +9986,7 @@ function proxySharedModule(options) {
|
|
|
10181
9986
|
if (shouldSkipTaggedImporterProxy(key, "__loadShare__")) return;
|
|
10182
9987
|
if (shouldSkipTaggedImporterProxy(key, "__prebuild__")) return;
|
|
10183
9988
|
const shareSource = key === "vue" && sharedSource.startsWith("vue/dist/") ? key : sharedSource;
|
|
10184
|
-
if (shouldKeepSharedImportLocal(
|
|
9989
|
+
if (shouldKeepSharedImportLocal(shareSource, importer, key, shared, importerPackage, federationOptions)) {
|
|
10185
9990
|
const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
|
|
10186
9991
|
return tryResolveFromProjectRoot(localSource) || localSource;
|
|
10187
9992
|
}
|
|
@@ -11140,6 +10945,360 @@ function isTestEnv() {
|
|
|
11140
10945
|
return process.env.NODE_ENV === "test" || process.env.VITEST != null || process.env.JEST_WORKER_ID != null;
|
|
11141
10946
|
}
|
|
11142
10947
|
//#endregion
|
|
10948
|
+
//#region src/utils/hostProvidesAllShared.ts
|
|
10949
|
+
/** Virtual-module prefix of the host's per-share re-export entries. */
|
|
10950
|
+
const SHARE_MODULE_PREFIX = "\0mf-host-provided-share:";
|
|
10951
|
+
/** `./a/b` → `a/b`, `.` → `index`: the fixed entry name of an expose, without `.js`. */
|
|
10952
|
+
function exposeEntryName(exposeKey) {
|
|
10953
|
+
return exposeKey === "." ? "index" : exposeKey.replace(/^\.\//, "");
|
|
10954
|
+
}
|
|
10955
|
+
/** Bare specifier a host uses for an expose: `remote` for `.`, `remote/a/b` otherwise. */
|
|
10956
|
+
function remoteSpecifier(remoteName, exposeKey) {
|
|
10957
|
+
const entry = exposeEntryName(exposeKey);
|
|
10958
|
+
return entry === "index" ? remoteName : `${remoteName}/${entry}`;
|
|
10959
|
+
}
|
|
10960
|
+
/** `id` is a remote alias or a subpath of one. */
|
|
10961
|
+
function isRemoteSpecifier(id, remoteKeys) {
|
|
10962
|
+
return remoteKeys.some((key) => id === key || id.startsWith(`${key}/`));
|
|
10963
|
+
}
|
|
10964
|
+
/**
|
|
10965
|
+
* The shared key that owns `id`: an exact match, else the longest key `id` is a subpath
|
|
10966
|
+
* of (`lodash-es/debounce` → `lodash-es`). Used to spot an unshared subpath of a shared
|
|
10967
|
+
* package, which would bundle a private copy of that package into a remote.
|
|
10968
|
+
*/
|
|
10969
|
+
function sharedKeyOwning(id, sharedKeys) {
|
|
10970
|
+
let owner;
|
|
10971
|
+
for (const key of sharedKeys) {
|
|
10972
|
+
if (id !== key && !id.startsWith(`${key}/`)) continue;
|
|
10973
|
+
if (!owner || key.length > owner.length) owner = key;
|
|
10974
|
+
}
|
|
10975
|
+
return owner;
|
|
10976
|
+
}
|
|
10977
|
+
/** Chunk name of the host's re-export entry for a shared key. */
|
|
10978
|
+
function shareChunkName(key) {
|
|
10979
|
+
return `shared/${key.replace(/^@/, "").replace(/[^\w-]+/g, "-")}`;
|
|
10980
|
+
}
|
|
10981
|
+
/** Reads a remote's `mf-manifest.json` from a URL or a path relative to `root`. */
|
|
10982
|
+
async function readHostProvidesAllSharedManifest(location, root) {
|
|
10983
|
+
let source;
|
|
10984
|
+
if (isAbsoluteUrl(location)) {
|
|
10985
|
+
const response = await fetch(location);
|
|
10986
|
+
if (!response.ok) throw new Error(`Failed to fetch ${location}: ${response.status} ${response.statusText}`);
|
|
10987
|
+
source = await response.text();
|
|
10988
|
+
} else source = await readFile(path$1.resolve(root, location), "utf8");
|
|
10989
|
+
const manifest = JSON.parse(source);
|
|
10990
|
+
if (!manifest.metaData || !Array.isArray(manifest.exposes)) throw new Error(`${location} is not a Module Federation manifest.`);
|
|
10991
|
+
if (manifest.metaData.remoteEntry) throw new Error(`${location} describes a Module Federation runtime remote (it has a remoteEntry). Build the remote with \`experiments: { hostProvidesAllShared: true }\`.`);
|
|
10992
|
+
return manifest;
|
|
10993
|
+
}
|
|
10994
|
+
/** URL prefix of a remote's files: `metaData.publicPath`, `auto` inferred from the manifest URL. */
|
|
10995
|
+
function remotePublicPath(manifest, location) {
|
|
10996
|
+
const publicPath = manifest.metaData.publicPath ?? "auto";
|
|
10997
|
+
if (publicPath !== "auto") return ensureTrailingSlash(publicPath);
|
|
10998
|
+
if (!isAbsoluteUrl(location)) throw new Error(`${location}: publicPath is "auto", which can only be inferred from a manifest URL. Reference the manifest by URL or set \`base\` / \`publicPath\` in the remote build.`);
|
|
10999
|
+
return ensureTrailingSlash(inferAutoPublicPath(location));
|
|
11000
|
+
}
|
|
11001
|
+
/** Import-map entries (`remote/Expose` → URL) for every expose of every remote. */
|
|
11002
|
+
async function collectRemoteImports(remotes, root) {
|
|
11003
|
+
const imports = {};
|
|
11004
|
+
for (const [alias, remote] of Object.entries(remotes)) {
|
|
11005
|
+
const manifest = await readHostProvidesAllSharedManifest(remote.entry, root);
|
|
11006
|
+
const publicPath = remotePublicPath(manifest, remote.entry);
|
|
11007
|
+
for (const expose of manifest.exposes) {
|
|
11008
|
+
const file = expose.assets.js.sync[0];
|
|
11009
|
+
if (!expose.path || !file) continue;
|
|
11010
|
+
imports[remoteSpecifier(alias, expose.path)] = isAbsoluteUrl(remote.entry) ? new URL(file, new URL(publicPath, remote.entry)).href : publicPath + file;
|
|
11011
|
+
}
|
|
11012
|
+
}
|
|
11013
|
+
return imports;
|
|
11014
|
+
}
|
|
11015
|
+
/** Top-level options that only the Module Federation runtime or `remoteEntry.js` pipeline reads. */
|
|
11016
|
+
const IGNORED_OPTIONS = [
|
|
11017
|
+
"filename",
|
|
11018
|
+
"ssrFilename",
|
|
11019
|
+
"varFilename",
|
|
11020
|
+
"library",
|
|
11021
|
+
"runtime",
|
|
11022
|
+
"shareScope",
|
|
11023
|
+
"shareStrategy",
|
|
11024
|
+
"runtimePlugins",
|
|
11025
|
+
"implementation",
|
|
11026
|
+
"getPublicPath",
|
|
11027
|
+
"ignoreOrigin",
|
|
11028
|
+
"virtualModuleDir",
|
|
11029
|
+
"hostInitInjectLocation",
|
|
11030
|
+
"bundleAllCSS",
|
|
11031
|
+
"treeShakingDir",
|
|
11032
|
+
"injectTreeShakingUsedExports",
|
|
11033
|
+
"treeShakingSharedPlugins",
|
|
11034
|
+
"treeShakingSharedExcludePlugins",
|
|
11035
|
+
"moduleParseTimeout",
|
|
11036
|
+
"moduleParseIdleTimeout",
|
|
11037
|
+
"target",
|
|
11038
|
+
"ssrExternals",
|
|
11039
|
+
"ssrEntryLoader",
|
|
11040
|
+
"disableRemote",
|
|
11041
|
+
"disableShared",
|
|
11042
|
+
"disableSnapshot"
|
|
11043
|
+
];
|
|
11044
|
+
const IGNORED_EXPERIMENTS = [
|
|
11045
|
+
"externalRuntime",
|
|
11046
|
+
"provideExternalRuntime",
|
|
11047
|
+
"ssrMode"
|
|
11048
|
+
];
|
|
11049
|
+
/** Per-share options: version negotiation, aliasing and fallbacks do not exist in this mode. */
|
|
11050
|
+
const IGNORED_SHARE_OPTIONS = [
|
|
11051
|
+
"eager",
|
|
11052
|
+
"requiredVersion",
|
|
11053
|
+
"strictVersion",
|
|
11054
|
+
"import",
|
|
11055
|
+
"request",
|
|
11056
|
+
"shareKey",
|
|
11057
|
+
"name",
|
|
11058
|
+
"version",
|
|
11059
|
+
"shareScope",
|
|
11060
|
+
"treeShaking",
|
|
11061
|
+
"allowNodeModulesSuffixMatch",
|
|
11062
|
+
"suppressMissingImportWarning"
|
|
11063
|
+
];
|
|
11064
|
+
const isSet = (value) => value !== void 0 && value !== false && !(Array.isArray(value) && value.length === 0);
|
|
11065
|
+
/** A single warning naming every option the user set that import-map mode ignores. */
|
|
11066
|
+
function getIgnoredOptionWarning(options) {
|
|
11067
|
+
const shared = options.shared;
|
|
11068
|
+
const ignored = [
|
|
11069
|
+
...IGNORED_OPTIONS.filter((key) => isSet(options[key])).map((key) => `\`${key}\``),
|
|
11070
|
+
...IGNORED_EXPERIMENTS.filter((key) => isSet(options.experiments?.[key])).map((key) => `\`experiments.${key}\``),
|
|
11071
|
+
...shared && !Array.isArray(shared) ? Object.entries(shared).flatMap(([key, config]) => typeof config === "object" && config !== null ? IGNORED_SHARE_OPTIONS.filter((option) => option === "import" ? config.import !== void 0 : isSet(config[option])).map((option) => `\`shared.${key}.${option}\``) : []) : []
|
|
11072
|
+
];
|
|
11073
|
+
if (ignored.length === 0) return void 0;
|
|
11074
|
+
return `experiments.hostProvidesAllShared: ${ignored.join(", ")} ignored. The Module Federation runtime is not used and the host provides the only copy of every shared key.`;
|
|
11075
|
+
}
|
|
11076
|
+
//#endregion
|
|
11077
|
+
//#region src/plugins/pluginHostProvidesAllSharedHost.ts
|
|
11078
|
+
const ESM_SYNTAX_RE = /(^|[\s;])(export|import)[\s{*]/m;
|
|
11079
|
+
const DEFAULT_EXPORT_RE = /export\s+default\b|export\s*\{[^}]*\bas\s+default\b/;
|
|
11080
|
+
const IDENTIFIER_RE = /^[A-Za-z_$][\w$]*$/;
|
|
11081
|
+
/**
|
|
11082
|
+
* Export names of a CommonJS package, read by loading it in Node from the project root
|
|
11083
|
+
* (what the bundler's interop exposes as named imports). Empty when it cannot be loaded
|
|
11084
|
+
* in Node, e.g. because it touches `window`.
|
|
11085
|
+
*/
|
|
11086
|
+
function cjsExportNames(key, root) {
|
|
11087
|
+
try {
|
|
11088
|
+
const exported = createRequire(path$1.join(root, "package.json"))(key);
|
|
11089
|
+
return Object.keys(exported ?? {}).filter((name) => name !== "default" && name !== "__esModule" && IDENTIFIER_RE.test(name));
|
|
11090
|
+
} catch {
|
|
11091
|
+
return [];
|
|
11092
|
+
}
|
|
11093
|
+
}
|
|
11094
|
+
/** Shape of a shared module, sniffed from its real package entry (never a pre-bundle). */
|
|
11095
|
+
function detectShareShape(key, entry, root) {
|
|
11096
|
+
const source = entry && fs$1.existsSync(entry) ? fs$1.readFileSync(entry, "utf8") : "";
|
|
11097
|
+
if (source !== "" && !ESM_SYNTAX_RE.test(source)) return {
|
|
11098
|
+
kind: "cjs",
|
|
11099
|
+
names: cjsExportNames(key, root)
|
|
11100
|
+
};
|
|
11101
|
+
return {
|
|
11102
|
+
kind: "esm",
|
|
11103
|
+
hasDefault: DEFAULT_EXPORT_RE.test(source)
|
|
11104
|
+
};
|
|
11105
|
+
}
|
|
11106
|
+
/**
|
|
11107
|
+
* Body of the re-export entry for one shared key. `export *` never forwards `default` and
|
|
11108
|
+
* forwards nothing named from CommonJS, so an ESM module adds `default` only when it has
|
|
11109
|
+
* one, and a CommonJS module re-exports each key explicitly (`react/jsx-runtime` → `jsx`,
|
|
11110
|
+
* `jsxs`) so remotes can `import { jsxs }`.
|
|
11111
|
+
*/
|
|
11112
|
+
function shareModuleCode(key, shape) {
|
|
11113
|
+
const spec = JSON.stringify(key);
|
|
11114
|
+
if (shape.kind === "cjs") return `import __mf_cjs from ${spec};\nexport default __mf_cjs;\n${shape.names.length ? `export const { ${shape.names.join(", ")} } = __mf_cjs;\n` : ""}`;
|
|
11115
|
+
return `export * from ${spec};\n${shape.hasDefault ? `export { default } from ${spec};\n` : ""}`;
|
|
11116
|
+
}
|
|
11117
|
+
/** BUILD: shared key → URL of its emitted entry chunk. */
|
|
11118
|
+
function bundledShareImports(bundle, base) {
|
|
11119
|
+
const imports = {};
|
|
11120
|
+
for (const chunk of Object.values(bundle)) if (chunk.type === "chunk" && chunk.facadeModuleId?.startsWith("\0mf-host-provided-share:")) imports[chunk.facadeModuleId.slice(24)] = `${base}${chunk.fileName}`;
|
|
11121
|
+
return imports;
|
|
11122
|
+
}
|
|
11123
|
+
/**
|
|
11124
|
+
* DEV: shared key → dev-server URL of its virtual re-export module. Vite serves `\0` ids
|
|
11125
|
+
* at `/@id/__x00__<id>`; import analysis then rewrites the module's own `from '<key>'` to
|
|
11126
|
+
* the same pre-bundle URL the host's code gets, so host and remotes share one instance.
|
|
11127
|
+
*/
|
|
11128
|
+
function devShareImports(sharedKeys, base) {
|
|
11129
|
+
const prefix = `${base}@id/__x00__${SHARE_MODULE_PREFIX.slice(1)}`;
|
|
11130
|
+
return Object.fromEntries(sharedKeys.map((key) => [key, `${prefix}${key}`]));
|
|
11131
|
+
}
|
|
11132
|
+
function importMapTag(imports) {
|
|
11133
|
+
return {
|
|
11134
|
+
tag: "script",
|
|
11135
|
+
attrs: { type: "importmap" },
|
|
11136
|
+
children: JSON.stringify({ imports }, null, 2),
|
|
11137
|
+
injectTo: "head-prepend"
|
|
11138
|
+
};
|
|
11139
|
+
}
|
|
11140
|
+
/**
|
|
11141
|
+
* Host side of `experiments.hostProvidesAllShared`. The host provides every shared key:
|
|
11142
|
+
*
|
|
11143
|
+
* 1. one re-export module per shared key, emitted in a build as a `preserveSignature:
|
|
11144
|
+
* 'strict'` entry chunk that the bundler dedupes with the host's own imports, and served
|
|
11145
|
+
* in dev as a virtual module; either way host and remotes land on one module instance;
|
|
11146
|
+
* 2. an import map in `index.html` pointing each shared key at that module and each remote
|
|
11147
|
+
* expose at the entry listed in the remote's `mf-manifest.json`.
|
|
11148
|
+
*/
|
|
11149
|
+
function pluginHostProvidesAllSharedHost(options) {
|
|
11150
|
+
const sharedKeys = Object.keys(options.shared);
|
|
11151
|
+
const remoteKeys = Object.keys(options.remotes);
|
|
11152
|
+
let isBuild = true;
|
|
11153
|
+
let base = "/";
|
|
11154
|
+
let root = process.cwd();
|
|
11155
|
+
let remoteImports = {};
|
|
11156
|
+
let resolveEntry;
|
|
11157
|
+
return {
|
|
11158
|
+
name: "module-federation:host-provides-all-shared-host",
|
|
11159
|
+
enforce: "pre",
|
|
11160
|
+
configResolved(config) {
|
|
11161
|
+
isBuild = config.command === "build";
|
|
11162
|
+
base = ensureTrailingSlash(config.base);
|
|
11163
|
+
root = config.root;
|
|
11164
|
+
resolveEntry = isBuild ? void 0 : config.createResolver();
|
|
11165
|
+
},
|
|
11166
|
+
async buildStart() {
|
|
11167
|
+
remoteImports = await collectRemoteImports(options.remotes, root);
|
|
11168
|
+
if (!isBuild) return;
|
|
11169
|
+
for (const key of sharedKeys) this.emitFile({
|
|
11170
|
+
type: "chunk",
|
|
11171
|
+
id: `${SHARE_MODULE_PREFIX}${key}`,
|
|
11172
|
+
name: shareChunkName(key),
|
|
11173
|
+
preserveSignature: "strict"
|
|
11174
|
+
});
|
|
11175
|
+
},
|
|
11176
|
+
resolveId(id) {
|
|
11177
|
+
if (id.startsWith("\0mf-host-provided-share:")) return id;
|
|
11178
|
+
if (!isRemoteSpecifier(id, remoteKeys)) return null;
|
|
11179
|
+
return {
|
|
11180
|
+
id: isBuild ? id : remoteImports[id] ?? id,
|
|
11181
|
+
external: true
|
|
11182
|
+
};
|
|
11183
|
+
},
|
|
11184
|
+
async load(id) {
|
|
11185
|
+
if (!id.startsWith("\0mf-host-provided-share:")) return null;
|
|
11186
|
+
const key = id.slice(24);
|
|
11187
|
+
const entry = resolveEntry ? await resolveEntry(key) : (await this.resolve(key, void 0, { skipSelf: true }))?.id;
|
|
11188
|
+
return shareModuleCode(key, detectShareShape(key, entry && stripQueryAndHash(entry), root));
|
|
11189
|
+
},
|
|
11190
|
+
transformIndexHtml: {
|
|
11191
|
+
order: "post",
|
|
11192
|
+
handler(html, context) {
|
|
11193
|
+
const shares = context.bundle ? bundledShareImports(context.bundle, base) : devShareImports(sharedKeys, base);
|
|
11194
|
+
return {
|
|
11195
|
+
html,
|
|
11196
|
+
tags: [importMapTag({
|
|
11197
|
+
...remoteImports,
|
|
11198
|
+
...shares
|
|
11199
|
+
})]
|
|
11200
|
+
};
|
|
11201
|
+
}
|
|
11202
|
+
}
|
|
11203
|
+
};
|
|
11204
|
+
}
|
|
11205
|
+
//#endregion
|
|
11206
|
+
//#region src/plugins/pluginHostProvidesAllSharedRemote.ts
|
|
11207
|
+
/**
|
|
11208
|
+
* Remote side of `experiments.hostProvidesAllShared`. The remote ships only its own code:
|
|
11209
|
+
*
|
|
11210
|
+
* - one fixed-name, signature-preserving entry per expose (`./Button` → `Button.js`), so
|
|
11211
|
+
* the host can map `<remote>/Button` to a stable URL;
|
|
11212
|
+
* - every shared key, and every configured remote, stays an external bare import that the
|
|
11213
|
+
* host's import map resolves at runtime;
|
|
11214
|
+
* - a standard `mf-manifest.json` without `remoteEntry`, listing each expose's entry file.
|
|
11215
|
+
*/
|
|
11216
|
+
function pluginHostProvidesAllSharedRemote(options) {
|
|
11217
|
+
const sharedKeys = Object.keys(options.shared);
|
|
11218
|
+
const remoteKeys = Object.keys(options.remotes);
|
|
11219
|
+
const isExternal = (id) => sharedKeys.includes(id) || isRemoteSpecifier(id, remoteKeys);
|
|
11220
|
+
const unsharedSubpaths = /* @__PURE__ */ new Map();
|
|
11221
|
+
let publicPath = "/";
|
|
11222
|
+
return {
|
|
11223
|
+
name: "module-federation:host-provides-all-shared-remote",
|
|
11224
|
+
enforce: "pre",
|
|
11225
|
+
apply: "build",
|
|
11226
|
+
config(config) {
|
|
11227
|
+
const root = path$1.resolve(config.root ?? process.cwd());
|
|
11228
|
+
return { build: { rollupOptions: {
|
|
11229
|
+
input: Object.fromEntries(Object.entries(options.exposes).map(([key, expose]) => [exposeEntryName(key), path$1.resolve(root, expose.import)])),
|
|
11230
|
+
external: isExternal,
|
|
11231
|
+
preserveEntrySignatures: "strict",
|
|
11232
|
+
output: {
|
|
11233
|
+
entryFileNames: "[name].js",
|
|
11234
|
+
chunkFileNames: "assets/[name]-[hash].js"
|
|
11235
|
+
}
|
|
11236
|
+
} } };
|
|
11237
|
+
},
|
|
11238
|
+
configResolved(config) {
|
|
11239
|
+
publicPath = options.publicPath ?? config.base;
|
|
11240
|
+
},
|
|
11241
|
+
buildStart() {
|
|
11242
|
+
unsharedSubpaths.clear();
|
|
11243
|
+
},
|
|
11244
|
+
resolveId(id, importer) {
|
|
11245
|
+
if (importer && !isExternal(id) && sharedKeyOwning(id, sharedKeys)) unsharedSubpaths.set(id, importer);
|
|
11246
|
+
return null;
|
|
11247
|
+
},
|
|
11248
|
+
buildEnd() {
|
|
11249
|
+
for (const [id, importer] of unsharedSubpaths) this.warn(`"${id}" (imported by ${importer}) is a subpath of a shared package but is not shared itself, so a private copy is bundled into this remote. Add it to \`shared\`.`);
|
|
11250
|
+
},
|
|
11251
|
+
generateBundle(_outputOptions, bundle) {
|
|
11252
|
+
const { name } = options;
|
|
11253
|
+
const exposes = [];
|
|
11254
|
+
for (const key of Object.keys(options.exposes)) {
|
|
11255
|
+
const entryName = exposeEntryName(key);
|
|
11256
|
+
const chunk = Object.values(bundle).find((item) => item.type === "chunk" && item.isEntry && item.name === entryName);
|
|
11257
|
+
if (!chunk) continue;
|
|
11258
|
+
exposes.push({
|
|
11259
|
+
id: `${name}:${entryName}`,
|
|
11260
|
+
name: entryName,
|
|
11261
|
+
path: key,
|
|
11262
|
+
assets: {
|
|
11263
|
+
js: {
|
|
11264
|
+
sync: [chunk.fileName],
|
|
11265
|
+
async: []
|
|
11266
|
+
},
|
|
11267
|
+
css: {
|
|
11268
|
+
sync: [],
|
|
11269
|
+
async: []
|
|
11270
|
+
}
|
|
11271
|
+
}
|
|
11272
|
+
});
|
|
11273
|
+
}
|
|
11274
|
+
const manifest = {
|
|
11275
|
+
id: name,
|
|
11276
|
+
name,
|
|
11277
|
+
metaData: {
|
|
11278
|
+
name,
|
|
11279
|
+
type: "app",
|
|
11280
|
+
buildInfo: {
|
|
11281
|
+
buildVersion: getBuildVersion(),
|
|
11282
|
+
buildName: name
|
|
11283
|
+
},
|
|
11284
|
+
globalName: name,
|
|
11285
|
+
pluginVersion: version$1,
|
|
11286
|
+
publicPath,
|
|
11287
|
+
types: resolveTypesMeta(options.dts)
|
|
11288
|
+
},
|
|
11289
|
+
shared: [],
|
|
11290
|
+
remotes: [],
|
|
11291
|
+
exposes
|
|
11292
|
+
};
|
|
11293
|
+
this.emitFile({
|
|
11294
|
+
type: "asset",
|
|
11295
|
+
fileName: typeof options.manifest === "object" && options.manifest.fileName || "mf-manifest.json",
|
|
11296
|
+
source: `${JSON.stringify(manifest, null, 2)}\n`
|
|
11297
|
+
});
|
|
11298
|
+
}
|
|
11299
|
+
};
|
|
11300
|
+
}
|
|
11301
|
+
//#endregion
|
|
11143
11302
|
//#region src/utils/normalizeOptimizeDeps.ts
|
|
11144
11303
|
var normalizeOptimizeDeps_default = {
|
|
11145
11304
|
name: "normalizeOptimizeDeps",
|
|
@@ -11475,17 +11634,20 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
|
|
|
11475
11634
|
addUsedRemote(remoteKey, request, options);
|
|
11476
11635
|
markStaticRemote(request, options);
|
|
11477
11636
|
markPreloadRemote(request, options);
|
|
11478
|
-
} else if (sharedKey && recordShared)
|
|
11637
|
+
} else if (sharedKey && recordShared) materializeSharedRequest(options, request);
|
|
11479
11638
|
else if (request && !typeOnly) enqueue(request, file, preloadRemotes && isStatic);
|
|
11480
11639
|
}
|
|
11481
11640
|
}
|
|
11482
11641
|
return hasJsxSource;
|
|
11483
11642
|
}
|
|
11643
|
+
function materializeSharedRequest(options, request) {
|
|
11644
|
+
addUsedShares(request, options);
|
|
11645
|
+
const packageName = getPackageName(request);
|
|
11646
|
+
if (packageName !== request && findSharedKey(packageName, options.shared)) addUsedShares(packageName, options);
|
|
11647
|
+
}
|
|
11484
11648
|
function materializeAutomaticJsxRuntime(options, runtime) {
|
|
11485
11649
|
if (!findSharedKey(runtime, options.shared)) return false;
|
|
11486
|
-
|
|
11487
|
-
const packageName = getPackageName(runtime);
|
|
11488
|
-
if (packageName !== runtime && findSharedKey(packageName, options.shared)) addUsedShares(packageName, options);
|
|
11650
|
+
materializeSharedRequest(options, runtime);
|
|
11489
11651
|
return true;
|
|
11490
11652
|
}
|
|
11491
11653
|
/**
|
|
@@ -11751,9 +11913,21 @@ function applyBuildTimeRuntimeDefines(define, options, { target, isAstro, defaul
|
|
|
11751
11913
|
});
|
|
11752
11914
|
if (options.target && define.ENV_TARGET !== JSON.stringify(options.target)) mfWarn(`ENV_TARGET define (${define.ENV_TARGET}) differs from target option ("${options.target}"). ENV_TARGET will not be overridden.`);
|
|
11753
11915
|
}
|
|
11916
|
+
/** Dynamic remote type hints are a runtime plugin; hostProvidesAllShared has no runtime. */
|
|
11917
|
+
function withoutDynamicRemoteTypeHints(options) {
|
|
11918
|
+
if (options.dev === false) return options;
|
|
11919
|
+
const dev = options.dev === true || options.dev === void 0 ? {} : options.dev;
|
|
11920
|
+
return {
|
|
11921
|
+
...options,
|
|
11922
|
+
dev: {
|
|
11923
|
+
...dev,
|
|
11924
|
+
disableDynamicRemoteTypeHints: true
|
|
11925
|
+
}
|
|
11926
|
+
};
|
|
11927
|
+
}
|
|
11754
11928
|
function loadPluginDts(options) {
|
|
11755
11929
|
if (options.dts === false) return [];
|
|
11756
|
-
return [import("./pluginDts-
|
|
11930
|
+
return [import("./pluginDts-DnEX3cp_.js").then(({ default: pluginDts }) => pluginDts(options))];
|
|
11757
11931
|
}
|
|
11758
11932
|
const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
|
|
11759
11933
|
function isInjectExternalRuntimeCorePlugin(specifier) {
|
|
@@ -11782,11 +11956,16 @@ function applyExternalRuntimeExperiments(options) {
|
|
|
11782
11956
|
function federation(mfUserOptions) {
|
|
11783
11957
|
if (isTestEnv()) return [];
|
|
11784
11958
|
const options = normalizeModuleFederationOptions(mfUserOptions);
|
|
11959
|
+
if (!options.name) throw createModuleFederationError("name is required");
|
|
11960
|
+
if (options.experiments.hostProvidesAllShared) {
|
|
11961
|
+
const ignored = getIgnoredOptionWarning(mfUserOptions);
|
|
11962
|
+
if (ignored) mfWarn(ignored);
|
|
11963
|
+
return [Object.keys(options.exposes).length > 0 ? pluginHostProvidesAllSharedRemote(options) : pluginHostProvidesAllSharedHost(options), ...loadPluginDts(withoutDynamicRemoteTypeHints(options))];
|
|
11964
|
+
}
|
|
11785
11965
|
applyExternalRuntimeExperiments(options);
|
|
11786
11966
|
const isVinext = hasPackageDependency("vinext");
|
|
11787
|
-
const {
|
|
11967
|
+
const { shared, filename, hostInitInjectLocation } = options;
|
|
11788
11968
|
const hasTreeShakingShared = Object.values(shared).some((share) => !!share.shareConfig.treeShaking);
|
|
11789
|
-
if (!name) throw createModuleFederationError("name is required");
|
|
11790
11969
|
const remoteEntryId = getRemoteEntryId(options);
|
|
11791
11970
|
const virtualExposesId = getVirtualExposesId(options);
|
|
11792
11971
|
const moduleParseController = createModuleParseController();
|
|
@@ -11804,6 +11983,7 @@ function federation(mfUserOptions) {
|
|
|
11804
11983
|
let rootResolveConditions;
|
|
11805
11984
|
let ssrResolveConditions;
|
|
11806
11985
|
let ssrTarget = "node";
|
|
11986
|
+
let inheritedEnvTarget;
|
|
11807
11987
|
const emittedRuntimeCapabilityWarnings = /* @__PURE__ */ new Set();
|
|
11808
11988
|
const getLoadHookExportConditions = (context, loadOptions) => {
|
|
11809
11989
|
const environment = context.environment;
|
|
@@ -12267,14 +12447,24 @@ function federation(mfUserOptions) {
|
|
|
12267
12447
|
config.build ??= {};
|
|
12268
12448
|
config.build.target ??= "esnext";
|
|
12269
12449
|
}
|
|
12450
|
+
const isBundledDev = Boolean(config.experimental?.bundledDev);
|
|
12451
|
+
if (isRolldown && _command === "serve" && isBundledDev) {
|
|
12452
|
+
config.build.rolldownOptions ??= {};
|
|
12453
|
+
config.build.rolldownOptions.experimental ??= {};
|
|
12454
|
+
const devMode = config.build.rolldownOptions.experimental.devMode;
|
|
12455
|
+
if (typeof devMode === "object") devMode.lazy ??= false;
|
|
12456
|
+
else if (devMode === void 0) config.build.rolldownOptions.experimental.devMode = { lazy: false };
|
|
12457
|
+
}
|
|
12270
12458
|
const isAstro = hasPackageDependency("astro");
|
|
12271
12459
|
const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
|
|
12272
12460
|
if (!config.define) config.define = {};
|
|
12461
|
+
const userSetEnvTarget = "ENV_TARGET" in config.define;
|
|
12273
12462
|
applyBuildTimeRuntimeDefines(config.define, options, {
|
|
12274
12463
|
target: resolvedTarget,
|
|
12275
12464
|
isAstro,
|
|
12276
12465
|
defaultDisableSnapshot: resolvedTarget === "node" ? true : void 0
|
|
12277
12466
|
});
|
|
12467
|
+
inheritedEnvTarget = userSetEnvTarget ? void 0 : config.define.ENV_TARGET;
|
|
12278
12468
|
for (const warning of getRuntimeCapabilityConfigurationWarnings(options)) {
|
|
12279
12469
|
if (emittedRuntimeCapabilityWarnings.has(warning)) continue;
|
|
12280
12470
|
emittedRuntimeCapabilityWarnings.add(warning);
|
|
@@ -12290,6 +12480,7 @@ function federation(mfUserOptions) {
|
|
|
12290
12480
|
if (!isServerEnvironment(name, config)) return;
|
|
12291
12481
|
const isAstro = hasPackageDependency("astro");
|
|
12292
12482
|
config.define = { ...config.define ?? {} };
|
|
12483
|
+
if (inheritedEnvTarget !== void 0 && config.define.ENV_TARGET === inheritedEnvTarget) delete config.define.ENV_TARGET;
|
|
12293
12484
|
applyBuildTimeRuntimeDefines(config.define, options, {
|
|
12294
12485
|
target: options.target ?? "node",
|
|
12295
12486
|
isAstro,
|