@module-federation/vite 1.11.1 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.cjs +352 -59
- package/lib/index.mjs +352 -59
- package/package.json +13 -12
package/lib/index.mjs
CHANGED
|
@@ -10,6 +10,7 @@ import { walk } from "estree-walker";
|
|
|
10
10
|
import { normalizeOptions } from "@module-federation/sdk";
|
|
11
11
|
import { consumeTypesAPI, generateTypesAPI, isTSProject, normalizeConsumeTypesOptions, normalizeDtsOptions, normalizeGenerateTypesOptions } from "@module-federation/dts-plugin";
|
|
12
12
|
import { rpc } from "@module-federation/dts-plugin/core";
|
|
13
|
+
import { createRequire as createRequire$1 } from "module";
|
|
13
14
|
import { fileURLToPath } from "url";
|
|
14
15
|
|
|
15
16
|
//#region \0rolldown/runtime.js
|
|
@@ -746,6 +747,22 @@ function serializeRuntimeOptions(options) {
|
|
|
746
747
|
|
|
747
748
|
//#endregion
|
|
748
749
|
//#region src/utils/VirtualModule.ts
|
|
750
|
+
/**
|
|
751
|
+
* Initialize virtual module infrastructure BEFORE VirtualModule class is used.
|
|
752
|
+
* This must be called in the config hook to ensure the directory exists
|
|
753
|
+
* before Vite's optimization phase.
|
|
754
|
+
*/
|
|
755
|
+
function initVirtualModuleInfrastructure(root, virtualModuleDir = "__mf__virtual") {
|
|
756
|
+
const virtualPackagePath = join(join(root, "node_modules"), virtualModuleDir);
|
|
757
|
+
if (!existsSync(virtualPackagePath)) {
|
|
758
|
+
mkdirSync(virtualPackagePath, { recursive: true });
|
|
759
|
+
writeFileSync(join(virtualPackagePath, "empty.js"), "");
|
|
760
|
+
writeFileSync(join(virtualPackagePath, "package.json"), JSON.stringify({
|
|
761
|
+
name: virtualModuleDir,
|
|
762
|
+
main: "empty.js"
|
|
763
|
+
}));
|
|
764
|
+
}
|
|
765
|
+
}
|
|
749
766
|
let rootDir;
|
|
750
767
|
function findNodeModulesDir(root = process.cwd()) {
|
|
751
768
|
let currentDir = root;
|
|
@@ -834,9 +851,10 @@ var VirtualModule = class {
|
|
|
834
851
|
|
|
835
852
|
//#endregion
|
|
836
853
|
//#region src/virtualModules/virtualExposes.ts
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
854
|
+
function getVirtualExposesId(options) {
|
|
855
|
+
return `virtual:mf-exposes:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
856
|
+
}
|
|
857
|
+
function generateExposes(options) {
|
|
840
858
|
return `
|
|
841
859
|
export default {
|
|
842
860
|
${Object.keys(options.exposes).map((key) => {
|
|
@@ -886,10 +904,10 @@ ${exportStatement}
|
|
|
886
904
|
//#region src/virtualModules/virtualRemotes.ts
|
|
887
905
|
const cacheRemoteMap = {};
|
|
888
906
|
const LOAD_REMOTE_TAG = "__loadRemote__";
|
|
889
|
-
function getRemoteVirtualModule(remote, command) {
|
|
907
|
+
function getRemoteVirtualModule(remote, command, isRolldown) {
|
|
890
908
|
if (!cacheRemoteMap[remote]) {
|
|
891
|
-
cacheRemoteMap[remote] = new VirtualModule(remote, LOAD_REMOTE_TAG, ".js");
|
|
892
|
-
cacheRemoteMap[remote].writeSync(generateRemotes(remote, command));
|
|
909
|
+
cacheRemoteMap[remote] = new VirtualModule(remote, LOAD_REMOTE_TAG, isRolldown ? ".mjs" : ".js");
|
|
910
|
+
cacheRemoteMap[remote].writeSync(generateRemotes(remote, command, isRolldown));
|
|
893
911
|
}
|
|
894
912
|
return cacheRemoteMap[remote];
|
|
895
913
|
}
|
|
@@ -901,11 +919,11 @@ function addUsedRemote(remoteKey, remoteModule) {
|
|
|
901
919
|
function getUsedRemotesMap() {
|
|
902
920
|
return usedRemotesMap;
|
|
903
921
|
}
|
|
904
|
-
function generateRemotes(id, command) {
|
|
905
|
-
const
|
|
906
|
-
const importLine =
|
|
907
|
-
const awaitOrPlaceholder =
|
|
908
|
-
const exportLine =
|
|
922
|
+
function generateRemotes(id, command, isRolldown) {
|
|
923
|
+
const useESM = command === "build" || isRolldown;
|
|
924
|
+
const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
925
|
+
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
926
|
+
const exportLine = command === "serve" && useESM ? "export default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
|
|
909
927
|
return `
|
|
910
928
|
${importLine}
|
|
911
929
|
const res = initPromise.then(runtime => runtime.loadRemote(${JSON.stringify(id)}))
|
|
@@ -916,6 +934,24 @@ function generateRemotes(id, command) {
|
|
|
916
934
|
|
|
917
935
|
//#endregion
|
|
918
936
|
//#region src/virtualModules/virtualShared_preBuild.ts
|
|
937
|
+
/**
|
|
938
|
+
* Even the resolveId hook cannot interfere with vite pre-build,
|
|
939
|
+
* and adding query parameter virtual modules will also fail.
|
|
940
|
+
* You can only proxy to the real file through alias
|
|
941
|
+
*/
|
|
942
|
+
/**
|
|
943
|
+
* shared will be proxied:
|
|
944
|
+
* 1. __prebuild__: export shareModule (pre-built source code of modules such as vue, react, etc.)
|
|
945
|
+
* 2. __loadShare__: load shareModule (mfRuntime.loadShare('vue'))
|
|
946
|
+
*/
|
|
947
|
+
function getPackageNamedExports(pkg) {
|
|
948
|
+
try {
|
|
949
|
+
const mod = createRequire$1(new URL("file://" + process.cwd() + "/package.json"))(pkg);
|
|
950
|
+
return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule");
|
|
951
|
+
} catch {
|
|
952
|
+
return [];
|
|
953
|
+
}
|
|
954
|
+
}
|
|
919
955
|
const preBuildCacheMap = {};
|
|
920
956
|
const PREBUILD_TAG = "__prebuild__";
|
|
921
957
|
function writePreBuildLibPath(pkg) {
|
|
@@ -928,17 +964,24 @@ function getPreBuildLibImportId(pkg) {
|
|
|
928
964
|
}
|
|
929
965
|
const LOAD_SHARE_TAG = "__loadShare__";
|
|
930
966
|
const loadShareCacheMap = {};
|
|
931
|
-
function getLoadShareModulePath(pkg) {
|
|
932
|
-
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".js");
|
|
967
|
+
function getLoadShareModulePath(pkg, isRolldown, command) {
|
|
968
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
|
|
933
969
|
return loadShareCacheMap[pkg].getPath();
|
|
934
970
|
}
|
|
935
|
-
function writeLoadShareModule(pkg, shareItem, command) {
|
|
936
|
-
|
|
937
|
-
const
|
|
938
|
-
const
|
|
939
|
-
const
|
|
971
|
+
function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
972
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
|
|
973
|
+
const useESM = command === "build" || isRolldown;
|
|
974
|
+
const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
975
|
+
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
976
|
+
const namedExports = getPackageNamedExports(pkg);
|
|
977
|
+
let exportLine;
|
|
978
|
+
if (namedExports.length > 0) {
|
|
979
|
+
const destructure = `const { ${namedExports.join(", ")} } = exportModule;`;
|
|
980
|
+
const namedExportLine = `export { ${namedExports.join(", ")} };`;
|
|
981
|
+
exportLine = useESM ? `export default exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.join(", ")} });`;
|
|
982
|
+
} else exportLine = useESM ? `export default exportModule\n export * from ${JSON.stringify(getPreBuildLibImportId(pkg))}` : "module.exports = exportModule";
|
|
940
983
|
loadShareCacheMap[pkg].writeSync(`
|
|
941
|
-
|
|
984
|
+
import ${JSON.stringify(getPreBuildLibImportId(pkg))};
|
|
942
985
|
${command !== "build" ? `;() => import(${JSON.stringify(pkg)}).catch(() => {});` : ""}
|
|
943
986
|
${importLine}
|
|
944
987
|
const res = initPromise.then(runtime => runtime.loadShare(${JSON.stringify(pkg)}, {
|
|
@@ -948,7 +991,7 @@ function writeLoadShareModule(pkg, shareItem, command) {
|
|
|
948
991
|
requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)}
|
|
949
992
|
}}
|
|
950
993
|
}))
|
|
951
|
-
const exportModule = ${awaitOrPlaceholder}res.then(factory => factory())
|
|
994
|
+
const exportModule = ${awaitOrPlaceholder}res.then((factory) => (typeof factory === "function" ? factory() : factory))
|
|
952
995
|
${exportLine}
|
|
953
996
|
`);
|
|
954
997
|
}
|
|
@@ -1047,7 +1090,10 @@ function generateLocalSharedImportMap() {
|
|
|
1047
1090
|
`;
|
|
1048
1091
|
}
|
|
1049
1092
|
const REMOTE_ENTRY_ID = "virtual:mf-REMOTE_ENTRY_ID";
|
|
1050
|
-
function
|
|
1093
|
+
function getRemoteEntryId(options) {
|
|
1094
|
+
return `${REMOTE_ENTRY_ID}:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
1095
|
+
}
|
|
1096
|
+
function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options)) {
|
|
1051
1097
|
const pluginImportNames = options.runtimePlugins.map((p, i) => {
|
|
1052
1098
|
if (typeof p === "string") return [
|
|
1053
1099
|
`$runtimePlugin_${i}`,
|
|
@@ -1063,7 +1109,7 @@ function generateRemoteEntry(options) {
|
|
|
1063
1109
|
return `
|
|
1064
1110
|
import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
|
|
1065
1111
|
${pluginImportNames.map((item) => item[1]).join("\n")}
|
|
1066
|
-
import exposesMap from "${
|
|
1112
|
+
import exposesMap from "${virtualExposesId}"
|
|
1067
1113
|
import {usedShared, usedRemotes} from "${getLocalSharedImportMapPath()}"
|
|
1068
1114
|
import {
|
|
1069
1115
|
initResolve
|
|
@@ -1115,9 +1161,9 @@ function generateRemoteEntry(options) {
|
|
|
1115
1161
|
*/
|
|
1116
1162
|
const HOST_AUTO_INIT_TAG = "__H_A_I__";
|
|
1117
1163
|
const hostAutoInitModule = new VirtualModule("hostAutoInit", HOST_AUTO_INIT_TAG);
|
|
1118
|
-
function writeHostAutoInit() {
|
|
1164
|
+
function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID) {
|
|
1119
1165
|
hostAutoInitModule.writeSync(`
|
|
1120
|
-
const remoteEntryPromise = import("${
|
|
1166
|
+
const remoteEntryPromise = import("${remoteEntryId}")
|
|
1121
1167
|
// __tla only serves as a hack for vite-plugin-top-level-await.
|
|
1122
1168
|
Promise.resolve(remoteEntryPromise)
|
|
1123
1169
|
.then(remoteEntry => {
|
|
@@ -1135,9 +1181,9 @@ function getHostAutoInitPath() {
|
|
|
1135
1181
|
|
|
1136
1182
|
//#endregion
|
|
1137
1183
|
//#region src/virtualModules/index.ts
|
|
1138
|
-
function initVirtualModules(command) {
|
|
1184
|
+
function initVirtualModules(command, remoteEntryId) {
|
|
1139
1185
|
writeLocalSharedImportMap();
|
|
1140
|
-
writeHostAutoInit();
|
|
1186
|
+
writeHostAutoInit(remoteEntryId);
|
|
1141
1187
|
writeRuntimeInitStatus(command);
|
|
1142
1188
|
}
|
|
1143
1189
|
|
|
@@ -1544,7 +1590,7 @@ function pluginModuleParseEnd_default(excludeFn, options) {
|
|
|
1544
1590
|
apply: "build",
|
|
1545
1591
|
moduleParsed(module) {
|
|
1546
1592
|
const id = module.id;
|
|
1547
|
-
if (id ===
|
|
1593
|
+
if (id === options.virtualExposesId) exposesParseEnd = true;
|
|
1548
1594
|
if (excludeFn(id)) return;
|
|
1549
1595
|
parseEndSet.add(id);
|
|
1550
1596
|
if (exposesParseEnd && parseStartSet.size === parseEndSet.size) _resolve(1);
|
|
@@ -1556,7 +1602,7 @@ function pluginModuleParseEnd_default(excludeFn, options) {
|
|
|
1556
1602
|
//#endregion
|
|
1557
1603
|
//#region src/plugins/pluginProxyRemoteEntry.ts
|
|
1558
1604
|
const filter = createFilter();
|
|
1559
|
-
function pluginProxyRemoteEntry_default() {
|
|
1605
|
+
function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
|
|
1560
1606
|
let viteConfig, _command;
|
|
1561
1607
|
return {
|
|
1562
1608
|
name: "proxyRemoteEntry",
|
|
@@ -1567,28 +1613,37 @@ function pluginProxyRemoteEntry_default() {
|
|
|
1567
1613
|
config(config, { command }) {
|
|
1568
1614
|
_command = command;
|
|
1569
1615
|
},
|
|
1616
|
+
async buildStart() {
|
|
1617
|
+
if (_command !== "build") return;
|
|
1618
|
+
for (const expose of Object.values(options.exposes)) {
|
|
1619
|
+
const resolved = await this.resolve(expose.import);
|
|
1620
|
+
if (resolved) this.emitFile({
|
|
1621
|
+
type: "chunk",
|
|
1622
|
+
id: resolved.id
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1625
|
+
},
|
|
1570
1626
|
async resolveId(id, importer) {
|
|
1571
|
-
if (id ===
|
|
1572
|
-
if (id ===
|
|
1627
|
+
if (id === remoteEntryId) return remoteEntryId;
|
|
1628
|
+
if (id === virtualExposesId) return virtualExposesId;
|
|
1573
1629
|
if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
|
|
1574
|
-
if (importer ===
|
|
1575
|
-
typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url);
|
|
1576
|
-
const resolved = await this.resolve(id,
|
|
1630
|
+
if (importer === remoteEntryId && !id.startsWith(".") && !id.startsWith("/") && !id.startsWith("\0") && !id.startsWith("virtual:")) {
|
|
1631
|
+
const importPath = typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url);
|
|
1632
|
+
const resolved = await this.resolve(id, importPath, { skipSelf: true });
|
|
1577
1633
|
if (resolved) return resolved;
|
|
1578
1634
|
}
|
|
1579
1635
|
},
|
|
1580
1636
|
load(id) {
|
|
1581
|
-
if (id ===
|
|
1582
|
-
if (id ===
|
|
1637
|
+
if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
|
|
1638
|
+
if (id === virtualExposesId) return generateExposes(options);
|
|
1583
1639
|
if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
|
|
1584
1640
|
},
|
|
1585
1641
|
transform(code, id) {
|
|
1586
1642
|
return mapCodeToCodeWithSourcemap((() => {
|
|
1587
1643
|
if (!filter(id)) return;
|
|
1588
|
-
if (id.includes(
|
|
1589
|
-
if (id ===
|
|
1644
|
+
if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
|
|
1645
|
+
if (id === virtualExposesId) return generateExposes(options);
|
|
1590
1646
|
if (id.includes(getHostAutoInitPath())) {
|
|
1591
|
-
const options = getNormalizeModuleFederationOptions();
|
|
1592
1647
|
if (_command === "serve") {
|
|
1593
1648
|
const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
|
|
1594
1649
|
const publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
|
|
@@ -1618,13 +1673,14 @@ function pluginProxyRemotes_default(options) {
|
|
|
1618
1673
|
return {
|
|
1619
1674
|
name: "proxyRemotes",
|
|
1620
1675
|
config(config, { command: _command }) {
|
|
1676
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
1621
1677
|
Object.keys(remotes).forEach((key) => {
|
|
1622
1678
|
const remote = remotes[key];
|
|
1623
1679
|
config.resolve.alias.push({
|
|
1624
1680
|
find: new RegExp(`^(${remote.name}(\/.*|$))`),
|
|
1625
1681
|
replacement: "$1",
|
|
1626
1682
|
customResolver(source) {
|
|
1627
|
-
const remoteModule = getRemoteVirtualModule(source, _command);
|
|
1683
|
+
const remoteModule = getRemoteVirtualModule(source, _command, isRolldown);
|
|
1628
1684
|
addUsedRemote(remote.name, source);
|
|
1629
1685
|
return remoteModule.getPath();
|
|
1630
1686
|
}
|
|
@@ -1671,8 +1727,10 @@ var PromiseStore = class {
|
|
|
1671
1727
|
//#endregion
|
|
1672
1728
|
//#region src/plugins/pluginProxySharedModule_preBuild.ts
|
|
1673
1729
|
function proxySharedModule(options) {
|
|
1674
|
-
|
|
1730
|
+
const { shared = {} } = options;
|
|
1675
1731
|
let _config;
|
|
1732
|
+
let _command = "serve";
|
|
1733
|
+
const savePrebuild = new PromiseStore();
|
|
1676
1734
|
return [{
|
|
1677
1735
|
name: "generateLocalSharedImportMap",
|
|
1678
1736
|
enforce: "post",
|
|
@@ -1685,19 +1743,23 @@ function proxySharedModule(options) {
|
|
|
1685
1743
|
}, {
|
|
1686
1744
|
name: "proxyPreBuildShared",
|
|
1687
1745
|
enforce: "post",
|
|
1688
|
-
configResolved(config) {
|
|
1689
|
-
_config = config;
|
|
1690
|
-
},
|
|
1691
1746
|
config(config, { command }) {
|
|
1747
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
1748
|
+
_command = command;
|
|
1692
1749
|
config.resolve.alias.push(...Object.keys(shared).map((key) => {
|
|
1693
|
-
const
|
|
1750
|
+
const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
|
|
1751
|
+
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1752
|
+
const escapedKeyBase = escapeRegex(keyBase);
|
|
1753
|
+
const pattern = key.endsWith("/") ? `^(${escapedKeyBase}(?:\\/.*)?)$` : `^(${escapedKeyBase})$`;
|
|
1694
1754
|
return {
|
|
1695
1755
|
find: new RegExp(pattern),
|
|
1696
1756
|
replacement: "$1",
|
|
1697
1757
|
customResolver(source, importer) {
|
|
1698
1758
|
if (/\.css$/.test(source)) return;
|
|
1699
|
-
|
|
1700
|
-
|
|
1759
|
+
if (importer && importer.includes("localSharedImportMap")) return;
|
|
1760
|
+
if (key.endsWith("/") && source !== key.slice(0, -1)) return;
|
|
1761
|
+
const loadSharePath = getLoadShareModulePath(source, isRolldown, command);
|
|
1762
|
+
writeLoadShareModule(source, shared[key], command, isRolldown);
|
|
1701
1763
|
writePreBuildLibPath(source);
|
|
1702
1764
|
addUsedShares(source);
|
|
1703
1765
|
writeLocalSharedImportMap();
|
|
@@ -1705,7 +1767,6 @@ function proxySharedModule(options) {
|
|
|
1705
1767
|
}
|
|
1706
1768
|
};
|
|
1707
1769
|
}));
|
|
1708
|
-
const savePrebuild = new PromiseStore();
|
|
1709
1770
|
config.resolve.alias.push(...Object.keys(shared).map((key) => {
|
|
1710
1771
|
return command === "build" ? {
|
|
1711
1772
|
find: new RegExp(`(.*${PREBUILD_TAG}.*)`),
|
|
@@ -1718,11 +1779,22 @@ function proxySharedModule(options) {
|
|
|
1718
1779
|
async customResolver(source, importer) {
|
|
1719
1780
|
const pkgName = assertModuleFound(PREBUILD_TAG, source).name;
|
|
1720
1781
|
const result = await this.resolve(pkgName, importer).then((item) => item.id);
|
|
1721
|
-
if (!result.includes(_config.cacheDir)) savePrebuild.set(pkgName, Promise.resolve(result));
|
|
1782
|
+
if (_config && !result.includes(_config.cacheDir)) savePrebuild.set(pkgName, Promise.resolve(result));
|
|
1722
1783
|
return await this.resolve(await savePrebuild.get(pkgName), importer);
|
|
1723
1784
|
}
|
|
1724
1785
|
};
|
|
1725
1786
|
}));
|
|
1787
|
+
},
|
|
1788
|
+
configResolved(config) {
|
|
1789
|
+
_config = config;
|
|
1790
|
+
const isRolldown = !!config.experimental?.rolldownDev;
|
|
1791
|
+
Object.keys(shared).forEach((key) => {
|
|
1792
|
+
if (key.endsWith("/")) return;
|
|
1793
|
+
writeLoadShareModule(key, shared[key], _command, isRolldown);
|
|
1794
|
+
writePreBuildLibPath(key);
|
|
1795
|
+
addUsedShares(key);
|
|
1796
|
+
});
|
|
1797
|
+
writeLocalSharedImportMap();
|
|
1726
1798
|
}
|
|
1727
1799
|
}];
|
|
1728
1800
|
}
|
|
@@ -1833,20 +1905,60 @@ var normalizeOptimizeDeps_default = {
|
|
|
1833
1905
|
config.optimizeDeps = {};
|
|
1834
1906
|
optimizeDeps = config.optimizeDeps;
|
|
1835
1907
|
}
|
|
1836
|
-
optimizeDeps.force = true;
|
|
1837
1908
|
if (!optimizeDeps.include) optimizeDeps.include = [];
|
|
1909
|
+
if (!optimizeDeps.exclude) optimizeDeps.exclude = [];
|
|
1838
1910
|
if (!optimizeDeps.needsInterop) optimizeDeps.needsInterop = [];
|
|
1839
1911
|
}
|
|
1840
1912
|
};
|
|
1841
1913
|
|
|
1842
1914
|
//#endregion
|
|
1843
1915
|
//#region src/index.ts
|
|
1916
|
+
/**
|
|
1917
|
+
* Plugin that runs FIRST to create virtual module files in the config hook.
|
|
1918
|
+
* This prevents 504 "Outdated Optimize Dep" errors by ensuring files exist
|
|
1919
|
+
* before Vite's optimization phase.
|
|
1920
|
+
*/
|
|
1921
|
+
function createEarlyVirtualModulesPlugin(options) {
|
|
1922
|
+
const { shared, remotes, virtualModuleDir } = options;
|
|
1923
|
+
return {
|
|
1924
|
+
name: "vite:module-federation-early-init",
|
|
1925
|
+
enforce: "pre",
|
|
1926
|
+
config(config, { command: _command }) {
|
|
1927
|
+
if (_command !== "serve") return;
|
|
1928
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
1929
|
+
const root = config.root || process.cwd();
|
|
1930
|
+
initVirtualModuleInfrastructure(root, virtualModuleDir);
|
|
1931
|
+
VirtualModule.setRoot(root);
|
|
1932
|
+
VirtualModule.ensureVirtualPackageExists();
|
|
1933
|
+
initVirtualModules(_command, getRemoteEntryId(options));
|
|
1934
|
+
if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
|
|
1935
|
+
if (shared && Object.keys(shared).length > 0) {
|
|
1936
|
+
config.optimizeDeps = config.optimizeDeps || {};
|
|
1937
|
+
config.optimizeDeps.include = config.optimizeDeps.include || [];
|
|
1938
|
+
config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
|
|
1939
|
+
for (const key of Object.keys(shared)) {
|
|
1940
|
+
if (key.endsWith("/")) continue;
|
|
1941
|
+
const shareItem = shared[key];
|
|
1942
|
+
getLoadShareModulePath(key, isRolldown);
|
|
1943
|
+
writeLoadShareModule(key, shareItem, _command, isRolldown);
|
|
1944
|
+
writePreBuildLibPath(key);
|
|
1945
|
+
addUsedShares(key);
|
|
1946
|
+
config.optimizeDeps.include.push(getPreBuildLibImportId(key));
|
|
1947
|
+
}
|
|
1948
|
+
writeLocalSharedImportMap();
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
};
|
|
1952
|
+
}
|
|
1844
1953
|
function federation(mfUserOptions) {
|
|
1845
1954
|
const options = normalizeModuleFederationOptions(mfUserOptions);
|
|
1846
1955
|
const { name, remotes, shared, filename, hostInitInjectLocation } = options;
|
|
1847
1956
|
if (!name) throw new Error("name is required");
|
|
1957
|
+
const remoteEntryId = getRemoteEntryId(options);
|
|
1958
|
+
const virtualExposesId = getVirtualExposesId(options);
|
|
1848
1959
|
let command;
|
|
1849
1960
|
return [
|
|
1961
|
+
createEarlyVirtualModulesPlugin(options),
|
|
1850
1962
|
{
|
|
1851
1963
|
name: "vite:module-federation-config",
|
|
1852
1964
|
enforce: "pre",
|
|
@@ -1856,7 +1968,7 @@ function federation(mfUserOptions) {
|
|
|
1856
1968
|
configResolved(config) {
|
|
1857
1969
|
VirtualModule.setRoot(config.root);
|
|
1858
1970
|
VirtualModule.ensureVirtualPackageExists();
|
|
1859
|
-
initVirtualModules(command);
|
|
1971
|
+
initVirtualModules(command, remoteEntryId);
|
|
1860
1972
|
}
|
|
1861
1973
|
},
|
|
1862
1974
|
aliasToArrayPlugin_default,
|
|
@@ -1865,7 +1977,7 @@ function federation(mfUserOptions) {
|
|
|
1865
1977
|
...pluginDts(options),
|
|
1866
1978
|
...addEntry({
|
|
1867
1979
|
entryName: "remoteEntry",
|
|
1868
|
-
entryPath:
|
|
1980
|
+
entryPath: remoteEntryId,
|
|
1869
1981
|
fileName: filename
|
|
1870
1982
|
}),
|
|
1871
1983
|
...addEntry({
|
|
@@ -1875,22 +1987,51 @@ function federation(mfUserOptions) {
|
|
|
1875
1987
|
}),
|
|
1876
1988
|
...addEntry({
|
|
1877
1989
|
entryName: "virtualExposes",
|
|
1878
|
-
entryPath:
|
|
1990
|
+
entryPath: virtualExposesId
|
|
1991
|
+
}),
|
|
1992
|
+
pluginProxyRemoteEntry_default({
|
|
1993
|
+
options,
|
|
1994
|
+
remoteEntryId,
|
|
1995
|
+
virtualExposesId
|
|
1879
1996
|
}),
|
|
1880
|
-
pluginProxyRemoteEntry_default(),
|
|
1881
1997
|
pluginProxyRemotes_default(options),
|
|
1882
1998
|
...pluginModuleParseEnd_default((id) => {
|
|
1883
|
-
return id.includes(getHostAutoInitImportId()) || id.includes(
|
|
1884
|
-
}, {
|
|
1999
|
+
return id.includes(getHostAutoInitImportId()) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath());
|
|
2000
|
+
}, {
|
|
2001
|
+
moduleParseTimeout: options.moduleParseTimeout,
|
|
2002
|
+
virtualExposesId
|
|
2003
|
+
}),
|
|
1885
2004
|
...proxySharedModule({ shared }),
|
|
1886
2005
|
{
|
|
1887
2006
|
name: "module-federation-esm-shims",
|
|
1888
2007
|
enforce: "pre",
|
|
1889
2008
|
apply: "build",
|
|
2009
|
+
config(config) {
|
|
2010
|
+
const runtimeInitId = virtualRuntimeInitStatus.getImportId();
|
|
2011
|
+
config.build = config.build || {};
|
|
2012
|
+
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
2013
|
+
if (!Array.isArray(config.build.rollupOptions.output)) {
|
|
2014
|
+
const output = config.build.rollupOptions.output ||= {};
|
|
2015
|
+
const existingManualChunks = output.manualChunks;
|
|
2016
|
+
output.manualChunks = function(id) {
|
|
2017
|
+
if (id.includes(runtimeInitId)) return "runtimeInit";
|
|
2018
|
+
if (id.includes(LOAD_SHARE_TAG)) {
|
|
2019
|
+
const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
|
|
2020
|
+
return match ? match[1] : "loadShare";
|
|
2021
|
+
}
|
|
2022
|
+
if (typeof existingManualChunks === "function") return existingManualChunks.apply(this, arguments);
|
|
2023
|
+
if (existingManualChunks && typeof existingManualChunks === "object") {
|
|
2024
|
+
for (const [key, ids] of Object.entries(existingManualChunks)) if (Array.isArray(ids) && ids.some((v) => id.includes(v))) return key;
|
|
2025
|
+
}
|
|
2026
|
+
};
|
|
2027
|
+
}
|
|
2028
|
+
},
|
|
1890
2029
|
load(id) {
|
|
1891
2030
|
if (id.startsWith("\0")) return;
|
|
1892
2031
|
if (id.includes(LOAD_SHARE_TAG) || id.includes(LOAD_REMOTE_TAG)) {
|
|
1893
2032
|
let code = readFileSync(id, "utf-8");
|
|
2033
|
+
code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
2034
|
+
code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
1894
2035
|
/**
|
|
1895
2036
|
* Shared/remote shims only have `export default exportModule`.
|
|
1896
2037
|
*
|
|
@@ -1913,6 +2054,134 @@ function federation(mfUserOptions) {
|
|
|
1913
2054
|
syntheticNamedExports: "__moduleExports"
|
|
1914
2055
|
};
|
|
1915
2056
|
}
|
|
2057
|
+
},
|
|
2058
|
+
generateBundle(_, bundle) {
|
|
2059
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
2060
|
+
if (chunk.type !== "chunk") continue;
|
|
2061
|
+
if (fileName.includes(LOAD_SHARE_TAG)) continue;
|
|
2062
|
+
let code = chunk.code;
|
|
2063
|
+
let m;
|
|
2064
|
+
const importedFromLoadShare = /* @__PURE__ */ new Set();
|
|
2065
|
+
const importRegex = /import\s*\{([^}]+)\}\s*from\s*["'][^"']*__loadShare__[^"']*["']/g;
|
|
2066
|
+
while ((m = importRegex.exec(code)) !== null) for (const spec of m[1].split(",")) {
|
|
2067
|
+
const parts = spec.trim().split(/\s+as\s+/);
|
|
2068
|
+
const local = (parts[1] || parts[0]).trim();
|
|
2069
|
+
if (local) importedFromLoadShare.add(local);
|
|
2070
|
+
}
|
|
2071
|
+
const allInits = [];
|
|
2072
|
+
for (const v of importedFromLoadShare) if (new RegExp("\\(" + v + "\\(\\)\\s*,\\s*\\w+\\(\\w+\\)\\)").test(code)) allInits.push(v);
|
|
2073
|
+
if (allInits.length === 0) continue;
|
|
2074
|
+
const awaits = allInits.map((v) => `await ${v}();`).join("");
|
|
2075
|
+
const lastFromRegex = /\bfrom\s*["'][^"']*["']\s*;?/g;
|
|
2076
|
+
let lastFromEnd = -1;
|
|
2077
|
+
while ((m = lastFromRegex.exec(code)) !== null) lastFromEnd = m.index + m[0].length;
|
|
2078
|
+
if (lastFromEnd !== -1) {
|
|
2079
|
+
chunk.code = code.slice(0, lastFromEnd) + awaits + code.slice(lastFromEnd);
|
|
2080
|
+
continue;
|
|
2081
|
+
}
|
|
2082
|
+
const exportIdx = code.search(/\bexport\s*[{d]/);
|
|
2083
|
+
if (exportIdx !== -1) {
|
|
2084
|
+
chunk.code = code.slice(0, exportIdx) + awaits + code.slice(exportIdx);
|
|
2085
|
+
continue;
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
const proxyChunks = /* @__PURE__ */ new Map();
|
|
2089
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
2090
|
+
if (chunk.type !== "chunk") continue;
|
|
2091
|
+
if (fileName.includes(LOAD_SHARE_TAG) && fileName.includes("commonjs-proxy")) proxyChunks.set(fileName, {
|
|
2092
|
+
code: chunk.code,
|
|
2093
|
+
fileName
|
|
2094
|
+
});
|
|
2095
|
+
}
|
|
2096
|
+
if (proxyChunks.size === 0) return;
|
|
2097
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
2098
|
+
if (chunk.type !== "chunk") continue;
|
|
2099
|
+
if (fileName.includes(LOAD_SHARE_TAG)) continue;
|
|
2100
|
+
let code = chunk.code;
|
|
2101
|
+
let modified = false;
|
|
2102
|
+
for (const [proxyFileName, proxyInfo] of proxyChunks) {
|
|
2103
|
+
const proxyBaseName = proxyFileName.replace(/^.*\//, "").replace(/\.js$/, "").replace(/-[A-Za-z0-9_-]+$/, "");
|
|
2104
|
+
const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${proxyBaseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[^"']*)["']\\s*;?`).exec(code);
|
|
2105
|
+
if (!importMatch) continue;
|
|
2106
|
+
const fullImport = importMatch[0];
|
|
2107
|
+
const bindings = importMatch[1].split(",").map((s) => {
|
|
2108
|
+
const parts = s.trim().split(/\s+as\s+/);
|
|
2109
|
+
return {
|
|
2110
|
+
imported: parts[0].trim(),
|
|
2111
|
+
local: (parts[1] || parts[0]).trim()
|
|
2112
|
+
};
|
|
2113
|
+
});
|
|
2114
|
+
const proxyCode = proxyInfo.code;
|
|
2115
|
+
const exportMapMatch = proxyCode.match(/export\s*\{([^}]+)\}/);
|
|
2116
|
+
if (!exportMapMatch) continue;
|
|
2117
|
+
const exportMap = {};
|
|
2118
|
+
for (const entry of exportMapMatch[1].split(",")) {
|
|
2119
|
+
const parts = entry.trim().split(/\s+as\s+/);
|
|
2120
|
+
if (parts.length === 2) exportMap[parts[1].trim()] = parts[0].trim();
|
|
2121
|
+
}
|
|
2122
|
+
const inlineable = [];
|
|
2123
|
+
const nonInlineable = [];
|
|
2124
|
+
for (const b of bindings) {
|
|
2125
|
+
const proxyLocal = exportMap[b.imported];
|
|
2126
|
+
if (!proxyLocal) {
|
|
2127
|
+
nonInlineable.push(b);
|
|
2128
|
+
continue;
|
|
2129
|
+
}
|
|
2130
|
+
const funcRe = new RegExp(`function\\s+${proxyLocal}\\s*\\([^)]*\\)\\s*\\{`);
|
|
2131
|
+
if (funcRe.test(proxyCode)) {
|
|
2132
|
+
const funcStart = proxyCode.search(funcRe);
|
|
2133
|
+
let depth = 0;
|
|
2134
|
+
let funcEnd = funcStart;
|
|
2135
|
+
for (let i = proxyCode.indexOf("{", funcStart); i < proxyCode.length; i++) if (proxyCode[i] === "{") depth++;
|
|
2136
|
+
else if (proxyCode[i] === "}") {
|
|
2137
|
+
depth--;
|
|
2138
|
+
if (depth === 0) {
|
|
2139
|
+
funcEnd = i + 1;
|
|
2140
|
+
break;
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
const renamedFunc = proxyCode.slice(funcStart, funcEnd).replace(new RegExp(`function\\s+${proxyLocal}\\s*\\(`), `function ${b.local}(`);
|
|
2144
|
+
inlineable.push({
|
|
2145
|
+
local: b.local,
|
|
2146
|
+
funcBody: renamedFunc
|
|
2147
|
+
});
|
|
2148
|
+
} else nonInlineable.push(b);
|
|
2149
|
+
}
|
|
2150
|
+
if (inlineable.length === 0) continue;
|
|
2151
|
+
let replacement = "";
|
|
2152
|
+
if (nonInlineable.length > 0) replacement = `import{${nonInlineable.map((b) => b.imported === b.local ? b.imported : `${b.imported} as ${b.local}`).join(",")}}from"${importMatch[2]}";`;
|
|
2153
|
+
replacement += inlineable.map((f) => f.funcBody).join("");
|
|
2154
|
+
code = code.replace(fullImport, replacement);
|
|
2155
|
+
modified = true;
|
|
2156
|
+
}
|
|
2157
|
+
if (modified) chunk.code = code;
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
},
|
|
2161
|
+
{
|
|
2162
|
+
name: "module-federation-dev-await-shared-init",
|
|
2163
|
+
apply: "serve",
|
|
2164
|
+
enforce: "post",
|
|
2165
|
+
transform(code, id) {
|
|
2166
|
+
if (!id.includes(".vite/deps/")) return;
|
|
2167
|
+
const initPattern = /\b(init_\w+__loadShare__\w+)\b/g;
|
|
2168
|
+
const initFns = /* @__PURE__ */ new Set();
|
|
2169
|
+
let match;
|
|
2170
|
+
while ((match = initPattern.exec(code)) !== null) initFns.add(match[1]);
|
|
2171
|
+
if (initFns.size === 0) return;
|
|
2172
|
+
if (![...initFns].some((fn) => {
|
|
2173
|
+
return code.includes(`${fn}(),`) || code.includes(`${fn}()`);
|
|
2174
|
+
})) return;
|
|
2175
|
+
if (/await\s+init_\w+__loadShare__/.test(code)) return;
|
|
2176
|
+
if (code.includes("__esmMin")) return;
|
|
2177
|
+
const awaits = [...initFns].map((fn) => `await ${fn}();`).join("\n");
|
|
2178
|
+
const topLevelImportRe = /^import\s/gm;
|
|
2179
|
+
let lastImportIdx = -1;
|
|
2180
|
+
let importMatch;
|
|
2181
|
+
while ((importMatch = topLevelImportRe.exec(code)) !== null) lastImportIdx = importMatch.index;
|
|
2182
|
+
if (lastImportIdx === -1) return;
|
|
2183
|
+
const lineEnd = code.indexOf("\n", lastImportIdx);
|
|
2184
|
+
return code.slice(0, lineEnd + 1) + awaits + "\n" + code.slice(lineEnd + 1);
|
|
1916
2185
|
}
|
|
1917
2186
|
},
|
|
1918
2187
|
PluginDevProxyModuleTopLevelAwait(),
|
|
@@ -1921,16 +2190,22 @@ function federation(mfUserOptions) {
|
|
|
1921
2190
|
enforce: "post",
|
|
1922
2191
|
_options: options,
|
|
1923
2192
|
config(config, { command: _command }) {
|
|
2193
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
2194
|
+
let implementation = options.implementation;
|
|
2195
|
+
if (isRolldown) implementation = implementation.replace(/\.cjs\.cjs$/, ".esm.js");
|
|
1924
2196
|
config.resolve.alias.push({
|
|
1925
2197
|
find: "@module-federation/runtime",
|
|
1926
|
-
replacement:
|
|
2198
|
+
replacement: implementation
|
|
1927
2199
|
});
|
|
1928
2200
|
config.build = defu(config.build || {}, { commonjsOptions: { strictRequires: "auto" } });
|
|
1929
2201
|
const virtualDir = options.virtualModuleDir || "__mf__virtual";
|
|
1930
2202
|
config.optimizeDeps?.include?.push("@module-federation/runtime");
|
|
1931
2203
|
config.optimizeDeps?.include?.push(virtualDir);
|
|
1932
|
-
config.
|
|
1933
|
-
|
|
2204
|
+
if (isRolldown) config.build = defu(config.build || {}, { target: "esnext" });
|
|
2205
|
+
else {
|
|
2206
|
+
config.optimizeDeps?.needsInterop?.push(virtualDir);
|
|
2207
|
+
config.optimizeDeps?.needsInterop?.push(getLocalSharedImportMapPath());
|
|
2208
|
+
}
|
|
1934
2209
|
const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
|
|
1935
2210
|
if (!config.define) config.define = {};
|
|
1936
2211
|
if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] = JSON.stringify(resolvedTarget);
|
|
@@ -1938,7 +2213,25 @@ function federation(mfUserOptions) {
|
|
|
1938
2213
|
}
|
|
1939
2214
|
},
|
|
1940
2215
|
...Manifest(),
|
|
1941
|
-
...VarRemoteEntry()
|
|
2216
|
+
...VarRemoteEntry(),
|
|
2217
|
+
...Object.keys(options.exposes).length > 0 ? [{
|
|
2218
|
+
name: "module-federation-fix-preload",
|
|
2219
|
+
enforce: "post",
|
|
2220
|
+
apply: "build",
|
|
2221
|
+
generateBundle(_, bundle) {
|
|
2222
|
+
for (const chunk of Object.values(bundle)) {
|
|
2223
|
+
if (chunk.type !== "chunk") continue;
|
|
2224
|
+
if (!chunk.code.includes("modulepreload")) continue;
|
|
2225
|
+
const replacement = "=function($1){return new URL(\"../\"+$1,import.meta.url).href}";
|
|
2226
|
+
const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'`][^"'`]*["'`]\s*\+\s*\1/, replacement);
|
|
2227
|
+
if (replaced !== chunk.code) {
|
|
2228
|
+
chunk.code = replaced;
|
|
2229
|
+
continue;
|
|
2230
|
+
}
|
|
2231
|
+
chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'`][^"'`]*["'`]\s*\+\s*\1\s*\}/, replacement);
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
}] : []
|
|
1942
2235
|
];
|
|
1943
2236
|
}
|
|
1944
2237
|
|