@module-federation/vite 1.14.3 → 1.14.5
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 +9 -4
- package/lib/index.cjs +261 -98
- package/lib/index.d.cts +1 -0
- package/lib/index.d.mts +1 -0
- package/lib/index.mjs +262 -99
- package/package.json +4 -9
package/lib/index.d.mts
CHANGED
package/lib/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import defu from "defu";
|
|
3
3
|
import * as fs from "fs";
|
|
4
|
-
import { existsSync, mkdirSync, readFileSync, statSync, writeFile, writeFileSync } from "fs";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFile, writeFileSync } from "fs";
|
|
5
5
|
import { createRequire as createRequire$1 } from "module";
|
|
6
6
|
import * as path$1 from "pathe";
|
|
7
7
|
import path, { basename, dirname, join, parse, resolve } from "pathe";
|
|
@@ -95,6 +95,15 @@ function setPackageDetectionCwd(cwd) {
|
|
|
95
95
|
function getPackageDetectionCwd() {
|
|
96
96
|
return packageDetectionCwd || process.cwd();
|
|
97
97
|
}
|
|
98
|
+
function resolveExportsEntry(exportsField) {
|
|
99
|
+
if (typeof exportsField === "string") return exportsField;
|
|
100
|
+
if (!exportsField || typeof exportsField !== "object") return void 0;
|
|
101
|
+
const rootExport = exportsField["."];
|
|
102
|
+
if (typeof rootExport === "string") return rootExport;
|
|
103
|
+
if (!rootExport || typeof rootExport !== "object") return void 0;
|
|
104
|
+
const rootExportObject = rootExport;
|
|
105
|
+
return typeof rootExportObject.import === "string" && rootExportObject.import || typeof rootExportObject.default === "string" && rootExportObject.default || typeof rootExportObject.require === "string" && rootExportObject.require || void 0;
|
|
106
|
+
}
|
|
98
107
|
/**
|
|
99
108
|
* Escaping rules:
|
|
100
109
|
* Convert using the format __${mapping}__, where _ and $ are not allowed in npm package names but can be used in variable names.
|
|
@@ -130,6 +139,84 @@ function removePathFromNpmPackage(packageString) {
|
|
|
130
139
|
const match = packageString.match(/^(?:@[^/]+\/)?[^/]+/);
|
|
131
140
|
return match ? match[0] : packageString;
|
|
132
141
|
}
|
|
142
|
+
function getInstalledPackageJson(pkg, opts) {
|
|
143
|
+
const cwd = opts?.cwd || getPackageDetectionCwd();
|
|
144
|
+
const packageName = opts?.packageName || removePathFromNpmPackage(pkg);
|
|
145
|
+
const tryReadPackageJson = (packageJsonPath) => {
|
|
146
|
+
if (!existsSync(packageJsonPath)) return void 0;
|
|
147
|
+
try {
|
|
148
|
+
return {
|
|
149
|
+
path: packageJsonPath,
|
|
150
|
+
dir: path.dirname(packageJsonPath),
|
|
151
|
+
packageJson: JSON.parse(readFileSync(packageJsonPath, "utf-8"))
|
|
152
|
+
};
|
|
153
|
+
} catch {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const findPackageInPnpmStore = (startDir) => {
|
|
158
|
+
let currentDir = startDir;
|
|
159
|
+
const rootDir = path.parse(currentDir).root;
|
|
160
|
+
while (true) {
|
|
161
|
+
const pnpmStoreDir = path.join(currentDir, "node_modules", ".pnpm");
|
|
162
|
+
if (existsSync(pnpmStoreDir)) try {
|
|
163
|
+
for (const entry of readdirSync(pnpmStoreDir, { withFileTypes: true })) {
|
|
164
|
+
if (!entry.isDirectory()) continue;
|
|
165
|
+
const candidate = tryReadPackageJson(path.join(pnpmStoreDir, entry.name, "node_modules", packageName, "package.json"));
|
|
166
|
+
if (candidate?.packageJson.name === packageName) return candidate;
|
|
167
|
+
}
|
|
168
|
+
} catch {}
|
|
169
|
+
if (currentDir === rootDir) break;
|
|
170
|
+
currentDir = path.dirname(currentDir);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
try {
|
|
174
|
+
const projectRequire = createRequire$1(new URL(`file://${path.join(cwd, "package.json")}`));
|
|
175
|
+
let resolvedPath;
|
|
176
|
+
try {
|
|
177
|
+
resolvedPath = projectRequire.resolve(pkg);
|
|
178
|
+
} catch {
|
|
179
|
+
resolvedPath = projectRequire.resolve(packageName);
|
|
180
|
+
}
|
|
181
|
+
let currentDir = path.dirname(resolvedPath);
|
|
182
|
+
const rootDir = path.parse(currentDir).root;
|
|
183
|
+
while (true) {
|
|
184
|
+
const packageJsonPath = path.join(currentDir, "package.json");
|
|
185
|
+
if (existsSync(packageJsonPath)) {
|
|
186
|
+
const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
|
|
187
|
+
try {
|
|
188
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
189
|
+
if (packageJson.name === packageName) return {
|
|
190
|
+
path: packageJsonPath,
|
|
191
|
+
dir: currentDir,
|
|
192
|
+
packageJson
|
|
193
|
+
};
|
|
194
|
+
} catch (error) {
|
|
195
|
+
if (!(error instanceof SyntaxError)) throw error;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (currentDir === rootDir) break;
|
|
199
|
+
currentDir = path.dirname(currentDir);
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
let currentDir = cwd;
|
|
203
|
+
const rootDir = path.parse(currentDir).root;
|
|
204
|
+
while (true) {
|
|
205
|
+
const directCandidate = tryReadPackageJson(path.join(currentDir, "node_modules", packageName, "package.json"));
|
|
206
|
+
if (directCandidate?.packageJson.name === packageName) return directCandidate;
|
|
207
|
+
if (currentDir === rootDir) break;
|
|
208
|
+
currentDir = path.dirname(currentDir);
|
|
209
|
+
}
|
|
210
|
+
return findPackageInPnpmStore(cwd);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function getInstalledPackageEntry(pkg, opts) {
|
|
214
|
+
const installed = getInstalledPackageJson(pkg, opts);
|
|
215
|
+
if (!installed) return void 0;
|
|
216
|
+
const packageJson = installed.packageJson;
|
|
217
|
+
const explicitEntry = resolveExportsEntry(packageJson.exports) || (typeof packageJson.module === "string" ? packageJson.module : void 0) || (typeof packageJson.main === "string" ? packageJson.main : void 0) || "index.js";
|
|
218
|
+
return path.join(installed.dir, explicitEntry);
|
|
219
|
+
}
|
|
133
220
|
/**
|
|
134
221
|
* Detect whether the current runtime is Vite 8+ by checking for a Vite version flag
|
|
135
222
|
* on the plugin hook context, with Rolldown metadata kept as a compatibility fallback.
|
|
@@ -855,6 +942,14 @@ function pluginDts(options) {
|
|
|
855
942
|
}
|
|
856
943
|
//#endregion
|
|
857
944
|
//#region src/utils/normalizeModuleFederationOptions.ts
|
|
945
|
+
const INTERNAL_NAME_PREFIX = "__mfe_internal__";
|
|
946
|
+
function toInternalModuleFederationName(name) {
|
|
947
|
+
return name.startsWith(INTERNAL_NAME_PREFIX) ? name : `${INTERNAL_NAME_PREFIX}${name}`;
|
|
948
|
+
}
|
|
949
|
+
function warnOnReservedInternalNamePrefix(name, kind) {
|
|
950
|
+
if (!name.startsWith(INTERNAL_NAME_PREFIX)) return;
|
|
951
|
+
mfWarn(`Reserved internal ${kind} prefix "${INTERNAL_NAME_PREFIX}" detected in public ${kind} "${name}". This prefix is reserved for internal module federation names and may cause conflicts.`);
|
|
952
|
+
}
|
|
858
953
|
function normalizeExposesItem(key, item) {
|
|
859
954
|
let importPath = "";
|
|
860
955
|
if (typeof item === "string") importPath = item;
|
|
@@ -878,6 +973,7 @@ function normalizeRemotes(remotes) {
|
|
|
878
973
|
return result;
|
|
879
974
|
}
|
|
880
975
|
function normalizeRemoteItem(key, remote) {
|
|
976
|
+
warnOnReservedInternalNamePrefix(key, "remoteAlias");
|
|
881
977
|
if (typeof remote === "string") {
|
|
882
978
|
const separatorIndex = remote.startsWith("@") ? remote.indexOf("@", 1) : remote.indexOf("@");
|
|
883
979
|
let entryGlobalName;
|
|
@@ -892,6 +988,7 @@ function normalizeRemoteItem(key, remote) {
|
|
|
892
988
|
return {
|
|
893
989
|
type: "var",
|
|
894
990
|
name: key,
|
|
991
|
+
internalName: toInternalModuleFederationName(key),
|
|
895
992
|
entry,
|
|
896
993
|
entryGlobalName,
|
|
897
994
|
shareScope: "default"
|
|
@@ -900,9 +997,13 @@ function normalizeRemoteItem(key, remote) {
|
|
|
900
997
|
return Object.assign({
|
|
901
998
|
type: "var",
|
|
902
999
|
name: key,
|
|
1000
|
+
internalName: toInternalModuleFederationName(key),
|
|
903
1001
|
shareScope: "default",
|
|
904
1002
|
entryGlobalName: key
|
|
905
|
-
},
|
|
1003
|
+
}, {
|
|
1004
|
+
...remote,
|
|
1005
|
+
internalName: toInternalModuleFederationName(remote.name || key)
|
|
1006
|
+
});
|
|
906
1007
|
}
|
|
907
1008
|
/**
|
|
908
1009
|
* Tries to find the package.json's version of a shared package
|
|
@@ -934,6 +1035,12 @@ function inferVersionFromRequiredVersion(requiredVersion) {
|
|
|
934
1035
|
if (!requiredVersion) return void 0;
|
|
935
1036
|
return requiredVersion.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0];
|
|
936
1037
|
}
|
|
1038
|
+
function getLitExportSubpathShares(sharedName) {
|
|
1039
|
+
if (sharedName !== "lit") return [];
|
|
1040
|
+
const exportsField = getInstalledPackageJson(sharedName, { packageName: sharedName })?.packageJson.exports;
|
|
1041
|
+
if (!exportsField || typeof exportsField === "string") return [];
|
|
1042
|
+
return Object.keys(exportsField).filter((key) => key.startsWith("./") && key !== "." && !key.includes("*")).map((key) => `${sharedName}/${key.slice(2)}`);
|
|
1043
|
+
}
|
|
937
1044
|
function normalizeShareItem(key, shareItem) {
|
|
938
1045
|
let version;
|
|
939
1046
|
if (!(typeof shareItem === "object" && shareItem.import === false)) try {
|
|
@@ -977,14 +1084,21 @@ function normalizeShareItem(key, shareItem) {
|
|
|
977
1084
|
function normalizeShared(shared) {
|
|
978
1085
|
if (!shared) return {};
|
|
979
1086
|
const result = {};
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
result[key] = normalizeShareItem(key,
|
|
1087
|
+
const sourceEntries = [];
|
|
1088
|
+
if (Array.isArray(shared)) shared.forEach((key) => {
|
|
1089
|
+
result[key] = normalizeShareItem(key, key);
|
|
1090
|
+
sourceEntries.push([key, key]);
|
|
1091
|
+
});
|
|
1092
|
+
else if (typeof shared === "object") Object.keys(shared).forEach((key) => {
|
|
1093
|
+
const value = shared[key];
|
|
1094
|
+
result[key] = normalizeShareItem(key, value);
|
|
1095
|
+
sourceEntries.push([key, value]);
|
|
1096
|
+
});
|
|
1097
|
+
sourceEntries.forEach(([key, value]) => {
|
|
1098
|
+
for (const subpathShare of getLitExportSubpathShares(key)) {
|
|
1099
|
+
if (result[subpathShare]) continue;
|
|
1100
|
+
result[subpathShare] = normalizeShareItem(subpathShare, value);
|
|
1101
|
+
}
|
|
988
1102
|
});
|
|
989
1103
|
return result;
|
|
990
1104
|
}
|
|
@@ -1009,10 +1123,12 @@ function getNormalizeShareItem(key) {
|
|
|
1009
1123
|
return options.shared[key] || options.shared[removePathFromNpmPackage(key)] || options.shared[removePathFromNpmPackage(key) + "/"];
|
|
1010
1124
|
}
|
|
1011
1125
|
function normalizeModuleFederationOptions(options) {
|
|
1126
|
+
warnOnReservedInternalNamePrefix(options.name, "containerName");
|
|
1012
1127
|
if (options.virtualModuleDir && options.virtualModuleDir.includes("/")) throw createModuleFederationError(`Invalid virtualModuleDir: "${options.virtualModuleDir}". The virtualModuleDir option cannot contain slashes (/). Please use a single directory name like '__mf__virtual__your_app_name'.`);
|
|
1013
1128
|
return config = {
|
|
1014
1129
|
exposes: normalizeExposes(options.exposes),
|
|
1015
1130
|
filename: options.filename || "remoteEntry-[hash]",
|
|
1131
|
+
internalName: toInternalModuleFederationName(options.name),
|
|
1016
1132
|
library: normalizeLibrary(options.library),
|
|
1017
1133
|
name: options.name,
|
|
1018
1134
|
remotes: normalizeRemotes(options.remotes),
|
|
@@ -1187,7 +1303,7 @@ var VirtualModule = class {
|
|
|
1187
1303
|
return resolve(getNodeModulesDir(), this.getImportId());
|
|
1188
1304
|
}
|
|
1189
1305
|
getImportId() {
|
|
1190
|
-
const {
|
|
1306
|
+
const { internalName: mfName, virtualModuleDir } = getNormalizeModuleFederationOptions();
|
|
1191
1307
|
return `${virtualModuleDir}/${packageNameEncode(`${mfName}${this.tag}${this.name}${this.tag}`)}${this.suffix}`;
|
|
1192
1308
|
}
|
|
1193
1309
|
writeSync(code, force) {
|
|
@@ -1210,7 +1326,7 @@ function getExposesCssMapPlaceholder() {
|
|
|
1210
1326
|
return EXPOSES_CSS_MAP_PLACEHOLDER;
|
|
1211
1327
|
}
|
|
1212
1328
|
function getVirtualExposesId(options) {
|
|
1213
|
-
return `virtual:mf-exposes:${`${options.
|
|
1329
|
+
return `virtual:mf-exposes:${`${options.internalName}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
1214
1330
|
}
|
|
1215
1331
|
function generateExposes(options) {
|
|
1216
1332
|
return `
|
|
@@ -1444,52 +1560,6 @@ function resolvePackageEntryFromProjectRoot(pkg) {
|
|
|
1444
1560
|
return;
|
|
1445
1561
|
}
|
|
1446
1562
|
}
|
|
1447
|
-
function getInstalledPackageJsonPath(pkg) {
|
|
1448
|
-
try {
|
|
1449
|
-
const packageName = removePathFromNpmPackage(pkg);
|
|
1450
|
-
const projectRequire = createRequire$1(new URL(`file://${path.join(getPackageDetectionCwd(), "package.json")}`));
|
|
1451
|
-
let resolvedPath;
|
|
1452
|
-
try {
|
|
1453
|
-
resolvedPath = projectRequire.resolve(pkg);
|
|
1454
|
-
} catch {
|
|
1455
|
-
resolvedPath = projectRequire.resolve(packageName);
|
|
1456
|
-
}
|
|
1457
|
-
let currentDir = path.dirname(resolvedPath);
|
|
1458
|
-
const rootDir = path.parse(currentDir).root;
|
|
1459
|
-
while (currentDir !== rootDir) {
|
|
1460
|
-
const packageJsonPath = path.join(currentDir, "package.json");
|
|
1461
|
-
if (existsSync(packageJsonPath)) {
|
|
1462
|
-
const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
|
|
1463
|
-
try {
|
|
1464
|
-
if (JSON.parse(packageJsonContent).name === packageName) return packageJsonPath;
|
|
1465
|
-
} catch (error) {
|
|
1466
|
-
if (!(error instanceof SyntaxError)) throw error;
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
currentDir = path.dirname(currentDir);
|
|
1470
|
-
}
|
|
1471
|
-
const rootPackageJsonPath = path.join(rootDir, "package.json");
|
|
1472
|
-
if (existsSync(rootPackageJsonPath)) {
|
|
1473
|
-
const rootPackageJsonContent = readFileSync(rootPackageJsonPath, "utf-8");
|
|
1474
|
-
try {
|
|
1475
|
-
if (JSON.parse(rootPackageJsonContent).name === packageName) return rootPackageJsonPath;
|
|
1476
|
-
} catch (error) {
|
|
1477
|
-
if (!(error instanceof SyntaxError)) throw error;
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
} catch {
|
|
1481
|
-
const packageName = removePathFromNpmPackage(pkg);
|
|
1482
|
-
let currentDir = getPackageDetectionCwd();
|
|
1483
|
-
const rootDir = path.parse(currentDir).root;
|
|
1484
|
-
while (currentDir !== rootDir) {
|
|
1485
|
-
const packageJsonPath = path.join(currentDir, "node_modules", packageName, "package.json");
|
|
1486
|
-
if (existsSync(packageJsonPath)) return packageJsonPath;
|
|
1487
|
-
currentDir = path.dirname(currentDir);
|
|
1488
|
-
}
|
|
1489
|
-
const rootPackageJsonPath = path.join(rootDir, "node_modules", packageName, "package.json");
|
|
1490
|
-
return existsSync(rootPackageJsonPath) ? rootPackageJsonPath : void 0;
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
1563
|
function resolveImportTarget(exportsField) {
|
|
1494
1564
|
if (typeof exportsField === "string") return exportsField;
|
|
1495
1565
|
if (!exportsField || typeof exportsField !== "object") return void 0;
|
|
@@ -1510,14 +1580,14 @@ function resolveImportTarget(exportsField) {
|
|
|
1510
1580
|
function getPackageEsmEntryPath(pkg) {
|
|
1511
1581
|
try {
|
|
1512
1582
|
const resolvedEntryPath = resolvePackageEntryFromProjectRoot(pkg);
|
|
1513
|
-
const
|
|
1514
|
-
if (!
|
|
1583
|
+
const installedPackageJson = getInstalledPackageJson(pkg);
|
|
1584
|
+
if (!installedPackageJson) return resolvedEntryPath;
|
|
1515
1585
|
const packageName = removePathFromNpmPackage(pkg);
|
|
1516
|
-
const packageJson =
|
|
1586
|
+
const packageJson = installedPackageJson.packageJson;
|
|
1517
1587
|
const subpath = pkg === packageName ? "." : `.${pkg.slice(packageName.length)}`;
|
|
1518
1588
|
const target = resolveImportTarget(typeof packageJson.exports === "string" ? subpath === "." ? packageJson.exports : void 0 : packageJson.exports?.[subpath] ?? (subpath === "." ? packageJson.exports?.["."] ?? (packageJson.exports && !Object.keys(packageJson.exports).some((key) => key.startsWith(".")) ? packageJson.exports : void 0) : void 0)) || packageJson.module;
|
|
1519
1589
|
if (!target) return resolvedEntryPath;
|
|
1520
|
-
return path.resolve(
|
|
1590
|
+
return path.resolve(installedPackageJson.dir, target);
|
|
1521
1591
|
} catch {
|
|
1522
1592
|
return resolvePackageEntryFromProjectRoot(pkg);
|
|
1523
1593
|
}
|
|
@@ -1661,8 +1731,11 @@ function getSharedImportSource(pkg, shareItem) {
|
|
|
1661
1731
|
}
|
|
1662
1732
|
const LOAD_SHARE_TAG = "__loadShare__";
|
|
1663
1733
|
const loadShareCacheMap = {};
|
|
1734
|
+
function shouldUseEsmLoadShare(pkg, command, isRolldown) {
|
|
1735
|
+
return command === "build" || !!isRolldown || pkg === "lit" || pkg.startsWith("lit/");
|
|
1736
|
+
}
|
|
1664
1737
|
function getLoadShareImportId(pkg, isRolldown, command) {
|
|
1665
|
-
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG,
|
|
1738
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, shouldUseEsmLoadShare(pkg, command, isRolldown) ? ".mjs" : ".js");
|
|
1666
1739
|
return loadShareCacheMap[pkg].getImportId();
|
|
1667
1740
|
}
|
|
1668
1741
|
function getLoadShareModulePath(pkg, isRolldown, command) {
|
|
@@ -1670,8 +1743,8 @@ function getLoadShareModulePath(pkg, isRolldown, command) {
|
|
|
1670
1743
|
return loadShareCacheMap[pkg].getPath();
|
|
1671
1744
|
}
|
|
1672
1745
|
function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
1673
|
-
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG,
|
|
1674
|
-
const useESM = command
|
|
1746
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, shouldUseEsmLoadShare(pkg, command, isRolldown) ? ".mjs" : ".js");
|
|
1747
|
+
const useESM = shouldUseEsmLoadShare(pkg, command, isRolldown);
|
|
1675
1748
|
const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
|
|
1676
1749
|
const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
1677
1750
|
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
@@ -1705,6 +1778,7 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1705
1778
|
const devImportSource = concreteSharedImportSource || pkg;
|
|
1706
1779
|
const localProviderPath = getLocalProviderImportPath(pkg);
|
|
1707
1780
|
const isWorkspacePackage = isWorkspaceFilePath(localProviderPath) || isWorkspaceFilePath(concreteSharedImportSource);
|
|
1781
|
+
const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
|
|
1708
1782
|
const providerImportId = localProviderPath || concreteSharedImportSource || sharedImportSource;
|
|
1709
1783
|
const namedExports = getPackageNamedExports(pkg);
|
|
1710
1784
|
let exportLine;
|
|
@@ -1713,8 +1787,8 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1713
1787
|
const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
|
|
1714
1788
|
exportLine = useESM ? `export default exportModule.default ?? exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.map((name, i) => `"${name}": __mf_${i}`).join(", ")} });`;
|
|
1715
1789
|
} else exportLine = useESM ? `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}` : "module.exports = exportModule";
|
|
1716
|
-
const prebuildImportLine = isWorkspacePackage && command !== "build" ? "" : `import ${escapeGeneratedStringLiteral(sharedImportSource)};`;
|
|
1717
|
-
const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
1790
|
+
const prebuildImportLine = isWorkspacePackage && command !== "build" || skipServePrebuildWarmup ? "" : `import ${escapeGeneratedStringLiteral(sharedImportSource)};`;
|
|
1791
|
+
const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
1718
1792
|
loadShareCacheMap[pkg].writeSync(`
|
|
1719
1793
|
${prebuildImportLine}
|
|
1720
1794
|
${devDynamicImportLine}
|
|
@@ -1788,7 +1862,7 @@ function generateLocalSharedImportMap() {
|
|
|
1788
1862
|
version: ${JSON.stringify(shareItem.version)},
|
|
1789
1863
|
scope: [${JSON.stringify(shareItem.scope)}],
|
|
1790
1864
|
loaded: false,
|
|
1791
|
-
from: ${JSON.stringify(options.
|
|
1865
|
+
from: ${JSON.stringify(options.internalName)},
|
|
1792
1866
|
async get () {
|
|
1793
1867
|
if (${shareItem.shareConfig.import === false}) {
|
|
1794
1868
|
throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
|
|
@@ -1839,7 +1913,7 @@ function generateLocalSharedImportMap() {
|
|
|
1839
1913
|
}
|
|
1840
1914
|
const REMOTE_ENTRY_ID = "virtual:mf-REMOTE_ENTRY_ID";
|
|
1841
1915
|
function getRemoteEntryId(options) {
|
|
1842
|
-
return `${REMOTE_ENTRY_ID}:${`${options.
|
|
1916
|
+
return `${REMOTE_ENTRY_ID}:${`${options.internalName}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
1843
1917
|
}
|
|
1844
1918
|
function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
|
|
1845
1919
|
const pluginImportNames = options.runtimePlugins.map((p, i) => {
|
|
@@ -1868,7 +1942,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1868
1942
|
${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
|
|
1869
1943
|
const initTokens = {}
|
|
1870
1944
|
const shareScopeName = ${JSON.stringify(options.shareScope)}
|
|
1871
|
-
const mfName = ${JSON.stringify(options.
|
|
1945
|
+
const mfName = ${JSON.stringify(options.internalName)}
|
|
1872
1946
|
let localSharedImportMapPromise
|
|
1873
1947
|
let exposesMapPromise
|
|
1874
1948
|
|
|
@@ -2435,7 +2509,7 @@ function pluginModuleParseEnd_default(excludeFn, options) {
|
|
|
2435
2509
|
}
|
|
2436
2510
|
//#endregion
|
|
2437
2511
|
//#region src/plugins/pluginProxyRemoteEntry.ts
|
|
2438
|
-
const filter = createFilter();
|
|
2512
|
+
const filter$1 = createFilter();
|
|
2439
2513
|
function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
|
|
2440
2514
|
let viteConfig, _command, root;
|
|
2441
2515
|
return {
|
|
@@ -2475,7 +2549,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
2475
2549
|
},
|
|
2476
2550
|
transform(code, id) {
|
|
2477
2551
|
return mapCodeToCodeWithSourcemap((() => {
|
|
2478
|
-
if (!filter(id)) return;
|
|
2552
|
+
if (!filter$1(id)) return;
|
|
2479
2553
|
if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
|
|
2480
2554
|
if (id === virtualExposesId) return generateExposes(options);
|
|
2481
2555
|
if (id.includes(getHostAutoInitPath())) {
|
|
@@ -2548,25 +2622,47 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
2548
2622
|
}
|
|
2549
2623
|
//#endregion
|
|
2550
2624
|
//#region src/plugins/pluginProxyRemotes.ts
|
|
2551
|
-
createFilter();
|
|
2625
|
+
const filter = createFilter();
|
|
2626
|
+
function isNodeModulesImporter(importer) {
|
|
2627
|
+
return importer?.includes("/node_modules/") || importer?.includes("\\node_modules\\");
|
|
2628
|
+
}
|
|
2552
2629
|
function pluginProxyRemotes_default(options) {
|
|
2630
|
+
let command;
|
|
2631
|
+
let root = process.cwd();
|
|
2553
2632
|
const { remotes } = options;
|
|
2633
|
+
function resolveRemoteId(source, importer, remoteName, isRolldown) {
|
|
2634
|
+
if (source === remoteName) {
|
|
2635
|
+
const installedPackageEntry = getInstalledPackageEntry(source, { cwd: root });
|
|
2636
|
+
if (installedPackageEntry && (importer === void 0 || isNodeModulesImporter(importer))) return installedPackageEntry;
|
|
2637
|
+
}
|
|
2638
|
+
const remoteModule = getRemoteVirtualModule(source, command, isRolldown);
|
|
2639
|
+
addUsedRemote(remoteName, source);
|
|
2640
|
+
return remoteModule.getPath();
|
|
2641
|
+
}
|
|
2554
2642
|
return {
|
|
2555
2643
|
name: "proxyRemotes",
|
|
2556
2644
|
config(config, { command: _command }) {
|
|
2645
|
+
command = _command;
|
|
2646
|
+
root = config.root || process.cwd();
|
|
2557
2647
|
const isRolldown = getIsRolldown(this);
|
|
2558
2648
|
Object.keys(remotes).forEach((key) => {
|
|
2559
2649
|
const remote = remotes[key];
|
|
2560
2650
|
config.resolve.alias.push({
|
|
2561
2651
|
find: new RegExp(`^(${remote.name}(\/.*|$))`),
|
|
2562
2652
|
replacement: "$1",
|
|
2563
|
-
customResolver(source) {
|
|
2564
|
-
|
|
2565
|
-
addUsedRemote(remote.name, source);
|
|
2566
|
-
return remoteModule.getPath();
|
|
2653
|
+
customResolver(source, importer) {
|
|
2654
|
+
return resolveRemoteId(source, importer, remote.name, isRolldown);
|
|
2567
2655
|
}
|
|
2568
2656
|
});
|
|
2569
2657
|
});
|
|
2658
|
+
},
|
|
2659
|
+
resolveId(source, importer) {
|
|
2660
|
+
if (!filter(source)) return;
|
|
2661
|
+
const isRolldown = getIsRolldown(this);
|
|
2662
|
+
for (const remote of Object.values(remotes)) {
|
|
2663
|
+
if (source !== remote.name) continue;
|
|
2664
|
+
return resolveRemoteId(source, importer, remote.name, isRolldown);
|
|
2665
|
+
}
|
|
2570
2666
|
}
|
|
2571
2667
|
};
|
|
2572
2668
|
}
|
|
@@ -3042,24 +3138,31 @@ function collectFromRegex(code, isRemoteImport) {
|
|
|
3042
3138
|
}
|
|
3043
3139
|
function pluginRemoteNamedExports(options) {
|
|
3044
3140
|
const remoteNames = Object.keys(options.remotes);
|
|
3045
|
-
|
|
3046
|
-
|
|
3141
|
+
const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
|
|
3142
|
+
function isRemoteImport(source, importerId) {
|
|
3143
|
+
return remoteNames.some((name) => {
|
|
3144
|
+
if (source.startsWith(name + "/")) return true;
|
|
3145
|
+
if (source !== name) return false;
|
|
3146
|
+
return !isNodeModulesId(importerId);
|
|
3147
|
+
}) || source.includes("__loadRemote__");
|
|
3047
3148
|
}
|
|
3048
3149
|
return {
|
|
3049
3150
|
name: "module-federation-remote-named-exports",
|
|
3050
3151
|
enforce: "post",
|
|
3051
3152
|
async transform(code, id) {
|
|
3153
|
+
if (!getIsRolldown(this)) return;
|
|
3052
3154
|
if (remoteNames.length === 0) return;
|
|
3053
3155
|
if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
|
|
3054
3156
|
if (!JS_EXTENSIONS_RE.test(id)) return;
|
|
3055
3157
|
if (!remoteNames.some((name) => code.includes(name))) return;
|
|
3158
|
+
const matchesRemoteImport = (source) => isRemoteImport(source, id);
|
|
3056
3159
|
let imports;
|
|
3057
3160
|
try {
|
|
3058
|
-
imports = await collectFromAST(this.parse(code), code,
|
|
3161
|
+
imports = await collectFromAST(this.parse(code), code, matchesRemoteImport);
|
|
3059
3162
|
} catch {
|
|
3060
|
-
imports = await collectFromEsLexer(code,
|
|
3163
|
+
imports = await collectFromEsLexer(code, matchesRemoteImport);
|
|
3061
3164
|
}
|
|
3062
|
-
if ((!imports || imports.length === 0) && REGEX_FALLBACK_EXTENSIONS_RE.test(id)) imports = collectFromRegex(code,
|
|
3165
|
+
if ((!imports || imports.length === 0) && REGEX_FALLBACK_EXTENSIONS_RE.test(id)) imports = collectFromRegex(code, matchesRemoteImport);
|
|
3063
3166
|
if (!imports) return;
|
|
3064
3167
|
return applyRewrites(code, imports, id);
|
|
3065
3168
|
}
|
|
@@ -3307,6 +3410,7 @@ function insertAfterLastTopLevelImport(code, snippet) {
|
|
|
3307
3410
|
*/
|
|
3308
3411
|
function createEarlyVirtualModulesPlugin(options) {
|
|
3309
3412
|
const { shared, remotes, virtualModuleDir } = options;
|
|
3413
|
+
const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
|
|
3310
3414
|
return {
|
|
3311
3415
|
name: "vite:module-federation-early-init",
|
|
3312
3416
|
enforce: "pre",
|
|
@@ -3319,16 +3423,23 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
3319
3423
|
VirtualModule.ensureVirtualPackageExists();
|
|
3320
3424
|
initVirtualModules(_command, getRemoteEntryId(options));
|
|
3321
3425
|
const isRolldown = getIsRolldown(this);
|
|
3322
|
-
if (remotes && Object.keys(remotes).length > 0)
|
|
3426
|
+
if (remotes && Object.keys(remotes).length > 0) {
|
|
3427
|
+
for (const key of Object.keys(remotes)) addUsedRemote(key, key);
|
|
3428
|
+
if (_command === "serve" && isRolldown) {
|
|
3429
|
+
config.optimizeDeps = config.optimizeDeps || {};
|
|
3430
|
+
config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
|
|
3431
|
+
config.optimizeDeps.include = config.optimizeDeps.include || [];
|
|
3432
|
+
const collidingInstalledRemotes = Object.keys(remotes || {}).filter((remoteName) => getInstalledPackageJson(remoteName, { cwd: root }));
|
|
3433
|
+
const collidingInstalledRemoteEntries = collidingInstalledRemotes.map((remoteName) => getInstalledPackageEntry(remoteName, { cwd: root }) || remoteName);
|
|
3434
|
+
config.optimizeDeps.exclude.push(...Object.keys(remotes || {}).filter((remoteName) => !collidingInstalledRemotes.includes(remoteName)));
|
|
3435
|
+
config.optimizeDeps.include.push(...collidingInstalledRemoteEntries);
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3323
3438
|
if (shared && Object.keys(shared).length > 0) {
|
|
3324
3439
|
if (_command === "serve") {
|
|
3325
3440
|
config.optimizeDeps = config.optimizeDeps || {};
|
|
3326
3441
|
config.optimizeDeps.include = config.optimizeDeps.include || [];
|
|
3327
3442
|
config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
|
|
3328
|
-
if (isRolldown) {
|
|
3329
|
-
config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
|
|
3330
|
-
config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
|
|
3331
|
-
}
|
|
3332
3443
|
}
|
|
3333
3444
|
for (const key of Object.keys(shared)) {
|
|
3334
3445
|
if (key.endsWith("/")) continue;
|
|
@@ -3342,8 +3453,13 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
3342
3453
|
if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(key, shareItem);
|
|
3343
3454
|
addUsedShares(key);
|
|
3344
3455
|
if (_command === "serve" && shareItem.shareConfig?.import !== false) {
|
|
3345
|
-
|
|
3346
|
-
|
|
3456
|
+
const optimizeDeps = config.optimizeDeps ??= {};
|
|
3457
|
+
optimizeDeps.include ??= [];
|
|
3458
|
+
optimizeDeps.exclude ??= [];
|
|
3459
|
+
const shouldBypassOptimizeDep = isLitShare(key);
|
|
3460
|
+
if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
|
|
3461
|
+
if (!isRolldown && !shouldBypassOptimizeDep) optimizeDeps.include.push(getLoadShareImportId(key, isRolldown, _command));
|
|
3462
|
+
optimizeDeps.include.push(getPreBuildLibImportId(key));
|
|
3347
3463
|
}
|
|
3348
3464
|
}
|
|
3349
3465
|
writeLocalSharedImportMap();
|
|
@@ -3361,6 +3477,7 @@ function federation(mfUserOptions) {
|
|
|
3361
3477
|
const virtualExposesId = getVirtualExposesId(options);
|
|
3362
3478
|
let command;
|
|
3363
3479
|
let depsDir = "/node_modules/.vite/deps/";
|
|
3480
|
+
let desiredRolldownOutput;
|
|
3364
3481
|
return [
|
|
3365
3482
|
createEarlyVirtualModulesPlugin(options),
|
|
3366
3483
|
...isVinext ? [{
|
|
@@ -3451,12 +3568,22 @@ function federation(mfUserOptions) {
|
|
|
3451
3568
|
};
|
|
3452
3569
|
}
|
|
3453
3570
|
let warnedAboutCodeSplitting = false;
|
|
3571
|
+
let warnedAboutCodeSplittingGroups = false;
|
|
3454
3572
|
const ensureCodeSplitting = (output) => {
|
|
3455
|
-
if (output?.codeSplitting
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3573
|
+
if (output?.codeSplitting === false) {
|
|
3574
|
+
delete output.codeSplitting;
|
|
3575
|
+
if (warnedAboutCodeSplitting) return;
|
|
3576
|
+
warnedAboutCodeSplitting = true;
|
|
3577
|
+
mfWarn("Ignoring `output.codeSplitting = false` because module federation requires chunk splitting.");
|
|
3578
|
+
return;
|
|
3579
|
+
}
|
|
3580
|
+
if (!output?.codeSplitting || typeof output.codeSplitting !== "object") return;
|
|
3581
|
+
if (!("groups" in output.codeSplitting)) return;
|
|
3582
|
+
delete output.codeSplitting.groups;
|
|
3583
|
+
if (Object.keys(output.codeSplitting).length === 0) delete output.codeSplitting;
|
|
3584
|
+
if (warnedAboutCodeSplittingGroups) return;
|
|
3585
|
+
warnedAboutCodeSplittingGroups = true;
|
|
3586
|
+
mfWarn("Ignoring `output.codeSplitting.groups` because it conflicts with module federation. Grouping shared dependency init wrappers with their dependent modules can break runtime init order and cause standalone remotes to fail before mount.");
|
|
3460
3587
|
};
|
|
3461
3588
|
let warnedAboutManualChunks = false;
|
|
3462
3589
|
const applyManualChunks = (output) => {
|
|
@@ -3464,7 +3591,7 @@ function federation(mfUserOptions) {
|
|
|
3464
3591
|
const isPatchedByPlugin = !!(output.manualChunks && patchedManualChunks.has(output.manualChunks));
|
|
3465
3592
|
if (output.manualChunks && !isPatchedByPlugin && !warnedAboutManualChunks) {
|
|
3466
3593
|
warnedAboutManualChunks = true;
|
|
3467
|
-
mfWarn("Ignoring `
|
|
3594
|
+
mfWarn("Ignoring `output.manualChunks` because it conflicts with module federation. Module federation transforms shared dependency imports with top-level await, and grouping these transformed modules into a single chunk creates circular async dependencies that cause the application to silently hang.");
|
|
3468
3595
|
}
|
|
3469
3596
|
const mfManualChunks = function(id) {
|
|
3470
3597
|
if (id.includes(runtimeInitId)) return "runtimeInit";
|
|
@@ -3477,10 +3604,46 @@ function federation(mfUserOptions) {
|
|
|
3477
3604
|
output.manualChunks = mfManualChunks;
|
|
3478
3605
|
};
|
|
3479
3606
|
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
3480
|
-
|
|
3607
|
+
const rollupOutput = config.build.rollupOptions.output;
|
|
3608
|
+
if (Array.isArray(rollupOutput)) rollupOutput.forEach((output) => applyManualChunks(output));
|
|
3609
|
+
else applyManualChunks(config.build.rollupOptions.output ||= {});
|
|
3481
3610
|
const buildWithRolldown = config.build;
|
|
3482
3611
|
buildWithRolldown.rolldownOptions = buildWithRolldown.rolldownOptions || {};
|
|
3483
|
-
|
|
3612
|
+
const rolldownOutput = buildWithRolldown.rolldownOptions.output;
|
|
3613
|
+
const snapshotRolldownOutput = (output) => ({
|
|
3614
|
+
entryFileNames: output.entryFileNames,
|
|
3615
|
+
chunkFileNames: output.chunkFileNames,
|
|
3616
|
+
assetFileNames: output.assetFileNames
|
|
3617
|
+
});
|
|
3618
|
+
if (Array.isArray(rolldownOutput)) {
|
|
3619
|
+
rolldownOutput.forEach((output) => applyManualChunks(output));
|
|
3620
|
+
desiredRolldownOutput = rolldownOutput.map((output) => snapshotRolldownOutput(output));
|
|
3621
|
+
} else {
|
|
3622
|
+
applyManualChunks(buildWithRolldown.rolldownOptions.output ||= {});
|
|
3623
|
+
desiredRolldownOutput = [snapshotRolldownOutput(buildWithRolldown.rolldownOptions.output)];
|
|
3624
|
+
}
|
|
3625
|
+
},
|
|
3626
|
+
async buildApp(builder) {
|
|
3627
|
+
if (!desiredRolldownOutput) return;
|
|
3628
|
+
const applyRolldownOutput = (output, restoredOutput) => {
|
|
3629
|
+
if (!output || !restoredOutput) return;
|
|
3630
|
+
if (restoredOutput.entryFileNames !== void 0) output.entryFileNames = restoredOutput.entryFileNames;
|
|
3631
|
+
if (restoredOutput.chunkFileNames !== void 0) output.chunkFileNames = restoredOutput.chunkFileNames;
|
|
3632
|
+
if (restoredOutput.assetFileNames !== void 0) output.assetFileNames = restoredOutput.assetFileNames;
|
|
3633
|
+
};
|
|
3634
|
+
for (const environment of Object.values(builder.environments)) {
|
|
3635
|
+
const getRolldownOptions = environment?.getRolldownOptions;
|
|
3636
|
+
if (typeof getRolldownOptions !== "function") continue;
|
|
3637
|
+
environment.getRolldownOptions = async () => {
|
|
3638
|
+
const rolldownOptions = await getRolldownOptions.call(environment);
|
|
3639
|
+
if (Array.isArray(rolldownOptions.output)) rolldownOptions.output.forEach((output, index) => applyRolldownOutput(output, desiredRolldownOutput?.[index]));
|
|
3640
|
+
else {
|
|
3641
|
+
rolldownOptions.output ||= {};
|
|
3642
|
+
applyRolldownOutput(rolldownOptions.output, desiredRolldownOutput[0]);
|
|
3643
|
+
}
|
|
3644
|
+
return rolldownOptions;
|
|
3645
|
+
};
|
|
3646
|
+
}
|
|
3484
3647
|
},
|
|
3485
3648
|
load(id) {
|
|
3486
3649
|
if (id.startsWith("\0")) return;
|
|
@@ -3739,12 +3902,12 @@ function federation(mfUserOptions) {
|
|
|
3739
3902
|
const prefixToRoot = chunkDir === "." ? "" : `${path.relative(chunkDir, ".")}/`;
|
|
3740
3903
|
const replacementExpr = prefixToRoot ? `${escapeUnsafeJsSourceChars(JSON.stringify(prefixToRoot))}+$1` : "$1";
|
|
3741
3904
|
const replacement = `=function($1){return new URL(${replacementExpr},import.meta.url).href}`;
|
|
3742
|
-
const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'][./][
|
|
3905
|
+
const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*[`"'][./][^`"']*[`"']\s*\+\s*\1/, replacement);
|
|
3743
3906
|
if (replaced !== chunk.code) {
|
|
3744
3907
|
chunk.code = replaced;
|
|
3745
3908
|
continue;
|
|
3746
3909
|
}
|
|
3747
|
-
chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'][./][
|
|
3910
|
+
chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*[`"'][./][^`"']*[`"']\s*\+\s*\1\s*\}/, replacement);
|
|
3748
3911
|
chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return new URL\("\.\.\/"\+\1,import\.meta\.url\)\.href\}/, replacement);
|
|
3749
3912
|
chunk.code = chunk.code.replace(/new URL\("\.\.\/"\+(\w+),import\.meta\.url\)\.href/g, `new URL(${replacementExpr},import.meta.url).href`);
|
|
3750
3913
|
}
|