@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
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as
|
|
3
|
-
import { C as
|
|
1
|
+
import { a as CodeRewriter, c as isAbsoluteUrl, d as rebaseImport, f as resolveHashPlaceholderFileName, i as createCodePositionMap, l as isHttpUrl, o as createSourceMap, r as mfWarn, t as createModuleFederationError, u as normalizePathForImport } from "./logger-D67aJYOe.js";
|
|
2
|
+
import { _ as removeTrailingSlash, a as matchesSharedSource, b as stripViteFsPrefix, 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 resolvePublicPath, x as toRelativeImport, y as stripQueryAndHash } from "./sharedKeyMatcher-C04bVN1q.js";
|
|
3
|
+
import { C as supportsCodeSplittingGroupDebugName, E as isReactCoreShare, S as sharedCacheHelperCode, T as REACT_DOM_CLIENT_SHARE, _ as packageNameDecode, a as getInstalledPackageEntry, b as resolveModulePath, c as getPackageDetectionCwd, d as getPackageNameFromNodeModulePath, f as getSharedCacheDescriptor, g as isPackageInstalled, h as isPackageExportAvailable, i as getDependencyNames, l as getPackageExportSpecifiersForFile, m as isNuxtProjectRoot, n as formatDevServerHostForOrigin, o as getInstalledPackageJson, p as hasPackageDependency, r as watchFileEvents, s as getIsRolldown, u as getPackageName, v as packageNameEncode, w as REACT_CLIENT_INTERNALS_KEY, x as setPackageDetectionCwd, y as resolveImportPath } from "./dtsConstants-CDuC8Bb7.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";
|
|
@@ -14,7 +14,6 @@ import { createHash } from "node:crypto";
|
|
|
14
14
|
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
|
-
import { isIPv6 } from "node:net";
|
|
18
17
|
import { inferAutoPublicPath } from "@module-federation/sdk";
|
|
19
18
|
import { readFile } from "node:fs/promises";
|
|
20
19
|
//#region src/utils/regexEscape.ts
|
|
@@ -259,8 +258,8 @@ function getPluginEnvironmentName(ctx) {
|
|
|
259
258
|
/**
|
|
260
259
|
* Classify a plugin hook context's Vite environment. Environment names are
|
|
261
260
|
* user-defined, so Vite's `config.consumer` is the semantic role; fall back to
|
|
262
|
-
* the name only when it is missing
|
|
263
|
-
*
|
|
261
|
+
* the name only when it is missing. Returns `undefined` when the hook has no
|
|
262
|
+
* environment context at all (Vite 5).
|
|
264
263
|
*/
|
|
265
264
|
function resolveEnvironmentConsumerTarget(ctx) {
|
|
266
265
|
if (ctx == null || typeof ctx !== "object") return void 0;
|
|
@@ -271,7 +270,7 @@ function resolveEnvironmentConsumerTarget(ctx) {
|
|
|
271
270
|
const envName = getPluginEnvironmentName(ctx);
|
|
272
271
|
return !envName || envName === "client" ? "client" : "server";
|
|
273
272
|
}
|
|
274
|
-
/**
|
|
273
|
+
/** Hooks without an environment context (Vite 5) keep their client build behavior. */
|
|
275
274
|
function isClientEnvironment(ctx) {
|
|
276
275
|
return resolveEnvironmentConsumerTarget(ctx) !== "server";
|
|
277
276
|
}
|
|
@@ -721,6 +720,11 @@ function normalizeLibrary(library) {
|
|
|
721
720
|
if (!library) return void 0;
|
|
722
721
|
return library;
|
|
723
722
|
}
|
|
723
|
+
/** An explicit `manifest.disableAssetsAnalyze` wins; otherwise `fallback` applies. */
|
|
724
|
+
function resolveDisableAssetsAnalyze(manifest, fallback) {
|
|
725
|
+
if (typeof manifest === "object" && manifest !== null && Object.hasOwn(manifest, "disableAssetsAnalyze")) return manifest.disableAssetsAnalyze === true;
|
|
726
|
+
return fallback;
|
|
727
|
+
}
|
|
724
728
|
function normalizeManifest(manifest) {
|
|
725
729
|
if (manifest === void 0) return;
|
|
726
730
|
if (typeof manifest === "boolean") return manifest;
|
|
@@ -977,16 +981,6 @@ function getSsrCapabilities(viteMajor, command, hasRemotes, isSsr = false) {
|
|
|
977
981
|
};
|
|
978
982
|
}
|
|
979
983
|
//#endregion
|
|
980
|
-
//#region src/utils/runtimePluginSpecifier.ts
|
|
981
|
-
function getRuntimePluginSpecifier(plugin) {
|
|
982
|
-
return typeof plugin === "string" ? plugin : plugin[0];
|
|
983
|
-
}
|
|
984
|
-
/** Drop SSR-only plugins from a client graph; a server graph keeps them all. */
|
|
985
|
-
function filterRuntimePluginsForTarget(runtimePlugins, ssrOnlySpecifiers, isServer) {
|
|
986
|
-
if (isServer) return [...runtimePlugins];
|
|
987
|
-
return runtimePlugins.filter((plugin) => !ssrOnlySpecifiers.has(getRuntimePluginSpecifier(plugin)));
|
|
988
|
-
}
|
|
989
|
-
//#endregion
|
|
990
984
|
//#region src/utils/serializeRuntimeOptions.ts
|
|
991
985
|
const UNSAFE_JS_CHAR_MAP = {
|
|
992
986
|
"<": "\\u003C",
|
|
@@ -999,6 +993,11 @@ function toSafeJsLiteral(value) {
|
|
|
999
993
|
if (json === void 0) return "undefined";
|
|
1000
994
|
return json.replace(UNSAFE_JS_CHAR_PATTERN, (char) => UNSAFE_JS_CHAR_MAP[char]);
|
|
1001
995
|
}
|
|
996
|
+
const JS_IDENTIFIER_PATTERN = `[\$_\\p{ID_Start}][\$_\\u200C\\u200D\\p{ID_Continue}]*`;
|
|
997
|
+
const JS_IDENTIFIER_REGEX = new RegExp(`^${JS_IDENTIFIER_PATTERN}$`, "u");
|
|
998
|
+
function isValidJsIdentifier(name) {
|
|
999
|
+
return JS_IDENTIFIER_REGEX.test(name);
|
|
1000
|
+
}
|
|
1002
1001
|
/**
|
|
1003
1002
|
* Serializes a JavaScript object into a string of source code that can be evaluated.
|
|
1004
1003
|
* This function is used to create runtime plugin options without relying solely on JSON.stringify,
|
|
@@ -1233,7 +1232,62 @@ function collectReExport(node, source, record, requireAllExports) {
|
|
|
1233
1232
|
}
|
|
1234
1233
|
record(names, source);
|
|
1235
1234
|
}
|
|
1235
|
+
const NEEDS_AST_RE = /\brequire\s*(?:\?\.\s*)?(?:\(|\/[*/])|\bexport(?:\s|\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/|\/\/[^\n]*\n)*\{(?:\s|\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/|\/\/[^\n]*\n)*\}/;
|
|
1236
|
+
/**
|
|
1237
|
+
* Vite 8 parses with oxc, whose module record lists static imports, re-exports
|
|
1238
|
+
* and dynamic imports without materializing the AST. Same result as the AST
|
|
1239
|
+
* walk below; `undefined` when this input needs the AST.
|
|
1240
|
+
*/
|
|
1241
|
+
function analyzeImportsFromModuleRecord(code) {
|
|
1242
|
+
const parseSync = vite.parseSync;
|
|
1243
|
+
if (typeof parseSync !== "function" || NEEDS_AST_RE.test(code)) return void 0;
|
|
1244
|
+
const result = parseSync("file.js", code, {
|
|
1245
|
+
lang: "js",
|
|
1246
|
+
preserveParens: false
|
|
1247
|
+
});
|
|
1248
|
+
if (result.errors.length > 0) return null;
|
|
1249
|
+
const { staticImports, staticExports, dynamicImports } = result.module;
|
|
1250
|
+
const found = [];
|
|
1251
|
+
const isStringName = (name) => name.start !== null && (code[name.start] === "\"" || code[name.start] === "'");
|
|
1252
|
+
const add = (start, source, names) => found.push({
|
|
1253
|
+
start,
|
|
1254
|
+
usage: {
|
|
1255
|
+
source,
|
|
1256
|
+
usedExports: names
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
for (const declaration of staticImports) {
|
|
1260
|
+
const source = declaration.moduleRequest.value;
|
|
1261
|
+
let names = declaration.entries.length === 0 ? null : [];
|
|
1262
|
+
for (const { importName } of declaration.entries) if (importName.kind === "Default") names?.push("default");
|
|
1263
|
+
else if (importName.kind === "Name" && importName.name && !isStringName(importName)) names?.push(importName.name);
|
|
1264
|
+
else names = null;
|
|
1265
|
+
add(declaration.start, source, names);
|
|
1266
|
+
}
|
|
1267
|
+
const importStarts = new Set(staticImports.map((declaration) => declaration.start));
|
|
1268
|
+
for (const declaration of staticExports) {
|
|
1269
|
+
const request = declaration.entries[0]?.moduleRequest;
|
|
1270
|
+
if (!request || importStarts.has(declaration.start)) continue;
|
|
1271
|
+
const source = request.value;
|
|
1272
|
+
let names = [];
|
|
1273
|
+
for (const { importName } of declaration.entries) if (importName.kind === "Name" && importName.name && !isStringName(importName)) names?.push(importName.name);
|
|
1274
|
+
else names = null;
|
|
1275
|
+
add(declaration.start, source, names);
|
|
1276
|
+
}
|
|
1277
|
+
const dynamicStarts = /* @__PURE__ */ new Set();
|
|
1278
|
+
for (const { start, moduleRequest } of dynamicImports) {
|
|
1279
|
+
if (dynamicStarts.has(start)) continue;
|
|
1280
|
+
dynamicStarts.add(start);
|
|
1281
|
+
const text = code.slice(moduleRequest.start, moduleRequest.end);
|
|
1282
|
+
const quote = text[0];
|
|
1283
|
+
if (text.length >= 2 && (quote === "\"" || quote === "'" || quote === "`") && text.at(-1) === quote && !text.includes("\\") && !text.slice(1, -1).includes(quote) && !(quote === "`" && text.includes("${"))) add(start, text.slice(1, -1), null);
|
|
1284
|
+
else if (text.includes("\\")) return;
|
|
1285
|
+
}
|
|
1286
|
+
return found.sort((a, b) => a.start - b.start).map(({ usage }) => usage);
|
|
1287
|
+
}
|
|
1236
1288
|
function analyzeImports(code) {
|
|
1289
|
+
const fromModuleRecord = analyzeImportsFromModuleRecord(code);
|
|
1290
|
+
if (fromModuleRecord !== void 0) return fromModuleRecord;
|
|
1237
1291
|
let ast;
|
|
1238
1292
|
try {
|
|
1239
1293
|
ast = vite.parseAst(code);
|
|
@@ -1299,13 +1353,8 @@ function analyzeImports(code) {
|
|
|
1299
1353
|
function shouldAnalyzeSharedExports(shareItem) {
|
|
1300
1354
|
return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
|
|
1301
1355
|
}
|
|
1302
|
-
const legacyTreeShakingState = {
|
|
1303
|
-
inferredUsage: /* @__PURE__ */ new Map(),
|
|
1304
|
-
buildMode: false
|
|
1305
|
-
};
|
|
1306
1356
|
const treeShakingStates = /* @__PURE__ */ new WeakMap();
|
|
1307
1357
|
function getTreeShakingState(options) {
|
|
1308
|
-
if (!options) return legacyTreeShakingState;
|
|
1309
1358
|
let state = treeShakingStates.get(options);
|
|
1310
1359
|
if (!state) {
|
|
1311
1360
|
state = {
|
|
@@ -1358,7 +1407,7 @@ function getExportRecords(sharedKey, request, options) {
|
|
|
1358
1407
|
inferredUsage.forEach((byRequest, configuredKey) => {
|
|
1359
1408
|
const wildcard = byRequest.get("*");
|
|
1360
1409
|
const exact = byRequest.get(request);
|
|
1361
|
-
const configuredRequest = getSharedRequest(configuredKey, options
|
|
1410
|
+
const configuredRequest = getSharedRequest(configuredKey, options.shared?.[configuredKey]);
|
|
1362
1411
|
const keyBase = configuredRequest.endsWith("/") ? configuredRequest.slice(0, -1) : configuredRequest;
|
|
1363
1412
|
const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
|
|
1364
1413
|
if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
|
|
@@ -1423,240 +1472,117 @@ async function collectTreeShakingImports(code, id, shared, findSharedKey, record
|
|
|
1423
1472
|
await Promise.all(pending);
|
|
1424
1473
|
}
|
|
1425
1474
|
//#endregion
|
|
1426
|
-
//#region src/utils/
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
"
|
|
1431
|
-
|
|
1432
|
-
".
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
".cjs"
|
|
1436
|
-
];
|
|
1437
|
-
function resolveSourceFile(importPath, root) {
|
|
1438
|
-
const cleanImport = stripQueryAndHash(importPath);
|
|
1439
|
-
if (!cleanImport.startsWith(".") && !path$1.isAbsolute(cleanImport)) return;
|
|
1440
|
-
const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
|
|
1441
|
-
return [
|
|
1442
|
-
candidate,
|
|
1443
|
-
...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
|
|
1444
|
-
...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
|
|
1445
|
-
].find((filePath) => {
|
|
1446
|
-
try {
|
|
1447
|
-
return fs$1.statSync(filePath).isFile();
|
|
1448
|
-
} catch {
|
|
1449
|
-
return false;
|
|
1450
|
-
}
|
|
1451
|
-
});
|
|
1452
|
-
}
|
|
1453
|
-
function localDefaultReexport(source) {
|
|
1454
|
-
const match = source.match(/export\s*{\s*(?:default(?:\s+as\s+default)?|[A-Za-z_$][\w$]*\s+as\s+default)\s*}\s*from\s*["']([^"']+)["']/);
|
|
1455
|
-
return match?.[1]?.startsWith(".") ? match[1] : void 0;
|
|
1475
|
+
//#region src/utils/typeArgumentScanner.ts
|
|
1476
|
+
function getTypeArgumentStartContext(source, start) {
|
|
1477
|
+
let previous = start - 1;
|
|
1478
|
+
while (previous >= 0 && /\s/.test(source[previous])) previous--;
|
|
1479
|
+
const previousChar = source[previous] || "";
|
|
1480
|
+
const followsNamedExpression = /[$_\u200C\u200D\p{ID_Continue})\]>]/u.test(previousChar);
|
|
1481
|
+
const startsStandaloneGeneric = previousChar !== "" && "=([{,:".includes(previousChar);
|
|
1482
|
+
if (!followsNamedExpression && !startsStandaloneGeneric) return void 0;
|
|
1483
|
+
return { followsNamedExpression };
|
|
1456
1484
|
}
|
|
1457
|
-
function
|
|
1458
|
-
if (
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
return
|
|
1485
|
+
function updateTypeArgumentGroupDepth(char, state) {
|
|
1486
|
+
if (char === "(" || char === "[" || char === "{") {
|
|
1487
|
+
state.groupDepth++;
|
|
1488
|
+
return "handled";
|
|
1489
|
+
}
|
|
1490
|
+
if (char !== ")" && char !== "]" && char !== "}") return void 0;
|
|
1491
|
+
if (state.groupDepth === 0) return "invalid";
|
|
1492
|
+
state.groupDepth--;
|
|
1493
|
+
return "handled";
|
|
1466
1494
|
}
|
|
1467
|
-
function
|
|
1468
|
-
const
|
|
1469
|
-
if (
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
source = fs$1.readFileSync(normalizedPath, "utf8");
|
|
1474
|
-
} catch {
|
|
1475
|
-
return false;
|
|
1495
|
+
function updateTypeArgumentAngleDepth(source, index, state) {
|
|
1496
|
+
const char = source[index];
|
|
1497
|
+
if (char === "<") {
|
|
1498
|
+
if (source[index + 1] === "=" || source[index + 1] === "<") return "invalid";
|
|
1499
|
+
state.angleDepth++;
|
|
1500
|
+
return "handled";
|
|
1476
1501
|
}
|
|
1477
|
-
if (
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1502
|
+
if (char !== ">") return void 0;
|
|
1503
|
+
if (source[index - 1] === "=" || source[index + 1] === "=") return "handled";
|
|
1504
|
+
state.angleDepth--;
|
|
1505
|
+
return state.angleDepth === 0 ? "closed" : "handled";
|
|
1506
|
+
}
|
|
1507
|
+
function hasLikelyTypeArgumentFollower(source, end, codePositions, followsNamedExpression) {
|
|
1508
|
+
let next = end + 1;
|
|
1509
|
+
while (next < source.length && (!codePositions[next] || /\s/.test(source[next]))) next++;
|
|
1510
|
+
if (next >= source.length || /[([.!?=;,)\]}:|&]/.test(source[next])) return true;
|
|
1511
|
+
if (source.slice(end + 1, next).includes("\n")) return true;
|
|
1512
|
+
const followingToken = source.slice(next).match(/^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*/u)?.[0];
|
|
1513
|
+
return followingToken === "as" || followingToken === "satisfies" || !followsNamedExpression && followingToken !== void 0;
|
|
1514
|
+
}
|
|
1515
|
+
function isInvalidTypeArgumentTerminator(source, index, followsNamedExpression) {
|
|
1516
|
+
const char = source[index];
|
|
1517
|
+
return char === ";" || char === "=" && source[index + 1] !== ">" && followsNamedExpression;
|
|
1482
1518
|
}
|
|
1483
1519
|
/**
|
|
1484
|
-
*
|
|
1485
|
-
*
|
|
1486
|
-
* to their unchanged default export.
|
|
1520
|
+
* Finds the end of a balanced, type-like angle-bracket range that contains a
|
|
1521
|
+
* comma. Ambiguous syntax returns `undefined` so callers can fail closed.
|
|
1487
1522
|
*/
|
|
1488
|
-
function
|
|
1489
|
-
|
|
1490
|
-
if (
|
|
1491
|
-
const
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1523
|
+
function findLikelyTypeArgumentEnd(source, start, codePositions) {
|
|
1524
|
+
const context = getTypeArgumentStartContext(source, start);
|
|
1525
|
+
if (!context) return void 0;
|
|
1526
|
+
const state = {
|
|
1527
|
+
angleDepth: 1,
|
|
1528
|
+
groupDepth: 0,
|
|
1529
|
+
sawTypeComma: false
|
|
1530
|
+
};
|
|
1531
|
+
for (let index = start + 1; index < source.length; index++) {
|
|
1532
|
+
if (!codePositions[index]) continue;
|
|
1533
|
+
const char = source[index];
|
|
1534
|
+
const groupAction = updateTypeArgumentGroupDepth(char, state);
|
|
1535
|
+
if (groupAction === "invalid") return void 0;
|
|
1536
|
+
if (groupAction === "handled") continue;
|
|
1537
|
+
const angleAction = updateTypeArgumentAngleDepth(source, index, state);
|
|
1538
|
+
if (angleAction === "invalid") return void 0;
|
|
1539
|
+
if (angleAction === "closed") return state.sawTypeComma && hasLikelyTypeArgumentFollower(source, index, codePositions, context.followsNamedExpression) ? index : void 0;
|
|
1540
|
+
if (angleAction === "handled") continue;
|
|
1541
|
+
if (char === "," && state.groupDepth === 0) {
|
|
1542
|
+
state.sawTypeComma = true;
|
|
1543
|
+
continue;
|
|
1544
|
+
}
|
|
1545
|
+
if (state.angleDepth === 1 && state.groupDepth === 0 && isInvalidTypeArgumentTerminator(source, index, context.followsNamedExpression)) return;
|
|
1495
1546
|
}
|
|
1496
|
-
return islandExposes;
|
|
1497
1547
|
}
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
}
|
|
1523
|
-
}
|
|
1524
|
-
const finalProps = Object.assign({}, serverProps, props || {});
|
|
1525
|
-
return Promise.all([import("react"), import("react-dom/client")]).then(([React, ReactDOMClient]) => {
|
|
1526
|
-
if (typeof ReactDOMClient.hydrateRoot !== "function") {
|
|
1527
|
-
throw new Error("[Module Federation] react-dom/client does not provide hydrateRoot");
|
|
1528
|
-
}
|
|
1529
|
-
return ReactDOMClient.hydrateRoot(
|
|
1530
|
-
root,
|
|
1531
|
-
React.createElement(importModule.default, finalProps)
|
|
1532
|
-
);
|
|
1533
|
-
});
|
|
1534
|
-
}
|
|
1535
|
-
}`;
|
|
1548
|
+
//#endregion
|
|
1549
|
+
//#region src/utils/sharedExportConditions.ts
|
|
1550
|
+
const DEFAULT_CLIENT_EXPORT_CONDITIONS = [
|
|
1551
|
+
"browser",
|
|
1552
|
+
"import",
|
|
1553
|
+
"module",
|
|
1554
|
+
"default"
|
|
1555
|
+
];
|
|
1556
|
+
const DEFAULT_NODE_SSR_EXPORT_CONDITIONS = [
|
|
1557
|
+
"node",
|
|
1558
|
+
"import",
|
|
1559
|
+
"module",
|
|
1560
|
+
"default"
|
|
1561
|
+
];
|
|
1562
|
+
const DEFAULT_WEBWORKER_SSR_EXPORT_CONDITIONS = [
|
|
1563
|
+
"worker",
|
|
1564
|
+
"browser",
|
|
1565
|
+
"import",
|
|
1566
|
+
"module",
|
|
1567
|
+
"default"
|
|
1568
|
+
];
|
|
1569
|
+
const VITE_DEV_PROD_CONDITION = "development|production";
|
|
1570
|
+
function appendConditions(conditions, fallbackConditions) {
|
|
1571
|
+
return [.../* @__PURE__ */ new Set([...conditions, ...fallbackConditions])];
|
|
1536
1572
|
}
|
|
1537
|
-
function
|
|
1538
|
-
|
|
1539
|
-
return
|
|
1540
|
-
exportModule.__mf_island = {
|
|
1541
|
-
version: 1,
|
|
1542
|
-
async renderToHtml(props) {
|
|
1543
|
-
if (typeof importModule.default !== "function" && typeof importModule.default !== "object") {
|
|
1544
|
-
throw new Error("[Module Federation] A React island expose must have a default component export");
|
|
1545
|
-
}
|
|
1546
|
-
const loadedProps = typeof importModule.load === "function" ? await importModule.load() : {};
|
|
1547
|
-
const finalProps = Object.assign({}, loadedProps || {}, props || {});
|
|
1548
|
-
const [React, ReactDOMServer] = await Promise.all([
|
|
1549
|
-
import("react"),
|
|
1550
|
-
import("react-dom/server")
|
|
1551
|
-
]);
|
|
1552
|
-
const body = ReactDOMServer.renderToString(
|
|
1553
|
-
React.createElement(importModule.default, finalProps)
|
|
1554
|
-
);
|
|
1555
|
-
const state = encodeURIComponent(JSON.stringify(finalProps));
|
|
1556
|
-
return '<div data-mf-island-state="' + state + '">' + body + '</div>';
|
|
1557
|
-
},
|
|
1558
|
-
hydrate() {
|
|
1559
|
-
return Promise.reject(new Error("[Module Federation] hydrate is only available in the browser remote entry"));
|
|
1560
|
-
}
|
|
1561
|
-
}`;
|
|
1573
|
+
function resolveViteModeCondition(conditions, isProduction) {
|
|
1574
|
+
const modeCondition = isProduction ? "production" : "development";
|
|
1575
|
+
return [...new Set(conditions.map((condition) => condition === VITE_DEV_PROD_CONDITION ? modeCondition : condition))];
|
|
1562
1576
|
}
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
const
|
|
1566
|
-
const
|
|
1567
|
-
|
|
1568
|
-
return
|
|
1577
|
+
function getSharedExportConditions({ environmentConditions, isProduction, isSsr, rootConditions, ssrConditions, ssrTarget = "node" }) {
|
|
1578
|
+
if (environmentConditions !== void 0) return resolveViteModeCondition(appendConditions(environmentConditions, ["import", "default"]), isProduction);
|
|
1579
|
+
const defaultConditions = isSsr ? ssrTarget === "webworker" ? DEFAULT_WEBWORKER_SSR_EXPORT_CONDITIONS : DEFAULT_NODE_SSR_EXPORT_CONDITIONS : DEFAULT_CLIENT_EXPORT_CONDITIONS;
|
|
1580
|
+
const configuredConditions = isSsr ? ssrConditions ?? rootConditions : rootConditions;
|
|
1581
|
+
if (configuredConditions !== void 0) return resolveViteModeCondition(appendConditions(configuredConditions, defaultConditions), isProduction);
|
|
1582
|
+
return [...defaultConditions];
|
|
1569
1583
|
}
|
|
1570
|
-
function
|
|
1571
|
-
return
|
|
1572
|
-
}
|
|
1573
|
-
function getReactIslandImportRemoteId(source) {
|
|
1574
|
-
const queryIndex = source.indexOf("?");
|
|
1575
|
-
if (queryIndex === -1) return;
|
|
1576
|
-
if (!new URLSearchParams(source.slice(queryIndex + 1)).has("mf-island")) return;
|
|
1577
|
-
return source.slice(0, queryIndex);
|
|
1578
|
-
}
|
|
1579
|
-
function getReactIslandServerImportId(remoteId) {
|
|
1580
|
-
return `${REACT_ISLAND_SERVER_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
|
|
1581
|
-
}
|
|
1582
|
-
function getReactIslandClientImportId(remoteId) {
|
|
1583
|
-
return `${REACT_ISLAND_CLIENT_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
|
|
1584
|
-
}
|
|
1585
|
-
function resolveReactIslandConsumerId(id) {
|
|
1586
|
-
if (id.startsWith("virtual:mf-react-island-server:")) return `\0${id}`;
|
|
1587
|
-
if (id.startsWith("virtual:mf-react-island-client:")) return `\0${id}`;
|
|
1588
|
-
}
|
|
1589
|
-
function remoteIdFromResolvedIslandId(id, prefix) {
|
|
1590
|
-
if (!id.startsWith(prefix)) return;
|
|
1591
|
-
return decodeIslandRemoteId(id.slice(prefix.length));
|
|
1592
|
-
}
|
|
1593
|
-
/** Generates the server half of the opt-in `?mf-island` consumer component. */
|
|
1594
|
-
function generateReactIslandConsumerServer(remoteId) {
|
|
1595
|
-
const source = JSON.stringify(remoteId);
|
|
1596
|
-
return `import * as React from "react";
|
|
1597
|
-
import IslandClient from ${JSON.stringify(getReactIslandClientImportId(remoteId))};
|
|
1598
|
-
|
|
1599
|
-
const islandModulePromise = import(${source});
|
|
1600
|
-
|
|
1601
|
-
async function loadIslandModule() {
|
|
1602
|
-
const namespace = await islandModulePromise;
|
|
1603
|
-
const pending = namespace && namespace.__mf_remote_pending;
|
|
1604
|
-
if (pending && typeof pending.then === "function") return pending;
|
|
1605
|
-
return namespace && namespace.__moduleExports || namespace;
|
|
1606
|
-
}
|
|
1607
|
-
|
|
1608
|
-
export default async function ModuleFederationIsland(props) {
|
|
1609
|
-
const remoteModule = await loadIslandModule();
|
|
1610
|
-
const shell = remoteModule && remoteModule.__mf_island;
|
|
1611
|
-
if (!shell || typeof shell.renderToHtml !== "function") {
|
|
1612
|
-
throw new Error(${JSON.stringify(`[Module Federation] ${remoteId} does not expose an SSR island capability`)});
|
|
1613
|
-
}
|
|
1614
|
-
const html = await shell.renderToHtml(props);
|
|
1615
|
-
return React.createElement(IslandClient, { html, islandProps: props });
|
|
1616
|
-
}`;
|
|
1617
|
-
}
|
|
1618
|
-
/** Generates the client boundary which hydrates with the remote-owned React. */
|
|
1619
|
-
function generateReactIslandConsumerClient(remoteId) {
|
|
1620
|
-
return `"use client";
|
|
1621
|
-
|
|
1622
|
-
import * as React from "react";
|
|
1623
|
-
|
|
1624
|
-
const islandModulePromise = import(${JSON.stringify(remoteId)});
|
|
1625
|
-
|
|
1626
|
-
async function loadIslandModule() {
|
|
1627
|
-
const namespace = await islandModulePromise;
|
|
1628
|
-
const pending = namespace && namespace.__mf_remote_pending;
|
|
1629
|
-
if (pending && typeof pending.then === "function") return pending;
|
|
1630
|
-
return namespace && namespace.__moduleExports || namespace;
|
|
1631
|
-
}
|
|
1632
|
-
|
|
1633
|
-
export default function ModuleFederationIslandClient({ html, islandProps }) {
|
|
1634
|
-
const ref = React.useRef(null);
|
|
1635
|
-
|
|
1636
|
-
React.useEffect(() => {
|
|
1637
|
-
const element = ref.current;
|
|
1638
|
-
if (!element) return;
|
|
1639
|
-
void loadIslandModule().then((remoteModule) => {
|
|
1640
|
-
const shell = remoteModule && remoteModule.__mf_island;
|
|
1641
|
-
if (!shell || typeof shell.hydrate !== "function") {
|
|
1642
|
-
throw new Error(${JSON.stringify(`[Module Federation] ${remoteId} does not expose a client island capability`)});
|
|
1643
|
-
}
|
|
1644
|
-
return shell.hydrate(element, islandProps);
|
|
1645
|
-
});
|
|
1646
|
-
}, []);
|
|
1647
|
-
|
|
1648
|
-
return React.createElement("div", {
|
|
1649
|
-
ref,
|
|
1650
|
-
suppressHydrationWarning: true,
|
|
1651
|
-
dangerouslySetInnerHTML: { __html: html },
|
|
1652
|
-
});
|
|
1653
|
-
}`;
|
|
1654
|
-
}
|
|
1655
|
-
function loadReactIslandConsumerModule(id) {
|
|
1656
|
-
const serverRemoteId = remoteIdFromResolvedIslandId(id, RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX);
|
|
1657
|
-
if (serverRemoteId !== void 0) return generateReactIslandConsumerServer(serverRemoteId);
|
|
1658
|
-
const clientRemoteId = remoteIdFromResolvedIslandId(id, RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX);
|
|
1659
|
-
if (clientRemoteId !== void 0) return generateReactIslandConsumerClient(clientRemoteId);
|
|
1584
|
+
function isReactServerConditions(conditions) {
|
|
1585
|
+
return Boolean(conditions?.includes("react-server"));
|
|
1660
1586
|
}
|
|
1661
1587
|
//#endregion
|
|
1662
1588
|
//#region src/virtualModules/virtualModuleScope.ts
|
|
@@ -1701,157 +1627,19 @@ function stableConfigValue(value, ancestors = /* @__PURE__ */ new WeakSet()) {
|
|
|
1701
1627
|
ancestors.delete(value);
|
|
1702
1628
|
return result;
|
|
1703
1629
|
}
|
|
1630
|
+
function hashConfig(value) {
|
|
1631
|
+
const identity = JSON.stringify(stableConfigValue(value));
|
|
1632
|
+
return BigInt(`0x${createHash("sha256").update(identity).digest("hex").slice(0, 12)}`);
|
|
1633
|
+
}
|
|
1634
|
+
const ownerIdFilenames = /* @__PURE__ */ new Map();
|
|
1704
1635
|
function getFederationScopeKey(options) {
|
|
1705
|
-
const identity =
|
|
1706
|
-
|
|
1636
|
+
const { filename, ...identity } = options;
|
|
1637
|
+
let ownerId = hashConfig(identity);
|
|
1638
|
+
if (!ownerIdFilenames.has(ownerId)) ownerIdFilenames.set(ownerId, filename);
|
|
1639
|
+
else if (ownerIdFilenames.get(ownerId) !== filename) ownerId = hashConfig(options);
|
|
1707
1640
|
return `${options.internalName}${MF_OWNER_INFIX}${ownerId}`;
|
|
1708
1641
|
}
|
|
1709
1642
|
//#endregion
|
|
1710
|
-
//#region src/virtualModules/virtualExposes.ts
|
|
1711
|
-
const EXPOSES_CSS_MAP_PLACEHOLDER = "__MF_EXPOSES_CSS_MAP__";
|
|
1712
|
-
function getExposesCssMapPlaceholder() {
|
|
1713
|
-
return EXPOSES_CSS_MAP_PLACEHOLDER;
|
|
1714
|
-
}
|
|
1715
|
-
function getVirtualExposesId(options) {
|
|
1716
|
-
return `virtual:mf-exposes:${getVirtualModuleScopeKey(options)}`;
|
|
1717
|
-
}
|
|
1718
|
-
function generateExposes(options, remoteDependencyMap = {}, command = "build", reactIslandExposes = /* @__PURE__ */ new Set()) {
|
|
1719
|
-
return `
|
|
1720
|
-
const cssAssetMap = ${JSON.stringify(options.bundleAllCSS ? EXPOSES_CSS_MAP_PLACEHOLDER : {})};
|
|
1721
|
-
const injectedCssHrefs = new Set();
|
|
1722
|
-
const exposeLoadPromises = new Map();
|
|
1723
|
-
|
|
1724
|
-
// Shared and remote readiness is handled by explicit Promise barriers below
|
|
1725
|
-
// and by remoteEntry's pendingShareLoads barrier. Keep this map scoped to a
|
|
1726
|
-
// single expose: unrelated exposes must stay independent and load in parallel.
|
|
1727
|
-
function loadExposedModule(exposeKey, loader) {
|
|
1728
|
-
let load = exposeLoadPromises.get(exposeKey);
|
|
1729
|
-
if (!load) {
|
|
1730
|
-
load = Promise.resolve()
|
|
1731
|
-
.then(loader)
|
|
1732
|
-
.catch((error) => {
|
|
1733
|
-
exposeLoadPromises.delete(exposeKey);
|
|
1734
|
-
throw error;
|
|
1735
|
-
});
|
|
1736
|
-
exposeLoadPromises.set(exposeKey, load);
|
|
1737
|
-
}
|
|
1738
|
-
return load;
|
|
1739
|
-
}
|
|
1740
|
-
|
|
1741
|
-
async function injectCssAssets(exposeKey) {
|
|
1742
|
-
if (typeof document === "undefined") {
|
|
1743
|
-
return;
|
|
1744
|
-
}
|
|
1745
|
-
|
|
1746
|
-
// Replaced at build time with expose -> css asset paths.
|
|
1747
|
-
const cssAssets = cssAssetMap[exposeKey] || [];
|
|
1748
|
-
|
|
1749
|
-
await Promise.all(
|
|
1750
|
-
cssAssets.map((cssAsset) => {
|
|
1751
|
-
const href = new URL(cssAsset, import.meta.url).href;
|
|
1752
|
-
|
|
1753
|
-
// Same expose can be resolved multiple times in one page.
|
|
1754
|
-
if (injectedCssHrefs.has(href)) {
|
|
1755
|
-
return Promise.resolve();
|
|
1756
|
-
}
|
|
1757
|
-
injectedCssHrefs.add(href);
|
|
1758
|
-
|
|
1759
|
-
// Check for any existing stylesheet with the same href, not just
|
|
1760
|
-
// MF-injected ones. This prevents duplicate <link> tags when Vite's
|
|
1761
|
-
// own CSS module injection or MF runtime's createLink has already
|
|
1762
|
-
// created a <link rel="stylesheet"> for the same URL.
|
|
1763
|
-
const existingLink = document.querySelector(
|
|
1764
|
-
\`link[rel="stylesheet"][href="\${href}"]\`
|
|
1765
|
-
);
|
|
1766
|
-
if (existingLink) {
|
|
1767
|
-
return Promise.resolve();
|
|
1768
|
-
}
|
|
1769
|
-
|
|
1770
|
-
return new Promise((resolve, reject) => {
|
|
1771
|
-
const link = document.createElement("link");
|
|
1772
|
-
link.rel = "stylesheet";
|
|
1773
|
-
link.href = href;
|
|
1774
|
-
link.onload = () => resolve();
|
|
1775
|
-
link.onerror = () => reject(new Error(\`[Module Federation] Failed to load CSS asset: \${href}\`));
|
|
1776
|
-
document.head.appendChild(link);
|
|
1777
|
-
});
|
|
1778
|
-
})
|
|
1779
|
-
);
|
|
1780
|
-
}
|
|
1781
|
-
|
|
1782
|
-
export default {
|
|
1783
|
-
${Object.keys(options.exposes).map((key) => {
|
|
1784
|
-
const remoteDependencyPreloads = (remoteDependencyMap[key] ?? []).map((remoteId) => {
|
|
1785
|
-
const virtualRemote = getRemoteVirtualModule(remoteId, command, false, "unified", options);
|
|
1786
|
-
return `import(${JSON.stringify(virtualRemote.getImportId())})
|
|
1787
|
-
.then((mod) => mod.__mf_remote_pending)`;
|
|
1788
|
-
}).join(",");
|
|
1789
|
-
return `
|
|
1790
|
-
${JSON.stringify(key)}: async () => {
|
|
1791
|
-
await injectCssAssets(${JSON.stringify(key)})
|
|
1792
|
-
await Promise.all([${remoteDependencyPreloads}])
|
|
1793
|
-
const importModule = await loadExposedModule(
|
|
1794
|
-
${JSON.stringify(key)},
|
|
1795
|
-
() => import(${JSON.stringify(options.exposes[key].import)})
|
|
1796
|
-
)
|
|
1797
|
-
const dependencyPending = importModule && importModule.__mf_remote_dependency_pending;
|
|
1798
|
-
if (dependencyPending && typeof dependencyPending.then === "function") {
|
|
1799
|
-
await dependencyPending;
|
|
1800
|
-
}
|
|
1801
|
-
const exportModule = {}
|
|
1802
|
-
Object.assign(exportModule, importModule)
|
|
1803
|
-
${generateReactIslandBrowserDefinition(reactIslandExposes.has(key))}
|
|
1804
|
-
Object.defineProperty(exportModule, "__esModule", {
|
|
1805
|
-
value: true,
|
|
1806
|
-
enumerable: false
|
|
1807
|
-
})
|
|
1808
|
-
return exportModule
|
|
1809
|
-
}
|
|
1810
|
-
`;
|
|
1811
|
-
}).join(",")}
|
|
1812
|
-
}
|
|
1813
|
-
`;
|
|
1814
|
-
}
|
|
1815
|
-
//#endregion
|
|
1816
|
-
//#region src/utils/sharedExportConditions.ts
|
|
1817
|
-
const DEFAULT_CLIENT_EXPORT_CONDITIONS = [
|
|
1818
|
-
"browser",
|
|
1819
|
-
"import",
|
|
1820
|
-
"module",
|
|
1821
|
-
"default"
|
|
1822
|
-
];
|
|
1823
|
-
const DEFAULT_NODE_SSR_EXPORT_CONDITIONS = [
|
|
1824
|
-
"node",
|
|
1825
|
-
"import",
|
|
1826
|
-
"module",
|
|
1827
|
-
"default"
|
|
1828
|
-
];
|
|
1829
|
-
const DEFAULT_WEBWORKER_SSR_EXPORT_CONDITIONS = [
|
|
1830
|
-
"worker",
|
|
1831
|
-
"browser",
|
|
1832
|
-
"import",
|
|
1833
|
-
"module",
|
|
1834
|
-
"default"
|
|
1835
|
-
];
|
|
1836
|
-
const VITE_DEV_PROD_CONDITION = "development|production";
|
|
1837
|
-
function appendConditions(conditions, fallbackConditions) {
|
|
1838
|
-
return [.../* @__PURE__ */ new Set([...conditions, ...fallbackConditions])];
|
|
1839
|
-
}
|
|
1840
|
-
function resolveViteModeCondition(conditions, isProduction) {
|
|
1841
|
-
const modeCondition = isProduction ? "production" : "development";
|
|
1842
|
-
return [...new Set(conditions.map((condition) => condition === VITE_DEV_PROD_CONDITION ? modeCondition : condition))];
|
|
1843
|
-
}
|
|
1844
|
-
function getSharedExportConditions({ environmentConditions, isProduction, isSsr, rootConditions, ssrConditions, ssrTarget = "node" }) {
|
|
1845
|
-
if (environmentConditions !== void 0) return resolveViteModeCondition(appendConditions(environmentConditions, ["import", "default"]), isProduction);
|
|
1846
|
-
const defaultConditions = isSsr ? ssrTarget === "webworker" ? DEFAULT_WEBWORKER_SSR_EXPORT_CONDITIONS : DEFAULT_NODE_SSR_EXPORT_CONDITIONS : DEFAULT_CLIENT_EXPORT_CONDITIONS;
|
|
1847
|
-
const configuredConditions = isSsr ? ssrConditions ?? rootConditions : rootConditions;
|
|
1848
|
-
if (configuredConditions !== void 0) return resolveViteModeCondition(appendConditions(configuredConditions, defaultConditions), isProduction);
|
|
1849
|
-
return [...defaultConditions];
|
|
1850
|
-
}
|
|
1851
|
-
function isReactServerConditions(conditions) {
|
|
1852
|
-
return Boolean(conditions?.includes("react-server"));
|
|
1853
|
-
}
|
|
1854
|
-
//#endregion
|
|
1855
1643
|
//#region src/virtualModules/virtualRuntimeInitStatus.ts
|
|
1856
1644
|
const virtualRuntimeInitStatus = new VirtualModule("runtimeInit");
|
|
1857
1645
|
const runtimeInitModules = /* @__PURE__ */ new WeakMap();
|
|
@@ -2034,102 +1822,10 @@ ${exportStatement}
|
|
|
2034
1822
|
`);
|
|
2035
1823
|
}
|
|
2036
1824
|
//#endregion
|
|
2037
|
-
//#region src/
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
let __mfReactDispatcher = __mfReactInternals.A;
|
|
2042
|
-
Object.defineProperty(__mfReactInternals, "A", {
|
|
2043
|
-
configurable: true,
|
|
2044
|
-
enumerable: true,
|
|
2045
|
-
get: () => __mfReactDispatcher,
|
|
2046
|
-
set: (next) => {
|
|
2047
|
-
if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
|
|
2048
|
-
__mfReactDispatcher = next;
|
|
2049
|
-
},
|
|
2050
|
-
});
|
|
2051
|
-
__mfReactInternals.A = __mfReactDispatcher;
|
|
2052
|
-
}`;
|
|
2053
|
-
}
|
|
2054
|
-
//#endregion
|
|
2055
|
-
//#region src/utils/typeArgumentScanner.ts
|
|
2056
|
-
function getTypeArgumentStartContext(source, start) {
|
|
2057
|
-
let previous = start - 1;
|
|
2058
|
-
while (previous >= 0 && /\s/.test(source[previous])) previous--;
|
|
2059
|
-
const previousChar = source[previous] || "";
|
|
2060
|
-
const followsNamedExpression = /[$_\u200C\u200D\p{ID_Continue})\]>]/u.test(previousChar);
|
|
2061
|
-
const startsStandaloneGeneric = previousChar !== "" && "=([{,:".includes(previousChar);
|
|
2062
|
-
if (!followsNamedExpression && !startsStandaloneGeneric) return void 0;
|
|
2063
|
-
return { followsNamedExpression };
|
|
2064
|
-
}
|
|
2065
|
-
function updateTypeArgumentGroupDepth(char, state) {
|
|
2066
|
-
if (char === "(" || char === "[" || char === "{") {
|
|
2067
|
-
state.groupDepth++;
|
|
2068
|
-
return "handled";
|
|
2069
|
-
}
|
|
2070
|
-
if (char !== ")" && char !== "]" && char !== "}") return void 0;
|
|
2071
|
-
if (state.groupDepth === 0) return "invalid";
|
|
2072
|
-
state.groupDepth--;
|
|
2073
|
-
return "handled";
|
|
2074
|
-
}
|
|
2075
|
-
function updateTypeArgumentAngleDepth(source, index, state) {
|
|
2076
|
-
const char = source[index];
|
|
2077
|
-
if (char === "<") {
|
|
2078
|
-
if (source[index + 1] === "=" || source[index + 1] === "<") return "invalid";
|
|
2079
|
-
state.angleDepth++;
|
|
2080
|
-
return "handled";
|
|
2081
|
-
}
|
|
2082
|
-
if (char !== ">") return void 0;
|
|
2083
|
-
if (source[index - 1] === "=" || source[index + 1] === "=") return "handled";
|
|
2084
|
-
state.angleDepth--;
|
|
2085
|
-
return state.angleDepth === 0 ? "closed" : "handled";
|
|
2086
|
-
}
|
|
2087
|
-
function hasLikelyTypeArgumentFollower(source, end, codePositions, followsNamedExpression) {
|
|
2088
|
-
let next = end + 1;
|
|
2089
|
-
while (next < source.length && (!codePositions[next] || /\s/.test(source[next]))) next++;
|
|
2090
|
-
if (next >= source.length || /[([.!?=;,)\]}:|&]/.test(source[next])) return true;
|
|
2091
|
-
if (source.slice(end + 1, next).includes("\n")) return true;
|
|
2092
|
-
const followingToken = source.slice(next).match(/^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*/u)?.[0];
|
|
2093
|
-
return followingToken === "as" || followingToken === "satisfies" || !followsNamedExpression && followingToken !== void 0;
|
|
2094
|
-
}
|
|
2095
|
-
function isInvalidTypeArgumentTerminator(source, index, followsNamedExpression) {
|
|
2096
|
-
const char = source[index];
|
|
2097
|
-
return char === ";" || char === "=" && source[index + 1] !== ">" && followsNamedExpression;
|
|
2098
|
-
}
|
|
2099
|
-
/**
|
|
2100
|
-
* Finds the end of a balanced, type-like angle-bracket range that contains a
|
|
2101
|
-
* comma. Ambiguous syntax returns `undefined` so callers can fail closed.
|
|
2102
|
-
*/
|
|
2103
|
-
function findLikelyTypeArgumentEnd(source, start, codePositions) {
|
|
2104
|
-
const context = getTypeArgumentStartContext(source, start);
|
|
2105
|
-
if (!context) return void 0;
|
|
2106
|
-
const state = {
|
|
2107
|
-
angleDepth: 1,
|
|
2108
|
-
groupDepth: 0,
|
|
2109
|
-
sawTypeComma: false
|
|
2110
|
-
};
|
|
2111
|
-
for (let index = start + 1; index < source.length; index++) {
|
|
2112
|
-
if (!codePositions[index]) continue;
|
|
2113
|
-
const char = source[index];
|
|
2114
|
-
const groupAction = updateTypeArgumentGroupDepth(char, state);
|
|
2115
|
-
if (groupAction === "invalid") return void 0;
|
|
2116
|
-
if (groupAction === "handled") continue;
|
|
2117
|
-
const angleAction = updateTypeArgumentAngleDepth(source, index, state);
|
|
2118
|
-
if (angleAction === "invalid") return void 0;
|
|
2119
|
-
if (angleAction === "closed") return state.sawTypeComma && hasLikelyTypeArgumentFollower(source, index, codePositions, context.followsNamedExpression) ? index : void 0;
|
|
2120
|
-
if (angleAction === "handled") continue;
|
|
2121
|
-
if (char === "," && state.groupDepth === 0) {
|
|
2122
|
-
state.sawTypeComma = true;
|
|
2123
|
-
continue;
|
|
2124
|
-
}
|
|
2125
|
-
if (state.angleDepth === 1 && state.groupDepth === 0 && isInvalidTypeArgumentTerminator(source, index, context.followsNamedExpression)) return;
|
|
2126
|
-
}
|
|
2127
|
-
}
|
|
2128
|
-
//#endregion
|
|
2129
|
-
//#region src/virtualModules/shareTags.ts
|
|
2130
|
-
const LOAD_SHARE_TAG = "__loadShare__";
|
|
2131
|
-
/** A share's local copy. Reachable only through `import()`, so it stays lazy. */
|
|
2132
|
-
const PREBUILD_TAG = "__prebuild__";
|
|
1825
|
+
//#region src/virtualModules/shareTags.ts
|
|
1826
|
+
const LOAD_SHARE_TAG = "__loadShare__";
|
|
1827
|
+
/** A share's local copy. Reachable only through `import()`, so it stays lazy. */
|
|
1828
|
+
const PREBUILD_TAG = "__prebuild__";
|
|
2133
1829
|
//#endregion
|
|
2134
1830
|
//#region src/virtualModules/loadShareSharedChunk.ts
|
|
2135
1831
|
const HELPERS_MODULE_NAME = "loadShareHelpers";
|
|
@@ -2208,7 +1904,6 @@ function findEagerFallbacksInSharedChunk(bundle) {
|
|
|
2208
1904
|
* 1. __prebuild__: export shareModule (pre-built source code of modules such as vue, react, etc.)
|
|
2209
1905
|
* 2. __loadShare__: load shareModule (mfRuntime.loadShare('vue'))
|
|
2210
1906
|
*/
|
|
2211
|
-
const JS_IDENTIFIER_REGEX = /* @__PURE__ */ new RegExp("^[$_\\p{ID_Start}][$_\\u200C\\u200D\\p{ID_Continue}]*$", "u");
|
|
2212
1907
|
function escapeGeneratedStringLiteral(value) {
|
|
2213
1908
|
return JSON.stringify(value).replace(/[<>\u2028\u2029]/g, (char) => {
|
|
2214
1909
|
switch (char) {
|
|
@@ -2220,16 +1915,15 @@ function escapeGeneratedStringLiteral(value) {
|
|
|
2220
1915
|
}
|
|
2221
1916
|
});
|
|
2222
1917
|
}
|
|
1918
|
+
function getDefaultOrNamespaceExpression(namespace) {
|
|
1919
|
+
return `Reflect.get(${namespace}, "default") ?? ${namespace}`;
|
|
1920
|
+
}
|
|
2223
1921
|
function getSharedCacheDescriptorLiteral(pkg, shareItem) {
|
|
2224
1922
|
return JSON.stringify(getSharedCacheDescriptor(pkg, shareItem));
|
|
2225
1923
|
}
|
|
2226
|
-
function isValidJsIdentifier(name) {
|
|
2227
|
-
return JS_IDENTIFIER_REGEX.test(name);
|
|
2228
|
-
}
|
|
2229
1924
|
function isValidEsmExportName(name) {
|
|
2230
1925
|
return !!name && name !== "default" && name !== "__esModule" && isValidJsIdentifier(name);
|
|
2231
1926
|
}
|
|
2232
|
-
const JS_IDENTIFIER_PATTERN = `[\$_\\p{ID_Start}][\$_\\u200C\\u200D\\p{ID_Continue}]*`;
|
|
2233
1927
|
function resolvePackageEntryFromProjectRoot(pkg) {
|
|
2234
1928
|
try {
|
|
2235
1929
|
return resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json"));
|
|
@@ -2237,14 +1931,18 @@ function resolvePackageEntryFromProjectRoot(pkg) {
|
|
|
2237
1931
|
return;
|
|
2238
1932
|
}
|
|
2239
1933
|
}
|
|
1934
|
+
let workspaceEntryConditions = [
|
|
1935
|
+
"browser",
|
|
1936
|
+
"import",
|
|
1937
|
+
"module",
|
|
1938
|
+
"default"
|
|
1939
|
+
];
|
|
1940
|
+
function setWorkspaceEntryConditions(conditions) {
|
|
1941
|
+
workspaceEntryConditions = conditions;
|
|
1942
|
+
}
|
|
2240
1943
|
function getPackageEsmEntryPath(pkg) {
|
|
2241
1944
|
return getInstalledPackageEntry(pkg, {
|
|
2242
|
-
conditions:
|
|
2243
|
-
"browser",
|
|
2244
|
-
"import",
|
|
2245
|
-
"module",
|
|
2246
|
-
"default"
|
|
2247
|
-
],
|
|
1945
|
+
conditions: workspaceEntryConditions,
|
|
2248
1946
|
resolveSubpathWithRequire: false
|
|
2249
1947
|
}) || resolvePackageEntryFromProjectRoot(pkg);
|
|
2250
1948
|
}
|
|
@@ -2484,160 +2182,59 @@ function resolveReExportModule(filePath, specifier, exportConditions) {
|
|
|
2484
2182
|
return;
|
|
2485
2183
|
}
|
|
2486
2184
|
}
|
|
2487
|
-
/** Marks a template-literal frame whose text (not its interpolation) is being scanned. */
|
|
2488
|
-
const TEMPLATE_TEXT = Symbol("templateText");
|
|
2489
2185
|
function getAdditionalTopLevelDeclaratorNames(source, start, codePositions) {
|
|
2490
2186
|
const names = [];
|
|
2491
2187
|
let depth = 0;
|
|
2492
|
-
let quote;
|
|
2493
|
-
let escaped = false;
|
|
2494
|
-
let canStartRegex = true;
|
|
2495
|
-
const templateFrames = [];
|
|
2496
|
-
const inTemplateText = () => templateFrames[templateFrames.length - 1] === TEMPLATE_TEXT;
|
|
2497
2188
|
for (let index = start; index < source.length; index++) {
|
|
2498
2189
|
const char = source[index];
|
|
2499
|
-
if (
|
|
2500
|
-
if (escaped) escaped = false;
|
|
2501
|
-
else if (char === "\\") escaped = true;
|
|
2502
|
-
else if (char === "$" && source[index + 1] === "{") {
|
|
2503
|
-
templateFrames.push(depth);
|
|
2504
|
-
index++;
|
|
2505
|
-
canStartRegex = true;
|
|
2506
|
-
} else if (char === "`") {
|
|
2507
|
-
templateFrames.pop();
|
|
2508
|
-
canStartRegex = false;
|
|
2509
|
-
}
|
|
2510
|
-
continue;
|
|
2511
|
-
}
|
|
2512
|
-
if (quote) {
|
|
2513
|
-
if (escaped) escaped = false;
|
|
2514
|
-
else if (char === "\\") escaped = true;
|
|
2515
|
-
else if (char === quote) quote = void 0;
|
|
2516
|
-
continue;
|
|
2517
|
-
}
|
|
2518
|
-
if (char === "`") {
|
|
2519
|
-
templateFrames.push(TEMPLATE_TEXT);
|
|
2520
|
-
canStartRegex = false;
|
|
2521
|
-
continue;
|
|
2522
|
-
}
|
|
2523
|
-
if (char === "\"" || char === "'") {
|
|
2524
|
-
quote = char;
|
|
2525
|
-
canStartRegex = false;
|
|
2526
|
-
continue;
|
|
2527
|
-
}
|
|
2190
|
+
if (!codePositions[index]) continue;
|
|
2528
2191
|
if (char === "<" && source[index + 1] === "/") {
|
|
2529
2192
|
const jsxClosingTag = source.slice(index).match(/^<\/\s*(?:[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}.:-]*\s*)?>/u);
|
|
2530
2193
|
if (jsxClosingTag) {
|
|
2531
2194
|
index += jsxClosingTag[0].length - 1;
|
|
2532
|
-
canStartRegex = false;
|
|
2533
2195
|
continue;
|
|
2534
2196
|
}
|
|
2535
2197
|
}
|
|
2536
|
-
if (char === "/" && source[index + 1] === "/") {
|
|
2537
|
-
index = source.indexOf("\n", index + 2);
|
|
2538
|
-
if (index === -1) return names;
|
|
2539
|
-
continue;
|
|
2540
|
-
}
|
|
2541
|
-
if (char === "/" && source[index + 1] === "*") {
|
|
2542
|
-
const commentEnd = source.indexOf("*/", index + 2);
|
|
2543
|
-
if (commentEnd === -1) return void 0;
|
|
2544
|
-
index = commentEnd + 1;
|
|
2545
|
-
continue;
|
|
2546
|
-
}
|
|
2547
|
-
if (char === "/" && canStartRegex) {
|
|
2548
|
-
let regexEscaped = false;
|
|
2549
|
-
let inCharacterClass = false;
|
|
2550
|
-
let closed = false;
|
|
2551
|
-
for (index++; index < source.length; index++) {
|
|
2552
|
-
const regexChar = source[index];
|
|
2553
|
-
if (regexEscaped) {
|
|
2554
|
-
regexEscaped = false;
|
|
2555
|
-
continue;
|
|
2556
|
-
}
|
|
2557
|
-
if (regexChar === "\\") {
|
|
2558
|
-
regexEscaped = true;
|
|
2559
|
-
continue;
|
|
2560
|
-
}
|
|
2561
|
-
if (regexChar === "[") {
|
|
2562
|
-
inCharacterClass = true;
|
|
2563
|
-
continue;
|
|
2564
|
-
}
|
|
2565
|
-
if (regexChar === "]" && inCharacterClass) {
|
|
2566
|
-
inCharacterClass = false;
|
|
2567
|
-
continue;
|
|
2568
|
-
}
|
|
2569
|
-
if (regexChar === "/" && !inCharacterClass) {
|
|
2570
|
-
closed = true;
|
|
2571
|
-
while (/[$_\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
|
|
2572
|
-
break;
|
|
2573
|
-
}
|
|
2574
|
-
if (regexChar === "\n" || regexChar === "\r") return void 0;
|
|
2575
|
-
}
|
|
2576
|
-
if (!closed) return void 0;
|
|
2577
|
-
canStartRegex = false;
|
|
2578
|
-
continue;
|
|
2579
|
-
}
|
|
2580
|
-
if (char === "/") {
|
|
2581
|
-
canStartRegex = true;
|
|
2582
|
-
continue;
|
|
2583
|
-
}
|
|
2584
2198
|
if (/[$_\p{ID_Start}]/u.test(char)) {
|
|
2585
2199
|
const tokenStart = index;
|
|
2586
2200
|
while (/[$_\u200C\u200D\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
|
|
2587
2201
|
const token = source.slice(tokenStart, index + 1);
|
|
2588
|
-
if (depth === 0 &&
|
|
2202
|
+
if (depth === 0 && token === "export") {
|
|
2589
2203
|
let previous = tokenStart - 1;
|
|
2590
2204
|
while (/\s/.test(source[previous] || "")) previous--;
|
|
2591
2205
|
if (source[previous] !== "." && /^\s+(?:(?:async\s+)?function\b|(?:abstract\s+)?class\b|const\b|let\b|var\b|enum\b|namespace\b|module\b|interface\b|type\b|declare\b|default\b|\{|\*)/.test(source.slice(index + 1))) return names;
|
|
2592
2206
|
}
|
|
2593
|
-
canStartRegex = /^(?:await|case|delete|in|instanceof|new|return|throw|typeof|void|yield)$/.test(token);
|
|
2594
2207
|
continue;
|
|
2595
2208
|
}
|
|
2596
2209
|
if (/\d/.test(char)) {
|
|
2597
2210
|
while (/[\w.]/.test(source[index + 1] || "")) index++;
|
|
2598
|
-
canStartRegex = false;
|
|
2599
|
-
continue;
|
|
2600
|
-
}
|
|
2601
|
-
if ((char === "+" || char === "-") && source[index + 1] === char) {
|
|
2602
|
-
index++;
|
|
2603
2211
|
continue;
|
|
2604
2212
|
}
|
|
2605
|
-
if (char === "!" && source[index + 1] !== "=") continue;
|
|
2606
2213
|
if (char === "<") {
|
|
2607
2214
|
const typeArgumentEnd = findLikelyTypeArgumentEnd(source, index, codePositions);
|
|
2608
2215
|
if (typeArgumentEnd !== void 0) {
|
|
2609
2216
|
index = typeArgumentEnd;
|
|
2610
|
-
canStartRegex = false;
|
|
2611
2217
|
continue;
|
|
2612
2218
|
}
|
|
2613
2219
|
}
|
|
2614
2220
|
if (char === "(" || char === "[" || char === "{") {
|
|
2615
2221
|
depth++;
|
|
2616
|
-
canStartRegex = true;
|
|
2617
2222
|
continue;
|
|
2618
2223
|
}
|
|
2619
2224
|
if (char === ")" || char === "]" || char === "}") {
|
|
2620
|
-
if (char === "}" && templateFrames.length > 0 && templateFrames[templateFrames.length - 1] === depth) {
|
|
2621
|
-
templateFrames.pop();
|
|
2622
|
-
canStartRegex = false;
|
|
2623
|
-
continue;
|
|
2624
|
-
}
|
|
2625
2225
|
depth = Math.max(0, depth - 1);
|
|
2626
|
-
canStartRegex = false;
|
|
2627
2226
|
continue;
|
|
2628
2227
|
}
|
|
2629
|
-
if (
|
|
2228
|
+
if (depth === 0 && char === ",") {
|
|
2630
2229
|
let bindingStart = index + 1;
|
|
2631
2230
|
while (/\s/.test(source[bindingStart] || "")) bindingStart++;
|
|
2632
2231
|
const binding = source.slice(bindingStart).match(new RegExp(`^(${JS_IDENTIFIER_PATTERN})`, "u"));
|
|
2633
2232
|
if (!binding || !isValidEsmExportName(binding[1])) return void 0;
|
|
2634
2233
|
names.push(binding[1]);
|
|
2635
2234
|
index = bindingStart + binding[1].length - 1;
|
|
2636
|
-
canStartRegex = false;
|
|
2637
2235
|
continue;
|
|
2638
2236
|
}
|
|
2639
|
-
if (
|
|
2640
|
-
if (!/\s/.test(char)) canStartRegex = char !== ".";
|
|
2237
|
+
if (depth === 0 && char === ";") return names;
|
|
2641
2238
|
}
|
|
2642
2239
|
return names;
|
|
2643
2240
|
}
|
|
@@ -2855,12 +2452,7 @@ function getLocalProviderImportPath(pkg) {
|
|
|
2855
2452
|
return isWorkspaceFilePath(resolved) ? resolved : void 0;
|
|
2856
2453
|
} catch {
|
|
2857
2454
|
const resolved = getInstalledPackageEntry(pkg, {
|
|
2858
|
-
conditions:
|
|
2859
|
-
"browser",
|
|
2860
|
-
"import",
|
|
2861
|
-
"module",
|
|
2862
|
-
"default"
|
|
2863
|
-
],
|
|
2455
|
+
conditions: workspaceEntryConditions,
|
|
2864
2456
|
resolveSubpathWithRequire: false
|
|
2865
2457
|
});
|
|
2866
2458
|
return isWorkspaceFilePath(resolved) ? resolved : void 0;
|
|
@@ -2898,12 +2490,7 @@ function resolveWorkspaceEsmEntry(pkg, resolved, cwd = getPackageDetectionCwd())
|
|
|
2898
2490
|
if (!isWorkspaceFilePath(resolved)) return resolved;
|
|
2899
2491
|
const esmEntry = getInstalledPackageEntry(pkg, {
|
|
2900
2492
|
cwd,
|
|
2901
|
-
conditions:
|
|
2902
|
-
"browser",
|
|
2903
|
-
"import",
|
|
2904
|
-
"module",
|
|
2905
|
-
"default"
|
|
2906
|
-
],
|
|
2493
|
+
conditions: workspaceEntryConditions,
|
|
2907
2494
|
resolveSubpathWithRequire: false
|
|
2908
2495
|
});
|
|
2909
2496
|
if (esmEntry && isWorkspaceFilePath(esmEntry)) return esmEntry;
|
|
@@ -3024,30 +2611,15 @@ function resolveConcreteSharedImportSource(pkg, projectRoot) {
|
|
|
3024
2611
|
currentDir = path$1.dirname(currentDir);
|
|
3025
2612
|
}
|
|
3026
2613
|
return tryResolveImportFromPackageRoot(pkg, currentDir) ?? getInstalledPackageEntry(pkg, {
|
|
3027
|
-
conditions:
|
|
2614
|
+
conditions: workspaceEntryConditions,
|
|
3028
2615
|
resolveSubpathWithRequire: false
|
|
3029
2616
|
});
|
|
3030
2617
|
}
|
|
3031
2618
|
const TREE_SHAKING_PROVIDER_TAG = "__treeShakingProvider__";
|
|
3032
2619
|
const TREE_SHAKING_GRAPH_QUERY = "__mf_tree_shaking_graph__";
|
|
3033
|
-
const legacySharedVirtualModuleState = {
|
|
3034
|
-
preBuildCacheMap: {},
|
|
3035
|
-
preBuildShareItemMap: {},
|
|
3036
|
-
treeShakingProviderCacheMap: {},
|
|
3037
|
-
materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
|
|
3038
|
-
loadShareCacheMap: {},
|
|
3039
|
-
warnedMissingImportFalse: /* @__PURE__ */ new Set(),
|
|
3040
|
-
coalescableLoadShares: /* @__PURE__ */ new Set()
|
|
3041
|
-
};
|
|
3042
2620
|
const sharedVirtualModuleStates = /* @__PURE__ */ new WeakMap();
|
|
3043
2621
|
const sharedVirtualModuleStatesByOwner = /* @__PURE__ */ new Map();
|
|
3044
2622
|
function getSharedVirtualModuleState(options) {
|
|
3045
|
-
if (!options) try {
|
|
3046
|
-
const currentOptions = getNormalizeModuleFederationOptions();
|
|
3047
|
-
return sharedVirtualModuleStates.get(currentOptions) ?? legacySharedVirtualModuleState;
|
|
3048
|
-
} catch {
|
|
3049
|
-
return legacySharedVirtualModuleState;
|
|
3050
|
-
}
|
|
3051
2623
|
let state = sharedVirtualModuleStates.get(options);
|
|
3052
2624
|
if (!state) {
|
|
3053
2625
|
state = {
|
|
@@ -3107,8 +2679,7 @@ function getConcreteTreeShakingExportUsage(pkg, shareItem, options) {
|
|
|
3107
2679
|
return getTreeShakingExportUsage(pkg, shareItem, shareItem?.name, options);
|
|
3108
2680
|
}
|
|
3109
2681
|
function getTreeShakingSharedProviderName(pkg, options) {
|
|
3110
|
-
|
|
3111
|
-
return `${getSharedVirtualModuleState(options).ownerKey ?? resolvedOptions.internalName ?? resolvedOptions.name}__tree_shaking__${packageNameEncode(pkg)}`;
|
|
2682
|
+
return `${getSharedVirtualModuleState(options).ownerKey ?? options.internalName ?? options.name}__tree_shaking__${packageNameEncode(pkg)}`;
|
|
3112
2683
|
}
|
|
3113
2684
|
function getTreeShakingSharedProviderImportId(pkg, options) {
|
|
3114
2685
|
const { treeShakingProviderCacheMap } = getSharedVirtualModuleState(options);
|
|
@@ -3166,7 +2737,6 @@ export default { get, init };
|
|
|
3166
2737
|
materializedTreeShakingProviders.add(pkg);
|
|
3167
2738
|
}
|
|
3168
2739
|
function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
|
|
3169
|
-
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
3170
2740
|
const { preBuildCacheMap, preBuildShareItemMap } = getSharedVirtualModuleState(options);
|
|
3171
2741
|
if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = createScopedSharedVirtualModule(pkg, PREBUILD_TAG, options);
|
|
3172
2742
|
preBuildShareItemMap[pkg] = shareItem;
|
|
@@ -3195,9 +2765,8 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
|
|
|
3195
2765
|
}
|
|
3196
2766
|
if (pkg === "react/jsx-dev-runtime") {
|
|
3197
2767
|
preBuildCacheMap[pkg].writeSync(`
|
|
3198
|
-
import __mfPrebuildDefault from ${escapeGeneratedStringLiteral(importSource)};
|
|
3199
2768
|
import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
|
|
3200
|
-
const __mfPrebuildExports =
|
|
2769
|
+
const __mfPrebuildExports = ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
|
|
3201
2770
|
export const Fragment = __mfPrebuildExports.Fragment;
|
|
3202
2771
|
export const jsxDEV = __mfPrebuildExports.jsxDEV;
|
|
3203
2772
|
export default __mfPrebuildExports;
|
|
@@ -3206,9 +2775,8 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
|
|
|
3206
2775
|
}
|
|
3207
2776
|
if (pkg === "react/jsx-runtime") {
|
|
3208
2777
|
preBuildCacheMap[pkg].writeSync(`
|
|
3209
|
-
import __mfPrebuildDefault from ${escapeGeneratedStringLiteral(importSource)};
|
|
3210
2778
|
import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
|
|
3211
|
-
const __mfPrebuildExports =
|
|
2779
|
+
const __mfPrebuildExports = ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
|
|
3212
2780
|
export const Fragment = __mfPrebuildExports.Fragment;
|
|
3213
2781
|
export const jsx = __mfPrebuildExports.jsx;
|
|
3214
2782
|
export const jsxs = __mfPrebuildExports.jsxs;
|
|
@@ -3218,7 +2786,7 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
|
|
|
3218
2786
|
}
|
|
3219
2787
|
const namedExports = getSharedNamedExports(pkg, shareItem, exportConditions) ?? [];
|
|
3220
2788
|
if (namedExports.length > 0) {
|
|
3221
|
-
const mutableExports = new Set(isLocalOnlyContainer(
|
|
2789
|
+
const mutableExports = new Set(isLocalOnlyContainer(options) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
|
|
3222
2790
|
const copiedExports = namedExports.filter((name) => !mutableExports.has(name));
|
|
3223
2791
|
const liveExports = namedExports.filter((name) => mutableExports.has(name));
|
|
3224
2792
|
const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
|
|
@@ -3231,26 +2799,23 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
|
|
|
3231
2799
|
${declarations}
|
|
3232
2800
|
${namedExportLine}
|
|
3233
2801
|
${liveExportLine}
|
|
3234
|
-
export default
|
|
2802
|
+
export default ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
|
|
3235
2803
|
`, true);
|
|
3236
2804
|
return;
|
|
3237
2805
|
}
|
|
3238
2806
|
preBuildCacheMap[pkg].writeSync(`
|
|
3239
2807
|
import * as __mfPrebuildExports from ${escapeGeneratedStringLiteral(importSource)};
|
|
3240
2808
|
export * from ${escapeGeneratedStringLiteral(importSource)};
|
|
3241
|
-
|
|
3242
|
-
// default export (for example antd/es/index.js), while preserving the
|
|
3243
|
-
// namespace fallback for packages that do provide one.
|
|
3244
|
-
export default Reflect.get(__mfPrebuildExports, "default") ?? __mfPrebuildExports;
|
|
2809
|
+
export default ${getDefaultOrNamespaceExpression("__mfPrebuildExports")};
|
|
3245
2810
|
`, true);
|
|
3246
2811
|
}
|
|
3247
2812
|
/** Re-render already materialized wrappers after import analysis discovers exports. */
|
|
3248
|
-
function refreshTreeShakingModules(options, command = "build",
|
|
2813
|
+
function refreshTreeShakingModules(options, command = "build", exportConditions) {
|
|
3249
2814
|
const { preBuildShareItemMap } = getSharedVirtualModuleState(options);
|
|
3250
2815
|
for (const [pkg, shareItem] of Object.entries(preBuildShareItemMap)) {
|
|
3251
2816
|
if (!shareItem?.shareConfig.treeShaking) continue;
|
|
3252
2817
|
writePreBuildLibPath(pkg, shareItem, options, exportConditions);
|
|
3253
|
-
writeLoadShareModule(pkg, shareItem, command,
|
|
2818
|
+
writeLoadShareModule(pkg, shareItem, command, options, exportConditions);
|
|
3254
2819
|
}
|
|
3255
2820
|
}
|
|
3256
2821
|
function getPreBuildLibImportId(pkg, options) {
|
|
@@ -3264,16 +2829,11 @@ function getPreBuildShareItem(pkg, options) {
|
|
|
3264
2829
|
function getSharedImportSource(pkg, shareItem, options) {
|
|
3265
2830
|
return getConcreteSharedImportSource(pkg, shareItem) || getPreBuildLibImportId(pkg, options);
|
|
3266
2831
|
}
|
|
3267
|
-
function
|
|
2832
|
+
function getLoadShareModulePath(pkg, options) {
|
|
3268
2833
|
const { loadShareCacheMap } = getSharedVirtualModuleState(options);
|
|
3269
2834
|
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
|
|
3270
2835
|
return loadShareCacheMap[pkg].getImportId();
|
|
3271
2836
|
}
|
|
3272
|
-
function getLoadShareModulePath(pkg, isRolldown, options) {
|
|
3273
|
-
const { loadShareCacheMap } = getSharedVirtualModuleState(options);
|
|
3274
|
-
if (!loadShareCacheMap[pkg]) getLoadShareImportId(pkg, isRolldown, options);
|
|
3275
|
-
return loadShareCacheMap[pkg].getImportId();
|
|
3276
|
-
}
|
|
3277
2837
|
function getCachedSharedVirtualPkg(id, tag) {
|
|
3278
2838
|
if (!id.includes(tag)) return;
|
|
3279
2839
|
const normalized = normalizeVirtualModuleId(id);
|
|
@@ -3297,7 +2857,7 @@ function materializeCachedLoadShareModule(options) {
|
|
|
3297
2857
|
const key = options.findSharedKey(pkg, options.shared);
|
|
3298
2858
|
if (!key) return;
|
|
3299
2859
|
const shareItem = options.shared[key];
|
|
3300
|
-
writeLoadShareModule(pkg, shareItem, options.command, options.
|
|
2860
|
+
writeLoadShareModule(pkg, shareItem, options.command, options.federationOptions);
|
|
3301
2861
|
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(pkg, shareItem, options.federationOptions);
|
|
3302
2862
|
options.addUsedShares(pkg);
|
|
3303
2863
|
options.writeLocalSharedImportMap();
|
|
@@ -3542,23 +3102,37 @@ function markLoadShareWrapperNotCoalescable(pkg, options, id) {
|
|
|
3542
3102
|
function isCoalescableLoadShareWrapper(pkg, options, id) {
|
|
3543
3103
|
return getSharedVirtualModuleStateForId(id, options).coalescableLoadShares.has(pkg);
|
|
3544
3104
|
}
|
|
3545
|
-
|
|
3546
|
-
|
|
3105
|
+
/** Keeps runtime-shared React dispatchers usable when a mixed-mode remote swaps them in. */
|
|
3106
|
+
const REACT_MIXED_MODE_GUARD = `const __mfReactInternals = mod[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
|
|
3107
|
+
if (__mfReactInternals && "A" in __mfReactInternals) {
|
|
3108
|
+
let __mfReactDispatcher = __mfReactInternals.A;
|
|
3109
|
+
Object.defineProperty(__mfReactInternals, "A", {
|
|
3110
|
+
configurable: true,
|
|
3111
|
+
enumerable: true,
|
|
3112
|
+
get: () => __mfReactDispatcher,
|
|
3113
|
+
set: (next) => {
|
|
3114
|
+
if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
|
|
3115
|
+
__mfReactDispatcher = next;
|
|
3116
|
+
},
|
|
3117
|
+
});
|
|
3118
|
+
__mfReactInternals.A = __mfReactDispatcher;
|
|
3119
|
+
}`;
|
|
3120
|
+
function writeLoadShareModule(pkg, shareItem, command, options, exportConditions, importFalseExportUsage) {
|
|
3547
3121
|
const { loadShareCacheMap, coalescableLoadShares } = getSharedVirtualModuleState(options);
|
|
3548
3122
|
const edges = createLocalPayloadEdges();
|
|
3549
3123
|
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
|
|
3550
3124
|
let importLine = getRuntimeModuleCacheBootstrapCode(exportConditions);
|
|
3551
3125
|
const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
|
|
3552
|
-
const cacheOwner = JSON.stringify(
|
|
3553
|
-
const runtimeInitOwnerImportId =
|
|
3554
|
-
const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ?
|
|
3126
|
+
const cacheOwner = JSON.stringify(options.name);
|
|
3127
|
+
const runtimeInitOwnerImportId = getRuntimeInitStatusImportId(options);
|
|
3128
|
+
const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ? options.name : void 0;
|
|
3555
3129
|
if (shareItem.shareConfig.import === false) {
|
|
3556
3130
|
const detectedNamedExports = getPackageNamedExports(pkg, exportConditions);
|
|
3557
3131
|
const namedExports = selectImportFalseNamedExports(detectedNamedExports, importFalseExportUsage);
|
|
3558
3132
|
let exportLine;
|
|
3559
3133
|
if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer);
|
|
3560
3134
|
else {
|
|
3561
|
-
const { warnedMissingImportFalse } = getSharedVirtualModuleState(
|
|
3135
|
+
const { warnedMissingImportFalse } = getSharedVirtualModuleState(options);
|
|
3562
3136
|
if (detectedNamedExports === void 0 && !shareItem.shareConfig.suppressMissingImportWarning && !warnedMissingImportFalse.has(pkg)) {
|
|
3563
3137
|
warnedMissingImportFalse.add(pkg);
|
|
3564
3138
|
mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
|
|
@@ -3584,20 +3158,22 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3584
3158
|
const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
|
|
3585
3159
|
const detectedNamedExports = getSharedNamedExports(pkg, shareItem, exportConditions);
|
|
3586
3160
|
const namedExports = detectedNamedExports ?? [];
|
|
3587
|
-
const mutableExports = new Set(isLocalOnlyContainer(
|
|
3161
|
+
const mutableExports = new Set(isLocalOnlyContainer(options) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
|
|
3588
3162
|
const copiedNamedExports = namedExports.filter((name) => !mutableExports.has(name));
|
|
3589
3163
|
const liveNamedExports = namedExports.filter((name) => mutableExports.has(name));
|
|
3590
3164
|
const liveNamedExportLine = edges.reExportNames(liveNamedExports, sharedImportSource);
|
|
3591
3165
|
const hasCompleteExportCoverage = detectedNamedExports !== void 0;
|
|
3592
|
-
const
|
|
3593
|
-
const
|
|
3594
|
-
const
|
|
3595
|
-
const
|
|
3596
|
-
const
|
|
3597
|
-
const
|
|
3166
|
+
const isSingleton = shareItem.shareConfig.singleton === true;
|
|
3167
|
+
const isWorkspaceSingleton = isWorkspacePackage && isSingleton;
|
|
3168
|
+
const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(options) && isSingleton || command === "build" && isRemoteContainer(options) && !isSharedSingletonConsumedByPeer(pkg, options, true));
|
|
3169
|
+
const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(options) && isSingleton;
|
|
3170
|
+
const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, options);
|
|
3171
|
+
const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(options) && isSingleton && options.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
|
|
3172
|
+
const usesDeferredEntryInjectedSingletonFallback = usesEntryInjectedRemoteFallback && !isReactCoreShare(pkg) && (pkg === "react-dom/client" || shareItem.shareConfig.eager !== true && !isSharedSingletonConsumedByPeer(pkg, options, true));
|
|
3598
3173
|
const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
|
|
3599
3174
|
const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
|
|
3600
|
-
const
|
|
3175
|
+
const rebindsSharedExports = isSingleton || options.shareStrategy === "version-first";
|
|
3176
|
+
const reactMixedModeGuard = pkg === "react" && isSingleton ? REACT_MIXED_MODE_GUARD : "";
|
|
3601
3177
|
let exportLine;
|
|
3602
3178
|
let initBlock = "";
|
|
3603
3179
|
if (usesDeferredTreeShakingFallback) {
|
|
@@ -3622,7 +3198,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3622
3198
|
${edges.reExportAll(coherentLocalSource)}`;
|
|
3623
3199
|
initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
3624
3200
|
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
|
|
3625
|
-
} else if (namedExports.length > 0 &&
|
|
3201
|
+
} else if (namedExports.length > 0 && rebindsSharedExports) {
|
|
3626
3202
|
const namedExportVars = copiedNamedExports.map((_name, i) => `__mf_${i}`);
|
|
3627
3203
|
exportLine = `${["let __mfDefaultExport;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ")}
|
|
3628
3204
|
const __mfApplySharedExports = (mod) => {
|
|
@@ -3661,7 +3237,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3661
3237
|
${liveNamedExportLine}`;
|
|
3662
3238
|
initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
3663
3239
|
__mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
|
|
3664
|
-
} else if (
|
|
3240
|
+
} else if (rebindsSharedExports) {
|
|
3665
3241
|
exportLine = `let __mfDefaultExport;
|
|
3666
3242
|
const __mfApplySharedDefaultExport = (mod) => {
|
|
3667
3243
|
${reactMixedModeGuard}
|
|
@@ -3681,7 +3257,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3681
3257
|
const staticLocalShareSource = detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource;
|
|
3682
3258
|
const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? !servesRemoteSingletonFallback && usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? edges.importNamespace(lazyLocalFallbackSource) : "" : edges.importNamespace(staticLocalShareSource);
|
|
3683
3259
|
const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
3684
|
-
const cacheHelpers = recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares) ? getSharedCacheHelpersImportCode(
|
|
3260
|
+
const cacheHelpers = recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares) ? getSharedCacheHelpersImportCode(options) : sharedCacheHelperCode;
|
|
3685
3261
|
const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback || usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? `
|
|
3686
3262
|
${usesDeferredEntryInjectedSingletonFallback ? "" : prebuildImportLine}
|
|
3687
3263
|
${devDynamicImportLine}
|
|
@@ -3702,14 +3278,430 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
|
|
|
3702
3278
|
}
|
|
3703
3279
|
${exportLine}
|
|
3704
3280
|
`;
|
|
3705
|
-
loadShareCacheMap[pkg].writeSync(moduleBody, true);
|
|
3281
|
+
loadShareCacheMap[pkg].writeSync(moduleBody, true);
|
|
3282
|
+
}
|
|
3283
|
+
//#endregion
|
|
3284
|
+
//#region src/utils/localShareImports.ts
|
|
3285
|
+
/**
|
|
3286
|
+
* The source file of a share whose `import` points at a project file rather than an installed
|
|
3287
|
+
* package, such as an application module shared with its micro frontends. Installed packages
|
|
3288
|
+
* describe their dependencies in `package.json`, so a path import of an installed package (a shim)
|
|
3289
|
+
* is not local. Undefined when the file cannot be found.
|
|
3290
|
+
*/
|
|
3291
|
+
function getLocalShareSourceFile(pkg, shareItem) {
|
|
3292
|
+
const importSource = shareItem?.shareConfig?.import;
|
|
3293
|
+
if (typeof importSource !== "string") return void 0;
|
|
3294
|
+
if (!importSource.startsWith(".") && !path$1.isAbsolute(importSource)) return void 0;
|
|
3295
|
+
if (getInstalledPackageJson(getPackageName(pkg)) !== void 0) return void 0;
|
|
3296
|
+
return resolveConfiguredImportPath(importSource);
|
|
3297
|
+
}
|
|
3298
|
+
const specifiersByFile = /* @__PURE__ */ new Map();
|
|
3299
|
+
/** Specifiers a file evaluates (static, not type-only), cached until the file changes; empty when it cannot be read. */
|
|
3300
|
+
function readStaticImportSpecifiers(file) {
|
|
3301
|
+
try {
|
|
3302
|
+
const { mtimeMs } = statSync(file);
|
|
3303
|
+
const cached = specifiersByFile.get(file);
|
|
3304
|
+
if (cached && cached.mtimeMs === mtimeMs) return cached.specifiers;
|
|
3305
|
+
const specifiers = findModuleImportDescriptors(readFileSync(file, "utf-8")).filter(({ kind, typeOnly }) => kind === "static" && !typeOnly).map(({ source }) => source);
|
|
3306
|
+
specifiersByFile.set(file, {
|
|
3307
|
+
mtimeMs,
|
|
3308
|
+
specifiers
|
|
3309
|
+
});
|
|
3310
|
+
return specifiers;
|
|
3311
|
+
} catch {
|
|
3312
|
+
return [];
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
/**
|
|
3316
|
+
* Keys of the other local shares that `sourceFile` imports at evaluation time, by key (or request)
|
|
3317
|
+
* or by source file, directly or through relative imports of project files that are not shared.
|
|
3318
|
+
* `localShareFiles` maps each local share's key to its source file; `requests` maps a share's
|
|
3319
|
+
* request to its key when they differ.
|
|
3320
|
+
*/
|
|
3321
|
+
function getImportedLocalShares(sourceFile, localShareFiles, requests = /* @__PURE__ */ new Map()) {
|
|
3322
|
+
const keysByFile = new Map(Array.from(localShareFiles, ([key, file]) => [file, key]));
|
|
3323
|
+
const imported = /* @__PURE__ */ new Set();
|
|
3324
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3325
|
+
const visit = (file) => {
|
|
3326
|
+
if (visited.has(file)) return;
|
|
3327
|
+
visited.add(file);
|
|
3328
|
+
for (const specifier of readStaticImportSpecifiers(file)) if (specifier.startsWith(".")) {
|
|
3329
|
+
const resolved = resolveRelativeModule(file, specifier);
|
|
3330
|
+
if (!resolved || resolved.split(path$1.sep).includes("node_modules")) continue;
|
|
3331
|
+
const key = keysByFile.get(resolved);
|
|
3332
|
+
if (key !== void 0) imported.add(key);
|
|
3333
|
+
else visit(resolved);
|
|
3334
|
+
} else {
|
|
3335
|
+
const key = localShareFiles.has(specifier) ? specifier : requests.get(specifier);
|
|
3336
|
+
if (key !== void 0) imported.add(key);
|
|
3337
|
+
}
|
|
3338
|
+
};
|
|
3339
|
+
visit(sourceFile);
|
|
3340
|
+
const self = keysByFile.get(sourceFile);
|
|
3341
|
+
if (self !== void 0) imported.delete(self);
|
|
3342
|
+
return [...imported];
|
|
3343
|
+
}
|
|
3344
|
+
//#endregion
|
|
3345
|
+
//#region src/utils/runtimePluginSpecifier.ts
|
|
3346
|
+
function getRuntimePluginSpecifier(plugin) {
|
|
3347
|
+
return typeof plugin === "string" ? plugin : plugin[0];
|
|
3348
|
+
}
|
|
3349
|
+
/** Drop SSR-only plugins from a client graph; a server graph keeps them all. */
|
|
3350
|
+
function filterRuntimePluginsForTarget(runtimePlugins, ssrOnlySpecifiers, isServer) {
|
|
3351
|
+
if (isServer) return [...runtimePlugins];
|
|
3352
|
+
return runtimePlugins.filter((plugin) => !ssrOnlySpecifiers.has(getRuntimePluginSpecifier(plugin)));
|
|
3353
|
+
}
|
|
3354
|
+
//#endregion
|
|
3355
|
+
//#region src/utils/reactIsland.ts
|
|
3356
|
+
const SOURCE_EXTENSIONS$1 = [
|
|
3357
|
+
".tsx",
|
|
3358
|
+
".jsx",
|
|
3359
|
+
".ts",
|
|
3360
|
+
".js",
|
|
3361
|
+
".mts",
|
|
3362
|
+
".mjs",
|
|
3363
|
+
".cts",
|
|
3364
|
+
".cjs"
|
|
3365
|
+
];
|
|
3366
|
+
function resolveSourceFile(importPath, root) {
|
|
3367
|
+
const cleanImport = stripQueryAndHash(importPath);
|
|
3368
|
+
if (!cleanImport.startsWith(".") && !path$1.isAbsolute(cleanImport)) return;
|
|
3369
|
+
const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
|
|
3370
|
+
return [
|
|
3371
|
+
candidate,
|
|
3372
|
+
...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
|
|
3373
|
+
...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
|
|
3374
|
+
].find((filePath) => {
|
|
3375
|
+
try {
|
|
3376
|
+
return fs$1.statSync(filePath).isFile();
|
|
3377
|
+
} catch {
|
|
3378
|
+
return false;
|
|
3379
|
+
}
|
|
3380
|
+
});
|
|
3381
|
+
}
|
|
3382
|
+
function localDefaultReexport(source) {
|
|
3383
|
+
const match = source.match(/export\s*{\s*(?:default(?:\s+as\s+default)?|[A-Za-z_$][\w$]*\s+as\s+default)\s*}\s*from\s*["']([^"']+)["']/);
|
|
3384
|
+
return match?.[1]?.startsWith(".") ? match[1] : void 0;
|
|
3385
|
+
}
|
|
3386
|
+
function isReactComponentSource(source, filePath = "component.tsx") {
|
|
3387
|
+
if (!(/\bexport\s+default\b/.test(source) || /\bexport\s*{[^}]*\bdefault\b[^}]*}(?:\s*from\s*["'][^"']+["'])?/.test(source))) return false;
|
|
3388
|
+
const extension = path$1.extname(stripQueryAndHash(filePath)).toLowerCase();
|
|
3389
|
+
const canContainJsx = extension === ".tsx" || extension === ".jsx";
|
|
3390
|
+
const hasJsx = /<>|<\s*[A-Za-z][\w.:-]*(?:\s[^<>]*?)?\s*\/?>/.test(source);
|
|
3391
|
+
const importsReact = /\bfrom\s*["']react["']|\brequire\(\s*["']react["']\s*\)/.test(source);
|
|
3392
|
+
const usesReactApi = /\b(?:React\.)?(?:createElement|jsx|jsxs)\s*\(/.test(source);
|
|
3393
|
+
const isClientModule = /^\s*["']use client["']\s*;?/m.test(source);
|
|
3394
|
+
return canContainJsx && hasJsx || importsReact && (hasJsx || usesReactApi || isClientModule);
|
|
3395
|
+
}
|
|
3396
|
+
function isReactComponentFile(filePath, seen = /* @__PURE__ */ new Set()) {
|
|
3397
|
+
const normalizedPath = path$1.resolve(filePath);
|
|
3398
|
+
if (seen.has(normalizedPath)) return false;
|
|
3399
|
+
seen.add(normalizedPath);
|
|
3400
|
+
let source;
|
|
3401
|
+
try {
|
|
3402
|
+
source = fs$1.readFileSync(normalizedPath, "utf8");
|
|
3403
|
+
} catch {
|
|
3404
|
+
return false;
|
|
3405
|
+
}
|
|
3406
|
+
if (isReactComponentSource(source, normalizedPath)) return true;
|
|
3407
|
+
const reexport = localDefaultReexport(source);
|
|
3408
|
+
if (!reexport) return false;
|
|
3409
|
+
const reexportPath = resolveSourceFile(reexport, path$1.dirname(normalizedPath));
|
|
3410
|
+
return reexportPath ? isReactComponentFile(reexportPath, seen) : false;
|
|
3411
|
+
}
|
|
3412
|
+
/**
|
|
3413
|
+
* React is shared by the normal MF runtime when explicitly configured. When it
|
|
3414
|
+
* is local, UI exposes can safely advertise an island capability in addition
|
|
3415
|
+
* to their unchanged default export.
|
|
3416
|
+
*/
|
|
3417
|
+
function getReactIslandExposes(options, root) {
|
|
3418
|
+
if (options.experiments.ssrMode !== "ISLAND") return /* @__PURE__ */ new Set();
|
|
3419
|
+
if (Object.hasOwn(options.shared, "react")) return /* @__PURE__ */ new Set();
|
|
3420
|
+
const islandExposes = /* @__PURE__ */ new Set();
|
|
3421
|
+
for (const [key, expose] of Object.entries(options.exposes)) {
|
|
3422
|
+
const sourceFile = resolveSourceFile(expose.import, root);
|
|
3423
|
+
if (sourceFile && isReactComponentFile(sourceFile)) islandExposes.add(key);
|
|
3424
|
+
}
|
|
3425
|
+
return islandExposes;
|
|
3426
|
+
}
|
|
3427
|
+
function generateReactIslandBrowserDefinition(enabled) {
|
|
3428
|
+
if (!enabled) return "";
|
|
3429
|
+
return `
|
|
3430
|
+
exportModule.__mf_island = {
|
|
3431
|
+
version: 1,
|
|
3432
|
+
renderToHtml() {
|
|
3433
|
+
return Promise.reject(new Error("[Module Federation] renderToHtml is only available in the SSR remote entry"));
|
|
3434
|
+
},
|
|
3435
|
+
hydrate(element, props) {
|
|
3436
|
+
const root = element && element.hasAttribute && element.hasAttribute("data-mf-island-state")
|
|
3437
|
+
? element
|
|
3438
|
+
: element && element.querySelector
|
|
3439
|
+
? element.querySelector("[data-mf-island-state]") || element
|
|
3440
|
+
: element;
|
|
3441
|
+
if (!root) {
|
|
3442
|
+
return Promise.reject(new Error("[Module Federation] Cannot hydrate an island without a root element"));
|
|
3443
|
+
}
|
|
3444
|
+
let serverProps = {};
|
|
3445
|
+
const encodedState = root.getAttribute && root.getAttribute("data-mf-island-state");
|
|
3446
|
+
if (encodedState) {
|
|
3447
|
+
try {
|
|
3448
|
+
serverProps = JSON.parse(decodeURIComponent(encodedState));
|
|
3449
|
+
} catch {
|
|
3450
|
+
serverProps = {};
|
|
3451
|
+
}
|
|
3452
|
+
}
|
|
3453
|
+
const finalProps = Object.assign({}, serverProps, props || {});
|
|
3454
|
+
return Promise.all([import("react"), import("react-dom/client")]).then(([React, ReactDOMClient]) => {
|
|
3455
|
+
if (typeof ReactDOMClient.hydrateRoot !== "function") {
|
|
3456
|
+
throw new Error("[Module Federation] react-dom/client does not provide hydrateRoot");
|
|
3457
|
+
}
|
|
3458
|
+
return ReactDOMClient.hydrateRoot(
|
|
3459
|
+
root,
|
|
3460
|
+
React.createElement(importModule.default, finalProps)
|
|
3461
|
+
);
|
|
3462
|
+
});
|
|
3463
|
+
}
|
|
3464
|
+
}`;
|
|
3465
|
+
}
|
|
3466
|
+
function generateReactIslandSSRDefinition(enabled) {
|
|
3467
|
+
if (!enabled) return "";
|
|
3468
|
+
return `
|
|
3469
|
+
exportModule.__mf_island = {
|
|
3470
|
+
version: 1,
|
|
3471
|
+
async renderToHtml(props) {
|
|
3472
|
+
if (typeof importModule.default !== "function" && typeof importModule.default !== "object") {
|
|
3473
|
+
throw new Error("[Module Federation] A React island expose must have a default component export");
|
|
3474
|
+
}
|
|
3475
|
+
const loadedProps = typeof importModule.load === "function" ? await importModule.load() : {};
|
|
3476
|
+
const finalProps = Object.assign({}, loadedProps || {}, props || {});
|
|
3477
|
+
const [React, ReactDOMServer] = await Promise.all([
|
|
3478
|
+
import("react"),
|
|
3479
|
+
import("react-dom/server")
|
|
3480
|
+
]);
|
|
3481
|
+
const body = ReactDOMServer.renderToString(
|
|
3482
|
+
React.createElement(importModule.default, finalProps)
|
|
3483
|
+
);
|
|
3484
|
+
const state = encodeURIComponent(JSON.stringify(finalProps));
|
|
3485
|
+
return '<div data-mf-island-state="' + state + '">' + body + '</div>';
|
|
3486
|
+
},
|
|
3487
|
+
hydrate() {
|
|
3488
|
+
return Promise.reject(new Error("[Module Federation] hydrate is only available in the browser remote entry"));
|
|
3489
|
+
}
|
|
3490
|
+
}`;
|
|
3491
|
+
}
|
|
3492
|
+
const REACT_ISLAND_CLIENT_ID_PREFIX = "virtual:mf-react-island-client:";
|
|
3493
|
+
const REACT_ISLAND_SERVER_ID_PREFIX = "virtual:mf-react-island-server:";
|
|
3494
|
+
const RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX = `\0${REACT_ISLAND_CLIENT_ID_PREFIX}`;
|
|
3495
|
+
const RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX = `\0${REACT_ISLAND_SERVER_ID_PREFIX}`;
|
|
3496
|
+
function encodeIslandRemoteId(remoteId) {
|
|
3497
|
+
return encodeURIComponent(remoteId);
|
|
3498
|
+
}
|
|
3499
|
+
function decodeIslandRemoteId(encodedRemoteId) {
|
|
3500
|
+
return decodeURIComponent(encodedRemoteId);
|
|
3501
|
+
}
|
|
3502
|
+
function getReactIslandImportRemoteId(source) {
|
|
3503
|
+
const queryIndex = source.indexOf("?");
|
|
3504
|
+
if (queryIndex === -1) return;
|
|
3505
|
+
if (!new URLSearchParams(source.slice(queryIndex + 1)).has("mf-island")) return;
|
|
3506
|
+
return source.slice(0, queryIndex);
|
|
3507
|
+
}
|
|
3508
|
+
function getReactIslandServerImportId(remoteId) {
|
|
3509
|
+
return `${REACT_ISLAND_SERVER_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
|
|
3510
|
+
}
|
|
3511
|
+
function getReactIslandClientImportId(remoteId) {
|
|
3512
|
+
return `${REACT_ISLAND_CLIENT_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
|
|
3513
|
+
}
|
|
3514
|
+
function resolveReactIslandConsumerId(id) {
|
|
3515
|
+
if (id.startsWith("virtual:mf-react-island-server:")) return `\0${id}`;
|
|
3516
|
+
if (id.startsWith("virtual:mf-react-island-client:")) return `\0${id}`;
|
|
3517
|
+
}
|
|
3518
|
+
function remoteIdFromResolvedIslandId(id, prefix) {
|
|
3519
|
+
if (!id.startsWith(prefix)) return;
|
|
3520
|
+
return decodeIslandRemoteId(id.slice(prefix.length));
|
|
3521
|
+
}
|
|
3522
|
+
/** Generates the server half of the opt-in `?mf-island` consumer component. */
|
|
3523
|
+
function generateReactIslandConsumerServer(remoteId) {
|
|
3524
|
+
const source = JSON.stringify(remoteId);
|
|
3525
|
+
return `import * as React from "react";
|
|
3526
|
+
import IslandClient from ${JSON.stringify(getReactIslandClientImportId(remoteId))};
|
|
3527
|
+
|
|
3528
|
+
const islandModulePromise = import(${source});
|
|
3529
|
+
|
|
3530
|
+
async function loadIslandModule() {
|
|
3531
|
+
const namespace = await islandModulePromise;
|
|
3532
|
+
const pending = namespace && namespace.__mf_remote_pending;
|
|
3533
|
+
if (pending && typeof pending.then === "function") return pending;
|
|
3534
|
+
return namespace && namespace.__moduleExports || namespace;
|
|
3535
|
+
}
|
|
3536
|
+
|
|
3537
|
+
export default async function ModuleFederationIsland(props) {
|
|
3538
|
+
const remoteModule = await loadIslandModule();
|
|
3539
|
+
const shell = remoteModule && remoteModule.__mf_island;
|
|
3540
|
+
if (!shell || typeof shell.renderToHtml !== "function") {
|
|
3541
|
+
throw new Error(${JSON.stringify(`[Module Federation] ${remoteId} does not expose an SSR island capability`)});
|
|
3542
|
+
}
|
|
3543
|
+
const html = await shell.renderToHtml(props);
|
|
3544
|
+
return React.createElement(IslandClient, { html, islandProps: props });
|
|
3545
|
+
}`;
|
|
3546
|
+
}
|
|
3547
|
+
/** Generates the client boundary which hydrates with the remote-owned React. */
|
|
3548
|
+
function generateReactIslandConsumerClient(remoteId) {
|
|
3549
|
+
return `"use client";
|
|
3550
|
+
|
|
3551
|
+
import * as React from "react";
|
|
3552
|
+
|
|
3553
|
+
const islandModulePromise = import(${JSON.stringify(remoteId)});
|
|
3554
|
+
|
|
3555
|
+
async function loadIslandModule() {
|
|
3556
|
+
const namespace = await islandModulePromise;
|
|
3557
|
+
const pending = namespace && namespace.__mf_remote_pending;
|
|
3558
|
+
if (pending && typeof pending.then === "function") return pending;
|
|
3559
|
+
return namespace && namespace.__moduleExports || namespace;
|
|
3560
|
+
}
|
|
3561
|
+
|
|
3562
|
+
export default function ModuleFederationIslandClient({ html, islandProps }) {
|
|
3563
|
+
const ref = React.useRef(null);
|
|
3564
|
+
|
|
3565
|
+
React.useEffect(() => {
|
|
3566
|
+
const element = ref.current;
|
|
3567
|
+
if (!element) return;
|
|
3568
|
+
void loadIslandModule().then((remoteModule) => {
|
|
3569
|
+
const shell = remoteModule && remoteModule.__mf_island;
|
|
3570
|
+
if (!shell || typeof shell.hydrate !== "function") {
|
|
3571
|
+
throw new Error(${JSON.stringify(`[Module Federation] ${remoteId} does not expose a client island capability`)});
|
|
3572
|
+
}
|
|
3573
|
+
return shell.hydrate(element, islandProps);
|
|
3574
|
+
});
|
|
3575
|
+
}, []);
|
|
3576
|
+
|
|
3577
|
+
return React.createElement("div", {
|
|
3578
|
+
ref,
|
|
3579
|
+
suppressHydrationWarning: true,
|
|
3580
|
+
dangerouslySetInnerHTML: { __html: html },
|
|
3581
|
+
});
|
|
3582
|
+
}`;
|
|
3583
|
+
}
|
|
3584
|
+
function loadReactIslandConsumerModule(id) {
|
|
3585
|
+
const serverRemoteId = remoteIdFromResolvedIslandId(id, RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX);
|
|
3586
|
+
if (serverRemoteId !== void 0) return generateReactIslandConsumerServer(serverRemoteId);
|
|
3587
|
+
const clientRemoteId = remoteIdFromResolvedIslandId(id, RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX);
|
|
3588
|
+
if (clientRemoteId !== void 0) return generateReactIslandConsumerClient(clientRemoteId);
|
|
3589
|
+
}
|
|
3590
|
+
//#endregion
|
|
3591
|
+
//#region src/virtualModules/virtualExposes.ts
|
|
3592
|
+
const EXPOSES_CSS_MAP_PLACEHOLDER = "__MF_EXPOSES_CSS_MAP__";
|
|
3593
|
+
function getExposesCssMapPlaceholder() {
|
|
3594
|
+
return EXPOSES_CSS_MAP_PLACEHOLDER;
|
|
3595
|
+
}
|
|
3596
|
+
function getVirtualExposesId(options) {
|
|
3597
|
+
return `virtual:mf-exposes:${getVirtualModuleScopeKey(options)}`;
|
|
3598
|
+
}
|
|
3599
|
+
function generateExposes(options, remoteDependencyMap = {}, command = "build", reactIslandExposes = /* @__PURE__ */ new Set()) {
|
|
3600
|
+
return `
|
|
3601
|
+
const cssAssetMap = ${JSON.stringify(options.bundleAllCSS ? EXPOSES_CSS_MAP_PLACEHOLDER : {})};
|
|
3602
|
+
const injectedCssHrefs = new Set();
|
|
3603
|
+
const exposeLoadPromises = new Map();
|
|
3604
|
+
|
|
3605
|
+
// Shared and remote readiness is handled by explicit Promise barriers below
|
|
3606
|
+
// and by remoteEntry's pendingShareLoads barrier. Keep this map scoped to a
|
|
3607
|
+
// single expose: unrelated exposes must stay independent and load in parallel.
|
|
3608
|
+
function loadExposedModule(exposeKey, loader) {
|
|
3609
|
+
let load = exposeLoadPromises.get(exposeKey);
|
|
3610
|
+
if (!load) {
|
|
3611
|
+
load = Promise.resolve()
|
|
3612
|
+
.then(loader)
|
|
3613
|
+
.catch((error) => {
|
|
3614
|
+
exposeLoadPromises.delete(exposeKey);
|
|
3615
|
+
throw error;
|
|
3616
|
+
});
|
|
3617
|
+
exposeLoadPromises.set(exposeKey, load);
|
|
3618
|
+
}
|
|
3619
|
+
return load;
|
|
3620
|
+
}
|
|
3621
|
+
|
|
3622
|
+
async function injectCssAssets(exposeKey) {
|
|
3623
|
+
if (typeof document === "undefined") {
|
|
3624
|
+
return;
|
|
3625
|
+
}
|
|
3626
|
+
|
|
3627
|
+
// Replaced at build time with expose -> css asset paths.
|
|
3628
|
+
const cssAssets = cssAssetMap[exposeKey] || [];
|
|
3629
|
+
|
|
3630
|
+
await Promise.all(
|
|
3631
|
+
cssAssets.map((cssAsset) => {
|
|
3632
|
+
const href = new URL(cssAsset, import.meta.url).href;
|
|
3633
|
+
|
|
3634
|
+
// Same expose can be resolved multiple times in one page.
|
|
3635
|
+
if (injectedCssHrefs.has(href)) {
|
|
3636
|
+
return Promise.resolve();
|
|
3637
|
+
}
|
|
3638
|
+
injectedCssHrefs.add(href);
|
|
3639
|
+
|
|
3640
|
+
// Check for any existing stylesheet with the same href, not just
|
|
3641
|
+
// MF-injected ones. This prevents duplicate <link> tags when Vite's
|
|
3642
|
+
// own CSS module injection or MF runtime's createLink has already
|
|
3643
|
+
// created a <link rel="stylesheet"> for the same URL.
|
|
3644
|
+
const existingLink = document.querySelector(
|
|
3645
|
+
\`link[rel="stylesheet"][href="\${href}"]\`
|
|
3646
|
+
);
|
|
3647
|
+
if (existingLink) {
|
|
3648
|
+
return Promise.resolve();
|
|
3649
|
+
}
|
|
3650
|
+
|
|
3651
|
+
return new Promise((resolve, reject) => {
|
|
3652
|
+
const link = document.createElement("link");
|
|
3653
|
+
link.rel = "stylesheet";
|
|
3654
|
+
link.href = href;
|
|
3655
|
+
link.onload = () => resolve();
|
|
3656
|
+
link.onerror = () => {
|
|
3657
|
+
injectedCssHrefs.delete(href);
|
|
3658
|
+
link.remove();
|
|
3659
|
+
reject(new Error(\`[Module Federation] Failed to load CSS asset: \${href}\`));
|
|
3660
|
+
};
|
|
3661
|
+
document.head.appendChild(link);
|
|
3662
|
+
});
|
|
3663
|
+
})
|
|
3664
|
+
);
|
|
3665
|
+
}
|
|
3666
|
+
|
|
3667
|
+
export default {
|
|
3668
|
+
${Object.keys(options.exposes).map((key) => {
|
|
3669
|
+
const remoteDependencyPreloads = (remoteDependencyMap[key] ?? []).map((remoteId) => {
|
|
3670
|
+
const virtualRemote = getRemoteVirtualModule(remoteId, command, false, "unified", options);
|
|
3671
|
+
return `import(${JSON.stringify(virtualRemote.getImportId())})
|
|
3672
|
+
.then((mod) => mod.__mf_remote_pending)`;
|
|
3673
|
+
}).join(",");
|
|
3674
|
+
return `
|
|
3675
|
+
${JSON.stringify(key)}: async () => {
|
|
3676
|
+
await injectCssAssets(${JSON.stringify(key)})
|
|
3677
|
+
await Promise.all([${remoteDependencyPreloads}])
|
|
3678
|
+
const importModule = await loadExposedModule(
|
|
3679
|
+
${JSON.stringify(key)},
|
|
3680
|
+
() => import(${JSON.stringify(options.exposes[key].import)})
|
|
3681
|
+
)
|
|
3682
|
+
const dependencyPending = importModule && importModule.__mf_remote_dependency_pending;
|
|
3683
|
+
if (dependencyPending && typeof dependencyPending.then === "function") {
|
|
3684
|
+
await dependencyPending;
|
|
3685
|
+
}
|
|
3686
|
+
const exportModule = {}
|
|
3687
|
+
Object.assign(exportModule, importModule)
|
|
3688
|
+
${generateReactIslandBrowserDefinition(reactIslandExposes.has(key))}
|
|
3689
|
+
Object.defineProperty(exportModule, "__esModule", {
|
|
3690
|
+
value: true,
|
|
3691
|
+
enumerable: false
|
|
3692
|
+
})
|
|
3693
|
+
return exportModule
|
|
3694
|
+
}
|
|
3695
|
+
`;
|
|
3696
|
+
}).join(",")}
|
|
3697
|
+
}
|
|
3698
|
+
`;
|
|
3706
3699
|
}
|
|
3707
3700
|
//#endregion
|
|
3708
3701
|
//#region src/virtualModules/virtualRemoteEntry.ts
|
|
3709
|
-
let usedShares = /* @__PURE__ */ new Set();
|
|
3710
3702
|
const usedSharesByOptions = /* @__PURE__ */ new WeakMap();
|
|
3711
3703
|
const materializedSharesByOptions = /* @__PURE__ */ new WeakMap();
|
|
3712
|
-
function
|
|
3704
|
+
function getUsedShares(options) {
|
|
3713
3705
|
let scoped = usedSharesByOptions.get(options);
|
|
3714
3706
|
if (!scoped) {
|
|
3715
3707
|
scoped = /* @__PURE__ */ new Set();
|
|
@@ -3717,25 +3709,17 @@ function getScopedUsedShares(options) {
|
|
|
3717
3709
|
}
|
|
3718
3710
|
return scoped;
|
|
3719
3711
|
}
|
|
3720
|
-
function getUsedShares(options) {
|
|
3721
|
-
if (options) return getScopedUsedShares(options);
|
|
3722
|
-
return usedShares;
|
|
3723
|
-
}
|
|
3724
3712
|
function addUsedShares(pkg, options) {
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
if (
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
scoped = /* @__PURE__ */ new Set();
|
|
3731
|
-
materializedSharesByOptions.set(options, scoped);
|
|
3732
|
-
}
|
|
3733
|
-
scoped.add(pkg);
|
|
3713
|
+
getUsedShares(options).add(pkg);
|
|
3714
|
+
let scoped = materializedSharesByOptions.get(options);
|
|
3715
|
+
if (!scoped) {
|
|
3716
|
+
scoped = /* @__PURE__ */ new Set();
|
|
3717
|
+
materializedSharesByOptions.set(options, scoped);
|
|
3734
3718
|
}
|
|
3719
|
+
scoped.add(pkg);
|
|
3735
3720
|
}
|
|
3736
3721
|
function addConfiguredShare(pkg, options) {
|
|
3737
|
-
|
|
3738
|
-
if (options) getScopedUsedShares(options).add(pkg);
|
|
3722
|
+
getUsedShares(options).add(pkg);
|
|
3739
3723
|
}
|
|
3740
3724
|
const LOCAL_SHARED_IMPORT_MAP_ID = "virtual:mf-localSharedImportMap";
|
|
3741
3725
|
const LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER = "__MF_LAZY_CONSUME_ONLY_SHARES__";
|
|
@@ -3757,15 +3741,13 @@ function getLocalSharedImportMapPath(options) {
|
|
|
3757
3741
|
function getResolvedLocalSharedImportMapId(options) {
|
|
3758
3742
|
return `\0${getLocalSharedImportMapPath(options)}`;
|
|
3759
3743
|
}
|
|
3760
|
-
let invalidateLocalSharedImportMap;
|
|
3761
3744
|
const localSharedImportMapInvalidators = /* @__PURE__ */ new WeakMap();
|
|
3762
3745
|
function setLocalSharedImportMapInvalidator(invalidator, options) {
|
|
3763
|
-
if (
|
|
3764
|
-
else if (invalidator) localSharedImportMapInvalidators.set(options, invalidator);
|
|
3746
|
+
if (invalidator) localSharedImportMapInvalidators.set(options, invalidator);
|
|
3765
3747
|
else localSharedImportMapInvalidators.delete(options);
|
|
3766
3748
|
}
|
|
3767
3749
|
function writeLocalSharedImportMap(options) {
|
|
3768
|
-
|
|
3750
|
+
localSharedImportMapInvalidators.get(options)?.();
|
|
3769
3751
|
}
|
|
3770
3752
|
function shouldUseDirectReactImport() {
|
|
3771
3753
|
const isVinext = hasPackageDependency("vinext");
|
|
@@ -3786,15 +3768,15 @@ function getDirectSharedCacheSeedImportPath(pkg, shareItem) {
|
|
|
3786
3768
|
function generateLocalSharedImportMap(options) {
|
|
3787
3769
|
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
3788
3770
|
const useDirectReactImport = shouldUseDirectReactImport();
|
|
3789
|
-
const orderedShares = getOrderedUsedShares(
|
|
3790
|
-
const sharesToMaterialize = new Set(getMaterializedShares(
|
|
3771
|
+
const orderedShares = getOrderedUsedShares(resolvedOptions);
|
|
3772
|
+
const sharesToMaterialize = new Set(getMaterializedShares(resolvedOptions));
|
|
3791
3773
|
const hasConsumeOnlyShare = orderedShares.some((pkg) => getNormalizeShareItem(pkg, resolvedOptions)?.shareConfig.import === false);
|
|
3792
3774
|
return `
|
|
3793
3775
|
import {loadShare} from "@module-federation/runtime";
|
|
3794
3776
|
${orderedShares.map((pkg, index) => {
|
|
3795
3777
|
const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
|
|
3796
3778
|
if (!shareItem || !shareItem.shareConfig.eager || shareItem.shareConfig.import === false) return "";
|
|
3797
|
-
return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem,
|
|
3779
|
+
return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, resolvedOptions))};`;
|
|
3798
3780
|
}).filter(Boolean).join("\n")}
|
|
3799
3781
|
${normalizeRuntimeShareCode}
|
|
3800
3782
|
const __mfGetCachedReactFamily = (keys, reactKeys, localVersion, requiredExport) => {
|
|
@@ -3867,7 +3849,7 @@ function generateLocalSharedImportMap(options) {
|
|
|
3867
3849
|
return `
|
|
3868
3850
|
${toSafeJsLiteral(pkg)}: async () => {
|
|
3869
3851
|
${shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
|
|
3870
|
-
return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem,
|
|
3852
|
+
return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, resolvedOptions))});
|
|
3871
3853
|
return pkg;`}
|
|
3872
3854
|
}
|
|
3873
3855
|
`;
|
|
@@ -3891,11 +3873,11 @@ function generateLocalSharedImportMap(options) {
|
|
|
3891
3873
|
const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
|
|
3892
3874
|
if (shareItem.shareConfig.import === false && !treeShakingConfig) return `
|
|
3893
3875
|
${toSafeJsLiteral(key)}: __mfConsumeOnly(${toSafeJsLiteral(key)}, ${toSafeJsLiteral(shareItem.version)}, ${toSafeJsLiteral(shareItem.scope)}, ${sharesToMaterialize.has(key)}, {singleton: ${shareItem.shareConfig.singleton}, requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)}, strictVersion: ${shareItem.shareConfig.strictVersion}, eager: ${Boolean(shareItem.shareConfig.eager)}, ${shareItem.shareConfig.request !== void 0 ? `request: ${toSafeJsLiteral(shareItem.shareConfig.request)},` : ""} ${shareItem.shareConfig.shareKey !== void 0 ? `shareKey: ${toSafeJsLiteral(shareItem.shareConfig.shareKey)},` : ""}})`;
|
|
3894
|
-
const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name,
|
|
3876
|
+
const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, resolvedOptions) : void 0;
|
|
3895
3877
|
const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
|
|
3896
3878
|
const treeShakingUsedExports = resolvedOptions.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
|
|
3897
3879
|
const disableRuntimeInference = treeShakingConfig?.mode === "runtime-infer" && resolvedOptions.injectTreeShakingUsedExports === false;
|
|
3898
|
-
const treeShakingProviderImportId = treeShakingConfig && !disableRuntimeInference && hasTreeShakingSharedProvider(key, shareItem,
|
|
3880
|
+
const treeShakingProviderImportId = treeShakingConfig && !disableRuntimeInference && hasTreeShakingSharedProvider(key, shareItem, resolvedOptions) ? getTreeShakingSharedProviderImportId(key, resolvedOptions) : void 0;
|
|
3899
3881
|
const treeShakingStatus = treeShakingUsage?.kind === "full" || disableRuntimeInference || treeShakingConfig?.mode === "runtime-infer" && !treeShakingProviderImportId && shareItem.shareConfig.import !== false ? 0 : 1;
|
|
3900
3882
|
return `
|
|
3901
3883
|
${toSafeJsLiteral(key)}: {
|
|
@@ -3980,7 +3962,7 @@ function generateLocalSharedImportMap(options) {
|
|
|
3980
3962
|
`;
|
|
3981
3963
|
}).filter((x) => x !== null).join(",")}
|
|
3982
3964
|
}
|
|
3983
|
-
const usedRemotes = [${Object.keys(getUsedRemotesMap(
|
|
3965
|
+
const usedRemotes = [${Object.keys(getUsedRemotesMap(resolvedOptions)).map((key) => {
|
|
3984
3966
|
const remote = resolvedOptions.remotes[key];
|
|
3985
3967
|
if (!remote) return null;
|
|
3986
3968
|
return `
|
|
@@ -4013,44 +3995,47 @@ function expandSharedPrefixKey(prefixKey, used) {
|
|
|
4013
3995
|
return [...expanded];
|
|
4014
3996
|
}
|
|
4015
3997
|
function getOrderedUsedShares(options) {
|
|
4016
|
-
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
4017
3998
|
const used = getUsedShares(options);
|
|
4018
3999
|
const shares = /* @__PURE__ */ new Set();
|
|
4019
4000
|
const addShare = (pkg) => {
|
|
4020
|
-
const shareItem = getNormalizeShareItem(pkg,
|
|
4001
|
+
const shareItem = getNormalizeShareItem(pkg, options);
|
|
4021
4002
|
shares.add(shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg);
|
|
4022
4003
|
};
|
|
4023
4004
|
used.forEach(addShare);
|
|
4024
|
-
Object.keys(
|
|
4025
|
-
const share =
|
|
4005
|
+
Object.keys(options.shared ?? {}).forEach((pkg) => {
|
|
4006
|
+
const share = options.shared?.[pkg];
|
|
4026
4007
|
if (share && !getSharedRequest(pkg, share).endsWith("/")) addShare(pkg);
|
|
4027
4008
|
});
|
|
4028
|
-
for (const [pkg, share] of Object.entries(
|
|
4009
|
+
for (const [pkg, share] of Object.entries(options.shared ?? {})) if (share.shareConfig?.eager && getSharedRequest(pkg, share).endsWith("/")) for (const concrete of expandSharedPrefixKey(getSharedRequest(pkg, share), used)) addShare(concrete);
|
|
4029
4010
|
return orderSharedDependenciesFirst(Array.from(shares).sort((a, b) => {
|
|
4030
4011
|
const priority = (pkg) => pkg === "react" ? 0 : pkg === "react-dom" ? 1 : pkg.startsWith("react/") ? 2 : 3;
|
|
4031
4012
|
return priority(a) - priority(b) || a.localeCompare(b);
|
|
4032
|
-
}));
|
|
4013
|
+
}), options);
|
|
4033
4014
|
}
|
|
4034
4015
|
function getMaterializedShares(options) {
|
|
4035
|
-
const
|
|
4036
|
-
const
|
|
4037
|
-
|
|
4038
|
-
const usedForEager = options ? usedSharesByOptions.get(options) ?? [] : usedShares;
|
|
4039
|
-
for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) {
|
|
4016
|
+
const shares = new Set(materializedSharesByOptions.get(options));
|
|
4017
|
+
const usedForEager = usedSharesByOptions.get(options) ?? [];
|
|
4018
|
+
for (const [pkg, share] of Object.entries(options.shared ?? {})) {
|
|
4040
4019
|
if (!share.shareConfig?.eager) continue;
|
|
4041
4020
|
const request = getSharedRequest(pkg, share);
|
|
4042
4021
|
if (request.endsWith("/")) for (const concrete of expandSharedPrefixKey(request, usedForEager)) shares.add(concrete);
|
|
4043
4022
|
else shares.add(pkg);
|
|
4044
4023
|
}
|
|
4045
4024
|
const configured = /* @__PURE__ */ new Map();
|
|
4046
|
-
|
|
4025
|
+
const orderedUsed = getOrderedUsedShares(options);
|
|
4026
|
+
for (const pkg of orderedUsed) {
|
|
4047
4027
|
const packageName = getPackageName(pkg);
|
|
4048
4028
|
if (!configured.has(packageName) || pkg === packageName) configured.set(packageName, pkg);
|
|
4049
4029
|
}
|
|
4030
|
+
const localImports = getLocalShareImports(orderedUsed, options);
|
|
4050
4031
|
const pending = [...shares];
|
|
4051
4032
|
while (pending.length) {
|
|
4052
4033
|
const pkg = pending.pop();
|
|
4053
|
-
const share = getNormalizeShareItem(pkg,
|
|
4034
|
+
const share = getNormalizeShareItem(pkg, options);
|
|
4035
|
+
for (const imported of localImports.get(pkg) ?? []) if (!shares.has(imported) && getNormalizeShareItem(imported, options)?.scope === share?.scope) {
|
|
4036
|
+
shares.add(imported);
|
|
4037
|
+
pending.push(imported);
|
|
4038
|
+
}
|
|
4054
4039
|
const packageName = getPackageName(pkg);
|
|
4055
4040
|
const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
|
|
4056
4041
|
const dependencies = {
|
|
@@ -4061,7 +4046,7 @@ function getMaterializedShares(options) {
|
|
|
4061
4046
|
};
|
|
4062
4047
|
for (const dependency of Object.keys(dependencies)) {
|
|
4063
4048
|
const sharedDependency = configured.get(dependency);
|
|
4064
|
-
const dependencyShare = sharedDependency ? getNormalizeShareItem(sharedDependency,
|
|
4049
|
+
const dependencyShare = sharedDependency ? getNormalizeShareItem(sharedDependency, options) : void 0;
|
|
4065
4050
|
if (sharedDependency && !shares.has(sharedDependency) && dependencyShare?.scope === share?.scope) {
|
|
4066
4051
|
shares.add(sharedDependency);
|
|
4067
4052
|
pending.push(sharedDependency);
|
|
@@ -4073,12 +4058,41 @@ function getMaterializedShares(options) {
|
|
|
4073
4058
|
return priority(a) - priority(b) || a.localeCompare(b);
|
|
4074
4059
|
});
|
|
4075
4060
|
return orderSharedDependenciesFirst([...new Set(sorted.map((pkg) => {
|
|
4076
|
-
const shareItem = getNormalizeShareItem(pkg,
|
|
4061
|
+
const shareItem = getNormalizeShareItem(pkg, options);
|
|
4077
4062
|
return shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg;
|
|
4078
|
-
}))]);
|
|
4063
|
+
}))], options);
|
|
4064
|
+
}
|
|
4065
|
+
/**
|
|
4066
|
+
* The other local shares each local share (one whose `import` is a project file) imports at module
|
|
4067
|
+
* evaluation, found through the static imports of its source and of the unshared project files it
|
|
4068
|
+
* imports, keyed by share. Only local shares have an entry.
|
|
4069
|
+
*/
|
|
4070
|
+
function getLocalShareImports(shares, options) {
|
|
4071
|
+
const localShareFiles = /* @__PURE__ */ new Map();
|
|
4072
|
+
const requests = /* @__PURE__ */ new Map();
|
|
4073
|
+
for (const pkg of shares) {
|
|
4074
|
+
const shareItem = getNormalizeShareItem(pkg, options);
|
|
4075
|
+
const sourceFile = getLocalShareSourceFile(pkg, shareItem);
|
|
4076
|
+
if (sourceFile === void 0) continue;
|
|
4077
|
+
localShareFiles.set(pkg, sourceFile);
|
|
4078
|
+
const request = getSharedRequest(pkg, shareItem);
|
|
4079
|
+
if (request !== pkg) requests.set(request, pkg);
|
|
4080
|
+
}
|
|
4081
|
+
return new Map(Array.from(localShareFiles, ([pkg, sourceFile]) => [pkg, getImportedLocalShares(sourceFile, localShareFiles, requests)]));
|
|
4082
|
+
}
|
|
4083
|
+
/**
|
|
4084
|
+
* Shares that must be materialized before each local share, keyed by share. A project file has no
|
|
4085
|
+
* package.json to read dependencies from and may import any shared package, directly or through
|
|
4086
|
+
* other project files, so every installed-package share comes first, followed by the local shares
|
|
4087
|
+
* its source imports (see #1507).
|
|
4088
|
+
*/
|
|
4089
|
+
function getLocalSharePrerequisites(shares, options) {
|
|
4090
|
+
const localImports = getLocalShareImports(shares, options);
|
|
4091
|
+
const packageShares = shares.filter((pkg) => !localImports.has(pkg));
|
|
4092
|
+
return new Map(Array.from(localImports, ([pkg, imports]) => [pkg, [...packageShares, ...imports]]));
|
|
4079
4093
|
}
|
|
4080
4094
|
/** Shared keys a share's package.json depends on (roots stand in for their subpaths, subpaths for their root), keyed by share. */
|
|
4081
|
-
function getSharePrerequisites(ordered) {
|
|
4095
|
+
function getSharePrerequisites(ordered, options) {
|
|
4082
4096
|
const roots = /* @__PURE__ */ new Map();
|
|
4083
4097
|
const subpaths = /* @__PURE__ */ new Map();
|
|
4084
4098
|
for (const pkg of ordered) {
|
|
@@ -4087,7 +4101,13 @@ function getSharePrerequisites(ordered) {
|
|
|
4087
4101
|
else subpaths.set(packageName, [...subpaths.get(packageName) ?? [], pkg]);
|
|
4088
4102
|
}
|
|
4089
4103
|
const prerequisitesByShare = /* @__PURE__ */ new Map();
|
|
4104
|
+
const localPrerequisites = getLocalSharePrerequisites(ordered, options);
|
|
4090
4105
|
for (const pkg of ordered) {
|
|
4106
|
+
const local = localPrerequisites.get(pkg);
|
|
4107
|
+
if (local) {
|
|
4108
|
+
prerequisitesByShare.set(pkg, local);
|
|
4109
|
+
continue;
|
|
4110
|
+
}
|
|
4091
4111
|
const packageName = getPackageName(pkg);
|
|
4092
4112
|
const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
|
|
4093
4113
|
const dependencies = {
|
|
@@ -4107,14 +4127,15 @@ function getSharePrerequisites(ordered) {
|
|
|
4107
4127
|
}
|
|
4108
4128
|
function getShareBatches(options, materializedOnly = true) {
|
|
4109
4129
|
const ordered = materializedOnly ? getMaterializedShares(options) : getOrderedUsedShares(options);
|
|
4110
|
-
const prerequisitesByShare = getSharePrerequisites(ordered);
|
|
4130
|
+
const prerequisitesByShare = getSharePrerequisites(ordered, options);
|
|
4111
4131
|
const levels = /* @__PURE__ */ new Map();
|
|
4112
4132
|
for (const pkg of ordered) levels.set(pkg, (prerequisitesByShare.get(pkg) ?? []).reduce((level, dependency) => Math.max(level, (levels.get(dependency) ?? 0) + 1), 0));
|
|
4113
4133
|
const batches = [];
|
|
4114
4134
|
for (const pkg of ordered) (batches[levels.get(pkg) ?? 0] ??= []).push(pkg);
|
|
4115
4135
|
return batches.filter(Boolean);
|
|
4116
4136
|
}
|
|
4117
|
-
function orderSharedDependenciesFirst(sharedPackages) {
|
|
4137
|
+
function orderSharedDependenciesFirst(sharedPackages, options) {
|
|
4138
|
+
const localPrerequisites = getLocalSharePrerequisites(sharedPackages, options);
|
|
4118
4139
|
const sharedKeyByPackageName = /* @__PURE__ */ new Map();
|
|
4119
4140
|
const subpathKeysByPackageName = /* @__PURE__ */ new Map();
|
|
4120
4141
|
sharedPackages.forEach((pkg) => {
|
|
@@ -4133,6 +4154,14 @@ function orderSharedDependenciesFirst(sharedPackages) {
|
|
|
4133
4154
|
if (visited.has(pkg)) return;
|
|
4134
4155
|
if (visiting.has(pkg)) return;
|
|
4135
4156
|
visiting.add(pkg);
|
|
4157
|
+
const local = localPrerequisites.get(pkg);
|
|
4158
|
+
if (local) {
|
|
4159
|
+
local.forEach(visit);
|
|
4160
|
+
visiting.delete(pkg);
|
|
4161
|
+
visited.add(pkg);
|
|
4162
|
+
ordered.push(pkg);
|
|
4163
|
+
return;
|
|
4164
|
+
}
|
|
4136
4165
|
const packageName = getPackageName(pkg);
|
|
4137
4166
|
const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
|
|
4138
4167
|
const dependencies = {
|
|
@@ -4413,7 +4442,7 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
|
|
|
4413
4442
|
const seedBatches = getShareBatches(options, false);
|
|
4414
4443
|
const seedOrder = seedBatches.flat();
|
|
4415
4444
|
const seedIndex = new Map(seedOrder.map((pkg, index) => [pkg, index]));
|
|
4416
|
-
const seedPrerequisites = Object.fromEntries(Array.from(getSharePrerequisites(seedOrder)).filter(([, prerequisites]) => prerequisites.length > 0).map(([pkg, prerequisites]) => [seedIndex.get(pkg), prerequisites.map((prerequisite) => seedIndex.get(prerequisite))]));
|
|
4445
|
+
const seedPrerequisites = Object.fromEntries(Array.from(getSharePrerequisites(seedOrder, options)).filter(([, prerequisites]) => prerequisites.length > 0).map(([pkg, prerequisites]) => [seedIndex.get(pkg), prerequisites.map((prerequisite) => seedIndex.get(prerequisite))]));
|
|
4417
4446
|
return `
|
|
4418
4447
|
const __mfSeedOrder = ${toSafeJsLiteral(seedOrder)};
|
|
4419
4448
|
const __mfSeedBatches = ${toSafeJsLiteral(seedBatches)};
|
|
@@ -4487,6 +4516,19 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
|
|
|
4487
4516
|
);
|
|
4488
4517
|
return;
|
|
4489
4518
|
}
|
|
4519
|
+
// A Vite container seeds its own copy into the module cache before the Runtime
|
|
4520
|
+
// marks its provider loaded. A non-singleton is cached under its version, so
|
|
4521
|
+
// look the selected provider's copy up under that version, not this share's.
|
|
4522
|
+
if (!share.shareConfig?.singleton && typeof externalProvider.version === 'string') {
|
|
4523
|
+
const externalCached = __mfReadSharedCache(
|
|
4524
|
+
__mfModuleCache.share,
|
|
4525
|
+
__mfGetSharedCacheDescriptor(pkg, false, externalProvider.version, share.scope)
|
|
4526
|
+
);
|
|
4527
|
+
if (externalCached !== undefined) {
|
|
4528
|
+
__mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, externalCached, externalProvider.from);
|
|
4529
|
+
return;
|
|
4530
|
+
}
|
|
4531
|
+
}
|
|
4490
4532
|
// Leave an unloaded webpack provider to the late bridge, which only takes a
|
|
4491
4533
|
// non-singleton of this share's own version; any other version seeds locally.
|
|
4492
4534
|
if (
|
|
@@ -4596,10 +4638,9 @@ function getBrowserImportPath(importPath) {
|
|
|
4596
4638
|
return importPath;
|
|
4597
4639
|
}
|
|
4598
4640
|
function getHostAutoInitSharedSeedItems(options) {
|
|
4599
|
-
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
4600
4641
|
return getMaterializedShares(options).map((pkg) => ({
|
|
4601
4642
|
pkg,
|
|
4602
|
-
shareItem: getShareItemForPreload(pkg,
|
|
4643
|
+
shareItem: getShareItemForPreload(pkg, options)
|
|
4603
4644
|
})).filter(({ shareItem }) => shareItem?.shareConfig?.import === false).sort((a, b) => {
|
|
4604
4645
|
const priority = (pkg) => pkg === "vue" ? 0 : pkg === "pinia" ? 1 : 2;
|
|
4605
4646
|
const aIsLocal = !!getLocalProviderImportPath(a.pkg);
|
|
@@ -4610,7 +4651,7 @@ function getHostAutoInitSharedSeedItems(options) {
|
|
|
4610
4651
|
function generateHostAutoInitSharedCacheSeedCode(command = "build", options) {
|
|
4611
4652
|
if (command === "build") return "";
|
|
4612
4653
|
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
4613
|
-
return getHostAutoInitSharedSeedItems(
|
|
4654
|
+
return getHostAutoInitSharedSeedItems(resolvedOptions).map(({ pkg, shareItem }) => {
|
|
4614
4655
|
if (!shareItem) return null;
|
|
4615
4656
|
return generateSharedCacheSeedItem(pkg, shareItem, getBrowserImportPath(getDirectSharedCacheSeedImportPath(pkg, shareItem)), resolvedOptions);
|
|
4616
4657
|
}).filter((item) => item !== null).join("\n");
|
|
@@ -5796,13 +5837,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
5796
5837
|
*/
|
|
5797
5838
|
const HOST_AUTO_INIT_TAG = "__H_A_I__";
|
|
5798
5839
|
const hostAutoInitStates = /* @__PURE__ */ new WeakMap();
|
|
5799
|
-
const legacyHostAutoInitState = {
|
|
5800
|
-
module: new VirtualModule("hostAutoInit", HOST_AUTO_INIT_TAG),
|
|
5801
|
-
remoteEntryId: REMOTE_ENTRY_ID,
|
|
5802
|
-
command: "build"
|
|
5803
|
-
};
|
|
5804
5840
|
function getHostAutoInitState(options) {
|
|
5805
|
-
if (!options) return legacyHostAutoInitState;
|
|
5806
5841
|
let state = hostAutoInitStates.get(options);
|
|
5807
5842
|
if (!state) {
|
|
5808
5843
|
const ownerKey = getLocalOwnerKey(options);
|
|
@@ -5818,7 +5853,7 @@ function getHostAutoInitState(options) {
|
|
|
5818
5853
|
function generateHostAutoInitCode(remoteEntryImport, _command = "build", options, exportConditions) {
|
|
5819
5854
|
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
5820
5855
|
const shouldPreloadShares = resolvedOptions.shareStrategy !== "loaded-first";
|
|
5821
|
-
const hostInitShareBatches = toSafeJsLiteral(getShareBatches(
|
|
5856
|
+
const hostInitShareBatches = toSafeJsLiteral(getShareBatches(resolvedOptions, false));
|
|
5822
5857
|
const cacheOwner = toSafeJsLiteral(resolvedOptions.name);
|
|
5823
5858
|
const preferLocalVinextReact = hasPackageDependency("vinext") && (!exportConditions?.includes("browser") || exportConditions.includes("worker"));
|
|
5824
5859
|
const hasConfiguredShared = hasShared(resolvedOptions);
|
|
@@ -5862,6 +5897,15 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
|
|
|
5862
5897
|
)
|
|
5863
5898
|
);
|
|
5864
5899
|
const __mfHostInitShareBatches = ${hostInitShareBatches};
|
|
5900
|
+
// The baked batches are generated before the build has seen every import, so a
|
|
5901
|
+
// share first used later in the graph, such as react-dom/client, is missing from
|
|
5902
|
+
// them. Negotiate those after the baked batches, once their package roots have
|
|
5903
|
+
// settled (#1503).
|
|
5904
|
+
{
|
|
5905
|
+
const bakedKeys = new Set(__mfHostInitShareBatches.flat());
|
|
5906
|
+
const lateKeys = Object.keys(usedShared).filter((pkg) => !bakedKeys.has(pkg));
|
|
5907
|
+
if (lateKeys.length) __mfHostInitShareBatches.push(lateKeys);
|
|
5908
|
+
}
|
|
5865
5909
|
${hostInitSharedProviderHelperCode}
|
|
5866
5910
|
for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
|
|
5867
5911
|
await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
|
|
@@ -5876,9 +5920,10 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
|
|
|
5876
5920
|
if (
|
|
5877
5921
|
__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined &&
|
|
5878
5922
|
${_command === "serve" ? `__mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) !== undefined &&
|
|
5879
|
-
!
|
|
5880
|
-
|
|
5881
|
-
(share.shareConfig?.singleton
|
|
5923
|
+
!__mfHasAlternativeSharedVersion(pkg, share)` : `(
|
|
5924
|
+
!__mfHasAlternativeSharedVersion(pkg, share) &&
|
|
5925
|
+
(share.shareConfig?.singleton ||
|
|
5926
|
+
__mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) === ${cacheOwner})
|
|
5882
5927
|
)`}
|
|
5883
5928
|
) return;
|
|
5884
5929
|
// An import:false share has nothing to load until a foreign provider
|
|
@@ -5968,7 +6013,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
|
|
|
5968
6013
|
export { initHost, hostInitPromise };
|
|
5969
6014
|
`;
|
|
5970
6015
|
}
|
|
5971
|
-
function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID, command
|
|
6016
|
+
function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID, command, options, exportConditions) {
|
|
5972
6017
|
const state = getHostAutoInitState(options);
|
|
5973
6018
|
state.remoteEntryId = remoteEntryId;
|
|
5974
6019
|
state.command = command;
|
|
@@ -5996,13 +6041,8 @@ function isOwnedHostAutoInitId(id, options) {
|
|
|
5996
6041
|
* free of wrapper references.
|
|
5997
6042
|
*/
|
|
5998
6043
|
const PENDING_SHARES_TAG = "__P_S__";
|
|
5999
|
-
const legacyPendingSharesState = {
|
|
6000
|
-
module: new VirtualModule("pendingShares", PENDING_SHARES_TAG),
|
|
6001
|
-
command: "build"
|
|
6002
|
-
};
|
|
6003
6044
|
const pendingSharesStates = /* @__PURE__ */ new WeakMap();
|
|
6004
6045
|
function getPendingSharesState(options) {
|
|
6005
|
-
if (!options) return legacyPendingSharesState;
|
|
6006
6046
|
let state = pendingSharesStates.get(options);
|
|
6007
6047
|
if (!state) {
|
|
6008
6048
|
state = {
|
|
@@ -6015,14 +6055,14 @@ function getPendingSharesState(options) {
|
|
|
6015
6055
|
}
|
|
6016
6056
|
function generatePendingSharesCode(command = "build", options) {
|
|
6017
6057
|
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
6018
|
-
const pendingSharePkgs = command === "build" ? getMaterializedShares(
|
|
6058
|
+
const pendingSharePkgs = command === "build" ? getMaterializedShares(resolvedOptions).filter((pkg) => {
|
|
6019
6059
|
const shareItem = getShareItemForPreload(pkg, resolvedOptions);
|
|
6020
6060
|
if (!shareItem || pkg.endsWith("/")) return false;
|
|
6021
6061
|
if (shareItem.shareConfig.eager) return false;
|
|
6022
6062
|
return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
|
|
6023
6063
|
}) : [];
|
|
6024
6064
|
if (command === "build" && shouldPreloadEntryDeferredReactDomClient(resolvedOptions) && !pendingSharePkgs.includes("react-dom/client")) pendingSharePkgs.push(REACT_DOM_CLIENT_SHARE);
|
|
6025
|
-
const pendingShareImports = pendingSharePkgs.map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg,
|
|
6065
|
+
const pendingShareImports = pendingSharePkgs.map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, resolvedOptions))})]`);
|
|
6026
6066
|
return `
|
|
6027
6067
|
${getRuntimeModuleCacheBootstrapCode()}
|
|
6028
6068
|
${sharedCacheHelperCode}
|
|
@@ -6048,7 +6088,7 @@ function generatePendingSharesCode(command = "build", options) {
|
|
|
6048
6088
|
}
|
|
6049
6089
|
`;
|
|
6050
6090
|
}
|
|
6051
|
-
function writePendingShares(command
|
|
6091
|
+
function writePendingShares(command, options) {
|
|
6052
6092
|
const state = getPendingSharesState(options);
|
|
6053
6093
|
state.command = command;
|
|
6054
6094
|
state.module.writeSync(generatePendingSharesCode(command, options), true);
|
|
@@ -6107,20 +6147,11 @@ function refreshRemoteModuleForEnvironment(id, options, exportConditions) {
|
|
|
6107
6147
|
virtual.write(generateRemotes(metadata.remote, metadata.command, metadata.enableSsrInit, metadata.consumer, options, exportConditions));
|
|
6108
6148
|
return true;
|
|
6109
6149
|
}
|
|
6110
|
-
const usedRemotesMap = {};
|
|
6111
6150
|
const usedRemotesByOptions = /* @__PURE__ */ new WeakMap();
|
|
6112
6151
|
const dynamicRemotesByOptions = /* @__PURE__ */ new WeakMap();
|
|
6113
6152
|
const staticRemotesByOptions = /* @__PURE__ */ new WeakMap();
|
|
6114
6153
|
const preloadRemotesByOptions = /* @__PURE__ */ new WeakMap();
|
|
6115
6154
|
const EMPTY_STATIC_REMOTES = /* @__PURE__ */ new Set();
|
|
6116
|
-
function getScopedUsedRemotesMap(options) {
|
|
6117
|
-
let scoped = usedRemotesByOptions.get(options);
|
|
6118
|
-
if (!scoped) {
|
|
6119
|
-
scoped = {};
|
|
6120
|
-
usedRemotesByOptions.set(options, scoped);
|
|
6121
|
-
}
|
|
6122
|
-
return scoped;
|
|
6123
|
-
}
|
|
6124
6155
|
function recordUsedRemote(map, remoteKey, remoteModule) {
|
|
6125
6156
|
ensureUsedRemoteKey(map, remoteKey).add(remoteModule);
|
|
6126
6157
|
}
|
|
@@ -6129,16 +6160,18 @@ function ensureUsedRemoteKey(map, remoteKey) {
|
|
|
6129
6160
|
return map[remoteKey];
|
|
6130
6161
|
}
|
|
6131
6162
|
function ensureUsedRemote(remoteKey, options) {
|
|
6132
|
-
ensureUsedRemoteKey(
|
|
6133
|
-
if (options) ensureUsedRemoteKey(getScopedUsedRemotesMap(options), remoteKey);
|
|
6163
|
+
ensureUsedRemoteKey(getUsedRemotesMap(options), remoteKey);
|
|
6134
6164
|
}
|
|
6135
6165
|
function addUsedRemote(remoteKey, remoteModule, options) {
|
|
6136
|
-
recordUsedRemote(
|
|
6137
|
-
if (options) recordUsedRemote(getScopedUsedRemotesMap(options), remoteKey, remoteModule);
|
|
6166
|
+
recordUsedRemote(getUsedRemotesMap(options), remoteKey, remoteModule);
|
|
6138
6167
|
}
|
|
6139
6168
|
function getUsedRemotesMap(options) {
|
|
6140
|
-
|
|
6141
|
-
|
|
6169
|
+
let usedRemotes = usedRemotesByOptions.get(options);
|
|
6170
|
+
if (!usedRemotes) {
|
|
6171
|
+
usedRemotes = {};
|
|
6172
|
+
usedRemotesByOptions.set(options, usedRemotes);
|
|
6173
|
+
}
|
|
6174
|
+
return usedRemotes;
|
|
6142
6175
|
}
|
|
6143
6176
|
function markDynamicRemote(remote, options) {
|
|
6144
6177
|
let remotes = dynamicRemotesByOptions.get(options);
|
|
@@ -6208,12 +6241,6 @@ function getEagerDeferredClientInit() {
|
|
|
6208
6241
|
return `__mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);
|
|
6209
6242
|
exportModule = __mfCreateDeferredRemoteProxy();`;
|
|
6210
6243
|
}
|
|
6211
|
-
function shouldIncludeDeferredProxy(initMode, consumer, eagerLoadClientRemote, deferRemoteLoad) {
|
|
6212
|
-
if (eagerLoadClientRemote && consumer !== "server") return true;
|
|
6213
|
-
if (initMode === "eager") return consumer !== "server" && (consumer === "unified" || !eagerLoadClientRemote);
|
|
6214
|
-
if (consumer === "client" && eagerLoadClientRemote) return false;
|
|
6215
|
-
return deferRemoteLoad || consumer !== "server";
|
|
6216
|
-
}
|
|
6217
6244
|
/** Codegen shared by every remote virtual module (no top-level await). */
|
|
6218
6245
|
function getRemoteModuleRuntimeHelpers() {
|
|
6219
6246
|
return `
|
|
@@ -6254,12 +6281,16 @@ function getDeferredProxyHelper(remoteCacheKey) {
|
|
|
6254
6281
|
function __mfCreateDeferredRemoteProxy() {
|
|
6255
6282
|
let pendingPromise;
|
|
6256
6283
|
const ensurePending = () => {
|
|
6257
|
-
|
|
6284
|
+
if (!pendingPromise) {
|
|
6285
|
+
pendingPromise = __mfStartRemoteLoad();
|
|
6286
|
+
// Property reads can start a load without an awaiter to handle failure.
|
|
6287
|
+
pendingPromise.then(undefined, () => { pendingPromise = undefined; });
|
|
6288
|
+
}
|
|
6258
6289
|
return pendingPromise;
|
|
6259
6290
|
};
|
|
6260
6291
|
const getModule = () => __mfModuleCache.remote[${JSON.stringify(remoteCacheKey)}];
|
|
6261
6292
|
const proxyTarget = function (...args) {
|
|
6262
|
-
|
|
6293
|
+
ensurePending();
|
|
6263
6294
|
const mod = getModule();
|
|
6264
6295
|
const fn = mod && (mod.default ?? mod);
|
|
6265
6296
|
if (fn !== undefined && fn !== null) {
|
|
@@ -6278,7 +6309,7 @@ function getDeferredProxyHelper(remoteCacheKey) {
|
|
|
6278
6309
|
if (mod) {
|
|
6279
6310
|
return prop in mod ? mod[prop] : mod.default?.[prop];
|
|
6280
6311
|
}
|
|
6281
|
-
|
|
6312
|
+
ensurePending();
|
|
6282
6313
|
if (prop === "default") return proxyTarget;
|
|
6283
6314
|
throw ensurePending();
|
|
6284
6315
|
},
|
|
@@ -6318,9 +6349,19 @@ function getDeferredProxyHelper(remoteCacheKey) {
|
|
|
6318
6349
|
}`;
|
|
6319
6350
|
}
|
|
6320
6351
|
function getLazyRemotePendingExport() {
|
|
6321
|
-
return `
|
|
6352
|
+
return `function __mfResetFailedRemotePending(pending) {
|
|
6353
|
+
pending.then(undefined, () => {
|
|
6354
|
+
if (__mfRemotePending === pending) __mfRemotePending = undefined;
|
|
6355
|
+
});
|
|
6356
|
+
}
|
|
6357
|
+
if (__mfRemotePending) __mfResetFailedRemotePending(__mfRemotePending);
|
|
6358
|
+
export const __mf_remote_pending = {
|
|
6322
6359
|
then(onFulfilled, onRejected) {
|
|
6323
|
-
|
|
6360
|
+
if (!__mfRemotePending) {
|
|
6361
|
+
__mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);
|
|
6362
|
+
__mfResetFailedRemotePending(__mfRemotePending);
|
|
6363
|
+
}
|
|
6364
|
+
return __mfRemotePending.then(onFulfilled, onRejected);
|
|
6324
6365
|
},
|
|
6325
6366
|
};`;
|
|
6326
6367
|
}
|
|
@@ -6380,12 +6421,11 @@ export { __mfDefaultExport as default };`;
|
|
|
6380
6421
|
function generateRemotes(id, command, enableSsrInit = false, consumer = "unified", options, exportConditions) {
|
|
6381
6422
|
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
6382
6423
|
const isLoadedFirst = resolvedOptions.shareStrategy === "loaded-first";
|
|
6383
|
-
const
|
|
6384
|
-
const deferRemoteLoad = shouldDeferRemoteLoad(initMode);
|
|
6424
|
+
const deferRemoteLoad = shouldDeferRemoteLoad(resolveRemoteInitMode(resolvedOptions.shareStrategy, consumer));
|
|
6385
6425
|
const runtimeRemoteId = getRuntimeRemoteId(id, resolvedOptions.remotes, options);
|
|
6386
6426
|
const remoteRegistration = getRemoteRegistration(id, resolvedOptions.remotes, options);
|
|
6387
6427
|
const registerRemoteCode = isLoadedFirst && remoteRegistration ? `runtime.registerRemotes([${JSON.stringify(remoteRegistration)}]);` : "";
|
|
6388
|
-
const hostAutoInitPath = getHostAutoInitPath(
|
|
6428
|
+
const hostAutoInitPath = getHostAutoInitPath(resolvedOptions);
|
|
6389
6429
|
const ssrRemotes = getSsrRuntimeRemotes(resolvedOptions.remotes, options);
|
|
6390
6430
|
const browserHostInitCode = `import(${JSON.stringify(hostAutoInitPath)})
|
|
6391
6431
|
.then((mod) => mod.hostInitPromise)
|
|
@@ -6398,20 +6438,13 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
|
|
|
6398
6438
|
${command === "serve" && consumer !== "server" ? browserHostInitCode : ""}`;
|
|
6399
6439
|
const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise()" : "initPromise";
|
|
6400
6440
|
const remoteCacheKey = `${getRuntimeRemoteCachePrefix(options)}${id}`;
|
|
6401
|
-
const remoteLoadFailureHandler = command === "build" ? `.catch((error) => {
|
|
6402
|
-
delete __mfModuleCache.remote[pendingKey];
|
|
6403
|
-
throw error;
|
|
6404
|
-
})` : `.catch((error) => {
|
|
6405
|
-
delete __mfModuleCache.remote[pendingKey];
|
|
6406
|
-
throw error;
|
|
6407
|
-
})`;
|
|
6408
6441
|
const remoteLoadCode = `
|
|
6409
6442
|
function __mfStartRemoteLoad() {
|
|
6410
6443
|
${`
|
|
6411
6444
|
const remoteCacheKey = ${JSON.stringify(remoteCacheKey)};
|
|
6412
6445
|
const pendingKey = "__mf_pending__" + remoteCacheKey;
|
|
6413
6446
|
if (!__mfModuleCache.remote[pendingKey]) {
|
|
6414
|
-
|
|
6447
|
+
const pending = ${remoteLoadRuntimePromise}
|
|
6415
6448
|
.then((runtime) => {
|
|
6416
6449
|
${registerRemoteCode}
|
|
6417
6450
|
const moduleCacheKey = Symbol.for(${JSON.stringify(MODULE_CACHE_SHARE_SCOPE_KEY)});
|
|
@@ -6428,22 +6461,25 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
|
|
|
6428
6461
|
delete __mfModuleCache.remote[pendingKey];
|
|
6429
6462
|
return mod;
|
|
6430
6463
|
})
|
|
6431
|
-
|
|
6464
|
+
.catch((error) => {
|
|
6465
|
+
if (__mfModuleCache.remote[pendingKey] === pending) {
|
|
6466
|
+
delete __mfModuleCache.remote[pendingKey];
|
|
6467
|
+
}
|
|
6468
|
+
throw error;
|
|
6469
|
+
});
|
|
6470
|
+
__mfModuleCache.remote[pendingKey] = pending;
|
|
6432
6471
|
}
|
|
6433
6472
|
return __mfModuleCache.remote[pendingKey];`}
|
|
6434
6473
|
}`;
|
|
6435
6474
|
const realRemoteInit = `__mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);`;
|
|
6436
|
-
const
|
|
6437
|
-
const eagerLoadClientRemote = id === remoteRegistration?.alias || shouldEagerLoadClientRemoteInDev(command, enableSsrInit);
|
|
6438
|
-
const eagerClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
|
|
6439
|
-
const loadedFirstClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
|
|
6475
|
+
const clientInit = id === remoteRegistration?.alias || shouldEagerLoadClientRemoteInDev(command, enableSsrInit) ? getEagerDeferredClientInit() : `exportModule = __mfCreateDeferredRemoteProxy();`;
|
|
6440
6476
|
const environmentSplitInit = (clientInit, serverInit) => consumer === "client" ? clientInit : consumer === "server" ? serverInit : `if (${SERVER_ENV_GUARD}) {
|
|
6441
6477
|
${serverInit}
|
|
6442
6478
|
} else {
|
|
6443
6479
|
${clientInit}
|
|
6444
6480
|
}`;
|
|
6445
|
-
const initExportModule =
|
|
6446
|
-
const includeProxyHelper =
|
|
6481
|
+
const initExportModule = environmentSplitInit(clientInit, realRemoteInit);
|
|
6482
|
+
const includeProxyHelper = consumer !== "server";
|
|
6447
6483
|
const deferredProxyCode = getDeferredProxyHelper(remoteCacheKey);
|
|
6448
6484
|
return `
|
|
6449
6485
|
${importLine}
|
|
@@ -6464,9 +6500,9 @@ const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !na
|
|
|
6464
6500
|
const HOST_INIT_PRELOAD_CHUNKS = [
|
|
6465
6501
|
(name) => name === "hostInit",
|
|
6466
6502
|
(name) => name === "remoteEntry",
|
|
6467
|
-
isPreloadableVirtualMfChunk
|
|
6468
|
-
(name) => name === "index"
|
|
6503
|
+
isPreloadableVirtualMfChunk
|
|
6469
6504
|
];
|
|
6505
|
+
const isHostInitPreloadSeed = (chunk) => chunk.isEntry || HOST_INIT_PRELOAD_CHUNKS.some((match) => match(chunk.name));
|
|
6470
6506
|
const isRemoteWarmupExcluded = (name) => name.includes("__prebuild__") || name.includes("__loadShare__");
|
|
6471
6507
|
const REMOTE_ENTRY_WARMUP_CHUNKS = [(name) => name === "hostInit", (name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)];
|
|
6472
6508
|
function getChunksByFileName(bundle) {
|
|
@@ -6503,7 +6539,7 @@ function injectHostInitPreloads(html, bundle, resolvePath, externalHrefs = []) {
|
|
|
6503
6539
|
hrefs.push(href);
|
|
6504
6540
|
}
|
|
6505
6541
|
const chunksByFileName = getChunksByFileName(bundle);
|
|
6506
|
-
const seeds = Array.from(chunksByFileName.values()).filter(
|
|
6542
|
+
const seeds = Array.from(chunksByFileName.values()).filter(isHostInitPreloadSeed);
|
|
6507
6543
|
for (const fileName of collectPreloadChunkFiles(chunksByFileName, seeds)) {
|
|
6508
6544
|
const href = resolvePath(fileName);
|
|
6509
6545
|
if (existingHrefs.has(href)) continue;
|
|
@@ -6598,7 +6634,7 @@ const ROLLDOWN_RUNTIME_GLOBAL = "__rolldown_runtime__";
|
|
|
6598
6634
|
* in every chunk and HMR patch it serves.
|
|
6599
6635
|
*/
|
|
6600
6636
|
function renameBundledDevRuntime(req, res, remoteName) {
|
|
6601
|
-
if (!req.url ||
|
|
6637
|
+
if (!req.url || !/\.m?js$/.test(stripQueryAndHash(req.url))) return;
|
|
6602
6638
|
const runtimeGlobal = `__mf_rt_${createHash("sha256").update(remoteName).digest("hex").slice(0, 10)}__`;
|
|
6603
6639
|
const end = res.end;
|
|
6604
6640
|
res.end = function(chunk, ...args) {
|
|
@@ -6615,6 +6651,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
6615
6651
|
const ENTRY_BOOTSTRAP_QUERY = `?${ENTRY_BOOTSTRAP_PARAM}`;
|
|
6616
6652
|
const waitsForInit = entryName === "hostInit";
|
|
6617
6653
|
const getEntryPath = () => typeof entryPath === "function" ? entryPath() : entryPath;
|
|
6654
|
+
const getFederationOptions = () => federationOptions ?? getNormalizeModuleFederationOptions();
|
|
6618
6655
|
let devEntryPath = "";
|
|
6619
6656
|
let entryFiles = [];
|
|
6620
6657
|
let htmlFilePath;
|
|
@@ -6634,8 +6671,14 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
6634
6671
|
let isBundledDevRemote = false;
|
|
6635
6672
|
let bundledDevRemoteEntryCode;
|
|
6636
6673
|
let resolveBundledDevRemoteEntryCode;
|
|
6674
|
+
function isBuildCommand() {
|
|
6675
|
+
return _command === "build" || viteConfig?.command === "build";
|
|
6676
|
+
}
|
|
6677
|
+
function isLoadedFirstClientBuildFor(shareStrategy) {
|
|
6678
|
+
return isBuildCommand() && waitsForInit && !viteConfig?.build?.ssr && shareStrategy === "loaded-first";
|
|
6679
|
+
}
|
|
6637
6680
|
function skipSvelteKitSsrBuild() {
|
|
6638
|
-
return (
|
|
6681
|
+
return isBuildCommand() && viteConfig?.build?.ssr && hasPackageDependency("@sveltejs/kit");
|
|
6639
6682
|
}
|
|
6640
6683
|
function isSvelteKitServerModule(id) {
|
|
6641
6684
|
return hasPackageDependency("@sveltejs/kit") && (id.includes(".svelte-kit/generated/") || id.includes("/@sveltejs/kit/src/runtime/server/"));
|
|
@@ -6670,10 +6713,6 @@ const __mfCurrentScript = document.currentScript;
|
|
|
6670
6713
|
function walkHtmlFiles(dir) {
|
|
6671
6714
|
return walkFiles(dir, (fileName) => fileName.endsWith(".html"));
|
|
6672
6715
|
}
|
|
6673
|
-
function toRelativeImport(fromFile, targetFile) {
|
|
6674
|
-
const relative = normalizePathForImport(path$1.relative(path$1.dirname(fromFile), targetFile));
|
|
6675
|
-
return relative.startsWith(".") ? relative : `./${relative}`;
|
|
6676
|
-
}
|
|
6677
6716
|
function patchSvelteKitStaticHtml() {
|
|
6678
6717
|
const buildDir = path$1.resolve(viteConfig.root, "build");
|
|
6679
6718
|
let initFile = emittedFileName ? path$1.resolve(buildDir, emittedFileName) : void 0;
|
|
@@ -6694,10 +6733,10 @@ const __mfCurrentScript = document.currentScript;
|
|
|
6694
6733
|
return patched;
|
|
6695
6734
|
}
|
|
6696
6735
|
function getRemoteEntryPreloadUrls() {
|
|
6697
|
-
const normalizedOptions =
|
|
6698
|
-
const isLoadedFirstClientBuild = (
|
|
6736
|
+
const normalizedOptions = getFederationOptions();
|
|
6737
|
+
const isLoadedFirstClientBuild = isLoadedFirstClientBuildFor(normalizedOptions.shareStrategy);
|
|
6699
6738
|
if (normalizedOptions.shareStrategy === "loaded-first" && !isLoadedFirstClientBuild) return [];
|
|
6700
|
-
const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(
|
|
6739
|
+
const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(normalizedOptions));
|
|
6701
6740
|
return Array.from(new Set(remoteSources.flatMap((remote) => {
|
|
6702
6741
|
const registration = getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions);
|
|
6703
6742
|
return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) && !/\.json(?:[?#]|$)/i.test(registration.entry) ? [registration.entry] : [];
|
|
@@ -6736,10 +6775,10 @@ const __mfCurrentScript = document.currentScript;
|
|
|
6736
6775
|
const entryImportDeclaration = isEncodedVirtualEntry ? `const __mfEntryUrl = ${JSON.stringify(entrySrc)};
|
|
6737
6776
|
` : "";
|
|
6738
6777
|
const entryImportExpression = isEncodedVirtualEntry ? "import(/* @vite-ignore */ __mfEntryUrl)" : importExpression(entrySrc);
|
|
6739
|
-
const normalizedOptions =
|
|
6740
|
-
const isLoadedFirstClientBuild = (
|
|
6778
|
+
const normalizedOptions = getFederationOptions();
|
|
6779
|
+
const isLoadedFirstClientBuild = isLoadedFirstClientBuildFor(normalizedOptions.shareStrategy);
|
|
6741
6780
|
const shouldPreloadRemotes = !options?.skipRemotePreload && (normalizedOptions.shareStrategy !== "loaded-first" || isLoadedFirstClientBuild);
|
|
6742
|
-
const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.entries(getUsedRemotesMap(
|
|
6781
|
+
const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.entries(getUsedRemotesMap(normalizedOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions));
|
|
6743
6782
|
const remotePreloads = shouldPreloadRemotes ? remoteSources.sort().map((remote) => {
|
|
6744
6783
|
const registration = isLoadedFirstClientBuild ? getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions) : void 0;
|
|
6745
6784
|
return `__mfPreloadRemote(${JSON.stringify(getRuntimeRemoteId(remote, normalizedOptions.remotes, federationOptions))}, ${JSON.stringify(remote)}${registration ? `, ${JSON.stringify(registration)}` : ""})`;
|
|
@@ -6754,7 +6793,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6754
6793
|
const shareItem = getNormalizeShareItem(pkg, federationOptions);
|
|
6755
6794
|
const isExplicitShare = Object.hasOwn(federationOptions.shared, pkg);
|
|
6756
6795
|
return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
|
|
6757
|
-
}).map((pkg) => getLoadShareModulePath(pkg,
|
|
6796
|
+
}).map((pkg) => getLoadShareModulePath(pkg, federationOptions)) : [];
|
|
6758
6797
|
const sharedPreloadBlock = sharedPreloadSources.length === 0 ? "" : options?.isBundled ? `
|
|
6759
6798
|
await Promise.all([${sharedPreloadSources.map((src) => `[${JSON.stringify(src)}, import(${JSON.stringify(src)})]`).join(", ")}].map(([src, load]) => load.catch((err) => console.warn("[module-federation] shared preload failed:", src, err))));` : `
|
|
6760
6799
|
const __mfSharedPreloadUrls = ${JSON.stringify(sharedPreloadSources.map(toViteEncodedId))};
|
|
@@ -6792,8 +6831,8 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
6792
6831
|
if (__mfReactServerModuleCache?.pendingShareLoads) {
|
|
6793
6832
|
await Promise.all(__mfReactServerModuleCache.pendingShareLoads);
|
|
6794
6833
|
}`;
|
|
6795
|
-
const pendingSharesBlock = waitsForInit && (
|
|
6796
|
-
const __mfPendingShares = await ${importExpression(options?.pendingSharesSrc ?? getPendingSharesPath(
|
|
6834
|
+
const pendingSharesBlock = waitsForInit && isBuildCommand() ? `
|
|
6835
|
+
const __mfPendingShares = await ${importExpression(options?.pendingSharesSrc ?? getPendingSharesPath(getFederationOptions()))}.catch(() => undefined);
|
|
6797
6836
|
if (__mfPendingShares && typeof __mfPendingShares.preloadPendingShares === "function") await __mfPendingShares.preloadPendingShares();` : "";
|
|
6798
6837
|
const importCode = `
|
|
6799
6838
|
(async () => {
|
|
@@ -7045,6 +7084,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
7045
7084
|
if (resolved && !resolved.external && (_command === "serve" || !resolved.id.startsWith("\0"))) addEntryFile(resolveProjectId(resolved.id));
|
|
7046
7085
|
}
|
|
7047
7086
|
if (_command === "serve") return;
|
|
7087
|
+
if (entryName === "hostInit" && federationOptions && !hasRemotes(federationOptions) && isServerBuildContext(this, viteConfig)) return;
|
|
7048
7088
|
if (skipSvelteKitSsrBuild()) return;
|
|
7049
7089
|
if (this.environment?.name === "ssr") return;
|
|
7050
7090
|
const hasHash = fileName?.includes?.("[hash");
|
|
@@ -7059,7 +7099,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
7059
7099
|
if (waitsForInit) pendingSharesEmitId = this.emitFile({
|
|
7060
7100
|
name: "pendingShares",
|
|
7061
7101
|
type: "chunk",
|
|
7062
|
-
id: getPendingSharesPath(
|
|
7102
|
+
id: getPendingSharesPath(getFederationOptions()),
|
|
7063
7103
|
preserveSignature: "strict"
|
|
7064
7104
|
});
|
|
7065
7105
|
if (htmlFilePath) addHtmlScriptEntries(htmlFilePath);
|
|
@@ -7068,7 +7108,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
7068
7108
|
if (isBundledDevRemote && _command === "serve") {
|
|
7069
7109
|
const remoteEntryChunk = Object.values(bundle).find((output) => output.type === "chunk" && output.isEntry && output.facadeModuleId === getEntryPath());
|
|
7070
7110
|
if (remoteEntryChunk?.type === "chunk") {
|
|
7071
|
-
const code = `export { ${remoteEntryChunk.exports.join(", ")} } from ${JSON.stringify(`./${remoteEntryChunk.fileName}`)};\n`;
|
|
7111
|
+
const code = `${Object.values(bundle).some((output) => output.type === "chunk" && output.code.includes("new ViteDevRuntime(")) ? "" : `import ${JSON.stringify(`${viteConfig.base}bundledDevClient.mjs`)};\n`}export { ${remoteEntryChunk.exports.join(", ")} } from ${JSON.stringify(`./${remoteEntryChunk.fileName}`)};\n`;
|
|
7072
7112
|
bundledDevRemoteEntryCode = Promise.resolve(code);
|
|
7073
7113
|
resolveBundledDevRemoteEntryCode?.(code);
|
|
7074
7114
|
}
|
|
@@ -7111,7 +7151,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
7111
7151
|
let bootstrapIndex = 0;
|
|
7112
7152
|
for (const fileName of htmlFileNames) {
|
|
7113
7153
|
let htmlAsset = bundle[fileName];
|
|
7114
|
-
if (htmlAsset.type === "chunk")
|
|
7154
|
+
if (htmlAsset.type === "chunk") continue;
|
|
7115
7155
|
let htmlContent = htmlAsset.source.toString() || "";
|
|
7116
7156
|
const initPath = resolvePath(file, fileName);
|
|
7117
7157
|
const scriptRegex = /<script\b(?=[^>]*\btype=["']module["'])(?=[^>]*\bsrc=["']([^"']+)["'])[^>]*>\s*<\/script>/gi;
|
|
@@ -7161,7 +7201,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
7161
7201
|
load(id) {
|
|
7162
7202
|
return virtualEntryCode.get(id);
|
|
7163
7203
|
},
|
|
7164
|
-
transform(code, id) {
|
|
7204
|
+
transform(code, id, transformOptions) {
|
|
7165
7205
|
if (skipSvelteKitSsrBuild()) return;
|
|
7166
7206
|
if (viteConfig?.command === "build" && !waitsForInit) return;
|
|
7167
7207
|
if (isSvelteKitServerModule(id)) return;
|
|
@@ -7173,7 +7213,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
|
|
|
7173
7213
|
if (normalizeModuleId(id).endsWith(".html")) return;
|
|
7174
7214
|
const projectId = resolveProjectId(id);
|
|
7175
7215
|
if (skipTransformIds.has(projectId)) return;
|
|
7176
|
-
if (
|
|
7216
|
+
if (isServerBuildContext(this, viteConfig) || transformOptions?.ssr) return;
|
|
7177
7217
|
const isVinext = hasPackageDependency("vinext");
|
|
7178
7218
|
if (isVinext && inject === "html" && id.includes("virtual:vite-rsc/remove-duplicate-server-css")) {
|
|
7179
7219
|
const namespaceReactImport = `import * as React from 'react';`;
|
|
@@ -7474,21 +7514,6 @@ const vueAdapter = {
|
|
|
7474
7514
|
} }
|
|
7475
7515
|
};
|
|
7476
7516
|
//#endregion
|
|
7477
|
-
//#region src/utils/devServerHost.ts
|
|
7478
|
-
const UNSPECIFIED_HOSTS = /* @__PURE__ */ new Set(["0.0.0.0", "::"]);
|
|
7479
|
-
/**
|
|
7480
|
-
* Hostname for client-facing HTTP/WS origins built from Vite `server.host`.
|
|
7481
|
-
*
|
|
7482
|
-
* Unspecified bind addresses (`0.0.0.0`, `::`) map to `localhost`, matching
|
|
7483
|
-
* Vite's own printed local URL. IPv6 addresses are wrapped in brackets so
|
|
7484
|
-
* `http://[::1]:5173` / `ws://[::1]:5173` parse as valid URLs.
|
|
7485
|
-
*/
|
|
7486
|
-
function formatDevServerHostForOrigin(host) {
|
|
7487
|
-
if (typeof host !== "string" || UNSPECIFIED_HOSTS.has(host)) return "localhost";
|
|
7488
|
-
if (host.startsWith("[") && host.endsWith("]")) return host;
|
|
7489
|
-
return isIPv6(host) ? `[${host}]` : host;
|
|
7490
|
-
}
|
|
7491
|
-
//#endregion
|
|
7492
7517
|
//#region src/plugins/hmr/fullReload.ts
|
|
7493
7518
|
const REMOTE_HMR_ENDPOINT = "__mf_hmr";
|
|
7494
7519
|
const REMOTE_HMR_EVENT = "mf:remote-update";
|
|
@@ -7496,7 +7521,7 @@ const REMOTE_HMR_CONNECT_RETRY_DELAY_MS = 1e3;
|
|
|
7496
7521
|
const REMOTE_HMR_CONNECT_MAX_RETRIES = 10;
|
|
7497
7522
|
function getBasePath(base) {
|
|
7498
7523
|
if (!base) return "/";
|
|
7499
|
-
if (
|
|
7524
|
+
if (isHttpUrl(base)) try {
|
|
7500
7525
|
return new URL(base).pathname || "/";
|
|
7501
7526
|
} catch {
|
|
7502
7527
|
return "/";
|
|
@@ -7595,14 +7620,8 @@ function setupRemoteBroadcast(server, options) {
|
|
|
7595
7620
|
}
|
|
7596
7621
|
});
|
|
7597
7622
|
};
|
|
7598
|
-
server.watcher
|
|
7599
|
-
server.
|
|
7600
|
-
server.watcher.on("unlink", broadcast);
|
|
7601
|
-
server.httpServer?.once("close", () => {
|
|
7602
|
-
server.watcher.off("change", broadcast);
|
|
7603
|
-
server.watcher.off("add", broadcast);
|
|
7604
|
-
server.watcher.off("unlink", broadcast);
|
|
7605
|
-
});
|
|
7623
|
+
const stopWatching = watchFileEvents(server.watcher, broadcast);
|
|
7624
|
+
server.httpServer?.once("close", stopWatching);
|
|
7606
7625
|
}
|
|
7607
7626
|
/**
|
|
7608
7627
|
* Installs the host-side full-reload relay. For each configured remote:
|
|
@@ -7664,9 +7683,13 @@ function setupHostFullReloadRelay(server, options) {
|
|
|
7664
7683
|
if (!message || message.event !== "mf:remote-update") return;
|
|
7665
7684
|
server.ws.send({ type: "full-reload" });
|
|
7666
7685
|
};
|
|
7667
|
-
|
|
7686
|
+
let opened = false;
|
|
7687
|
+
ws.onopen = () => {
|
|
7688
|
+
opened = true;
|
|
7689
|
+
clearReconnectTimer(remoteName);
|
|
7690
|
+
};
|
|
7668
7691
|
ws.onerror = (error) => mfWarn(`Remote HMR socket error for "${remoteName}":`, error);
|
|
7669
|
-
ws.onclose = () => scheduleReconnect(remoteName, remote, attempt, "socket closed");
|
|
7692
|
+
ws.onclose = () => scheduleReconnect(remoteName, remote, opened ? 0 : attempt, "socket closed");
|
|
7670
7693
|
connections.push(ws);
|
|
7671
7694
|
} catch (error) {
|
|
7672
7695
|
mfWarn(`Failed to connect remote HMR for "${remoteName}" on attempt ${attempt + 1}: ${getStringPreview(error)}`);
|
|
@@ -7687,9 +7710,7 @@ function setupHostFullReloadRelay(server, options) {
|
|
|
7687
7710
|
if (shouldIgnoreFile(file, options)) return;
|
|
7688
7711
|
server.ws.send({ type: "full-reload" });
|
|
7689
7712
|
};
|
|
7690
|
-
server.watcher
|
|
7691
|
-
server.watcher.on("add", triggerHostReload);
|
|
7692
|
-
server.watcher.on("unlink", triggerHostReload);
|
|
7713
|
+
watchFileEvents(server.watcher, triggerHostReload);
|
|
7693
7714
|
server.httpServer?.once("close", teardown);
|
|
7694
7715
|
}
|
|
7695
7716
|
//#endregion
|
|
@@ -7760,8 +7781,8 @@ function collectHostTags(server, options, adapters) {
|
|
|
7760
7781
|
return tags;
|
|
7761
7782
|
}
|
|
7762
7783
|
function pluginDevRemoteHmr(options) {
|
|
7763
|
-
const isHost =
|
|
7764
|
-
const isRemote =
|
|
7784
|
+
const isHost = hasRemotes(options);
|
|
7785
|
+
const isRemote = isRemoteContainer(options);
|
|
7765
7786
|
let adapters = [];
|
|
7766
7787
|
let strategy = "full-reload";
|
|
7767
7788
|
let root;
|
|
@@ -8039,9 +8060,10 @@ function pluginExternalRuntimeCore() {
|
|
|
8039
8060
|
//#endregion
|
|
8040
8061
|
//#region src/virtualModules/index.ts
|
|
8041
8062
|
function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8063
|
+
const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
|
|
8064
|
+
writeLocalSharedImportMap(resolvedOptions);
|
|
8065
|
+
writeHostAutoInit(remoteEntryId, command, resolvedOptions);
|
|
8066
|
+
writeRuntimeInitStatus(command, enableSsrInit, getHostAutoInitPath(resolvedOptions), options, options ? getSsrRuntimeRemotes(options.remotes, options) : void 0);
|
|
8045
8067
|
}
|
|
8046
8068
|
//#endregion
|
|
8047
8069
|
//#region src/utils/cssModuleHelpers.ts
|
|
@@ -8290,16 +8312,15 @@ function pluginLazyConsumeOnlyShares(options) {
|
|
|
8290
8312
|
renderChunk(code, chunk, _outputOptions, meta) {
|
|
8291
8313
|
const renderedChunk = chunk;
|
|
8292
8314
|
const chunks = meta?.chunks;
|
|
8293
|
-
if (!chunks ||
|
|
8315
|
+
if (!chunks || !isRemoteContainer(options)) return null;
|
|
8294
8316
|
if (isServerBuildContext(this, viteConfig)) return null;
|
|
8295
8317
|
let graph = graphs.get(chunks);
|
|
8296
8318
|
if (!graph) {
|
|
8297
|
-
const isRolldown = getIsRolldown(this);
|
|
8298
8319
|
const wrapperShares = /* @__PURE__ */ new Map();
|
|
8299
8320
|
for (const shareKey of getUsedShares(options)) {
|
|
8300
8321
|
const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
|
|
8301
8322
|
if (shareConfig?.import !== false || shareConfig.eager || shareConfig.treeShaking) continue;
|
|
8302
|
-
wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey,
|
|
8323
|
+
wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, options)), shareKey);
|
|
8303
8324
|
}
|
|
8304
8325
|
const root = viteConfig?.root ?? process.cwd();
|
|
8305
8326
|
graph = buildLazyShareGraph(chunks, wrapperShares, new Set(Object.values(options.exposes).map((expose) => stripKnownJsExtension(path$1.resolve(root, expose.import)))));
|
|
@@ -8319,15 +8340,16 @@ function pluginLazyConsumeOnlyShares(options) {
|
|
|
8319
8340
|
break;
|
|
8320
8341
|
}
|
|
8321
8342
|
const chunkDir = path$1.posix.dirname(renderedChunk.fileName);
|
|
8322
|
-
|
|
8343
|
+
let codePositions;
|
|
8323
8344
|
let usesHelper = false;
|
|
8324
8345
|
for (const match of isImportMapChunk ? [] : code.matchAll(DYNAMIC_IMPORT_REGEX)) {
|
|
8325
8346
|
const [expression, , specifier] = match;
|
|
8326
8347
|
const start = match.index;
|
|
8327
|
-
if (!codePositions[start]) continue;
|
|
8328
8348
|
const target = path$1.posix.normalize(path$1.posix.join(chunkDir, specifier));
|
|
8329
8349
|
const shares = graph.sharesByChunk.get(target);
|
|
8330
8350
|
if (!shares || !renderedChunk.dynamicImports.includes(target)) continue;
|
|
8351
|
+
codePositions ??= createCodePositionMap(code);
|
|
8352
|
+
if (!codePositions[start]) continue;
|
|
8331
8353
|
rewriter.overwrite(start, start + expression.length, `${helperName}(${JSON.stringify(shares)}).then(() => ${expression})`);
|
|
8332
8354
|
usesHelper = edited = true;
|
|
8333
8355
|
}
|
|
@@ -8350,7 +8372,7 @@ function ${helperName}(names) {
|
|
|
8350
8372
|
}
|
|
8351
8373
|
//#endregion
|
|
8352
8374
|
//#region package.json
|
|
8353
|
-
var version$1 = "1.23.
|
|
8375
|
+
var version$1 = "1.23.7";
|
|
8354
8376
|
//#endregion
|
|
8355
8377
|
//#region src/virtualModules/virtualExposesSSR.ts
|
|
8356
8378
|
/**
|
|
@@ -8397,6 +8419,15 @@ const REMOTE_ENTRY_SSR_ID = "virtual:mf-REMOTE_ENTRY_SSR_ID";
|
|
|
8397
8419
|
function getRemoteEntrySSRId(options) {
|
|
8398
8420
|
return `${REMOTE_ENTRY_SSR_ID}:${getVirtualModuleScopeKey(options)}`;
|
|
8399
8421
|
}
|
|
8422
|
+
const SSR_HOST_INIT_ID = "virtual:mf-ssr-host-init";
|
|
8423
|
+
/**
|
|
8424
|
+
* The SSR entry's import of the host bootstrap. Keyed by config scope, not by federation()
|
|
8425
|
+
* instance: under the Vite builder the entry plugin is shared by every environment, so the
|
|
8426
|
+
* instance building each environment resolves it to its own bootstrap.
|
|
8427
|
+
*/
|
|
8428
|
+
function getSsrHostInitId(options) {
|
|
8429
|
+
return `${SSR_HOST_INIT_ID}:${getVirtualModuleScopeKey(options)}`;
|
|
8430
|
+
}
|
|
8400
8431
|
const FILE_EXTENSION_RE = /\.[^.]+$/;
|
|
8401
8432
|
function getSsrFileNameParts(browserFilename) {
|
|
8402
8433
|
const filename = resolveHashPlaceholderFileName(browserFilename);
|
|
@@ -8447,7 +8478,7 @@ function generateRemoteEntrySSR(options) {
|
|
|
8447
8478
|
const virtualExposesSSRId = getVirtualExposesSSRId(options);
|
|
8448
8479
|
const sharedSingletons = getSsrSharedSingletons(options);
|
|
8449
8480
|
return `
|
|
8450
|
-
import { init as runtimeInit } from "@module-federation/runtime";
|
|
8481
|
+
${hasRemotes(options) ? `import { hostInitPromise } from ${JSON.stringify(getSsrHostInitId(options))};` : "import { init as runtimeInit } from \"@module-federation/runtime\";"}
|
|
8451
8482
|
|
|
8452
8483
|
const sharedSingletons = ${JSON.stringify(sharedSingletons)};
|
|
8453
8484
|
const moduleCacheKey = Symbol.for(${JSON.stringify(MODULE_CACHE_SHARE_SCOPE_KEY)});
|
|
@@ -8477,11 +8508,11 @@ function generateRemoteEntrySSR(options) {
|
|
|
8477
8508
|
* to set up a minimal runtime instance for the remote container.
|
|
8478
8509
|
*/
|
|
8479
8510
|
async function init(shared = {}, initScope = []) {
|
|
8480
|
-
const initRes = runtimeInit({
|
|
8511
|
+
const initRes = ${hasRemotes(options) ? "await hostInitPromise" : `runtimeInit({
|
|
8481
8512
|
name: ${JSON.stringify(options.name)},
|
|
8482
8513
|
remotes: [],
|
|
8483
8514
|
shared: {},
|
|
8484
|
-
});
|
|
8515
|
+
})`};
|
|
8485
8516
|
if (initScope.indexOf(initToken) >= 0) return;
|
|
8486
8517
|
initScope.push(initToken);
|
|
8487
8518
|
const shareScopeNames = Array.isArray(${JSON.stringify(options.shareScope)})
|
|
@@ -8626,13 +8657,13 @@ function collectImportedCss(chunks) {
|
|
|
8626
8657
|
* dependency even though the expose statically imports it. Advertising it as a sync
|
|
8627
8658
|
* asset makes a preloader fetch a provider the host is going to supply anyway.
|
|
8628
8659
|
*/
|
|
8629
|
-
function collectDeferredShareModules(options
|
|
8660
|
+
function collectDeferredShareModules(options) {
|
|
8630
8661
|
const deferred = /* @__PURE__ */ new Set();
|
|
8631
8662
|
for (const shareKey of getUsedShares(options)) {
|
|
8632
8663
|
const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
|
|
8633
8664
|
if (shareConfig?.eager === true) continue;
|
|
8634
8665
|
if (shareConfig?.import === false) continue;
|
|
8635
|
-
deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey,
|
|
8666
|
+
deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, options)));
|
|
8636
8667
|
}
|
|
8637
8668
|
return deferred;
|
|
8638
8669
|
}
|
|
@@ -8647,9 +8678,9 @@ function isDeferredShareChunk(chunk, deferredShareModules) {
|
|
|
8647
8678
|
if (!chunk || chunk.type !== "chunk" || deferredShareModules.size === 0) return false;
|
|
8648
8679
|
return [chunk.facadeModuleId, ...chunk.moduleIds ?? []].some((id) => typeof id === "string" && deferredShareModules.has(normalizeVirtualModuleId(id)));
|
|
8649
8680
|
}
|
|
8650
|
-
function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options
|
|
8681
|
+
function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options) {
|
|
8651
8682
|
if (exposeModules.length === 0) return;
|
|
8652
|
-
const deferredShareModules = collectDeferredShareModules(options
|
|
8683
|
+
const deferredShareModules = collectDeferredShareModules(options);
|
|
8653
8684
|
const containerChunks = remoteEntryFileName ? collectStaticChunks(bundle, [remoteEntryFileName]) : [];
|
|
8654
8685
|
const bootstrapChunks = containerChunks.slice(1);
|
|
8655
8686
|
const seen = new Set(containerChunks.map((chunk) => chunk.fileName));
|
|
@@ -8705,18 +8736,11 @@ function getRemoteContainerName(remoteKey, remote) {
|
|
|
8705
8736
|
}
|
|
8706
8737
|
const Manifest = (providedOptions) => {
|
|
8707
8738
|
const mfOptions = providedOptions ?? getNormalizeModuleFederationOptions();
|
|
8708
|
-
const {
|
|
8739
|
+
const { filename, getPublicPath, manifest: manifestOptions } = mfOptions;
|
|
8709
8740
|
let mfManifestName = manifestOptions === true ? "mf-manifest.json" : typeof manifestOptions === "object" ? normalizePathForImport(path$1.join(manifestOptions?.filePath || "", manifestOptions?.fileName || "mf-manifest.json")) : void 0;
|
|
8710
8741
|
let mfManifestStatsName = mfManifestName ? getStatsFileName(mfManifestName) : void 0;
|
|
8711
|
-
const isConsumerProject =
|
|
8742
|
+
const isConsumerProject = !isRemoteContainer(mfOptions);
|
|
8712
8743
|
let disableAssetsAnalyze = false;
|
|
8713
|
-
const getDefaultDisableAssetsAnalyze = (command) => command === "serve" && isConsumerProject && (typeof manifestOptions !== "object" || !Object.hasOwn(manifestOptions, "disableAssetsAnalyze"));
|
|
8714
|
-
const getConfiguredDisableAssetsAnalyze = (command) => {
|
|
8715
|
-
if (typeof manifestOptions === "object" && manifestOptions !== null) {
|
|
8716
|
-
if (Object.hasOwn(manifestOptions, "disableAssetsAnalyze")) return manifestOptions.disableAssetsAnalyze === true;
|
|
8717
|
-
}
|
|
8718
|
-
return getDefaultDisableAssetsAnalyze(command);
|
|
8719
|
-
};
|
|
8720
8744
|
let root;
|
|
8721
8745
|
let remoteEntryFile;
|
|
8722
8746
|
let ssrRemoteEntryFile;
|
|
@@ -8744,7 +8768,7 @@ const Manifest = (providedOptions) => {
|
|
|
8744
8768
|
configureServer(server) {
|
|
8745
8769
|
server.middlewares.use((req, res, next) => {
|
|
8746
8770
|
const devRemoteEntryFile = resolveHashPlaceholderFileName(filename);
|
|
8747
|
-
if (devRemoteEntryFile !== filename &&
|
|
8771
|
+
if (devRemoteEntryFile !== filename && isRemoteContainer(mfOptions) && req.url?.startsWith((viteConfig.base + devRemoteEntryFile).replace(/^\/?/, "/"))) {
|
|
8748
8772
|
req.url = req.url.replace(devRemoteEntryFile, filename);
|
|
8749
8773
|
next();
|
|
8750
8774
|
return;
|
|
@@ -8757,39 +8781,7 @@ const Manifest = (providedOptions) => {
|
|
|
8757
8781
|
res.setHeader("Content-Type", "application/json");
|
|
8758
8782
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
8759
8783
|
(async () => {
|
|
8760
|
-
const manifest = await applyManifestAdditionalData({
|
|
8761
|
-
...generateMFManifest({}, disableAssetsAnalyze),
|
|
8762
|
-
id: name,
|
|
8763
|
-
name,
|
|
8764
|
-
metaData: {
|
|
8765
|
-
name,
|
|
8766
|
-
type: "app",
|
|
8767
|
-
buildInfo: {
|
|
8768
|
-
buildVersion: getBuildVersion(),
|
|
8769
|
-
buildName: name,
|
|
8770
|
-
...getTreeShakingBuildInfo(mfOptions)
|
|
8771
|
-
},
|
|
8772
|
-
remoteEntry: {
|
|
8773
|
-
name: devRemoteEntryFile,
|
|
8774
|
-
path: "",
|
|
8775
|
-
type: "module"
|
|
8776
|
-
},
|
|
8777
|
-
ssrRemoteEntry: {
|
|
8778
|
-
name: getSsrRemoteEntryFileName(mfOptions, devRemoteEntryFile),
|
|
8779
|
-
path: "/__mf_ssr__/",
|
|
8780
|
-
type: "module"
|
|
8781
|
-
},
|
|
8782
|
-
varRemoteEntry: varFilename ? {
|
|
8783
|
-
name: varFilename,
|
|
8784
|
-
path: "",
|
|
8785
|
-
type: "var"
|
|
8786
|
-
} : void 0,
|
|
8787
|
-
types: resolveTypesMeta(mfOptions.dts),
|
|
8788
|
-
globalName: name,
|
|
8789
|
-
pluginVersion: version$1,
|
|
8790
|
-
publicPath
|
|
8791
|
-
}
|
|
8792
|
-
});
|
|
8784
|
+
const manifest = await applyManifestAdditionalData(generateMFManifest({}, disableAssetsAnalyze));
|
|
8793
8785
|
res.end(JSON.stringify(manifest));
|
|
8794
8786
|
})().catch(next);
|
|
8795
8787
|
} else next();
|
|
@@ -8807,7 +8799,7 @@ const Manifest = (providedOptions) => {
|
|
|
8807
8799
|
_command = command;
|
|
8808
8800
|
if (!config.build) config.build = {};
|
|
8809
8801
|
if (!config.build.manifest) config.build.manifest = config.build.manifest || !!mfManifestName;
|
|
8810
|
-
disableAssetsAnalyze =
|
|
8802
|
+
disableAssetsAnalyze = resolveDisableAssetsAnalyze(manifestOptions, command === "serve" && isConsumerProject);
|
|
8811
8803
|
_originalConfigBase = config.base;
|
|
8812
8804
|
},
|
|
8813
8805
|
configResolved(config) {
|
|
@@ -8864,7 +8856,7 @@ const Manifest = (providedOptions) => {
|
|
|
8864
8856
|
const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions);
|
|
8865
8857
|
const foundSsrRemoteEntryFile = Object.values(bundle).find((file) => file.fileName === expectedSsrRemoteEntryFile)?.fileName;
|
|
8866
8858
|
if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
|
|
8867
|
-
ssrRemoteEntryFile = foundSsrRemoteEntryFile
|
|
8859
|
+
ssrRemoteEntryFile = foundSsrRemoteEntryFile;
|
|
8868
8860
|
const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
|
|
8869
8861
|
if (allCssAssets.size > 0) {
|
|
8870
8862
|
const secondaryCss = /* @__PURE__ */ new Set();
|
|
@@ -8886,7 +8878,7 @@ const Manifest = (providedOptions) => {
|
|
|
8886
8878
|
root,
|
|
8887
8879
|
stripKnownJsExtensions: true
|
|
8888
8880
|
});
|
|
8889
|
-
expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions
|
|
8881
|
+
expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions);
|
|
8890
8882
|
const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(mfOptions), this.resolve.bind(this), mfOptions);
|
|
8891
8883
|
processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
|
|
8892
8884
|
const deferredSharedAssets = {
|
|
@@ -8934,13 +8926,13 @@ const Manifest = (providedOptions) => {
|
|
|
8934
8926
|
function generateMFManifest(preloadMap, disableAssetsAnalyze = false) {
|
|
8935
8927
|
const options = mfOptions;
|
|
8936
8928
|
const { name, varFilename } = options;
|
|
8937
|
-
const resolvedRemoteEntryFile = _command === "serve" ?
|
|
8929
|
+
const resolvedRemoteEntryFile = _command === "serve" ? resolveHashPlaceholderFileName(filename) : remoteEntryFile;
|
|
8938
8930
|
const remoteEntry = {
|
|
8939
8931
|
name: resolvedRemoteEntryFile,
|
|
8940
8932
|
path: "",
|
|
8941
8933
|
type: "module"
|
|
8942
8934
|
};
|
|
8943
|
-
const resolvedSsrRemoteEntryFile = _command === "serve" ?
|
|
8935
|
+
const resolvedSsrRemoteEntryFile = _command === "serve" ? getSsrRemoteEntryFileName(mfOptions, resolvedRemoteEntryFile) : ssrRemoteEntryFile;
|
|
8944
8936
|
const ssrRemoteEntry = resolvedSsrRemoteEntryFile ? {
|
|
8945
8937
|
name: resolvedSsrRemoteEntryFile,
|
|
8946
8938
|
path: _command === "serve" ? "/__mf_ssr__/" : "",
|
|
@@ -9239,6 +9231,8 @@ function createModuleParseController() {
|
|
|
9239
9231
|
discardWarned: false,
|
|
9240
9232
|
externalSet: /* @__PURE__ */ new Set(),
|
|
9241
9233
|
resolutionProbed: /* @__PURE__ */ new Set(),
|
|
9234
|
+
reached: /* @__PURE__ */ new Set(),
|
|
9235
|
+
deferredImports: /* @__PURE__ */ new Map(),
|
|
9242
9236
|
lastLoadedModule: "",
|
|
9243
9237
|
lastParsedModule: ""
|
|
9244
9238
|
};
|
|
@@ -9262,6 +9256,8 @@ function resetParseState(controller) {
|
|
|
9262
9256
|
controller.parseEndSet = /* @__PURE__ */ new Set();
|
|
9263
9257
|
controller.externalSet = /* @__PURE__ */ new Set();
|
|
9264
9258
|
controller.resolutionProbed = /* @__PURE__ */ new Set();
|
|
9259
|
+
controller.reached = /* @__PURE__ */ new Set();
|
|
9260
|
+
controller.deferredImports = /* @__PURE__ */ new Map();
|
|
9265
9261
|
controller.discardWarned = false;
|
|
9266
9262
|
controller.lastLoadedModule = "";
|
|
9267
9263
|
controller.lastParsedModule = "";
|
|
@@ -9337,7 +9333,10 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
|
|
|
9337
9333
|
const entryImports = /* @__PURE__ */ new Set([...options.exposedModuleImports || [], ...configuredInputImports]);
|
|
9338
9334
|
for (const importSource of entryImports) {
|
|
9339
9335
|
const resolved = await this.resolve(importSource);
|
|
9340
|
-
if (resolved && !resolved.external && !excludeFn(resolved.id))
|
|
9336
|
+
if (resolved && !resolved.external && !excludeFn(resolved.id)) {
|
|
9337
|
+
controller.parseStartSet.add(resolved.id);
|
|
9338
|
+
controller.reached.add(resolved.id);
|
|
9339
|
+
}
|
|
9341
9340
|
}
|
|
9342
9341
|
},
|
|
9343
9342
|
load(id) {
|
|
@@ -9358,7 +9357,11 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
|
|
|
9358
9357
|
if (idleTimeout) resetIdleTimeout(controller, idleTimeout);
|
|
9359
9358
|
const parsedModule = module;
|
|
9360
9359
|
const addPendingResolutions = (resolutions) => {
|
|
9361
|
-
for (const resolution of resolutions || [])
|
|
9360
|
+
for (const resolution of resolutions || []) {
|
|
9361
|
+
if (resolution.external) continue;
|
|
9362
|
+
if (excludeFn(resolution.id)) reach(resolution.id);
|
|
9363
|
+
else addPending(resolution.id);
|
|
9364
|
+
}
|
|
9362
9365
|
};
|
|
9363
9366
|
const probeExternal = (pendingId) => {
|
|
9364
9367
|
if (typeof this.resolve !== "function") return;
|
|
@@ -9373,15 +9376,39 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
|
|
|
9373
9376
|
};
|
|
9374
9377
|
const addPendingIds = (ids) => {
|
|
9375
9378
|
for (const pendingId of ids || []) {
|
|
9376
|
-
if (controller.externalSet.has(pendingId) || matchesExternal(configuredExternal, pendingId, id)
|
|
9377
|
-
|
|
9379
|
+
if (controller.externalSet.has(pendingId) || matchesExternal(configuredExternal, pendingId, id)) continue;
|
|
9380
|
+
if (excludeFn(pendingId)) {
|
|
9381
|
+
reach(pendingId);
|
|
9382
|
+
continue;
|
|
9383
|
+
}
|
|
9384
|
+
addPending(pendingId);
|
|
9378
9385
|
if (!controller.parseEndSet.has(pendingId)) probeExternal(pendingId);
|
|
9379
9386
|
}
|
|
9380
9387
|
};
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9388
|
+
const seedImports = (resolutions, ids) => {
|
|
9389
|
+
if (resolutions === void 0) addPendingIds(ids);
|
|
9390
|
+
else addPendingResolutions(resolutions);
|
|
9391
|
+
};
|
|
9392
|
+
const reach = (moduleId) => {
|
|
9393
|
+
if (controller.reached.has(moduleId)) return;
|
|
9394
|
+
controller.reached.add(moduleId);
|
|
9395
|
+
const seedDeferred = controller.deferredImports.get(moduleId);
|
|
9396
|
+
controller.deferredImports.delete(moduleId);
|
|
9397
|
+
seedDeferred?.();
|
|
9398
|
+
};
|
|
9399
|
+
const addPending = (pendingId) => {
|
|
9400
|
+
controller.parseStartSet.add(pendingId);
|
|
9401
|
+
reach(pendingId);
|
|
9402
|
+
};
|
|
9403
|
+
const seedAllImports = () => {
|
|
9404
|
+
seedImports(parsedModule.importedIdResolutions, module.importedIds);
|
|
9405
|
+
seedImports(parsedModule.dynamicallyImportedIdResolutions, module.dynamicallyImportedIds);
|
|
9406
|
+
};
|
|
9407
|
+
if (module.isEntry === false && !controller.reached.has(id)) controller.deferredImports.set(id, seedAllImports);
|
|
9408
|
+
else {
|
|
9409
|
+
controller.reached.add(id);
|
|
9410
|
+
seedAllImports();
|
|
9411
|
+
}
|
|
9385
9412
|
if (!excludeFn(id)) controller.parseEndSet.add(id);
|
|
9386
9413
|
scheduleParseCompletionCheck(controller);
|
|
9387
9414
|
},
|
|
@@ -9391,7 +9418,228 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
|
|
|
9391
9418
|
reason: "build-end"
|
|
9392
9419
|
});
|
|
9393
9420
|
}
|
|
9394
|
-
}];
|
|
9421
|
+
}];
|
|
9422
|
+
}
|
|
9423
|
+
//#endregion
|
|
9424
|
+
//#region src/utils/hostProvidesAllShared.ts
|
|
9425
|
+
/** Virtual-module prefix of the host's per-share re-export entries. */
|
|
9426
|
+
const SHARE_MODULE_PREFIX = "\0mf-host-provided-share:";
|
|
9427
|
+
/** `./a/b` → `a/b`, `.` → `index`: the fixed entry name of an expose, without `.js`. */
|
|
9428
|
+
function exposeEntryName(exposeKey) {
|
|
9429
|
+
return exposeKey === "." ? "index" : exposeKey.replace(/^\.\//, "");
|
|
9430
|
+
}
|
|
9431
|
+
/** Bare specifier a host uses for an expose: `remote` for `.`, `remote/a/b` otherwise. */
|
|
9432
|
+
function remoteSpecifier(remoteName, exposeKey) {
|
|
9433
|
+
const entry = exposeEntryName(exposeKey);
|
|
9434
|
+
return entry === "index" ? remoteName : `${remoteName}/${entry}`;
|
|
9435
|
+
}
|
|
9436
|
+
/** `id` is a remote alias or a subpath of one. */
|
|
9437
|
+
function isRemoteSpecifier(id, remoteKeys) {
|
|
9438
|
+
return remoteKeys.some((key) => id === key || id.startsWith(`${key}/`));
|
|
9439
|
+
}
|
|
9440
|
+
/**
|
|
9441
|
+
* The shared key that owns `id`: an exact match, else the longest key `id` is a subpath
|
|
9442
|
+
* of (`lodash-es/debounce` → `lodash-es`). Used to spot an unshared subpath of a shared
|
|
9443
|
+
* package, which would bundle a private copy of that package into a remote.
|
|
9444
|
+
*/
|
|
9445
|
+
function sharedKeyOwning(id, sharedKeys) {
|
|
9446
|
+
let owner;
|
|
9447
|
+
for (const key of sharedKeys) {
|
|
9448
|
+
if (id !== key && !id.startsWith(`${key}/`)) continue;
|
|
9449
|
+
if (!owner || key.length > owner.length) owner = key;
|
|
9450
|
+
}
|
|
9451
|
+
return owner;
|
|
9452
|
+
}
|
|
9453
|
+
/** Chunk name of the host's re-export entry for a shared key. */
|
|
9454
|
+
function shareChunkName(key) {
|
|
9455
|
+
return `shared/${key.replace(/^@/, "").replace(/[^\w-]+/g, "-")}`;
|
|
9456
|
+
}
|
|
9457
|
+
/** Reads a remote's `mf-manifest.json` from a URL or a path relative to `root`. */
|
|
9458
|
+
async function readHostProvidesAllSharedManifest(location, root) {
|
|
9459
|
+
let source;
|
|
9460
|
+
if (isAbsoluteUrl(location)) {
|
|
9461
|
+
const response = await fetch(location);
|
|
9462
|
+
if (!response.ok) throw new Error(`Failed to fetch ${location}: ${response.status} ${response.statusText}`);
|
|
9463
|
+
source = await response.text();
|
|
9464
|
+
} else source = await readFile(path$1.resolve(root, location), "utf8");
|
|
9465
|
+
const manifest = JSON.parse(source);
|
|
9466
|
+
if (!manifest.metaData || !Array.isArray(manifest.exposes)) throw new Error(`${location} is not a Module Federation manifest.`);
|
|
9467
|
+
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 }\`.`);
|
|
9468
|
+
return manifest;
|
|
9469
|
+
}
|
|
9470
|
+
/** URL prefix of a remote's files: `metaData.publicPath`, `auto` inferred from the manifest URL. */
|
|
9471
|
+
function remotePublicPath(manifest, location) {
|
|
9472
|
+
const publicPath = manifest.metaData.publicPath ?? "auto";
|
|
9473
|
+
if (publicPath !== "auto") return ensureTrailingSlash(publicPath);
|
|
9474
|
+
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.`);
|
|
9475
|
+
return ensureTrailingSlash(inferAutoPublicPath(location));
|
|
9476
|
+
}
|
|
9477
|
+
/** Import-map entries (`remote/Expose` → URL) for every expose of every remote. */
|
|
9478
|
+
async function collectRemoteImports(remotes, root) {
|
|
9479
|
+
const imports = {};
|
|
9480
|
+
for (const [alias, remote] of Object.entries(remotes)) {
|
|
9481
|
+
const manifest = await readHostProvidesAllSharedManifest(remote.entry, root);
|
|
9482
|
+
const publicPath = remotePublicPath(manifest, remote.entry);
|
|
9483
|
+
for (const expose of manifest.exposes) {
|
|
9484
|
+
const file = expose.assets.js.sync[0];
|
|
9485
|
+
if (!expose.path || !file) continue;
|
|
9486
|
+
imports[remoteSpecifier(alias, expose.path)] = isAbsoluteUrl(remote.entry) ? new URL(file, new URL(publicPath, remote.entry)).href : publicPath + file;
|
|
9487
|
+
}
|
|
9488
|
+
}
|
|
9489
|
+
return imports;
|
|
9490
|
+
}
|
|
9491
|
+
/** Top-level options that only the Module Federation runtime or `remoteEntry.js` pipeline reads. */
|
|
9492
|
+
const IGNORED_OPTIONS = [
|
|
9493
|
+
"filename",
|
|
9494
|
+
"ssrFilename",
|
|
9495
|
+
"varFilename",
|
|
9496
|
+
"library",
|
|
9497
|
+
"runtime",
|
|
9498
|
+
"shareScope",
|
|
9499
|
+
"shareStrategy",
|
|
9500
|
+
"runtimePlugins",
|
|
9501
|
+
"implementation",
|
|
9502
|
+
"getPublicPath",
|
|
9503
|
+
"ignoreOrigin",
|
|
9504
|
+
"virtualModuleDir",
|
|
9505
|
+
"hostInitInjectLocation",
|
|
9506
|
+
"bundleAllCSS",
|
|
9507
|
+
"treeShakingDir",
|
|
9508
|
+
"injectTreeShakingUsedExports",
|
|
9509
|
+
"treeShakingSharedPlugins",
|
|
9510
|
+
"treeShakingSharedExcludePlugins",
|
|
9511
|
+
"moduleParseTimeout",
|
|
9512
|
+
"moduleParseIdleTimeout",
|
|
9513
|
+
"target",
|
|
9514
|
+
"ssrExternals",
|
|
9515
|
+
"ssrEntryLoader",
|
|
9516
|
+
"disableRemote",
|
|
9517
|
+
"disableShared",
|
|
9518
|
+
"disableSnapshot"
|
|
9519
|
+
];
|
|
9520
|
+
const IGNORED_EXPERIMENTS = [
|
|
9521
|
+
"externalRuntime",
|
|
9522
|
+
"provideExternalRuntime",
|
|
9523
|
+
"ssrMode"
|
|
9524
|
+
];
|
|
9525
|
+
/** Per-share options: version negotiation, aliasing and fallbacks do not exist in this mode. */
|
|
9526
|
+
const IGNORED_SHARE_OPTIONS = [
|
|
9527
|
+
"eager",
|
|
9528
|
+
"requiredVersion",
|
|
9529
|
+
"strictVersion",
|
|
9530
|
+
"import",
|
|
9531
|
+
"request",
|
|
9532
|
+
"shareKey",
|
|
9533
|
+
"name",
|
|
9534
|
+
"version",
|
|
9535
|
+
"shareScope",
|
|
9536
|
+
"treeShaking",
|
|
9537
|
+
"allowNodeModulesSuffixMatch",
|
|
9538
|
+
"suppressMissingImportWarning"
|
|
9539
|
+
];
|
|
9540
|
+
const isSet = (value) => value !== void 0 && value !== false && !(Array.isArray(value) && value.length === 0);
|
|
9541
|
+
/** A single warning naming every option the user set that import-map mode ignores. */
|
|
9542
|
+
function getIgnoredOptionWarning(options) {
|
|
9543
|
+
const shared = options.shared;
|
|
9544
|
+
const ignored = [
|
|
9545
|
+
...IGNORED_OPTIONS.filter((key) => isSet(options[key])).map((key) => `\`${key}\``),
|
|
9546
|
+
...IGNORED_EXPERIMENTS.filter((key) => isSet(options.experiments?.[key])).map((key) => `\`experiments.${key}\``),
|
|
9547
|
+
...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}\``) : []) : []
|
|
9548
|
+
];
|
|
9549
|
+
if (ignored.length === 0) return void 0;
|
|
9550
|
+
return `experiments.hostProvidesAllShared: ${ignored.join(", ")} ignored. The Module Federation runtime is not used and the host provides the only copy of every shared key.`;
|
|
9551
|
+
}
|
|
9552
|
+
//#endregion
|
|
9553
|
+
//#region src/utils/remoteDependencies.ts
|
|
9554
|
+
function collectImportSources(code) {
|
|
9555
|
+
const sources = /* @__PURE__ */ new Map();
|
|
9556
|
+
for (const { source, kind, syntax, typeOnly } of findModuleImportDescriptors(code)) {
|
|
9557
|
+
if (syntax !== "import" || typeOnly) continue;
|
|
9558
|
+
const dynamic = kind === "dynamic";
|
|
9559
|
+
sources.set(source, (sources.get(source) ?? true) && dynamic);
|
|
9560
|
+
}
|
|
9561
|
+
return Array.from(sources, ([source, dynamic]) => ({
|
|
9562
|
+
source,
|
|
9563
|
+
dynamic
|
|
9564
|
+
})).sort((a, b) => a.source.localeCompare(b.source));
|
|
9565
|
+
}
|
|
9566
|
+
function shouldScanResolvedImport(id) {
|
|
9567
|
+
if (!id || id.includes("\0")) return false;
|
|
9568
|
+
if (isNodeModulePath(id)) return false;
|
|
9569
|
+
return /\.(?:[cm]?[jt]sx?|vue|svelte)(?:\?|$)/.test(id);
|
|
9570
|
+
}
|
|
9571
|
+
const TS_MODULE_RE = /\.[cm]?tsx?$/;
|
|
9572
|
+
/**
|
|
9573
|
+
* The module as Vite's TypeScript transform leaves it. A value-style import used only as a type
|
|
9574
|
+
* (`import { Props } from 'remote/Widget'`) is dropped there, so it loads nothing at runtime.
|
|
9575
|
+
* `transformWithOxc` is Vite 8+; `transformWithEsbuild` needs esbuild, which Vite 8 no longer ships.
|
|
9576
|
+
*/
|
|
9577
|
+
async function withoutTypeOnlyImports(id, code) {
|
|
9578
|
+
if (!TS_MODULE_RE.test(id)) return code;
|
|
9579
|
+
const { transformWithOxc } = vite;
|
|
9580
|
+
try {
|
|
9581
|
+
return (transformWithOxc ? await transformWithOxc(code, id, { jsx: "preserve" }) : await vite.transformWithEsbuild(code, id, { jsx: "preserve" })).code;
|
|
9582
|
+
} catch {
|
|
9583
|
+
return code;
|
|
9584
|
+
}
|
|
9585
|
+
}
|
|
9586
|
+
async function readModuleEdges(ctx, id, isRemoteImport) {
|
|
9587
|
+
let code;
|
|
9588
|
+
try {
|
|
9589
|
+
code = getScannableModuleSource(id, readFileSync$1(id, "utf8"));
|
|
9590
|
+
} catch {
|
|
9591
|
+
return {
|
|
9592
|
+
remotes: [],
|
|
9593
|
+
staticImports: [],
|
|
9594
|
+
dynamicImports: []
|
|
9595
|
+
};
|
|
9596
|
+
}
|
|
9597
|
+
let sources = collectImportSources(code);
|
|
9598
|
+
if (sources.some(({ source }) => isRemoteImport(source))) sources = collectImportSources(await withoutTypeOnlyImports(id, code));
|
|
9599
|
+
const edges = {
|
|
9600
|
+
remotes: [],
|
|
9601
|
+
staticImports: [],
|
|
9602
|
+
dynamicImports: []
|
|
9603
|
+
};
|
|
9604
|
+
for (const { source, dynamic } of sources) {
|
|
9605
|
+
if (isRemoteImport(source)) {
|
|
9606
|
+
if (!dynamic) edges.remotes.push(source);
|
|
9607
|
+
continue;
|
|
9608
|
+
}
|
|
9609
|
+
let resolved;
|
|
9610
|
+
try {
|
|
9611
|
+
resolved = await ctx.resolve(source, id);
|
|
9612
|
+
} catch {
|
|
9613
|
+
continue;
|
|
9614
|
+
}
|
|
9615
|
+
if (resolved?.id && shouldScanResolvedImport(resolved.id)) (dynamic ? edges.dynamicImports : edges.staticImports).push(resolved.id);
|
|
9616
|
+
}
|
|
9617
|
+
return edges;
|
|
9618
|
+
}
|
|
9619
|
+
/**
|
|
9620
|
+
* Static remote imports in the module graph rooted at `id`: the remotes whose
|
|
9621
|
+
* bindings must be ready before the graph is used. `followDynamicImports: false`
|
|
9622
|
+
* stops at local `import()` boundaries, which wait for their own remotes.
|
|
9623
|
+
*/
|
|
9624
|
+
async function collectRemoteDependencies(ctx, id, isRemoteImport, { followDynamicImports = true, cache = /* @__PURE__ */ new Map() } = {}) {
|
|
9625
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
9626
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9627
|
+
const pending = [id];
|
|
9628
|
+
while (pending.length) {
|
|
9629
|
+
const current = pending.pop();
|
|
9630
|
+
if (seen.has(current) || !shouldScanResolvedImport(current)) continue;
|
|
9631
|
+
seen.add(current);
|
|
9632
|
+
let edges = cache.get(current);
|
|
9633
|
+
if (!edges) {
|
|
9634
|
+
edges = readModuleEdges(ctx, current, isRemoteImport);
|
|
9635
|
+
cache.set(current, edges);
|
|
9636
|
+
}
|
|
9637
|
+
const { remotes, staticImports, dynamicImports } = await edges;
|
|
9638
|
+
for (const remote of remotes) dependencies.add(remote);
|
|
9639
|
+
pending.push(...staticImports);
|
|
9640
|
+
if (followDynamicImports) pending.push(...dynamicImports);
|
|
9641
|
+
}
|
|
9642
|
+
return Array.from(dependencies).sort();
|
|
9395
9643
|
}
|
|
9396
9644
|
//#endregion
|
|
9397
9645
|
//#region src/plugins/pluginProxyRemoteEntry.ts
|
|
@@ -9407,67 +9655,39 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
9407
9655
|
let refreshPromise;
|
|
9408
9656
|
let dependencyInvalidationVersion = 0;
|
|
9409
9657
|
let reactIslandExposes = /* @__PURE__ */ new Set();
|
|
9658
|
+
let isTanStackStart = false;
|
|
9410
9659
|
const isHostAutoInitId = (id) => {
|
|
9411
|
-
|
|
9412
|
-
return cleanId.includes(getHostAutoInitPath(options)) || cleanId.includes(getHostAutoInitPath());
|
|
9660
|
+
return id.split("?")[0].includes(getHostAutoInitPath(options));
|
|
9413
9661
|
};
|
|
9414
9662
|
const getEnvironmentConditions = (context) => context.environment?.config?.resolve?.conditions;
|
|
9415
9663
|
const isSsrBuild = (context) => isServerBuildContext(context, viteConfig);
|
|
9664
|
+
const loadRemoteEntryCode = (context) => getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(context), isSsrBuild(context)));
|
|
9665
|
+
const loadExposesCode = async (context) => {
|
|
9666
|
+
await refreshExposeRemoteDependencies(context);
|
|
9667
|
+
return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
|
|
9668
|
+
};
|
|
9416
9669
|
function isRemoteImport(source) {
|
|
9417
|
-
return Object.keys(options.remotes)
|
|
9418
|
-
}
|
|
9419
|
-
function collectImportSources(code) {
|
|
9420
|
-
const sources = /* @__PURE__ */ new Map();
|
|
9421
|
-
for (const { source, kind, syntax, typeOnly } of findModuleImportDescriptors(code)) {
|
|
9422
|
-
if (syntax !== "import" || typeOnly) continue;
|
|
9423
|
-
const dynamic = kind === "dynamic";
|
|
9424
|
-
sources.set(source, (sources.get(source) ?? true) && dynamic);
|
|
9425
|
-
}
|
|
9426
|
-
return Array.from(sources, ([source, dynamic]) => ({
|
|
9427
|
-
source,
|
|
9428
|
-
dynamic
|
|
9429
|
-
})).sort((a, b) => a.source.localeCompare(b.source));
|
|
9430
|
-
}
|
|
9431
|
-
function shouldScanResolvedImport(id) {
|
|
9432
|
-
if (!id || id.includes("\0")) return false;
|
|
9433
|
-
if (id.includes("/node_modules/") || id.includes("\\node_modules\\")) return false;
|
|
9434
|
-
return /\.(?:[cm]?[jt]sx?|vue|svelte)(?:\?|$)/.test(id);
|
|
9435
|
-
}
|
|
9436
|
-
async function collectRemoteDependencies(ctx, id, seen = /* @__PURE__ */ new Set()) {
|
|
9437
|
-
if (seen.has(id) || !shouldScanResolvedImport(id)) return [];
|
|
9438
|
-
seen.add(id);
|
|
9439
|
-
let code;
|
|
9440
|
-
try {
|
|
9441
|
-
code = getScannableModuleSource(id, readFileSync$1(id, "utf8"));
|
|
9442
|
-
} catch {
|
|
9443
|
-
return [];
|
|
9444
|
-
}
|
|
9445
|
-
const dependencies = /* @__PURE__ */ new Set();
|
|
9446
|
-
for (const { source, dynamic } of collectImportSources(code)) {
|
|
9447
|
-
if (isRemoteImport(source)) {
|
|
9448
|
-
if (!dynamic) dependencies.add(source);
|
|
9449
|
-
continue;
|
|
9450
|
-
}
|
|
9451
|
-
let resolved;
|
|
9452
|
-
try {
|
|
9453
|
-
resolved = await ctx.resolve(source, id);
|
|
9454
|
-
} catch {
|
|
9455
|
-
continue;
|
|
9456
|
-
}
|
|
9457
|
-
if (!resolved?.id || !shouldScanResolvedImport(resolved.id)) continue;
|
|
9458
|
-
for (const dependency of await collectRemoteDependencies(ctx, resolved.id, seen)) dependencies.add(dependency);
|
|
9459
|
-
}
|
|
9460
|
-
return Array.from(dependencies).sort();
|
|
9670
|
+
return isRemoteSpecifier(source, Object.keys(options.remotes));
|
|
9461
9671
|
}
|
|
9462
9672
|
async function refreshExposeRemoteDependencies(ctx) {
|
|
9463
9673
|
if (!exposeRemoteDependenciesDirty) return;
|
|
9674
|
+
if (!hasRemotes(options)) {
|
|
9675
|
+
exposeRemoteDependencies = {};
|
|
9676
|
+
exposeRemoteDependenciesDirty = false;
|
|
9677
|
+
return;
|
|
9678
|
+
}
|
|
9464
9679
|
if (!refreshPromise) {
|
|
9465
9680
|
const refreshVersion = dependencyInvalidationVersion;
|
|
9466
9681
|
refreshPromise = (async () => {
|
|
9467
9682
|
const next = {};
|
|
9683
|
+
const cache = /* @__PURE__ */ new Map();
|
|
9684
|
+
const followDynamicImports = options.shareStrategy !== "loaded-first";
|
|
9468
9685
|
for (const [exposeKey, expose] of Object.entries(options.exposes)) {
|
|
9469
9686
|
const resolved = await ctx.resolve(expose.import);
|
|
9470
|
-
next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id
|
|
9687
|
+
next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id, isRemoteImport, {
|
|
9688
|
+
followDynamicImports,
|
|
9689
|
+
cache
|
|
9690
|
+
}) : [];
|
|
9471
9691
|
}
|
|
9472
9692
|
exposeRemoteDependencies = next;
|
|
9473
9693
|
if (refreshVersion === dependencyInvalidationVersion) exposeRemoteDependenciesDirty = false;
|
|
@@ -9487,6 +9707,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
9487
9707
|
configResolved(config) {
|
|
9488
9708
|
viteConfig = config;
|
|
9489
9709
|
root = config.root;
|
|
9710
|
+
isTanStackStart = config.plugins?.some((plugin) => plugin.name === "tanstack-start-core:config") ?? false;
|
|
9490
9711
|
reactIslandExposes = getReactIslandExposes(options, root);
|
|
9491
9712
|
},
|
|
9492
9713
|
config(config, { command }) {
|
|
@@ -9495,7 +9716,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
9495
9716
|
},
|
|
9496
9717
|
async buildStart() {
|
|
9497
9718
|
await refreshExposeRemoteDependencies(this);
|
|
9498
|
-
if (_command !== "build" ||
|
|
9719
|
+
if (_command !== "build" || isTanStackStart) return;
|
|
9499
9720
|
for (const expose of Object.values(options.exposes)) {
|
|
9500
9721
|
const resolved = await this.resolve(expose.import);
|
|
9501
9722
|
if (resolved) this.emitFile({
|
|
@@ -9521,21 +9742,15 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
9521
9742
|
}
|
|
9522
9743
|
},
|
|
9523
9744
|
async load(id) {
|
|
9524
|
-
if (id === remoteEntryId) return
|
|
9525
|
-
if (id === virtualExposesId)
|
|
9526
|
-
await refreshExposeRemoteDependencies(this);
|
|
9527
|
-
return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
|
|
9528
|
-
}
|
|
9745
|
+
if (id === remoteEntryId) return loadRemoteEntryCode(this);
|
|
9746
|
+
if (id === virtualExposesId) return loadExposesCode(this);
|
|
9529
9747
|
if (_command === "serve" && isHostAutoInitId(id)) return id;
|
|
9530
9748
|
},
|
|
9531
9749
|
async transform(code, id) {
|
|
9532
9750
|
return mapCodeToCodeWithSourcemap(await (async () => {
|
|
9533
9751
|
if (!filterId(id)) return;
|
|
9534
|
-
if (id.includes(remoteEntryId)) return
|
|
9535
|
-
if (id === virtualExposesId)
|
|
9536
|
-
await refreshExposeRemoteDependencies(this);
|
|
9537
|
-
return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
|
|
9538
|
-
}
|
|
9752
|
+
if (id.includes(remoteEntryId)) return loadRemoteEntryCode(this);
|
|
9753
|
+
if (id === virtualExposesId) return loadExposesCode(this);
|
|
9539
9754
|
if (isHostAutoInitId(id)) {
|
|
9540
9755
|
if (_command === "serve") {
|
|
9541
9756
|
const host = formatDevServerHostForOrigin(viteConfig.server?.host);
|
|
@@ -9649,7 +9864,7 @@ function pluginProxyRemotes_default(options) {
|
|
|
9649
9864
|
},
|
|
9650
9865
|
configResolved(config) {
|
|
9651
9866
|
hasMultiEnvironment = Boolean(config.environments?.ssr);
|
|
9652
|
-
enableSsrInit = getSsrCapabilities(parseInt(version, 10), command,
|
|
9867
|
+
enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, hasRemotes(options), isSsrConfig(config)).enableSsrInitBootstrap;
|
|
9653
9868
|
},
|
|
9654
9869
|
resolveId(source, importer) {
|
|
9655
9870
|
const resolvedIslandConsumerId = resolveReactIslandConsumerId(source);
|
|
@@ -9782,6 +9997,20 @@ function getSharedPackageFromFile(importer, shared, cwd = getPackageDetectionCwd
|
|
|
9782
9997
|
const normalizedImporter = normalizePathForImport(importer);
|
|
9783
9998
|
return [...cached.entries].find(([dir]) => normalizedImporter === dir || normalizedImporter.startsWith(`${dir}/`))?.[1] ?? getWorkspacePackageNameFromFile(normalizedImporter);
|
|
9784
9999
|
}
|
|
10000
|
+
/**
|
|
10001
|
+
* Whether an import of its own package from `importer` keeps an ordinary module edge. Internal
|
|
10002
|
+
* files and files of shared subpaths do; a file published only under an unshared subpath (e.g.
|
|
10003
|
+
* `vue/sub` when only `vue` is shared) imports the shared root like any consumer.
|
|
10004
|
+
*/
|
|
10005
|
+
function keepsOwnPackageEdge(importer, shared, cwd = getPackageDetectionCwd()) {
|
|
10006
|
+
const nodeModulePackage = importer && getPackageNameFromNodeModulePath(importer);
|
|
10007
|
+
if (!nodeModulePackage) return true;
|
|
10008
|
+
if (getInstalledPackageJson(nodeModulePackage, { cwd })?.packageJson.exports == null) return true;
|
|
10009
|
+
const packageSubpath = getNodeModulesSuffix(importer)?.slice(nodeModulePackage.length + 1);
|
|
10010
|
+
if (!packageSubpath) return true;
|
|
10011
|
+
const specifiers = getPackageExportSpecifiersForFile(nodeModulePackage, packageSubpath, { cwd });
|
|
10012
|
+
return specifiers.length === 0 || specifiers.some((specifier) => findSharedKey(specifier, shared));
|
|
10013
|
+
}
|
|
9785
10014
|
const workspacePackageNameCache = /* @__PURE__ */ new Map();
|
|
9786
10015
|
/** Name from the nearest `package.json` above `file`, for files outside `node_modules`. */
|
|
9787
10016
|
function getWorkspacePackageNameFromFile(file) {
|
|
@@ -10076,7 +10305,6 @@ function proxySharedModule(options) {
|
|
|
10076
10305
|
const getBuildImportAnalysis = (environment) => getImportAnalysis(environment ?? _config ?? options);
|
|
10077
10306
|
let _command = "serve";
|
|
10078
10307
|
let useDirectReactImport = false;
|
|
10079
|
-
let useRolldown = false;
|
|
10080
10308
|
let isProduction = false;
|
|
10081
10309
|
let rootResolveConditions;
|
|
10082
10310
|
let ssrResolveConditions;
|
|
@@ -10105,7 +10333,7 @@ function proxySharedModule(options) {
|
|
|
10105
10333
|
root: _config?.root || getPackageDetectionCwd(),
|
|
10106
10334
|
conditions: getRuntimeDependencyConditions(context, resolveOptions)
|
|
10107
10335
|
}));
|
|
10108
|
-
const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command,
|
|
10336
|
+
const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command, getEnvironmentConditions(context));
|
|
10109
10337
|
const normalizeTreeShakingOutputPath = (value) => {
|
|
10110
10338
|
const normalized = normalizePathForImport(value);
|
|
10111
10339
|
if (path$1.posix.isAbsolute(normalized) || /^[A-Za-z]:\//.test(normalized) || normalized.split("/").includes("..")) throw new Error(`Invalid treeShakingDir "${value}": absolute paths and parent segments are not allowed.`);
|
|
@@ -10117,8 +10345,7 @@ function proxySharedModule(options) {
|
|
|
10117
10345
|
};
|
|
10118
10346
|
const getTreeShakingProviderFileName = (pkg, shareItem) => {
|
|
10119
10347
|
if (!shareItem.shareConfig.treeShaking) return void 0;
|
|
10120
|
-
const
|
|
10121
|
-
const outputDir = normalizedOptions.treeShakingDir ? normalizeTreeShakingOutputPath(normalizedOptions.treeShakingDir) : void 0;
|
|
10348
|
+
const outputDir = federationOptions.treeShakingDir ? normalizeTreeShakingOutputPath(federationOptions.treeShakingDir) : void 0;
|
|
10122
10349
|
const fileName = outputDir ? path$1.posix.join(outputDir, `${getTreeShakingSharedProviderName(pkg, federationOptions)}.js`) : void 0;
|
|
10123
10350
|
if (!fileName) return void 0;
|
|
10124
10351
|
return fileName;
|
|
@@ -10182,9 +10409,7 @@ function proxySharedModule(options) {
|
|
|
10182
10409
|
workspacePackageNameCache.clear();
|
|
10183
10410
|
const isVinext = hasPackageDependency("vinext");
|
|
10184
10411
|
const isAstro = hasPackageDependency("astro");
|
|
10185
|
-
const isRolldown = getIsRolldown(this);
|
|
10186
10412
|
_command = command;
|
|
10187
|
-
useRolldown = isRolldown;
|
|
10188
10413
|
useDirectReactImport = isVinext || isAstro;
|
|
10189
10414
|
if (command === "serve") excludeSharedSubDependencies(shared);
|
|
10190
10415
|
},
|
|
@@ -10194,9 +10419,7 @@ function proxySharedModule(options) {
|
|
|
10194
10419
|
rootResolveConditions = config.resolve?.conditions ? [...config.resolve.conditions] : void 0;
|
|
10195
10420
|
ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
|
|
10196
10421
|
ssrTarget = config.ssr?.target ?? "node";
|
|
10197
|
-
const
|
|
10198
|
-
const resolvedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
|
|
10199
|
-
const registerConfiguredShare = _command === "build" && Object.keys(resolvedOptions.exposes).length > 0 ? addUsedShares : addConfiguredShare;
|
|
10422
|
+
const registerConfiguredShare = _command === "build" && isRemoteContainer(federationOptions) ? addUsedShares : addConfiguredShare;
|
|
10200
10423
|
Object.keys(shared).forEach((key) => {
|
|
10201
10424
|
if (key.endsWith("/") || getSharedRequest(key, shared[key]).endsWith("/")) return;
|
|
10202
10425
|
const runtimeKey = getSharedRuntimeKey(key, shared[key]);
|
|
@@ -10204,7 +10427,7 @@ function proxySharedModule(options) {
|
|
|
10204
10427
|
registerConfiguredShare(runtimeKey, federationOptions);
|
|
10205
10428
|
return;
|
|
10206
10429
|
}
|
|
10207
|
-
writeLoadShareModule(runtimeKey, shared[key], _command,
|
|
10430
|
+
writeLoadShareModule(runtimeKey, shared[key], _command, federationOptions);
|
|
10208
10431
|
if (shared[key].shareConfig.import !== false) writePreBuildLibPath(runtimeKey, shared[key], federationOptions);
|
|
10209
10432
|
registerConfiguredShare(runtimeKey, federationOptions);
|
|
10210
10433
|
});
|
|
@@ -10291,7 +10514,7 @@ function proxySharedModule(options) {
|
|
|
10291
10514
|
return taggedModule.name === sharedKey || matchesSharedSource(sharedSource, taggedModule.name);
|
|
10292
10515
|
};
|
|
10293
10516
|
const importerPackage = getSharedPackageFromFile(importer, shared);
|
|
10294
|
-
if (importerPackage === getPackageName(key)) return;
|
|
10517
|
+
if (importerPackage === getPackageName(key) && keepsOwnPackageEdge(importer, shared)) return;
|
|
10295
10518
|
if (importerPackage && shared[key].shareConfig.import !== false) {
|
|
10296
10519
|
const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
|
|
10297
10520
|
const request = getSharedRequest(key, shared[key]);
|
|
@@ -10311,10 +10534,10 @@ function proxySharedModule(options) {
|
|
|
10311
10534
|
const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
|
|
10312
10535
|
return tryResolveFromProjectRoot(localSource) || localSource;
|
|
10313
10536
|
}
|
|
10314
|
-
const loadSharePath = getLoadShareModulePath(shareSource,
|
|
10537
|
+
const loadSharePath = getLoadShareModulePath(shareSource, federationOptions);
|
|
10315
10538
|
if (!materializedLoadShareSources.has(shareSource)) {
|
|
10316
10539
|
materializedLoadShareSources.add(shareSource);
|
|
10317
|
-
writeLoadShareModule(shareSource, shared[key], _command,
|
|
10540
|
+
writeLoadShareModule(shareSource, shared[key], _command, federationOptions);
|
|
10318
10541
|
if (shared[key].shareConfig.import !== false) writePreBuildLibPath(shareSource, shared[key], federationOptions);
|
|
10319
10542
|
addUsedShares(shareSource, federationOptions);
|
|
10320
10543
|
writeLocalSharedImportMap(federationOptions);
|
|
@@ -10447,6 +10670,13 @@ function applyRewrites(code, imports, id) {
|
|
|
10447
10670
|
ms.overwrite(imp.start, imp.end, wrapDynamicImport(imp.originalText));
|
|
10448
10671
|
changed = true;
|
|
10449
10672
|
break;
|
|
10673
|
+
case "local-dynamic": {
|
|
10674
|
+
if (imp.remotes.length === 0) break;
|
|
10675
|
+
const ready = imp.remotes.map((remote) => `import(${JSON.stringify(remote)}).then(function(__mf_m__) { return __mf_m__.__mf_remote_pending; })`);
|
|
10676
|
+
ms.overwrite(imp.start, imp.end, `Promise.all([${imp.originalText}, ${ready.join(", ")}]).then(function(__mf_r__) { return __mf_r__[0]; })`);
|
|
10677
|
+
changed = true;
|
|
10678
|
+
break;
|
|
10679
|
+
}
|
|
10450
10680
|
}
|
|
10451
10681
|
if (!changed) return;
|
|
10452
10682
|
if (dependencyPendingIds.length > 0) ms.overwrite(code.length, code.length, `\nexport const __mf_remote_dependency_pending = Promise.all([${dependencyPendingIds.join(", ")}]);`);
|
|
@@ -10455,7 +10685,7 @@ function applyRewrites(code, imports, id) {
|
|
|
10455
10685
|
map: ms.generateMap(id)
|
|
10456
10686
|
};
|
|
10457
10687
|
}
|
|
10458
|
-
async function collectFromAST(ast, code, isRemoteImport) {
|
|
10688
|
+
async function collectFromAST(ast, code, isRemoteImport, collectLocalDynamic) {
|
|
10459
10689
|
const result = [];
|
|
10460
10690
|
walkAST(ast, { enter(node) {
|
|
10461
10691
|
if (node.type === "ImportDeclaration" && node.source?.value) {
|
|
@@ -10505,19 +10735,28 @@ async function collectFromAST(ast, code, isRemoteImport) {
|
|
|
10505
10735
|
const source = node.source;
|
|
10506
10736
|
if (source.type !== "Literal" && source.type !== "StringLiteral" && source.type !== "TemplateLiteral") return;
|
|
10507
10737
|
const value = source.type === "TemplateLiteral" ? source.quasis?.length === 1 ? source.quasis[0].value?.cooked : void 0 : source.value;
|
|
10508
|
-
if (!value
|
|
10509
|
-
|
|
10738
|
+
if (!value) return;
|
|
10739
|
+
const originalText = code.slice(node.start, node.end);
|
|
10740
|
+
if (isRemoteImport(value)) result.push({
|
|
10510
10741
|
kind: "dynamic",
|
|
10511
10742
|
source: value,
|
|
10512
10743
|
start: node.start,
|
|
10513
10744
|
end: node.end,
|
|
10514
|
-
originalText
|
|
10745
|
+
originalText
|
|
10746
|
+
});
|
|
10747
|
+
else if (collectLocalDynamic) result.push({
|
|
10748
|
+
kind: "local-dynamic",
|
|
10749
|
+
source: value,
|
|
10750
|
+
start: node.start,
|
|
10751
|
+
end: node.end,
|
|
10752
|
+
originalText,
|
|
10753
|
+
remotes: []
|
|
10515
10754
|
});
|
|
10516
10755
|
}
|
|
10517
10756
|
} });
|
|
10518
10757
|
return result;
|
|
10519
10758
|
}
|
|
10520
|
-
function collectFromRegex(code, isRemoteImport) {
|
|
10759
|
+
function collectFromRegex(code, isRemoteImport, collectLocalDynamic) {
|
|
10521
10760
|
const result = [];
|
|
10522
10761
|
const codePositions = createCodePositionMap(code);
|
|
10523
10762
|
const importAttributes = String.raw`(?:\s+(?:with|assert)\s+\{[^;]*\})?`;
|
|
@@ -10584,26 +10823,35 @@ function collectFromRegex(code, isRemoteImport) {
|
|
|
10584
10823
|
for (const match of code.matchAll(/import\(\s*(?:\/\*[\s\S]*?\*\/\s*)?(['"])([^'"]+)\1\s*\)/g)) {
|
|
10585
10824
|
const [full, , source] = match;
|
|
10586
10825
|
if (!codePositions[match.index]) continue;
|
|
10587
|
-
|
|
10588
|
-
result.push({
|
|
10589
|
-
kind: "dynamic",
|
|
10826
|
+
const position = {
|
|
10590
10827
|
source,
|
|
10591
10828
|
start: match.index,
|
|
10592
|
-
end: match.index + full.length
|
|
10829
|
+
end: match.index + full.length
|
|
10830
|
+
};
|
|
10831
|
+
if (isRemoteImport(source)) result.push({
|
|
10832
|
+
kind: "dynamic",
|
|
10833
|
+
...position,
|
|
10593
10834
|
originalText: full
|
|
10594
10835
|
});
|
|
10836
|
+
else if (collectLocalDynamic) result.push({
|
|
10837
|
+
kind: "local-dynamic",
|
|
10838
|
+
...position,
|
|
10839
|
+
originalText: full,
|
|
10840
|
+
remotes: []
|
|
10841
|
+
});
|
|
10595
10842
|
}
|
|
10596
10843
|
return result.length > 0 ? result : void 0;
|
|
10597
10844
|
}
|
|
10598
10845
|
function pluginRemoteNamedExports(options) {
|
|
10599
10846
|
const remoteNames = Object.keys(options.remotes);
|
|
10847
|
+
const waitsAtDynamicImports = options.shareStrategy === "loaded-first";
|
|
10848
|
+
let remoteDependencyCache = /* @__PURE__ */ new Map();
|
|
10600
10849
|
let root = process.cwd();
|
|
10601
|
-
const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
|
|
10602
10850
|
function isRemoteImport(source, importerId) {
|
|
10603
10851
|
return remoteNames.some((name) => {
|
|
10604
10852
|
if (source.startsWith(name + "/")) return true;
|
|
10605
10853
|
if (source !== name) return false;
|
|
10606
|
-
return !
|
|
10854
|
+
return !isNodeModulePath(importerId) || !getInstalledPackageEntry(source, { cwd: root });
|
|
10607
10855
|
}) || source.includes("__loadRemote__");
|
|
10608
10856
|
}
|
|
10609
10857
|
return {
|
|
@@ -10612,11 +10860,15 @@ function pluginRemoteNamedExports(options) {
|
|
|
10612
10860
|
configResolved(config) {
|
|
10613
10861
|
root = config.root || process.cwd();
|
|
10614
10862
|
},
|
|
10863
|
+
watchChange() {
|
|
10864
|
+
remoteDependencyCache = /* @__PURE__ */ new Map();
|
|
10865
|
+
},
|
|
10615
10866
|
async transform(code, id) {
|
|
10616
10867
|
if (remoteNames.length === 0) return;
|
|
10617
10868
|
if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
|
|
10618
10869
|
if (!JS_EXTENSIONS_RE.test(id)) return;
|
|
10619
|
-
|
|
10870
|
+
const collectLocalDynamic = waitsAtDynamicImports && !isNodeModulePath(id) && /\bimport\s*\(/.test(code);
|
|
10871
|
+
if (!collectLocalDynamic && !remoteNames.some((name) => code.includes(name))) return;
|
|
10620
10872
|
const descriptors = findModuleImportDescriptors(code);
|
|
10621
10873
|
const resolvedElsewhere = /* @__PURE__ */ new Set();
|
|
10622
10874
|
for (const source of new Set(descriptors.map((d) => d.source))) {
|
|
@@ -10628,12 +10880,26 @@ function pluginRemoteNamedExports(options) {
|
|
|
10628
10880
|
for (const { kind, source, typeOnly } of descriptors) if (kind === "static" && !typeOnly && matchesRemoteImport(source)) markStaticRemote(source, options);
|
|
10629
10881
|
let imports;
|
|
10630
10882
|
try {
|
|
10631
|
-
imports = await collectFromAST(this.parse(code), code, matchesRemoteImport);
|
|
10883
|
+
imports = await collectFromAST(this.parse(code), code, matchesRemoteImport, collectLocalDynamic);
|
|
10632
10884
|
} catch {
|
|
10633
10885
|
if ((id.includes(".vue") || id.includes(".svelte")) && /^\s*</.test(code)) return;
|
|
10634
|
-
imports = collectFromRegex(code, matchesRemoteImport);
|
|
10886
|
+
imports = collectFromRegex(code, matchesRemoteImport, collectLocalDynamic);
|
|
10635
10887
|
}
|
|
10636
10888
|
if (!imports) return;
|
|
10889
|
+
for (const localImport of imports) {
|
|
10890
|
+
if (localImport.kind !== "local-dynamic") continue;
|
|
10891
|
+
let resolved;
|
|
10892
|
+
try {
|
|
10893
|
+
resolved = await this.resolve(localImport.source, id);
|
|
10894
|
+
} catch {
|
|
10895
|
+
continue;
|
|
10896
|
+
}
|
|
10897
|
+
if (!resolved?.id) continue;
|
|
10898
|
+
localImport.remotes = await collectRemoteDependencies(this, resolved.id, (source) => isRemoteSpecifier(source, remoteNames), {
|
|
10899
|
+
followDynamicImports: false,
|
|
10900
|
+
cache: remoteDependencyCache
|
|
10901
|
+
});
|
|
10902
|
+
}
|
|
10637
10903
|
for (const remoteImport of imports) if (remoteImport.kind === "dynamic") markDynamicRemote(remoteImport.source, options);
|
|
10638
10904
|
return applyRewrites(code, imports, id);
|
|
10639
10905
|
}
|
|
@@ -10768,6 +11034,8 @@ function readBoundedRunnerBody(req, res) {
|
|
|
10768
11034
|
*/
|
|
10769
11035
|
function pluginSSRRemoteEntry(options) {
|
|
10770
11036
|
const remoteEntrySSRId = getRemoteEntrySSRId(options);
|
|
11037
|
+
const ssrHostInitId = getSsrHostInitId(options);
|
|
11038
|
+
let hostInitChunkRef;
|
|
10771
11039
|
const virtualExposesSSRId = getVirtualExposesSSRId(options);
|
|
10772
11040
|
let cachedSsrRemoteEntrySource;
|
|
10773
11041
|
const ssrOutputFilename = getSsrRemoteEntryFileName(options);
|
|
@@ -10799,7 +11067,7 @@ function pluginSSRRemoteEntry(options) {
|
|
|
10799
11067
|
const environmentName = environment?.name;
|
|
10800
11068
|
const hasSsrEnvironment = Boolean(viteConfig?.environments?.ssr);
|
|
10801
11069
|
const isLegacySsrBuild = Boolean(environment?.config?.build?.ssr ?? viteConfig?.build?.ssr);
|
|
10802
|
-
return
|
|
11070
|
+
return isRemoteContainer(options) && !(hasSsrEnvironment && environmentName !== "ssr" || !hasSsrEnvironment && !isLegacySsrBuild);
|
|
10803
11071
|
};
|
|
10804
11072
|
const getSsrRemoteEntrySource = () => {
|
|
10805
11073
|
if (cachedSsrRemoteEntrySource === void 0) cachedSsrRemoteEntrySource = generateRemoteEntrySSR(options);
|
|
@@ -10831,6 +11099,7 @@ function pluginSSRRemoteEntry(options) {
|
|
|
10831
11099
|
resolveId(id, importer) {
|
|
10832
11100
|
if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
|
|
10833
11101
|
if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
|
|
11102
|
+
if (id === ssrHostInitId) return this.resolve(getHostAutoInitPath(options), importer, { skipSelf: true });
|
|
10834
11103
|
if (!importer || !ssrModuleIds.has(importer)) return;
|
|
10835
11104
|
if (ssrOnlyExternalPattern.test(id) && !isNoExternal(id)) return {
|
|
10836
11105
|
id,
|
|
@@ -10901,8 +11170,13 @@ function pluginSSRRemoteEntry(options) {
|
|
|
10901
11170
|
} };
|
|
10902
11171
|
} catch {}
|
|
10903
11172
|
}
|
|
11173
|
+
const fetchedId = body.data.name === "fetchModule" ? body.data.data[0] : void 0;
|
|
11174
|
+
const shared = typeof fetchedId === "string" && !!findSharedKey(fetchedId, options.shared);
|
|
10904
11175
|
res.setHeader("Content-Type", "application/json");
|
|
10905
|
-
res.end(JSON.stringify(
|
|
11176
|
+
res.end(JSON.stringify(shared ? {
|
|
11177
|
+
...result,
|
|
11178
|
+
shared
|
|
11179
|
+
} : result));
|
|
10906
11180
|
} catch (e) {
|
|
10907
11181
|
res.setHeader("Content-Type", "application/json");
|
|
10908
11182
|
res.end(JSON.stringify({ error: { message: String(e instanceof Error ? e.message : e) } }));
|
|
@@ -10938,6 +11212,12 @@ function pluginSSRRemoteEntry(options) {
|
|
|
10938
11212
|
const isRolldown = getIsRolldown(this);
|
|
10939
11213
|
const environment = this.environment;
|
|
10940
11214
|
if (!isSsrRemoteEntryBuild(environment)) return;
|
|
11215
|
+
if (!isRolldown && hasRemotes(options)) hostInitChunkRef = this.emitFile({
|
|
11216
|
+
type: "chunk",
|
|
11217
|
+
id: ssrHostInitId,
|
|
11218
|
+
name: "hostInit",
|
|
11219
|
+
preserveSignature: "strict"
|
|
11220
|
+
});
|
|
10941
11221
|
if (isRolldown) this.emitFile({
|
|
10942
11222
|
type: "chunk",
|
|
10943
11223
|
id: remoteEntrySSRId,
|
|
@@ -10945,7 +11225,7 @@ function pluginSSRRemoteEntry(options) {
|
|
|
10945
11225
|
fileName: ssrOutputFilename,
|
|
10946
11226
|
preserveSignature: "strict"
|
|
10947
11227
|
});
|
|
10948
|
-
else if (
|
|
11228
|
+
else if (isRemoteContainer(options) && !isNuxtLike()) this.emitFile({
|
|
10949
11229
|
type: "chunk",
|
|
10950
11230
|
id: virtualExposesSSRId,
|
|
10951
11231
|
name: "ssrExposes",
|
|
@@ -10960,11 +11240,8 @@ function pluginSSRRemoteEntry(options) {
|
|
|
10960
11240
|
const exposesChunk = findNuxtExposesChunk(bundle) ?? findEmittedExposesChunk(bundle);
|
|
10961
11241
|
if (!isRolldown && isSsrRemoteEntryBuild(environment)) {
|
|
10962
11242
|
let source = getSsrRemoteEntrySource();
|
|
10963
|
-
if (
|
|
10964
|
-
|
|
10965
|
-
if (!exposesImport.startsWith(".")) exposesImport = `./${exposesImport}`;
|
|
10966
|
-
source = source.replace(/import\("virtual:mf-exposes-ssr:[^"]+"\)/g, `import("${exposesImport}")`);
|
|
10967
|
-
}
|
|
11243
|
+
if (hasRemotes(options) && hostInitChunkRef) source = source.replace(JSON.stringify(ssrHostInitId), JSON.stringify(toRelativeImport(ssrOutputFilename, this.getFileName(hostInitChunkRef))));
|
|
11244
|
+
if (exposesChunk) source = source.replace(/import\("virtual:mf-exposes-ssr:[^"]+"\)/g, `import("${toRelativeImport(ssrOutputFilename, exposesChunk)}")`);
|
|
10968
11245
|
this.emitFile({
|
|
10969
11246
|
type: "asset",
|
|
10970
11247
|
fileName: ssrOutputFilename,
|
|
@@ -11095,7 +11372,13 @@ const VarRemoteEntry = (providedOptions) => {
|
|
|
11095
11372
|
}
|
|
11096
11373
|
}];
|
|
11097
11374
|
function isValidVarName(name) {
|
|
11098
|
-
|
|
11375
|
+
if (!isValidJsIdentifier(name)) return false;
|
|
11376
|
+
try {
|
|
11377
|
+
new Function(`var ${name};`);
|
|
11378
|
+
return true;
|
|
11379
|
+
} catch {
|
|
11380
|
+
return false;
|
|
11381
|
+
}
|
|
11099
11382
|
}
|
|
11100
11383
|
/**
|
|
11101
11384
|
* Generates the final "var" remote entry file
|
|
@@ -11107,27 +11390,122 @@ const VarRemoteEntry = (providedOptions) => {
|
|
|
11107
11390
|
const isValidName = isValidVarName(name);
|
|
11108
11391
|
return `
|
|
11109
11392
|
${isValidName ? `var ${name};` : ""}
|
|
11110
|
-
|
|
11393
|
+
(function (global) {
|
|
11394
|
+
const name = ${toSafeJsLiteral(name)};
|
|
11395
|
+
const descriptor = Object.getOwnPropertyDescriptor(global, name);
|
|
11396
|
+
const prototype = Object.getPrototypeOf(global);
|
|
11397
|
+
const emptyVarSlot = ${isValidName} && descriptor && 'value' in descriptor && descriptor.value === undefined && descriptor.writable && !(prototype && name in prototype);
|
|
11398
|
+
if (name in global && !emptyVarSlot) {
|
|
11399
|
+
const existing = descriptor && 'value' in descriptor ? descriptor.value : undefined;
|
|
11400
|
+
if (existing && typeof existing.get === 'function' && typeof existing.init === 'function') {
|
|
11401
|
+
return;
|
|
11402
|
+
}
|
|
11403
|
+
throw new Error('[Module Federation] Cannot register var remote "' + name + '" because the global already exists. Choose a different federation name or use an ESM remote.');
|
|
11404
|
+
}
|
|
11405
|
+
|
|
11111
11406
|
function getScriptUrl() {
|
|
11112
11407
|
const currentScript = document.currentScript;
|
|
11113
11408
|
if (!currentScript) {
|
|
11114
|
-
console.error(
|
|
11409
|
+
console.error(${toSafeJsLiteral(`[Module Federation] ${varFilename} script should be called from sync <script> tag (document.currentScript is undefined)`)})
|
|
11115
11410
|
return '/';
|
|
11116
11411
|
}
|
|
11117
11412
|
return document.currentScript.src.replace(/\\/[^/]*$/, '/');
|
|
11118
11413
|
}
|
|
11119
11414
|
|
|
11120
|
-
const entry = getScriptUrl() +
|
|
11415
|
+
const entry = getScriptUrl() + ${toSafeJsLiteral(remoteEntryFile)};
|
|
11121
11416
|
|
|
11122
|
-
|
|
11417
|
+
global[name] = {
|
|
11123
11418
|
get: (...args) => import(entry).then(m => m.get(...args)),
|
|
11124
11419
|
init: (...args) => import(entry).then(m => m.init(...args)),
|
|
11125
11420
|
};
|
|
11126
|
-
})();
|
|
11421
|
+
})(globalThis);
|
|
11127
11422
|
`;
|
|
11128
11423
|
}
|
|
11129
11424
|
};
|
|
11130
11425
|
//#endregion
|
|
11426
|
+
//#region src/plugins/pluginSsrRuntimeInit.ts
|
|
11427
|
+
/** Register the SSR host before application evaluation, without preloading remotes. */
|
|
11428
|
+
function pluginSsrRuntimeInit(options) {
|
|
11429
|
+
if (!hasRemotes(options)) return [];
|
|
11430
|
+
let command;
|
|
11431
|
+
let legacySsr = false;
|
|
11432
|
+
let supported = false;
|
|
11433
|
+
const server = (ctx, ssr) => supported && isServerContext(ctx, ssr === true || legacySsr);
|
|
11434
|
+
return [{
|
|
11435
|
+
name: "module-federation-ssr-runtime-init",
|
|
11436
|
+
enforce: "post",
|
|
11437
|
+
config(_config, env) {
|
|
11438
|
+
command = env.command;
|
|
11439
|
+
},
|
|
11440
|
+
configResolved(config) {
|
|
11441
|
+
legacySsr = Boolean(config.build.ssr);
|
|
11442
|
+
supported = getSsrCapabilities(parseInt(version, 10), command, true, isSsrConfig(config)).enableSsrInitBootstrap;
|
|
11443
|
+
},
|
|
11444
|
+
resolveId: {
|
|
11445
|
+
order: "pre",
|
|
11446
|
+
handler(id, _importer, resolveOptions) {
|
|
11447
|
+
if (server(this, resolveOptions.ssr) && id === options.implementation) return {
|
|
11448
|
+
id: options.implementation,
|
|
11449
|
+
external: false
|
|
11450
|
+
};
|
|
11451
|
+
}
|
|
11452
|
+
},
|
|
11453
|
+
transform(code, id, transformOptions) {
|
|
11454
|
+
if (!server(this, transformOptions?.ssr)) return;
|
|
11455
|
+
if (isOwnedHostAutoInitId(id, options)) {
|
|
11456
|
+
const pluginImports = options.runtimePlugins.map((plugin, index) => `import plugin${index} from ${toSafeJsLiteral(getRuntimePluginSpecifier(plugin))};`).join("\n");
|
|
11457
|
+
const plugins = options.runtimePlugins.map((plugin, index) => `plugin${index}(${Array.isArray(plugin) ? serializeRuntimeOptions(plugin[1]) : ""})`).join(",");
|
|
11458
|
+
return {
|
|
11459
|
+
code: `
|
|
11460
|
+
import { init } from ${toSafeJsLiteral(options.implementation)};
|
|
11461
|
+
import { usedShared, usedRemotes } from ${toSafeJsLiteral(getLocalSharedImportMapPath(options))};
|
|
11462
|
+
${pluginImports}
|
|
11463
|
+
${getRuntimeInitBootstrapCode(false, getRuntimeInitStatusImportId(options))}
|
|
11464
|
+
globalThis[globalKey].ssrInitStarted = true;
|
|
11465
|
+
// These remotes are registered before application code, under owner-scoped
|
|
11466
|
+
// names aliased to their configured names, and the runtime resolves an id
|
|
11467
|
+
// against the first remote whose name or alias matches. Drop the alias once the
|
|
11468
|
+
// application registers a remote under that name or alias, so its entry wins.
|
|
11469
|
+
const bootstrapRemoteNames = new Set(usedRemotes.map((remote) => remote.name));
|
|
11470
|
+
const applicationRemotePlugin = {
|
|
11471
|
+
name: 'vite-ssr-application-remote-plugin',
|
|
11472
|
+
beforeRegisterRemote(args) {
|
|
11473
|
+
const { name, alias } = args.remote;
|
|
11474
|
+
if (bootstrapRemoteNames.has(name)) return args;
|
|
11475
|
+
for (const registered of args.origin.options.remotes) {
|
|
11476
|
+
if (
|
|
11477
|
+
bootstrapRemoteNames.has(registered.name) &&
|
|
11478
|
+
(registered.alias === name || registered.alias === alias)
|
|
11479
|
+
) {
|
|
11480
|
+
delete registered.alias;
|
|
11481
|
+
}
|
|
11482
|
+
}
|
|
11483
|
+
return args;
|
|
11484
|
+
},
|
|
11485
|
+
};
|
|
11486
|
+
const runtime = init({
|
|
11487
|
+
name: ${toSafeJsLiteral(options.name)},
|
|
11488
|
+
remotes: usedRemotes,
|
|
11489
|
+
shared: usedShared,
|
|
11490
|
+
plugins: [applicationRemotePlugin, ${plugins}],
|
|
11491
|
+
shareStrategy: ${toSafeJsLiteral(options.shareStrategy)},
|
|
11492
|
+
});
|
|
11493
|
+
const hostInitPromise = Promise.resolve(runtime);
|
|
11494
|
+
globalThis[globalKey].initResolve(runtime);
|
|
11495
|
+
function initHost() { return hostInitPromise; }
|
|
11496
|
+
export { initHost, hostInitPromise };
|
|
11497
|
+
`,
|
|
11498
|
+
map: null
|
|
11499
|
+
};
|
|
11500
|
+
}
|
|
11501
|
+
if (!(command === "build" && this.getModuleInfo(id)?.isEntry) && !findModuleImportSources(code).includes("@module-federation/runtime")) return;
|
|
11502
|
+
const injection = `import ${toSafeJsLiteral(getHostAutoInitPath(options))};\n`;
|
|
11503
|
+
if (code.includes(injection.trim())) return;
|
|
11504
|
+
return mapCodeToCodeWithSourcemap(injection + code);
|
|
11505
|
+
}
|
|
11506
|
+
}];
|
|
11507
|
+
}
|
|
11508
|
+
//#endregion
|
|
11131
11509
|
//#region src/utils/aliasToArrayPlugin.ts
|
|
11132
11510
|
var aliasToArrayPlugin_default = {
|
|
11133
11511
|
name: "alias-transform-plugin",
|
|
@@ -11276,145 +11654,6 @@ function sanitizeFederationControlChunk(code, fileName, filename) {
|
|
|
11276
11654
|
return nextCode;
|
|
11277
11655
|
}
|
|
11278
11656
|
//#endregion
|
|
11279
|
-
//#region src/utils/isTestEnv.ts
|
|
11280
|
-
/**
|
|
11281
|
-
* Detects whether the current process is running in a test environment
|
|
11282
|
-
* Set `MFE_VITE_NO_TEST_ENV_CHECK=true` to load federation plugins during tests.
|
|
11283
|
-
*/
|
|
11284
|
-
function isTestEnv() {
|
|
11285
|
-
if (process.env.MFE_VITE_NO_TEST_ENV_CHECK === "true") return false;
|
|
11286
|
-
return process.env.NODE_ENV === "test" || process.env.VITEST != null || process.env.JEST_WORKER_ID != null;
|
|
11287
|
-
}
|
|
11288
|
-
//#endregion
|
|
11289
|
-
//#region src/utils/hostProvidesAllShared.ts
|
|
11290
|
-
/** Virtual-module prefix of the host's per-share re-export entries. */
|
|
11291
|
-
const SHARE_MODULE_PREFIX = "\0mf-host-provided-share:";
|
|
11292
|
-
/** `./a/b` → `a/b`, `.` → `index`: the fixed entry name of an expose, without `.js`. */
|
|
11293
|
-
function exposeEntryName(exposeKey) {
|
|
11294
|
-
return exposeKey === "." ? "index" : exposeKey.replace(/^\.\//, "");
|
|
11295
|
-
}
|
|
11296
|
-
/** Bare specifier a host uses for an expose: `remote` for `.`, `remote/a/b` otherwise. */
|
|
11297
|
-
function remoteSpecifier(remoteName, exposeKey) {
|
|
11298
|
-
const entry = exposeEntryName(exposeKey);
|
|
11299
|
-
return entry === "index" ? remoteName : `${remoteName}/${entry}`;
|
|
11300
|
-
}
|
|
11301
|
-
/** `id` is a remote alias or a subpath of one. */
|
|
11302
|
-
function isRemoteSpecifier(id, remoteKeys) {
|
|
11303
|
-
return remoteKeys.some((key) => id === key || id.startsWith(`${key}/`));
|
|
11304
|
-
}
|
|
11305
|
-
/**
|
|
11306
|
-
* The shared key that owns `id`: an exact match, else the longest key `id` is a subpath
|
|
11307
|
-
* of (`lodash-es/debounce` → `lodash-es`). Used to spot an unshared subpath of a shared
|
|
11308
|
-
* package, which would bundle a private copy of that package into a remote.
|
|
11309
|
-
*/
|
|
11310
|
-
function sharedKeyOwning(id, sharedKeys) {
|
|
11311
|
-
let owner;
|
|
11312
|
-
for (const key of sharedKeys) {
|
|
11313
|
-
if (id !== key && !id.startsWith(`${key}/`)) continue;
|
|
11314
|
-
if (!owner || key.length > owner.length) owner = key;
|
|
11315
|
-
}
|
|
11316
|
-
return owner;
|
|
11317
|
-
}
|
|
11318
|
-
/** Chunk name of the host's re-export entry for a shared key. */
|
|
11319
|
-
function shareChunkName(key) {
|
|
11320
|
-
return `shared/${key.replace(/^@/, "").replace(/[^\w-]+/g, "-")}`;
|
|
11321
|
-
}
|
|
11322
|
-
/** Reads a remote's `mf-manifest.json` from a URL or a path relative to `root`. */
|
|
11323
|
-
async function readHostProvidesAllSharedManifest(location, root) {
|
|
11324
|
-
let source;
|
|
11325
|
-
if (isAbsoluteUrl(location)) {
|
|
11326
|
-
const response = await fetch(location);
|
|
11327
|
-
if (!response.ok) throw new Error(`Failed to fetch ${location}: ${response.status} ${response.statusText}`);
|
|
11328
|
-
source = await response.text();
|
|
11329
|
-
} else source = await readFile(path$1.resolve(root, location), "utf8");
|
|
11330
|
-
const manifest = JSON.parse(source);
|
|
11331
|
-
if (!manifest.metaData || !Array.isArray(manifest.exposes)) throw new Error(`${location} is not a Module Federation manifest.`);
|
|
11332
|
-
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 }\`.`);
|
|
11333
|
-
return manifest;
|
|
11334
|
-
}
|
|
11335
|
-
/** URL prefix of a remote's files: `metaData.publicPath`, `auto` inferred from the manifest URL. */
|
|
11336
|
-
function remotePublicPath(manifest, location) {
|
|
11337
|
-
const publicPath = manifest.metaData.publicPath ?? "auto";
|
|
11338
|
-
if (publicPath !== "auto") return ensureTrailingSlash(publicPath);
|
|
11339
|
-
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.`);
|
|
11340
|
-
return ensureTrailingSlash(inferAutoPublicPath(location));
|
|
11341
|
-
}
|
|
11342
|
-
/** Import-map entries (`remote/Expose` → URL) for every expose of every remote. */
|
|
11343
|
-
async function collectRemoteImports(remotes, root) {
|
|
11344
|
-
const imports = {};
|
|
11345
|
-
for (const [alias, remote] of Object.entries(remotes)) {
|
|
11346
|
-
const manifest = await readHostProvidesAllSharedManifest(remote.entry, root);
|
|
11347
|
-
const publicPath = remotePublicPath(manifest, remote.entry);
|
|
11348
|
-
for (const expose of manifest.exposes) {
|
|
11349
|
-
const file = expose.assets.js.sync[0];
|
|
11350
|
-
if (!expose.path || !file) continue;
|
|
11351
|
-
imports[remoteSpecifier(alias, expose.path)] = isAbsoluteUrl(remote.entry) ? new URL(file, new URL(publicPath, remote.entry)).href : publicPath + file;
|
|
11352
|
-
}
|
|
11353
|
-
}
|
|
11354
|
-
return imports;
|
|
11355
|
-
}
|
|
11356
|
-
/** Top-level options that only the Module Federation runtime or `remoteEntry.js` pipeline reads. */
|
|
11357
|
-
const IGNORED_OPTIONS = [
|
|
11358
|
-
"filename",
|
|
11359
|
-
"ssrFilename",
|
|
11360
|
-
"varFilename",
|
|
11361
|
-
"library",
|
|
11362
|
-
"runtime",
|
|
11363
|
-
"shareScope",
|
|
11364
|
-
"shareStrategy",
|
|
11365
|
-
"runtimePlugins",
|
|
11366
|
-
"implementation",
|
|
11367
|
-
"getPublicPath",
|
|
11368
|
-
"ignoreOrigin",
|
|
11369
|
-
"virtualModuleDir",
|
|
11370
|
-
"hostInitInjectLocation",
|
|
11371
|
-
"bundleAllCSS",
|
|
11372
|
-
"treeShakingDir",
|
|
11373
|
-
"injectTreeShakingUsedExports",
|
|
11374
|
-
"treeShakingSharedPlugins",
|
|
11375
|
-
"treeShakingSharedExcludePlugins",
|
|
11376
|
-
"moduleParseTimeout",
|
|
11377
|
-
"moduleParseIdleTimeout",
|
|
11378
|
-
"target",
|
|
11379
|
-
"ssrExternals",
|
|
11380
|
-
"ssrEntryLoader",
|
|
11381
|
-
"disableRemote",
|
|
11382
|
-
"disableShared",
|
|
11383
|
-
"disableSnapshot"
|
|
11384
|
-
];
|
|
11385
|
-
const IGNORED_EXPERIMENTS = [
|
|
11386
|
-
"externalRuntime",
|
|
11387
|
-
"provideExternalRuntime",
|
|
11388
|
-
"ssrMode"
|
|
11389
|
-
];
|
|
11390
|
-
/** Per-share options: version negotiation, aliasing and fallbacks do not exist in this mode. */
|
|
11391
|
-
const IGNORED_SHARE_OPTIONS = [
|
|
11392
|
-
"eager",
|
|
11393
|
-
"requiredVersion",
|
|
11394
|
-
"strictVersion",
|
|
11395
|
-
"import",
|
|
11396
|
-
"request",
|
|
11397
|
-
"shareKey",
|
|
11398
|
-
"name",
|
|
11399
|
-
"version",
|
|
11400
|
-
"shareScope",
|
|
11401
|
-
"treeShaking",
|
|
11402
|
-
"allowNodeModulesSuffixMatch",
|
|
11403
|
-
"suppressMissingImportWarning"
|
|
11404
|
-
];
|
|
11405
|
-
const isSet = (value) => value !== void 0 && value !== false && !(Array.isArray(value) && value.length === 0);
|
|
11406
|
-
/** A single warning naming every option the user set that import-map mode ignores. */
|
|
11407
|
-
function getIgnoredOptionWarning(options) {
|
|
11408
|
-
const shared = options.shared;
|
|
11409
|
-
const ignored = [
|
|
11410
|
-
...IGNORED_OPTIONS.filter((key) => isSet(options[key])).map((key) => `\`${key}\``),
|
|
11411
|
-
...IGNORED_EXPERIMENTS.filter((key) => isSet(options.experiments?.[key])).map((key) => `\`experiments.${key}\``),
|
|
11412
|
-
...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}\``) : []) : []
|
|
11413
|
-
];
|
|
11414
|
-
if (ignored.length === 0) return void 0;
|
|
11415
|
-
return `experiments.hostProvidesAllShared: ${ignored.join(", ")} ignored. The Module Federation runtime is not used and the host provides the only copy of every shared key.`;
|
|
11416
|
-
}
|
|
11417
|
-
//#endregion
|
|
11418
11657
|
//#region src/plugins/pluginHostProvidesAllSharedHost.ts
|
|
11419
11658
|
const ESM_SYNTAX_RE = /(^|[\s;])(export|import)[\s{*]/m;
|
|
11420
11659
|
const DEFAULT_EXPORT_RE = /export\s+default\b|export\s*\{[^}]*\bas\s+default\b/;
|
|
@@ -11640,28 +11879,6 @@ function pluginHostProvidesAllSharedRemote(options) {
|
|
|
11640
11879
|
};
|
|
11641
11880
|
}
|
|
11642
11881
|
//#endregion
|
|
11643
|
-
//#region src/utils/normalizeOptimizeDeps.ts
|
|
11644
|
-
var normalizeOptimizeDeps_default = {
|
|
11645
|
-
name: "normalizeOptimizeDeps",
|
|
11646
|
-
config: (config) => {
|
|
11647
|
-
let { optimizeDeps } = config;
|
|
11648
|
-
if (!optimizeDeps) {
|
|
11649
|
-
config.optimizeDeps = {};
|
|
11650
|
-
optimizeDeps = config.optimizeDeps;
|
|
11651
|
-
}
|
|
11652
|
-
if (!optimizeDeps.include) optimizeDeps.include = [];
|
|
11653
|
-
if (!optimizeDeps.exclude) optimizeDeps.exclude = [];
|
|
11654
|
-
if (!optimizeDeps.needsInterop) optimizeDeps.needsInterop = [];
|
|
11655
|
-
},
|
|
11656
|
-
configResolved: (config) => {
|
|
11657
|
-
const include = config.optimizeDeps?.include;
|
|
11658
|
-
const exclude = config.optimizeDeps?.exclude;
|
|
11659
|
-
if (!include?.length || !exclude?.length) return;
|
|
11660
|
-
const included = new Set(include);
|
|
11661
|
-
config.optimizeDeps.exclude = exclude.filter((dep) => !included.has(dep));
|
|
11662
|
-
}
|
|
11663
|
-
};
|
|
11664
|
-
//#endregion
|
|
11665
11882
|
//#region src/utils/runtimeCapabilityOptimization.ts
|
|
11666
11883
|
const RUNTIME_CAPABILITIES = [
|
|
11667
11884
|
{
|
|
@@ -11691,11 +11908,11 @@ function applyRuntimeCapabilityDefines(define, options, { defaultDisableSnapshot
|
|
|
11691
11908
|
}
|
|
11692
11909
|
if (explicitValue !== void 0 && !isEquivalentBooleanDefine(define[capability.define], explicitValue)) onConflict?.(`${capability.define} define (${define[capability.define]}) differs from ${capability.option} option (${explicitValue}). The existing define will not be overridden.`);
|
|
11693
11910
|
}
|
|
11694
|
-
if (!("FEDERATION_HAS_EXPOSES" in define)) define["FEDERATION_HAS_EXPOSES"] = JSON.stringify(
|
|
11911
|
+
if (!("FEDERATION_HAS_EXPOSES" in define)) define["FEDERATION_HAS_EXPOSES"] = JSON.stringify(isRemoteContainer(options));
|
|
11695
11912
|
}
|
|
11696
11913
|
function getRuntimeCapabilityConfigurationWarnings(options) {
|
|
11697
11914
|
const warnings = [];
|
|
11698
|
-
if (options.disableRemote &&
|
|
11915
|
+
if (options.disableRemote && hasRemotes(options)) warnings.push("disableRemote is true, but remotes are configured. Remote loading will be unavailable at runtime.");
|
|
11699
11916
|
if (options.disableShared && hasShared(options)) warnings.push("disableShared is true, but shared dependencies are configured. Shared dependency loading will be unavailable at runtime.");
|
|
11700
11917
|
return warnings;
|
|
11701
11918
|
}
|
|
@@ -11863,15 +12080,8 @@ function isBarePackageSubpath(specifier) {
|
|
|
11863
12080
|
* Vite then resolves the package's own dependency graph using its normal
|
|
11864
12081
|
* scanner, preserving package and peer-dependency resolution semantics.
|
|
11865
12082
|
*/
|
|
11866
|
-
function
|
|
12083
|
+
function collectLinkedSharedEntries(shared, projectRoot, exposes) {
|
|
11867
12084
|
const additions = /* @__PURE__ */ new Set();
|
|
11868
|
-
const entries = new Set(Array.isArray(optimizeDeps.entries) ? optimizeDeps.entries : optimizeDeps.entries ? [optimizeDeps.entries] : [
|
|
11869
|
-
"**/*.html",
|
|
11870
|
-
"!**/node_modules/**",
|
|
11871
|
-
`!**/${outDir.replace(/\\/g, "/")}/**`,
|
|
11872
|
-
"!**/__tests__/**",
|
|
11873
|
-
"!**/coverage/**"
|
|
11874
|
-
]);
|
|
11875
12085
|
for (const [packageName, share] of Object.entries(shared ?? {})) {
|
|
11876
12086
|
if (share?.shareConfig?.import === false) continue;
|
|
11877
12087
|
const configuredImport = share?.shareConfig?.import;
|
|
@@ -11894,13 +12104,7 @@ function includeLinkedSharedEntries(optimizeDeps, shared, projectRoot, exposes,
|
|
|
11894
12104
|
if (existsSync(entry)) additions.add(entry);
|
|
11895
12105
|
}
|
|
11896
12106
|
}
|
|
11897
|
-
|
|
11898
|
-
for (const entry of additions) entries.add(entry);
|
|
11899
|
-
optimizeDeps.entries = [...entries];
|
|
11900
|
-
}
|
|
11901
|
-
function stabilizeOptimizeDeps(optimizeDeps) {
|
|
11902
|
-
optimizeDeps.include = [...new Set(optimizeDeps.include ?? [])].sort();
|
|
11903
|
-
optimizeDeps.exclude = [...new Set(optimizeDeps.exclude ?? [])].sort();
|
|
12107
|
+
return [...additions];
|
|
11904
12108
|
}
|
|
11905
12109
|
function isFile(candidate) {
|
|
11906
12110
|
try {
|
|
@@ -12012,18 +12216,23 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
12012
12216
|
return {
|
|
12013
12217
|
name: "vite:module-federation-early-init",
|
|
12014
12218
|
enforce: "pre",
|
|
12015
|
-
config(config, { command: _command }) {
|
|
12219
|
+
config(config, { command: _command, mode }) {
|
|
12016
12220
|
if (_command === "serve") ignoreFederationGeneratedFiles(config, options);
|
|
12017
12221
|
const root = config.root || process.cwd();
|
|
12018
12222
|
const buildInput = getBuildInput(config);
|
|
12019
12223
|
const resolvedConfiguredEntryFiles = (typeof buildInput === "string" ? [buildInput] : Array.isArray(buildInput) ? buildInput : buildInput && typeof buildInput === "object" ? Object.values(buildInput) : []).map((entry) => String(entry)).filter((entry) => !isReactRouterBuildClientRouteInput(entry)).map((entry) => entry.split(/[?#]/)[0]).map((entry) => path$1.isAbsolute(entry) ? entry : path$1.resolve(root, entry));
|
|
12020
12224
|
resetConcreteSharedImportSourceCache();
|
|
12021
12225
|
setPackageDetectionCwd(root);
|
|
12226
|
+
setWorkspaceEntryConditions(getSharedExportConditions({
|
|
12227
|
+
isProduction: mode === "production",
|
|
12228
|
+
isSsr: false,
|
|
12229
|
+
rootConditions: config.resolve?.conditions
|
|
12230
|
+
}));
|
|
12022
12231
|
resolveSharedVersions(shared, root);
|
|
12023
12232
|
const isVinext = hasPackageDependency("vinext");
|
|
12024
12233
|
initVirtualModules(_command, getRemoteEntryId(options), false, options);
|
|
12025
12234
|
const isRolldown = getIsRolldown(this);
|
|
12026
|
-
if (
|
|
12235
|
+
if (hasRemotes(options)) {
|
|
12027
12236
|
for (const key of Object.keys(remotes)) ensureUsedRemote(key, options);
|
|
12028
12237
|
if (_command === "serve") {
|
|
12029
12238
|
config.optimizeDeps = config.optimizeDeps || {};
|
|
@@ -12045,7 +12254,7 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
12045
12254
|
const preparedShares = /* @__PURE__ */ new Map();
|
|
12046
12255
|
const writeSharedModules = (source, shareItem) => {
|
|
12047
12256
|
if (preparedShares.get(source) === shareItem) return;
|
|
12048
|
-
writeLoadShareModule(source, shareItem, _command,
|
|
12257
|
+
writeLoadShareModule(source, shareItem, _command, options);
|
|
12049
12258
|
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
|
|
12050
12259
|
preparedShares.set(source, shareItem);
|
|
12051
12260
|
};
|
|
@@ -12061,7 +12270,7 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
12061
12270
|
if (!id.startsWith("module-federation:optimized-require-")) return;
|
|
12062
12271
|
const sourcePackage = id.slice(36);
|
|
12063
12272
|
if (sourcePackage !== "react" && sourcePackage !== "react-dom") return;
|
|
12064
|
-
const loadSharePath = getLoadShareModulePath(sourcePackage,
|
|
12273
|
+
const loadSharePath = getLoadShareModulePath(sourcePackage, options);
|
|
12065
12274
|
const source = JSON.stringify(loadSharePath);
|
|
12066
12275
|
return "import * as __mfShared from " + source + ";\nexport * from " + source + ";\nexport default __mfShared.default ?? __mfShared;";
|
|
12067
12276
|
},
|
|
@@ -12074,7 +12283,7 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
12074
12283
|
const key = findSharedKey(source, shared);
|
|
12075
12284
|
if (!key) return;
|
|
12076
12285
|
const importerPackage = getSharedPackageFromFile(importer, shared, root);
|
|
12077
|
-
if (!isReactDomSelfReference(source, importer) && (importerPackage === getPackageName(key) || importerPackage && isSharedPackageDependency(key, importerPackage))) return;
|
|
12286
|
+
if (!isReactDomSelfReference(source, importer) && (importerPackage === getPackageName(key) && keepsOwnPackageEdge(importer, shared, root) || importerPackage && isSharedPackageDependency(key, importerPackage))) return;
|
|
12078
12287
|
if (isAssetLikeImport(source)) return;
|
|
12079
12288
|
const shareItem = shared[key];
|
|
12080
12289
|
const isReactSingleton = source === "react" && key === "react" && shareItem.shareConfig?.singleton === true;
|
|
@@ -12087,7 +12296,7 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
12087
12296
|
writeSharedModules(source, shareItem);
|
|
12088
12297
|
return { id: `module-federation:optimized-require-${source}` };
|
|
12089
12298
|
}
|
|
12090
|
-
const loadSharePath = getLoadShareModulePath(source,
|
|
12299
|
+
const loadSharePath = getLoadShareModulePath(source, options);
|
|
12091
12300
|
writeSharedModules(source, shareItem);
|
|
12092
12301
|
return {
|
|
12093
12302
|
id: loadSharePath,
|
|
@@ -12115,12 +12324,12 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
12115
12324
|
const key = findSharedKey(args.path, shared);
|
|
12116
12325
|
if (!key || isAssetLikeImport(args.path)) return;
|
|
12117
12326
|
const importerPackage = getSharedPackageFromFile(args.importer, shared, root);
|
|
12118
|
-
if (importerPackage === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer)) return;
|
|
12327
|
+
if (importerPackage === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer) && keepsOwnPackageEdge(args.importer, shared, root)) return;
|
|
12119
12328
|
if (importerPackage && isSharedPackageDependency(key, importerPackage)) return;
|
|
12120
12329
|
addUsedShares(args.path, options);
|
|
12121
12330
|
if (args.kind === "import-statement" || args.kind === "dynamic-import") {
|
|
12122
12331
|
const shareItem = shared[key];
|
|
12123
|
-
const loadSharePath = getLoadShareModulePath(args.path,
|
|
12332
|
+
const loadSharePath = getLoadShareModulePath(args.path, options);
|
|
12124
12333
|
writeSharedModules(args.path, shareItem);
|
|
12125
12334
|
return {
|
|
12126
12335
|
path: loadSharePath,
|
|
@@ -12139,7 +12348,7 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
12139
12348
|
const key = findSharedKey(args.path, shared);
|
|
12140
12349
|
if (!key) return;
|
|
12141
12350
|
const shareItem = shared[key];
|
|
12142
|
-
const loadSharePath = getLoadShareModulePath(args.path,
|
|
12351
|
+
const loadSharePath = getLoadShareModulePath(args.path, options);
|
|
12143
12352
|
writeSharedModules(args.path, shareItem);
|
|
12144
12353
|
return {
|
|
12145
12354
|
loader: "js",
|
|
@@ -12174,8 +12383,8 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
12174
12383
|
addConfiguredShare(runtimeKey, options);
|
|
12175
12384
|
continue;
|
|
12176
12385
|
}
|
|
12177
|
-
getLoadShareModulePath(runtimeKey,
|
|
12178
|
-
writeLoadShareModule(runtimeKey, shareItem, _command,
|
|
12386
|
+
getLoadShareModulePath(runtimeKey, options);
|
|
12387
|
+
writeLoadShareModule(runtimeKey, shareItem, _command, options);
|
|
12179
12388
|
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(runtimeKey, shareItem, options);
|
|
12180
12389
|
addConfiguredShare(runtimeKey, options);
|
|
12181
12390
|
if (_command === "serve" && shareItem.shareConfig?.import !== false) {
|
|
@@ -12197,8 +12406,8 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
12197
12406
|
optimizeDeps.exclude.push(subpath);
|
|
12198
12407
|
continue;
|
|
12199
12408
|
}
|
|
12200
|
-
getLoadShareModulePath(subpath,
|
|
12201
|
-
writeLoadShareModule(subpath, shareItem, _command,
|
|
12409
|
+
getLoadShareModulePath(subpath, options);
|
|
12410
|
+
writeLoadShareModule(subpath, shareItem, _command, options);
|
|
12202
12411
|
writePreBuildLibPath(subpath, shareItem, options);
|
|
12203
12412
|
addConfiguredShare(subpath, options);
|
|
12204
12413
|
if (canResolveSubpath) {
|
|
@@ -12211,9 +12420,19 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
12211
12420
|
writeLocalSharedImportMap(options);
|
|
12212
12421
|
}
|
|
12213
12422
|
if (_command === "serve") {
|
|
12214
|
-
|
|
12215
|
-
|
|
12216
|
-
|
|
12423
|
+
const generatedEntries = collectLinkedSharedEntries(shared, root, options.exposes);
|
|
12424
|
+
if (generatedEntries.length > 0) {
|
|
12425
|
+
config.optimizeDeps ??= {};
|
|
12426
|
+
const outDir = config.build?.outDir ?? "dist";
|
|
12427
|
+
const { entries } = config.optimizeDeps;
|
|
12428
|
+
config.optimizeDeps.entries = [.../* @__PURE__ */ new Set([...entries === void 0 ? [
|
|
12429
|
+
"**/*.html",
|
|
12430
|
+
"!**/node_modules/**",
|
|
12431
|
+
`!**/${outDir.replace(/\\/g, "/")}/**`,
|
|
12432
|
+
"!**/__tests__/**",
|
|
12433
|
+
"!**/coverage/**"
|
|
12434
|
+
] : typeof entries === "string" ? [entries] : entries, ...generatedEntries])];
|
|
12435
|
+
}
|
|
12217
12436
|
}
|
|
12218
12437
|
},
|
|
12219
12438
|
configResolved(config) {
|
|
@@ -12236,18 +12455,22 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
12236
12455
|
"@module-federation/sdk"
|
|
12237
12456
|
];
|
|
12238
12457
|
const resolvedShared = {};
|
|
12239
|
-
for (const pkg of [...commonSharedPkgs, ...sharedKeys])
|
|
12240
|
-
|
|
12241
|
-
} catch {
|
|
12458
|
+
for (const pkg of [...commonSharedPkgs, ...sharedKeys]) {
|
|
12459
|
+
const resolutionSpecifier = removeTrailingSlash(pkg);
|
|
12242
12460
|
try {
|
|
12243
|
-
resolvedShared[pkg] =
|
|
12244
|
-
} catch {
|
|
12461
|
+
resolvedShared[pkg] = projectRequire.resolve(resolutionSpecifier);
|
|
12462
|
+
} catch {
|
|
12463
|
+
try {
|
|
12464
|
+
resolvedShared[pkg] = resolveImportPath(resolutionSpecifier);
|
|
12465
|
+
} catch {}
|
|
12466
|
+
}
|
|
12245
12467
|
}
|
|
12246
12468
|
const ssrEntryLoaderSpecifier = SSR_ENTRY_LOADER_SPECIFIER;
|
|
12247
12469
|
try {
|
|
12248
12470
|
resolveImportPath(ssrEntryLoaderSpecifier);
|
|
12249
12471
|
options.runtimePlugins.push([ssrEntryLoaderSpecifier, {
|
|
12250
12472
|
resolvedShared,
|
|
12473
|
+
...config.command === "build" && { rebaseSharedAtRuntime: true },
|
|
12251
12474
|
...options.ssrEntryLoader
|
|
12252
12475
|
}]);
|
|
12253
12476
|
} catch {}
|
|
@@ -12277,7 +12500,7 @@ function withoutDynamicRemoteTypeHints(options) {
|
|
|
12277
12500
|
}
|
|
12278
12501
|
function loadPluginDts(options) {
|
|
12279
12502
|
if (options.dts === false) return [];
|
|
12280
|
-
return [import("./pluginDts-
|
|
12503
|
+
return [import("./pluginDts-rZMRTCTz.js").then(({ default: pluginDts }) => pluginDts(options))];
|
|
12281
12504
|
}
|
|
12282
12505
|
const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
|
|
12283
12506
|
function isInjectExternalRuntimeCorePlugin(specifier) {
|
|
@@ -12304,13 +12527,13 @@ function applyExternalRuntimeExperiments(options) {
|
|
|
12304
12527
|
}
|
|
12305
12528
|
}
|
|
12306
12529
|
function federation(mfUserOptions) {
|
|
12307
|
-
if (
|
|
12530
|
+
if (process.env.MFE_VITE_NO_TEST_ENV_CHECK !== "true" && (process.env.NODE_ENV === "test" || process.env.VITEST != null || process.env.JEST_WORKER_ID != null)) return [];
|
|
12308
12531
|
const options = normalizeModuleFederationOptions(mfUserOptions);
|
|
12309
12532
|
if (!options.name) throw createModuleFederationError("name is required");
|
|
12310
12533
|
if (options.experiments.hostProvidesAllShared) {
|
|
12311
12534
|
const ignored = getIgnoredOptionWarning(mfUserOptions);
|
|
12312
12535
|
if (ignored) mfWarn(ignored);
|
|
12313
|
-
return [
|
|
12536
|
+
return [isRemoteContainer(options) ? pluginHostProvidesAllSharedRemote(options) : pluginHostProvidesAllSharedHost(options), ...loadPluginDts(withoutDynamicRemoteTypeHints(options))];
|
|
12314
12537
|
}
|
|
12315
12538
|
applyExternalRuntimeExperiments(options);
|
|
12316
12539
|
const isVinext = hasPackageDependency("vinext");
|
|
@@ -12365,9 +12588,9 @@ function federation(mfUserOptions) {
|
|
|
12365
12588
|
const key = findSharedKey(pkg, shared);
|
|
12366
12589
|
if (!key) return "not-applicable";
|
|
12367
12590
|
const requestedModule = VirtualModule.findById(id);
|
|
12368
|
-
const ownedModule = VirtualModule.findById(getLoadShareModulePath(pkg,
|
|
12591
|
+
const ownedModule = VirtualModule.findById(getLoadShareModulePath(pkg, options));
|
|
12369
12592
|
if (!requestedModule || requestedModule !== ownedModule) return "not-owned";
|
|
12370
|
-
writeLoadShareModule(pkg, shared[key], command,
|
|
12593
|
+
writeLoadShareModule(pkg, shared[key], command, options, getLoadHookExportConditions(context, loadOptions), importFalseExportUsage);
|
|
12371
12594
|
return "refreshed";
|
|
12372
12595
|
};
|
|
12373
12596
|
const getCompleteImportFalseExportUsage = (id) => {
|
|
@@ -12510,9 +12733,7 @@ function federation(mfUserOptions) {
|
|
|
12510
12733
|
name: "vite:module-federation-virtual-modules",
|
|
12511
12734
|
enforce: "pre",
|
|
12512
12735
|
configureServer(server) {
|
|
12513
|
-
server.watcher
|
|
12514
|
-
server.watcher.on("add", invalidateSharedExportInspectionCache);
|
|
12515
|
-
server.watcher.on("unlink", invalidateSharedExportInspectionCache);
|
|
12736
|
+
watchFileEvents(server.watcher, invalidateSharedExportInspectionCache);
|
|
12516
12737
|
},
|
|
12517
12738
|
resolveId(id) {
|
|
12518
12739
|
if (id === "@module-federation/vite/ssrEntryLoader") return resolveImportPath(id);
|
|
@@ -12522,7 +12743,6 @@ function federation(mfUserOptions) {
|
|
|
12522
12743
|
id,
|
|
12523
12744
|
shared: options.shared,
|
|
12524
12745
|
command,
|
|
12525
|
-
isRolldown: getIsRolldown(this),
|
|
12526
12746
|
findSharedKey,
|
|
12527
12747
|
addUsedShares: (pkg) => addUsedShares(pkg, options),
|
|
12528
12748
|
writeLocalSharedImportMap: () => writeLocalSharedImportMap(options),
|
|
@@ -12583,14 +12803,29 @@ function federation(mfUserOptions) {
|
|
|
12583
12803
|
ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
|
|
12584
12804
|
ssrTarget = config.ssr?.target ?? "node";
|
|
12585
12805
|
isProduction = config.isProduction;
|
|
12586
|
-
const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command,
|
|
12806
|
+
const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, hasRemotes(options), isSsrConfig(config));
|
|
12587
12807
|
resolveSharedVersions(shared, config.root);
|
|
12588
12808
|
initVirtualModules(command, remoteEntryId, ssrCapabilities.enableSsrInitBootstrap, options);
|
|
12589
12809
|
}
|
|
12590
12810
|
},
|
|
12591
12811
|
aliasToArrayPlugin_default,
|
|
12592
12812
|
checkAliasConflicts({ shared }),
|
|
12593
|
-
|
|
12813
|
+
{
|
|
12814
|
+
name: "normalizeOptimizeDeps",
|
|
12815
|
+
config(config) {
|
|
12816
|
+
config.optimizeDeps ||= {};
|
|
12817
|
+
config.optimizeDeps.include ||= [];
|
|
12818
|
+
config.optimizeDeps.exclude ||= [];
|
|
12819
|
+
config.optimizeDeps.needsInterop ||= [];
|
|
12820
|
+
},
|
|
12821
|
+
configResolved(config) {
|
|
12822
|
+
const include = config.optimizeDeps?.include;
|
|
12823
|
+
const exclude = config.optimizeDeps?.exclude;
|
|
12824
|
+
if (!include?.length || !exclude?.length) return;
|
|
12825
|
+
const included = new Set(include);
|
|
12826
|
+
config.optimizeDeps.exclude = exclude.filter((dep) => !included.has(dep));
|
|
12827
|
+
}
|
|
12828
|
+
},
|
|
12594
12829
|
...loadPluginDts(options),
|
|
12595
12830
|
pluginDevRemoteHmr(options),
|
|
12596
12831
|
{
|
|
@@ -12615,7 +12850,7 @@ function federation(mfUserOptions) {
|
|
|
12615
12850
|
entryName: "hostInit",
|
|
12616
12851
|
entryPath: () => getHostAutoInitPath(options),
|
|
12617
12852
|
inject: hostInitInjectLocation,
|
|
12618
|
-
forceClientInjected:
|
|
12853
|
+
forceClientInjected: isRemoteContainer(options),
|
|
12619
12854
|
skipTransformFor: Object.values(options.exposes).map((expose) => expose.import),
|
|
12620
12855
|
federationOptions: options
|
|
12621
12856
|
}),
|
|
@@ -12813,10 +13048,6 @@ function federation(mfUserOptions) {
|
|
|
12813
13048
|
config.optimizeDeps.include.push(optimizeDep);
|
|
12814
13049
|
}
|
|
12815
13050
|
});
|
|
12816
|
-
if (isRolldown) {
|
|
12817
|
-
config.build ??= {};
|
|
12818
|
-
config.build.target ??= "esnext";
|
|
12819
|
-
}
|
|
12820
13051
|
const isBundledDev = Boolean(config.experimental?.bundledDev);
|
|
12821
13052
|
if (isRolldown && _command === "serve" && isBundledDev) {
|
|
12822
13053
|
config.build.rolldownOptions ??= {};
|
|
@@ -12860,6 +13091,7 @@ function federation(mfUserOptions) {
|
|
|
12860
13091
|
},
|
|
12861
13092
|
...Manifest(options),
|
|
12862
13093
|
...pluginSSRRemoteEntry(options),
|
|
13094
|
+
...pluginSsrRuntimeInit(options),
|
|
12863
13095
|
...VarRemoteEntry(options),
|
|
12864
13096
|
{
|
|
12865
13097
|
name: "module-federation-vinext-fix-rsc-preload-as",
|
|
@@ -12896,20 +13128,12 @@ function federation(mfUserOptions) {
|
|
|
12896
13128
|
},
|
|
12897
13129
|
...(function() {
|
|
12898
13130
|
let disablePreload = false;
|
|
12899
|
-
return
|
|
13131
|
+
return isRemoteContainer(options) ? [{
|
|
12900
13132
|
name: "module-federation-fix-preload",
|
|
12901
13133
|
enforce: "post",
|
|
12902
13134
|
apply: "build",
|
|
12903
|
-
config(
|
|
12904
|
-
|
|
12905
|
-
const getDefaultDisableAssetsAnalyze = (cfgCommand) => cfgCommand === "serve" && (typeof manifest !== "object" || !Object.hasOwn(manifest, "disableAssetsAnalyze"));
|
|
12906
|
-
const getConfiguredDisableAssetsAnalyze = (cfgCommand) => {
|
|
12907
|
-
if (typeof manifest === "object" && manifest !== null) {
|
|
12908
|
-
if (Object.hasOwn(manifest, "disableAssetsAnalyze")) return manifest.disableAssetsAnalyze === true;
|
|
12909
|
-
}
|
|
12910
|
-
return getDefaultDisableAssetsAnalyze(cfgCommand);
|
|
12911
|
-
};
|
|
12912
|
-
disablePreload = getConfiguredDisableAssetsAnalyze(command);
|
|
13135
|
+
config() {
|
|
13136
|
+
disablePreload = resolveDisableAssetsAnalyze(options.manifest, false);
|
|
12913
13137
|
},
|
|
12914
13138
|
generateBundle(_outputOptions, bundle, _isWrite) {
|
|
12915
13139
|
if (disablePreload) return;
|