@module-federation/vite 1.13.2 → 1.13.3
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 +322 -52
- package/lib/index.mjs +322 -52
- package/package.json +2 -1
package/lib/index.cjs
CHANGED
|
@@ -49,35 +49,25 @@ async function mapCodeToCodeWithSourcemap(code) {
|
|
|
49
49
|
//#endregion
|
|
50
50
|
//#region src/utils/htmlEntryUtils.ts
|
|
51
51
|
function sanitizeDevEntryPath(devEntryPath) {
|
|
52
|
-
return devEntryPath.replace(
|
|
52
|
+
return devEntryPath.replace(/\\\\?/g, "/");
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* If no entry scripts are found, falls back to injecting a separate script tag.
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* // Before (two separate scripts, race condition):
|
|
63
|
-
* // <script type="module" src="/__mf__virtual/hostAutoInit.js"><\/script>
|
|
64
|
-
* // <script type="module" src="/src/main.js"><\/script>
|
|
65
|
-
* // After (single inline script, sequential execution):
|
|
66
|
-
* // <script type="module">await import("/__mf__virtual/hostAutoInit.js");await import("/src/main.js");<\/script>
|
|
55
|
+
* Rewrites entry module script tags to point at an external wrapper module.
|
|
56
|
+
* The wrapper can then sequence federation init before the app entry without
|
|
57
|
+
* relying on CSP-breaking inline `<script type="module">`.
|
|
67
58
|
*/
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
const scriptTagRegex = /<script\s+([^>]*\btype=["']module["'][^>]*\bsrc=["'][^"']+["'][^>]*)>/gi;
|
|
71
|
-
let hasEntry = false;
|
|
72
|
-
const result = html.replace(scriptTagRegex, (match, attrs) => {
|
|
59
|
+
function rewriteEntryScripts(html, createProxySrc) {
|
|
60
|
+
return html.replace(/<script\s+([^>]*\btype=["']module["'][^>]*\bsrc=["'][^"']+["'][^>]*)>/gi, (match, attrs) => {
|
|
73
61
|
const srcMatch = attrs.match(/\bsrc=["']([^"']+)["']/i);
|
|
74
62
|
if (!srcMatch) return match;
|
|
75
63
|
const originalSrc = srcMatch[1];
|
|
76
64
|
if (originalSrc.includes("@vite/client")) return match;
|
|
77
|
-
|
|
78
|
-
return
|
|
65
|
+
const proxySrc = createProxySrc(originalSrc);
|
|
66
|
+
return match.replace(srcMatch[0], `src=${JSON.stringify(proxySrc)}`);
|
|
79
67
|
});
|
|
80
|
-
|
|
68
|
+
}
|
|
69
|
+
function injectEntryScript(html, initSrc) {
|
|
70
|
+
const src = sanitizeDevEntryPath(initSrc);
|
|
81
71
|
return html.replace("<head>", `<head><script type="module" src=${JSON.stringify(src)}><\/script>`);
|
|
82
72
|
}
|
|
83
73
|
//#endregion
|
|
@@ -122,6 +112,9 @@ function getDependencyCacheKey(cwd, dependencyName) {
|
|
|
122
112
|
function setPackageDetectionCwd(cwd) {
|
|
123
113
|
packageDetectionCwd = cwd;
|
|
124
114
|
}
|
|
115
|
+
function getPackageDetectionCwd() {
|
|
116
|
+
return packageDetectionCwd || process.cwd();
|
|
117
|
+
}
|
|
125
118
|
/**
|
|
126
119
|
* Escaping rules:
|
|
127
120
|
* Convert using the format __${mapping}__, where _ and $ are not allowed in npm package names but can be used in variable names.
|
|
@@ -189,6 +182,7 @@ function getFirstHtmlEntryFile(entryFiles) {
|
|
|
189
182
|
return entryFiles.find((file) => file.endsWith(".html"));
|
|
190
183
|
}
|
|
191
184
|
const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
|
|
185
|
+
const DEV_HTML_PROXY_PREFIX = "virtual:mf-html-entry-proxy?";
|
|
192
186
|
const getEntryPath = () => typeof entryPath === "function" ? entryPath() : entryPath;
|
|
193
187
|
let devEntryPath = "";
|
|
194
188
|
let entryFiles = [];
|
|
@@ -212,8 +206,13 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
|
|
|
212
206
|
configResolved(config) {
|
|
213
207
|
viteConfig = config;
|
|
214
208
|
const resolvedEntryPath = getEntryPath();
|
|
215
|
-
|
|
216
|
-
|
|
209
|
+
if (resolvedEntryPath.startsWith("virtual:mf")) devEntryPath = config.base + "@id/" + resolvedEntryPath;
|
|
210
|
+
else {
|
|
211
|
+
const normalized = resolvedEntryPath.replace(/\\\\?/g, "/");
|
|
212
|
+
const root = config.root.replace(/\\\\?/g, "/").replace(/\/$/, "");
|
|
213
|
+
const relativePath = normalized.startsWith(root + "/") ? normalized.slice(root.length) : "/" + normalized.replace(/^[A-Za-z]:[\\/]/, "");
|
|
214
|
+
devEntryPath = config.base + relativePath.replace(/^\//, "");
|
|
215
|
+
}
|
|
217
216
|
},
|
|
218
217
|
configureServer(server) {
|
|
219
218
|
server.middlewares.use((req, res, next) => {
|
|
@@ -228,7 +227,29 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
|
|
|
228
227
|
transformIndexHtml(c) {
|
|
229
228
|
if (!injectHtml()) return;
|
|
230
229
|
clientInjected = true;
|
|
231
|
-
|
|
230
|
+
const html = rewriteEntryScripts(c, (originalSrc) => {
|
|
231
|
+
const query = new URLSearchParams({
|
|
232
|
+
init: sanitizeDevEntryPath(devEntryPath),
|
|
233
|
+
entry: originalSrc
|
|
234
|
+
}).toString();
|
|
235
|
+
return `${viteConfig.base}@id/${DEV_HTML_PROXY_PREFIX}${query}`;
|
|
236
|
+
});
|
|
237
|
+
return html === c ? injectEntryScript(c, devEntryPath) : html;
|
|
238
|
+
},
|
|
239
|
+
resolveId(id) {
|
|
240
|
+
if (id.startsWith(DEV_HTML_PROXY_PREFIX)) return id;
|
|
241
|
+
},
|
|
242
|
+
load(id) {
|
|
243
|
+
if (!id.startsWith(DEV_HTML_PROXY_PREFIX)) return;
|
|
244
|
+
const params = new URLSearchParams(id.slice(28));
|
|
245
|
+
const initSrc = params.get("init");
|
|
246
|
+
const entrySrc = params.get("entry");
|
|
247
|
+
if (!initSrc || !entrySrc) return;
|
|
248
|
+
return `
|
|
249
|
+
const baseUrl = document.baseURI || window.location.href;
|
|
250
|
+
await import(new URL(${JSON.stringify(initSrc)}, baseUrl).href);
|
|
251
|
+
await import(new URL(${JSON.stringify(entrySrc)}, baseUrl).href);
|
|
252
|
+
`;
|
|
232
253
|
},
|
|
233
254
|
transform(code, id) {
|
|
234
255
|
if (id.includes("node_modules") || inject !== "html" || htmlFilePath) return;
|
|
@@ -995,15 +1016,61 @@ var VirtualModule = class {
|
|
|
995
1016
|
};
|
|
996
1017
|
//#endregion
|
|
997
1018
|
//#region src/virtualModules/virtualExposes.ts
|
|
1019
|
+
const EXPOSES_CSS_MAP_PLACEHOLDER = "__MF_EXPOSES_CSS_MAP__";
|
|
1020
|
+
function getExposesCssMapPlaceholder() {
|
|
1021
|
+
return EXPOSES_CSS_MAP_PLACEHOLDER;
|
|
1022
|
+
}
|
|
998
1023
|
function getVirtualExposesId(options) {
|
|
999
1024
|
return `virtual:mf-exposes:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
1000
1025
|
}
|
|
1001
1026
|
function generateExposes(options) {
|
|
1002
1027
|
return `
|
|
1028
|
+
const cssAssetMap = ${JSON.stringify(options.bundleAllCSS ? EXPOSES_CSS_MAP_PLACEHOLDER : {})};
|
|
1029
|
+
const injectedCssHrefs = new Set();
|
|
1030
|
+
|
|
1031
|
+
async function injectCssAssets(exposeKey) {
|
|
1032
|
+
if (typeof document === "undefined") {
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
// Replaced at build time with expose -> css asset paths.
|
|
1037
|
+
const cssAssets = cssAssetMap[exposeKey] || [];
|
|
1038
|
+
|
|
1039
|
+
await Promise.all(
|
|
1040
|
+
cssAssets.map((cssAsset) => {
|
|
1041
|
+
const href = new URL(cssAsset, import.meta.url).href;
|
|
1042
|
+
|
|
1043
|
+
// Same expose can be resolved multiple times in one page.
|
|
1044
|
+
if (injectedCssHrefs.has(href)) {
|
|
1045
|
+
return Promise.resolve();
|
|
1046
|
+
}
|
|
1047
|
+
injectedCssHrefs.add(href);
|
|
1048
|
+
|
|
1049
|
+
const existingLink = document.querySelector(
|
|
1050
|
+
\`link[rel="stylesheet"][data-mf-href="\${href}"]\`
|
|
1051
|
+
);
|
|
1052
|
+
if (existingLink) {
|
|
1053
|
+
return Promise.resolve();
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
return new Promise((resolve, reject) => {
|
|
1057
|
+
const link = document.createElement("link");
|
|
1058
|
+
link.rel = "stylesheet";
|
|
1059
|
+
link.href = href;
|
|
1060
|
+
link.setAttribute("data-mf-href", href);
|
|
1061
|
+
link.onload = () => resolve();
|
|
1062
|
+
link.onerror = () => reject(new Error(\`[Module Federation] Failed to load CSS asset: \${href}\`));
|
|
1063
|
+
document.head.appendChild(link);
|
|
1064
|
+
});
|
|
1065
|
+
})
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1003
1069
|
export default {
|
|
1004
1070
|
${Object.keys(options.exposes).map((key) => {
|
|
1005
1071
|
return `
|
|
1006
1072
|
${JSON.stringify(key)}: async () => {
|
|
1073
|
+
await injectCssAssets(${JSON.stringify(key)})
|
|
1007
1074
|
const importModule = await import(${JSON.stringify(options.exposes[key].import)})
|
|
1008
1075
|
const exportModule = {}
|
|
1009
1076
|
Object.assign(exportModule, importModule)
|
|
@@ -1150,32 +1217,159 @@ function generateRemotes(id, command, isRolldown) {
|
|
|
1150
1217
|
* 1. __prebuild__: export shareModule (pre-built source code of modules such as vue, react, etc.)
|
|
1151
1218
|
* 2. __loadShare__: load shareModule (mfRuntime.loadShare('vue'))
|
|
1152
1219
|
*/
|
|
1220
|
+
function escapeGeneratedStringLiteral(value) {
|
|
1221
|
+
return JSON.stringify(value).replace(/[<>\u2028\u2029]/g, (char) => {
|
|
1222
|
+
switch (char) {
|
|
1223
|
+
case "<": return "\\u003C";
|
|
1224
|
+
case ">": return "\\u003E";
|
|
1225
|
+
case "\u2028": return "\\u2028";
|
|
1226
|
+
case "\u2029": return "\\u2029";
|
|
1227
|
+
default: return char;
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
const localRequire = (0, module$1.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
1232
|
+
function resolvePackageEntryFromProjectRoot(pkg) {
|
|
1233
|
+
try {
|
|
1234
|
+
return (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`)).resolve(pkg);
|
|
1235
|
+
} catch {
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
function getInstalledPackageJsonPath(pkg) {
|
|
1240
|
+
try {
|
|
1241
|
+
const packageName = removePathFromNpmPackage(pkg);
|
|
1242
|
+
const projectRequire = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`));
|
|
1243
|
+
let resolvedPath;
|
|
1244
|
+
try {
|
|
1245
|
+
resolvedPath = projectRequire.resolve(pkg);
|
|
1246
|
+
} catch {
|
|
1247
|
+
resolvedPath = projectRequire.resolve(packageName);
|
|
1248
|
+
}
|
|
1249
|
+
let currentDir = pathe.default.dirname(resolvedPath);
|
|
1250
|
+
const rootDir = pathe.default.parse(currentDir).root;
|
|
1251
|
+
while (currentDir !== rootDir) {
|
|
1252
|
+
const packageJsonPath = pathe.default.join(currentDir, "package.json");
|
|
1253
|
+
if ((0, fs.existsSync)(packageJsonPath)) {
|
|
1254
|
+
if (JSON.parse((0, fs.readFileSync)(packageJsonPath, "utf-8")).name === packageName) return packageJsonPath;
|
|
1255
|
+
}
|
|
1256
|
+
currentDir = pathe.default.dirname(currentDir);
|
|
1257
|
+
}
|
|
1258
|
+
const rootPackageJsonPath = pathe.default.join(rootDir, "package.json");
|
|
1259
|
+
if ((0, fs.existsSync)(rootPackageJsonPath)) {
|
|
1260
|
+
if (JSON.parse((0, fs.readFileSync)(rootPackageJsonPath, "utf-8")).name === packageName) return rootPackageJsonPath;
|
|
1261
|
+
}
|
|
1262
|
+
} catch {
|
|
1263
|
+
const packageName = removePathFromNpmPackage(pkg);
|
|
1264
|
+
let currentDir = getPackageDetectionCwd();
|
|
1265
|
+
const rootDir = pathe.default.parse(currentDir).root;
|
|
1266
|
+
while (currentDir !== rootDir) {
|
|
1267
|
+
const packageJsonPath = pathe.default.join(currentDir, "node_modules", packageName, "package.json");
|
|
1268
|
+
if ((0, fs.existsSync)(packageJsonPath)) return packageJsonPath;
|
|
1269
|
+
currentDir = pathe.default.dirname(currentDir);
|
|
1270
|
+
}
|
|
1271
|
+
const rootPackageJsonPath = pathe.default.join(rootDir, "node_modules", packageName, "package.json");
|
|
1272
|
+
return (0, fs.existsSync)(rootPackageJsonPath) ? rootPackageJsonPath : void 0;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
function resolveImportTarget(exportsField) {
|
|
1276
|
+
if (typeof exportsField === "string") return exportsField;
|
|
1277
|
+
if (!exportsField || typeof exportsField !== "object") return void 0;
|
|
1278
|
+
const record = exportsField;
|
|
1279
|
+
for (const condition of [
|
|
1280
|
+
"import",
|
|
1281
|
+
"module",
|
|
1282
|
+
"default"
|
|
1283
|
+
]) {
|
|
1284
|
+
const target = resolveImportTarget(record[condition]);
|
|
1285
|
+
if (target) return target;
|
|
1286
|
+
}
|
|
1287
|
+
for (const target of Object.values(record)) {
|
|
1288
|
+
const resolved = resolveImportTarget(target);
|
|
1289
|
+
if (resolved) return resolved;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
function getPackageEsmEntryPath(pkg) {
|
|
1293
|
+
try {
|
|
1294
|
+
const resolvedEntryPath = resolvePackageEntryFromProjectRoot(pkg);
|
|
1295
|
+
const packageJsonPath = getInstalledPackageJsonPath(pkg);
|
|
1296
|
+
if (!packageJsonPath) return resolvedEntryPath;
|
|
1297
|
+
const packageName = removePathFromNpmPackage(pkg);
|
|
1298
|
+
const packageJson = JSON.parse((0, fs.readFileSync)(packageJsonPath, "utf-8"));
|
|
1299
|
+
const subpath = pkg === packageName ? "." : `.${pkg.slice(packageName.length)}`;
|
|
1300
|
+
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;
|
|
1301
|
+
if (!target) return resolvedEntryPath;
|
|
1302
|
+
return pathe.default.resolve(pathe.default.dirname(packageJsonPath), target);
|
|
1303
|
+
} catch {
|
|
1304
|
+
return resolvePackageEntryFromProjectRoot(pkg);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
function getEsmNamedExports(pkg) {
|
|
1308
|
+
try {
|
|
1309
|
+
const entryPath = getPackageEsmEntryPath(pkg);
|
|
1310
|
+
if (!entryPath) return [];
|
|
1311
|
+
const { initSync, parse } = localRequire("es-module-lexer");
|
|
1312
|
+
initSync();
|
|
1313
|
+
const [, exports] = parse((0, fs.readFileSync)(entryPath, "utf-8"), entryPath);
|
|
1314
|
+
return exports.map((item) => item.n).filter((name) => !!name && name !== "default" && name !== "__esModule" && /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name));
|
|
1315
|
+
} catch {
|
|
1316
|
+
return [];
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1153
1319
|
function getPackageNamedExports(pkg) {
|
|
1154
1320
|
try {
|
|
1155
|
-
const mod = (0, module$1.createRequire)(new URL(
|
|
1321
|
+
const mod = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`))(pkg);
|
|
1156
1322
|
return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule" && /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(k));
|
|
1157
1323
|
} catch {
|
|
1158
|
-
return
|
|
1324
|
+
return getEsmNamedExports(pkg);
|
|
1159
1325
|
}
|
|
1160
1326
|
}
|
|
1161
1327
|
function getLocalProviderImportPath(pkg) {
|
|
1162
1328
|
try {
|
|
1163
|
-
const resolved = (0, module$1.createRequire)(new URL(
|
|
1329
|
+
const resolved = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`)).resolve(pkg);
|
|
1164
1330
|
return resolved.includes("/node_modules/") || resolved.includes("\\node_modules\\") ? void 0 : resolved;
|
|
1165
1331
|
} catch {
|
|
1166
1332
|
return;
|
|
1167
1333
|
}
|
|
1168
1334
|
}
|
|
1335
|
+
function tryResolveImportFromPackageRoot(pkg, root) {
|
|
1336
|
+
try {
|
|
1337
|
+
return (0, module$1.createRequire)(new URL(`file://${pathe.default.join(root, "package.json")}`)).resolve(pkg);
|
|
1338
|
+
} catch {
|
|
1339
|
+
return;
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
function getConcreteSharedImportSource(pkg, shareItem) {
|
|
1343
|
+
const configuredImport = shareItem?.shareConfig.import;
|
|
1344
|
+
if (typeof configuredImport === "string") return configuredImport;
|
|
1345
|
+
const projectRoot = getPackageDetectionCwd();
|
|
1346
|
+
if (tryResolveImportFromPackageRoot(pkg, projectRoot)) return;
|
|
1347
|
+
let currentDir = pathe.default.dirname(projectRoot);
|
|
1348
|
+
while (currentDir !== pathe.default.dirname(currentDir)) {
|
|
1349
|
+
const resolved = tryResolveImportFromPackageRoot(pkg, currentDir);
|
|
1350
|
+
if (resolved) return resolved;
|
|
1351
|
+
currentDir = pathe.default.dirname(currentDir);
|
|
1352
|
+
}
|
|
1353
|
+
return tryResolveImportFromPackageRoot(pkg, currentDir);
|
|
1354
|
+
}
|
|
1169
1355
|
const preBuildCacheMap = {};
|
|
1356
|
+
const preBuildShareItemMap = {};
|
|
1170
1357
|
const PREBUILD_TAG = "__prebuild__";
|
|
1171
|
-
function writePreBuildLibPath(pkg) {
|
|
1358
|
+
function writePreBuildLibPath(pkg, shareItem) {
|
|
1172
1359
|
if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG);
|
|
1173
|
-
|
|
1360
|
+
preBuildShareItemMap[pkg] = shareItem;
|
|
1361
|
+
preBuildCacheMap[pkg].writeSync("", true);
|
|
1174
1362
|
}
|
|
1175
1363
|
function getPreBuildLibImportId(pkg) {
|
|
1176
1364
|
if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG);
|
|
1177
1365
|
return preBuildCacheMap[pkg].getImportId();
|
|
1178
1366
|
}
|
|
1367
|
+
function getPreBuildShareItem(pkg) {
|
|
1368
|
+
return preBuildShareItemMap[pkg];
|
|
1369
|
+
}
|
|
1370
|
+
function getSharedImportSource(pkg, shareItem) {
|
|
1371
|
+
return getConcreteSharedImportSource(pkg, shareItem) || getPreBuildLibImportId(pkg);
|
|
1372
|
+
}
|
|
1179
1373
|
const LOAD_SHARE_TAG = "__loadShare__";
|
|
1180
1374
|
const loadShareCacheMap = {};
|
|
1181
1375
|
function getLoadShareImportId(pkg, isRolldown, command) {
|
|
@@ -1193,22 +1387,25 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1193
1387
|
const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
1194
1388
|
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
1195
1389
|
const useSsrProviderFallback = hasPackageDependency("vinext") && command === "build" && pkg === "react";
|
|
1196
|
-
const
|
|
1390
|
+
const concreteSharedImportSource = getConcreteSharedImportSource(pkg, shareItem);
|
|
1391
|
+
const sharedImportSource = concreteSharedImportSource || getPreBuildLibImportId(pkg);
|
|
1392
|
+
const devImportSource = concreteSharedImportSource || pkg;
|
|
1393
|
+
const providerImportId = getLocalProviderImportPath(pkg) || concreteSharedImportSource || sharedImportSource;
|
|
1197
1394
|
const namedExports = getPackageNamedExports(pkg);
|
|
1198
1395
|
let exportLine;
|
|
1199
1396
|
if (namedExports.length > 0) {
|
|
1200
1397
|
const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
|
|
1201
1398
|
const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
|
|
1202
1399
|
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(", ")} });`;
|
|
1203
|
-
} else exportLine = useESM ? `export default exportModule.default ?? exportModule\n export * from ${
|
|
1400
|
+
} else exportLine = useESM ? `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}` : "module.exports = exportModule";
|
|
1204
1401
|
loadShareCacheMap[pkg].writeSync(`
|
|
1205
|
-
import ${
|
|
1206
|
-
${command !== "build" ? `;() => import(${
|
|
1402
|
+
import ${escapeGeneratedStringLiteral(sharedImportSource)};
|
|
1403
|
+
${command !== "build" ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : ""}
|
|
1207
1404
|
${importLine}
|
|
1208
1405
|
${useSsrProviderFallback ? `const providerModulePromise = typeof window === "undefined"
|
|
1209
|
-
? import(${
|
|
1406
|
+
? import(${escapeGeneratedStringLiteral(providerImportId)})
|
|
1210
1407
|
: undefined` : ""}
|
|
1211
|
-
const res = initPromise.then(runtime => runtime.loadShare(${
|
|
1408
|
+
const res = initPromise.then(runtime => runtime.loadShare(${escapeGeneratedStringLiteral(pkg)}, {
|
|
1212
1409
|
customShareInfo: {shareConfig:{
|
|
1213
1410
|
singleton: ${shareItem.shareConfig.singleton},
|
|
1214
1411
|
strictVersion: ${shareItem.shareConfig.strictVersion},
|
|
@@ -1219,7 +1416,7 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1219
1416
|
? ((await providerModulePromise)?.default ?? await providerModulePromise)
|
|
1220
1417
|
: ${awaitOrPlaceholder}res.then((factory) => (typeof factory === "function" ? factory() : factory)))` : `${awaitOrPlaceholder}res.then((factory) => (typeof factory === "function" ? factory() : factory))`}
|
|
1221
1418
|
${exportLine}
|
|
1222
|
-
|
|
1419
|
+
`, true);
|
|
1223
1420
|
}
|
|
1224
1421
|
//#endregion
|
|
1225
1422
|
//#region src/virtualModules/virtualRemoteEntry.ts
|
|
@@ -1253,7 +1450,7 @@ function generateLocalSharedImportMap() {
|
|
|
1253
1450
|
return `
|
|
1254
1451
|
${JSON.stringify(pkg)}: async () => {
|
|
1255
1452
|
${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(pkg)}}' must be provided by host\`);` : isVinext && pkg === "react" ? `let pkg = await import("react");
|
|
1256
|
-
return pkg;` : `let pkg = await import(
|
|
1453
|
+
return pkg;` : `let pkg = await import(${JSON.stringify(getSharedImportSource(pkg, shareItem))});
|
|
1257
1454
|
return pkg;`}
|
|
1258
1455
|
}
|
|
1259
1456
|
`;
|
|
@@ -1535,6 +1732,18 @@ const processModuleAssets = (bundle, filesMap, moduleMatcher) => {
|
|
|
1535
1732
|
}
|
|
1536
1733
|
};
|
|
1537
1734
|
/**
|
|
1735
|
+
* Adds global CSS assets to all module exports
|
|
1736
|
+
* @param filesMap - The preload map to update
|
|
1737
|
+
* @param cssAssets - Set of CSS asset filenames to add
|
|
1738
|
+
*/
|
|
1739
|
+
const addCssAssetsToAllExports = (filesMap, cssAssets) => {
|
|
1740
|
+
Object.keys(filesMap).forEach((key) => {
|
|
1741
|
+
cssAssets.forEach((cssAsset) => {
|
|
1742
|
+
trackAsset(filesMap, key, cssAsset, false, "css");
|
|
1743
|
+
});
|
|
1744
|
+
});
|
|
1745
|
+
};
|
|
1746
|
+
/**
|
|
1538
1747
|
* Deduplicates assets in the files map
|
|
1539
1748
|
* @param filesMap - The preload map to deduplicate
|
|
1540
1749
|
* @returns New deduplicated preload map
|
|
@@ -1860,12 +2069,13 @@ function pluginModuleParseEnd_default(excludeFn, options) {
|
|
|
1860
2069
|
//#region src/plugins/pluginProxyRemoteEntry.ts
|
|
1861
2070
|
const filter = (0, _rollup_pluginutils.createFilter)();
|
|
1862
2071
|
function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
|
|
1863
|
-
let viteConfig, _command;
|
|
2072
|
+
let viteConfig, _command, root;
|
|
1864
2073
|
return {
|
|
1865
2074
|
name: "proxyRemoteEntry",
|
|
1866
2075
|
enforce: "post",
|
|
1867
2076
|
configResolved(config) {
|
|
1868
2077
|
viteConfig = config;
|
|
2078
|
+
root = config.root;
|
|
1869
2079
|
},
|
|
1870
2080
|
config(config, { command }) {
|
|
1871
2081
|
_command = command;
|
|
@@ -1920,6 +2130,51 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
1920
2130
|
return code;
|
|
1921
2131
|
}
|
|
1922
2132
|
})());
|
|
2133
|
+
},
|
|
2134
|
+
generateBundle(_, bundle) {
|
|
2135
|
+
if (_command !== "build") return;
|
|
2136
|
+
const filesMap = {};
|
|
2137
|
+
const exposeEntries = Object.entries(options.exposes);
|
|
2138
|
+
const allCssAssets = options.bundleAllCSS ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
|
|
2139
|
+
processModuleAssets(bundle, filesMap, (modulePath) => {
|
|
2140
|
+
const absoluteModulePath = pathe.resolve(root, modulePath);
|
|
2141
|
+
return exposeEntries.find(([_, exposeOptions]) => {
|
|
2142
|
+
const exposePath = pathe.resolve(root, exposeOptions.import);
|
|
2143
|
+
if (absoluteModulePath === exposePath) return true;
|
|
2144
|
+
const stripKnownJsExt = (filePath) => {
|
|
2145
|
+
const ext = pathe.extname(filePath);
|
|
2146
|
+
return [
|
|
2147
|
+
".ts",
|
|
2148
|
+
".tsx",
|
|
2149
|
+
".jsx",
|
|
2150
|
+
".mjs",
|
|
2151
|
+
".cjs"
|
|
2152
|
+
].includes(ext) ? pathe.join(pathe.dirname(filePath), pathe.basename(filePath, ext)) : filePath;
|
|
2153
|
+
};
|
|
2154
|
+
return stripKnownJsExt(absoluteModulePath) === stripKnownJsExt(exposePath);
|
|
2155
|
+
})?.[1].import;
|
|
2156
|
+
});
|
|
2157
|
+
if (options.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
|
|
2158
|
+
const ensureRelativeImportPath = (fromFile, toFile) => {
|
|
2159
|
+
let relativePath = pathe.relative(pathe.dirname(fromFile), toFile);
|
|
2160
|
+
if (!relativePath.startsWith(".")) relativePath = `./${relativePath}`;
|
|
2161
|
+
return relativePath;
|
|
2162
|
+
};
|
|
2163
|
+
const placeholderValue = getExposesCssMapPlaceholder();
|
|
2164
|
+
const placeholderPatterns = [
|
|
2165
|
+
JSON.stringify(placeholderValue),
|
|
2166
|
+
`'${placeholderValue}'`,
|
|
2167
|
+
`\`${placeholderValue}\``
|
|
2168
|
+
];
|
|
2169
|
+
for (const file of Object.values(bundle)) {
|
|
2170
|
+
if (file.type !== "chunk" || !file.code.includes(placeholderValue)) continue;
|
|
2171
|
+
const cssAssetMap = exposeEntries.reduce((acc, [exposeKey, expose]) => {
|
|
2172
|
+
const assets = filesMap[expose.import] || createEmptyAssetMap();
|
|
2173
|
+
acc[exposeKey] = [...assets.css.sync, ...assets.css.async].map((cssAsset) => ensureRelativeImportPath(file.fileName, cssAsset));
|
|
2174
|
+
return acc;
|
|
2175
|
+
}, {});
|
|
2176
|
+
for (const placeholderPattern of placeholderPatterns) file.code = file.code.replace(placeholderPattern, JSON.stringify(cssAssetMap));
|
|
2177
|
+
}
|
|
1923
2178
|
}
|
|
1924
2179
|
};
|
|
1925
2180
|
}
|
|
@@ -1982,6 +2237,9 @@ var PromiseStore = class {
|
|
|
1982
2237
|
};
|
|
1983
2238
|
//#endregion
|
|
1984
2239
|
//#region src/plugins/pluginProxySharedModule_preBuild.ts
|
|
2240
|
+
function getPrebuildResolutionSource(pkgName, shareItem) {
|
|
2241
|
+
return getConcreteSharedImportSource(pkgName, shareItem) || pkgName;
|
|
2242
|
+
}
|
|
1985
2243
|
function proxySharedModule(options) {
|
|
1986
2244
|
const { shared = {} } = options;
|
|
1987
2245
|
let _config;
|
|
@@ -2020,7 +2278,7 @@ function proxySharedModule(options) {
|
|
|
2020
2278
|
if (key.endsWith("/") && source !== key.slice(0, -1)) return;
|
|
2021
2279
|
const loadSharePath = getLoadShareModulePath(source, isRolldown, command);
|
|
2022
2280
|
writeLoadShareModule(source, shared[key], command, isRolldown);
|
|
2023
|
-
writePreBuildLibPath(source);
|
|
2281
|
+
writePreBuildLibPath(source, shared[key]);
|
|
2024
2282
|
addUsedShares(source);
|
|
2025
2283
|
writeLocalSharedImportMap();
|
|
2026
2284
|
return this.resolve(loadSharePath, importer);
|
|
@@ -2031,14 +2289,18 @@ function proxySharedModule(options) {
|
|
|
2031
2289
|
return command === "build" ? {
|
|
2032
2290
|
find: new RegExp(`(.*${PREBUILD_TAG}.*)`),
|
|
2033
2291
|
replacement: function($1) {
|
|
2034
|
-
|
|
2292
|
+
const pkgName = assertModuleFound(PREBUILD_TAG, $1).name;
|
|
2293
|
+
return getPrebuildResolutionSource(pkgName, getPreBuildShareItem(pkgName));
|
|
2035
2294
|
}
|
|
2036
2295
|
} : {
|
|
2037
2296
|
find: new RegExp(`(.*${PREBUILD_TAG}.*)`),
|
|
2038
2297
|
replacement: "$1",
|
|
2039
2298
|
async customResolver(source, importer) {
|
|
2040
2299
|
const pkgName = assertModuleFound(PREBUILD_TAG, source).name;
|
|
2041
|
-
const
|
|
2300
|
+
const importSource = getPrebuildResolutionSource(pkgName, getPreBuildShareItem(pkgName));
|
|
2301
|
+
const resolved = await this.resolve(importSource, importer);
|
|
2302
|
+
if (!resolved?.id) return;
|
|
2303
|
+
const result = resolved.id;
|
|
2042
2304
|
if (_config && !result.includes(_config.cacheDir)) savePrebuild.set(pkgName, Promise.resolve(result));
|
|
2043
2305
|
return await this.resolve(await savePrebuild.get(pkgName), importer);
|
|
2044
2306
|
}
|
|
@@ -2055,7 +2317,7 @@ function proxySharedModule(options) {
|
|
|
2055
2317
|
return;
|
|
2056
2318
|
}
|
|
2057
2319
|
writeLoadShareModule(key, shared[key], _command, isRolldown);
|
|
2058
|
-
writePreBuildLibPath(key);
|
|
2320
|
+
writePreBuildLibPath(key, shared[key]);
|
|
2059
2321
|
addUsedShares(key);
|
|
2060
2322
|
});
|
|
2061
2323
|
writeLocalSharedImportMap();
|
|
@@ -2177,14 +2439,19 @@ function stripEmptyPreloadCalls(code) {
|
|
|
2177
2439
|
while (cursor < nextCode.length) {
|
|
2178
2440
|
const char = nextCode[cursor];
|
|
2179
2441
|
if (char === "(") depth++;
|
|
2180
|
-
else if (char === ")")
|
|
2181
|
-
|
|
2442
|
+
else if (char === ")") {
|
|
2443
|
+
depth--;
|
|
2444
|
+
if (depth < 0) break;
|
|
2445
|
+
} else if (depth === 0 && nextCode.startsWith(",[],import.meta.url)", cursor)) {
|
|
2182
2446
|
replacementEnd = cursor;
|
|
2183
2447
|
break;
|
|
2184
2448
|
}
|
|
2185
2449
|
cursor++;
|
|
2186
2450
|
}
|
|
2187
|
-
if (replacementEnd === -1)
|
|
2451
|
+
if (replacementEnd === -1) {
|
|
2452
|
+
start = nextCode.indexOf(marker, start + marker.length);
|
|
2453
|
+
continue;
|
|
2454
|
+
}
|
|
2188
2455
|
const expression = nextCode.slice(exprStart, replacementEnd);
|
|
2189
2456
|
nextCode = nextCode.slice(0, start) + expression + nextCode.slice(replacementEnd + 20);
|
|
2190
2457
|
start = nextCode.indexOf(marker, start + expression.length);
|
|
@@ -2261,13 +2528,14 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
2261
2528
|
VirtualModule.setRoot(root);
|
|
2262
2529
|
VirtualModule.ensureVirtualPackageExists();
|
|
2263
2530
|
initVirtualModules(_command, getRemoteEntryId(options));
|
|
2264
|
-
if (_command !== "serve") return;
|
|
2265
2531
|
const isRolldown = getIsRolldown(this);
|
|
2266
2532
|
if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
|
|
2267
2533
|
if (shared && Object.keys(shared).length > 0) {
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2534
|
+
if (_command === "serve") {
|
|
2535
|
+
config.optimizeDeps = config.optimizeDeps || {};
|
|
2536
|
+
config.optimizeDeps.include = config.optimizeDeps.include || [];
|
|
2537
|
+
config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
|
|
2538
|
+
}
|
|
2271
2539
|
for (const key of Object.keys(shared)) {
|
|
2272
2540
|
if (key.endsWith("/")) continue;
|
|
2273
2541
|
const shareItem = shared[key];
|
|
@@ -2277,10 +2545,12 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
2277
2545
|
}
|
|
2278
2546
|
getLoadShareModulePath(key, isRolldown);
|
|
2279
2547
|
writeLoadShareModule(key, shareItem, _command, isRolldown);
|
|
2280
|
-
writePreBuildLibPath(key);
|
|
2548
|
+
writePreBuildLibPath(key, shareItem);
|
|
2281
2549
|
addUsedShares(key);
|
|
2282
|
-
|
|
2283
|
-
|
|
2550
|
+
if (_command === "serve") {
|
|
2551
|
+
if (!isRolldown) config.optimizeDeps.include.push(getLoadShareImportId(key, isRolldown, _command));
|
|
2552
|
+
config.optimizeDeps.include.push(getPreBuildLibImportId(key));
|
|
2553
|
+
}
|
|
2284
2554
|
}
|
|
2285
2555
|
writeLocalSharedImportMap();
|
|
2286
2556
|
}
|
package/lib/index.mjs
CHANGED
|
@@ -27,35 +27,25 @@ async function mapCodeToCodeWithSourcemap(code) {
|
|
|
27
27
|
//#endregion
|
|
28
28
|
//#region src/utils/htmlEntryUtils.ts
|
|
29
29
|
function sanitizeDevEntryPath(devEntryPath) {
|
|
30
|
-
return devEntryPath.replace(
|
|
30
|
+
return devEntryPath.replace(/\\\\?/g, "/");
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* If no entry scripts are found, falls back to injecting a separate script tag.
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* // Before (two separate scripts, race condition):
|
|
41
|
-
* // <script type="module" src="/__mf__virtual/hostAutoInit.js"><\/script>
|
|
42
|
-
* // <script type="module" src="/src/main.js"><\/script>
|
|
43
|
-
* // After (single inline script, sequential execution):
|
|
44
|
-
* // <script type="module">await import("/__mf__virtual/hostAutoInit.js");await import("/src/main.js");<\/script>
|
|
33
|
+
* Rewrites entry module script tags to point at an external wrapper module.
|
|
34
|
+
* The wrapper can then sequence federation init before the app entry without
|
|
35
|
+
* relying on CSP-breaking inline `<script type="module">`.
|
|
45
36
|
*/
|
|
46
|
-
function
|
|
47
|
-
|
|
48
|
-
const scriptTagRegex = /<script\s+([^>]*\btype=["']module["'][^>]*\bsrc=["'][^"']+["'][^>]*)>/gi;
|
|
49
|
-
let hasEntry = false;
|
|
50
|
-
const result = html.replace(scriptTagRegex, (match, attrs) => {
|
|
37
|
+
function rewriteEntryScripts(html, createProxySrc) {
|
|
38
|
+
return html.replace(/<script\s+([^>]*\btype=["']module["'][^>]*\bsrc=["'][^"']+["'][^>]*)>/gi, (match, attrs) => {
|
|
51
39
|
const srcMatch = attrs.match(/\bsrc=["']([^"']+)["']/i);
|
|
52
40
|
if (!srcMatch) return match;
|
|
53
41
|
const originalSrc = srcMatch[1];
|
|
54
42
|
if (originalSrc.includes("@vite/client")) return match;
|
|
55
|
-
|
|
56
|
-
return
|
|
43
|
+
const proxySrc = createProxySrc(originalSrc);
|
|
44
|
+
return match.replace(srcMatch[0], `src=${JSON.stringify(proxySrc)}`);
|
|
57
45
|
});
|
|
58
|
-
|
|
46
|
+
}
|
|
47
|
+
function injectEntryScript(html, initSrc) {
|
|
48
|
+
const src = sanitizeDevEntryPath(initSrc);
|
|
59
49
|
return html.replace("<head>", `<head><script type="module" src=${JSON.stringify(src)}><\/script>`);
|
|
60
50
|
}
|
|
61
51
|
//#endregion
|
|
@@ -100,6 +90,9 @@ function getDependencyCacheKey(cwd, dependencyName) {
|
|
|
100
90
|
function setPackageDetectionCwd(cwd) {
|
|
101
91
|
packageDetectionCwd = cwd;
|
|
102
92
|
}
|
|
93
|
+
function getPackageDetectionCwd() {
|
|
94
|
+
return packageDetectionCwd || process.cwd();
|
|
95
|
+
}
|
|
103
96
|
/**
|
|
104
97
|
* Escaping rules:
|
|
105
98
|
* Convert using the format __${mapping}__, where _ and $ are not allowed in npm package names but can be used in variable names.
|
|
@@ -167,6 +160,7 @@ function getFirstHtmlEntryFile(entryFiles) {
|
|
|
167
160
|
return entryFiles.find((file) => file.endsWith(".html"));
|
|
168
161
|
}
|
|
169
162
|
const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
|
|
163
|
+
const DEV_HTML_PROXY_PREFIX = "virtual:mf-html-entry-proxy?";
|
|
170
164
|
const getEntryPath = () => typeof entryPath === "function" ? entryPath() : entryPath;
|
|
171
165
|
let devEntryPath = "";
|
|
172
166
|
let entryFiles = [];
|
|
@@ -190,8 +184,13 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
|
|
|
190
184
|
configResolved(config) {
|
|
191
185
|
viteConfig = config;
|
|
192
186
|
const resolvedEntryPath = getEntryPath();
|
|
193
|
-
|
|
194
|
-
|
|
187
|
+
if (resolvedEntryPath.startsWith("virtual:mf")) devEntryPath = config.base + "@id/" + resolvedEntryPath;
|
|
188
|
+
else {
|
|
189
|
+
const normalized = resolvedEntryPath.replace(/\\\\?/g, "/");
|
|
190
|
+
const root = config.root.replace(/\\\\?/g, "/").replace(/\/$/, "");
|
|
191
|
+
const relativePath = normalized.startsWith(root + "/") ? normalized.slice(root.length) : "/" + normalized.replace(/^[A-Za-z]:[\\/]/, "");
|
|
192
|
+
devEntryPath = config.base + relativePath.replace(/^\//, "");
|
|
193
|
+
}
|
|
195
194
|
},
|
|
196
195
|
configureServer(server) {
|
|
197
196
|
server.middlewares.use((req, res, next) => {
|
|
@@ -206,7 +205,29 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
|
|
|
206
205
|
transformIndexHtml(c) {
|
|
207
206
|
if (!injectHtml()) return;
|
|
208
207
|
clientInjected = true;
|
|
209
|
-
|
|
208
|
+
const html = rewriteEntryScripts(c, (originalSrc) => {
|
|
209
|
+
const query = new URLSearchParams({
|
|
210
|
+
init: sanitizeDevEntryPath(devEntryPath),
|
|
211
|
+
entry: originalSrc
|
|
212
|
+
}).toString();
|
|
213
|
+
return `${viteConfig.base}@id/${DEV_HTML_PROXY_PREFIX}${query}`;
|
|
214
|
+
});
|
|
215
|
+
return html === c ? injectEntryScript(c, devEntryPath) : html;
|
|
216
|
+
},
|
|
217
|
+
resolveId(id) {
|
|
218
|
+
if (id.startsWith(DEV_HTML_PROXY_PREFIX)) return id;
|
|
219
|
+
},
|
|
220
|
+
load(id) {
|
|
221
|
+
if (!id.startsWith(DEV_HTML_PROXY_PREFIX)) return;
|
|
222
|
+
const params = new URLSearchParams(id.slice(28));
|
|
223
|
+
const initSrc = params.get("init");
|
|
224
|
+
const entrySrc = params.get("entry");
|
|
225
|
+
if (!initSrc || !entrySrc) return;
|
|
226
|
+
return `
|
|
227
|
+
const baseUrl = document.baseURI || window.location.href;
|
|
228
|
+
await import(new URL(${JSON.stringify(initSrc)}, baseUrl).href);
|
|
229
|
+
await import(new URL(${JSON.stringify(entrySrc)}, baseUrl).href);
|
|
230
|
+
`;
|
|
210
231
|
},
|
|
211
232
|
transform(code, id) {
|
|
212
233
|
if (id.includes("node_modules") || inject !== "html" || htmlFilePath) return;
|
|
@@ -972,15 +993,61 @@ var VirtualModule = class {
|
|
|
972
993
|
};
|
|
973
994
|
//#endregion
|
|
974
995
|
//#region src/virtualModules/virtualExposes.ts
|
|
996
|
+
const EXPOSES_CSS_MAP_PLACEHOLDER = "__MF_EXPOSES_CSS_MAP__";
|
|
997
|
+
function getExposesCssMapPlaceholder() {
|
|
998
|
+
return EXPOSES_CSS_MAP_PLACEHOLDER;
|
|
999
|
+
}
|
|
975
1000
|
function getVirtualExposesId(options) {
|
|
976
1001
|
return `virtual:mf-exposes:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
977
1002
|
}
|
|
978
1003
|
function generateExposes(options) {
|
|
979
1004
|
return `
|
|
1005
|
+
const cssAssetMap = ${JSON.stringify(options.bundleAllCSS ? EXPOSES_CSS_MAP_PLACEHOLDER : {})};
|
|
1006
|
+
const injectedCssHrefs = new Set();
|
|
1007
|
+
|
|
1008
|
+
async function injectCssAssets(exposeKey) {
|
|
1009
|
+
if (typeof document === "undefined") {
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// Replaced at build time with expose -> css asset paths.
|
|
1014
|
+
const cssAssets = cssAssetMap[exposeKey] || [];
|
|
1015
|
+
|
|
1016
|
+
await Promise.all(
|
|
1017
|
+
cssAssets.map((cssAsset) => {
|
|
1018
|
+
const href = new URL(cssAsset, import.meta.url).href;
|
|
1019
|
+
|
|
1020
|
+
// Same expose can be resolved multiple times in one page.
|
|
1021
|
+
if (injectedCssHrefs.has(href)) {
|
|
1022
|
+
return Promise.resolve();
|
|
1023
|
+
}
|
|
1024
|
+
injectedCssHrefs.add(href);
|
|
1025
|
+
|
|
1026
|
+
const existingLink = document.querySelector(
|
|
1027
|
+
\`link[rel="stylesheet"][data-mf-href="\${href}"]\`
|
|
1028
|
+
);
|
|
1029
|
+
if (existingLink) {
|
|
1030
|
+
return Promise.resolve();
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
return new Promise((resolve, reject) => {
|
|
1034
|
+
const link = document.createElement("link");
|
|
1035
|
+
link.rel = "stylesheet";
|
|
1036
|
+
link.href = href;
|
|
1037
|
+
link.setAttribute("data-mf-href", href);
|
|
1038
|
+
link.onload = () => resolve();
|
|
1039
|
+
link.onerror = () => reject(new Error(\`[Module Federation] Failed to load CSS asset: \${href}\`));
|
|
1040
|
+
document.head.appendChild(link);
|
|
1041
|
+
});
|
|
1042
|
+
})
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
980
1046
|
export default {
|
|
981
1047
|
${Object.keys(options.exposes).map((key) => {
|
|
982
1048
|
return `
|
|
983
1049
|
${JSON.stringify(key)}: async () => {
|
|
1050
|
+
await injectCssAssets(${JSON.stringify(key)})
|
|
984
1051
|
const importModule = await import(${JSON.stringify(options.exposes[key].import)})
|
|
985
1052
|
const exportModule = {}
|
|
986
1053
|
Object.assign(exportModule, importModule)
|
|
@@ -1127,32 +1194,159 @@ function generateRemotes(id, command, isRolldown) {
|
|
|
1127
1194
|
* 1. __prebuild__: export shareModule (pre-built source code of modules such as vue, react, etc.)
|
|
1128
1195
|
* 2. __loadShare__: load shareModule (mfRuntime.loadShare('vue'))
|
|
1129
1196
|
*/
|
|
1197
|
+
function escapeGeneratedStringLiteral(value) {
|
|
1198
|
+
return JSON.stringify(value).replace(/[<>\u2028\u2029]/g, (char) => {
|
|
1199
|
+
switch (char) {
|
|
1200
|
+
case "<": return "\\u003C";
|
|
1201
|
+
case ">": return "\\u003E";
|
|
1202
|
+
case "\u2028": return "\\u2028";
|
|
1203
|
+
case "\u2029": return "\\u2029";
|
|
1204
|
+
default: return char;
|
|
1205
|
+
}
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
const localRequire = createRequire$1(import.meta.url);
|
|
1209
|
+
function resolvePackageEntryFromProjectRoot(pkg) {
|
|
1210
|
+
try {
|
|
1211
|
+
return createRequire$1(new URL(`file://${path.join(getPackageDetectionCwd(), "package.json")}`)).resolve(pkg);
|
|
1212
|
+
} catch {
|
|
1213
|
+
return;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
function getInstalledPackageJsonPath(pkg) {
|
|
1217
|
+
try {
|
|
1218
|
+
const packageName = removePathFromNpmPackage(pkg);
|
|
1219
|
+
const projectRequire = createRequire$1(new URL(`file://${path.join(getPackageDetectionCwd(), "package.json")}`));
|
|
1220
|
+
let resolvedPath;
|
|
1221
|
+
try {
|
|
1222
|
+
resolvedPath = projectRequire.resolve(pkg);
|
|
1223
|
+
} catch {
|
|
1224
|
+
resolvedPath = projectRequire.resolve(packageName);
|
|
1225
|
+
}
|
|
1226
|
+
let currentDir = path.dirname(resolvedPath);
|
|
1227
|
+
const rootDir = path.parse(currentDir).root;
|
|
1228
|
+
while (currentDir !== rootDir) {
|
|
1229
|
+
const packageJsonPath = path.join(currentDir, "package.json");
|
|
1230
|
+
if (existsSync(packageJsonPath)) {
|
|
1231
|
+
if (JSON.parse(readFileSync(packageJsonPath, "utf-8")).name === packageName) return packageJsonPath;
|
|
1232
|
+
}
|
|
1233
|
+
currentDir = path.dirname(currentDir);
|
|
1234
|
+
}
|
|
1235
|
+
const rootPackageJsonPath = path.join(rootDir, "package.json");
|
|
1236
|
+
if (existsSync(rootPackageJsonPath)) {
|
|
1237
|
+
if (JSON.parse(readFileSync(rootPackageJsonPath, "utf-8")).name === packageName) return rootPackageJsonPath;
|
|
1238
|
+
}
|
|
1239
|
+
} catch {
|
|
1240
|
+
const packageName = removePathFromNpmPackage(pkg);
|
|
1241
|
+
let currentDir = getPackageDetectionCwd();
|
|
1242
|
+
const rootDir = path.parse(currentDir).root;
|
|
1243
|
+
while (currentDir !== rootDir) {
|
|
1244
|
+
const packageJsonPath = path.join(currentDir, "node_modules", packageName, "package.json");
|
|
1245
|
+
if (existsSync(packageJsonPath)) return packageJsonPath;
|
|
1246
|
+
currentDir = path.dirname(currentDir);
|
|
1247
|
+
}
|
|
1248
|
+
const rootPackageJsonPath = path.join(rootDir, "node_modules", packageName, "package.json");
|
|
1249
|
+
return existsSync(rootPackageJsonPath) ? rootPackageJsonPath : void 0;
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
function resolveImportTarget(exportsField) {
|
|
1253
|
+
if (typeof exportsField === "string") return exportsField;
|
|
1254
|
+
if (!exportsField || typeof exportsField !== "object") return void 0;
|
|
1255
|
+
const record = exportsField;
|
|
1256
|
+
for (const condition of [
|
|
1257
|
+
"import",
|
|
1258
|
+
"module",
|
|
1259
|
+
"default"
|
|
1260
|
+
]) {
|
|
1261
|
+
const target = resolveImportTarget(record[condition]);
|
|
1262
|
+
if (target) return target;
|
|
1263
|
+
}
|
|
1264
|
+
for (const target of Object.values(record)) {
|
|
1265
|
+
const resolved = resolveImportTarget(target);
|
|
1266
|
+
if (resolved) return resolved;
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
function getPackageEsmEntryPath(pkg) {
|
|
1270
|
+
try {
|
|
1271
|
+
const resolvedEntryPath = resolvePackageEntryFromProjectRoot(pkg);
|
|
1272
|
+
const packageJsonPath = getInstalledPackageJsonPath(pkg);
|
|
1273
|
+
if (!packageJsonPath) return resolvedEntryPath;
|
|
1274
|
+
const packageName = removePathFromNpmPackage(pkg);
|
|
1275
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
1276
|
+
const subpath = pkg === packageName ? "." : `.${pkg.slice(packageName.length)}`;
|
|
1277
|
+
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;
|
|
1278
|
+
if (!target) return resolvedEntryPath;
|
|
1279
|
+
return path.resolve(path.dirname(packageJsonPath), target);
|
|
1280
|
+
} catch {
|
|
1281
|
+
return resolvePackageEntryFromProjectRoot(pkg);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
function getEsmNamedExports(pkg) {
|
|
1285
|
+
try {
|
|
1286
|
+
const entryPath = getPackageEsmEntryPath(pkg);
|
|
1287
|
+
if (!entryPath) return [];
|
|
1288
|
+
const { initSync, parse } = localRequire("es-module-lexer");
|
|
1289
|
+
initSync();
|
|
1290
|
+
const [, exports] = parse(readFileSync(entryPath, "utf-8"), entryPath);
|
|
1291
|
+
return exports.map((item) => item.n).filter((name) => !!name && name !== "default" && name !== "__esModule" && /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name));
|
|
1292
|
+
} catch {
|
|
1293
|
+
return [];
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1130
1296
|
function getPackageNamedExports(pkg) {
|
|
1131
1297
|
try {
|
|
1132
|
-
const mod = createRequire$1(new URL(
|
|
1298
|
+
const mod = createRequire$1(new URL(`file://${path.join(getPackageDetectionCwd(), "package.json")}`))(pkg);
|
|
1133
1299
|
return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule" && /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(k));
|
|
1134
1300
|
} catch {
|
|
1135
|
-
return
|
|
1301
|
+
return getEsmNamedExports(pkg);
|
|
1136
1302
|
}
|
|
1137
1303
|
}
|
|
1138
1304
|
function getLocalProviderImportPath(pkg) {
|
|
1139
1305
|
try {
|
|
1140
|
-
const resolved = createRequire$1(new URL(
|
|
1306
|
+
const resolved = createRequire$1(new URL(`file://${path.join(getPackageDetectionCwd(), "package.json")}`)).resolve(pkg);
|
|
1141
1307
|
return resolved.includes("/node_modules/") || resolved.includes("\\node_modules\\") ? void 0 : resolved;
|
|
1142
1308
|
} catch {
|
|
1143
1309
|
return;
|
|
1144
1310
|
}
|
|
1145
1311
|
}
|
|
1312
|
+
function tryResolveImportFromPackageRoot(pkg, root) {
|
|
1313
|
+
try {
|
|
1314
|
+
return createRequire$1(new URL(`file://${path.join(root, "package.json")}`)).resolve(pkg);
|
|
1315
|
+
} catch {
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
function getConcreteSharedImportSource(pkg, shareItem) {
|
|
1320
|
+
const configuredImport = shareItem?.shareConfig.import;
|
|
1321
|
+
if (typeof configuredImport === "string") return configuredImport;
|
|
1322
|
+
const projectRoot = getPackageDetectionCwd();
|
|
1323
|
+
if (tryResolveImportFromPackageRoot(pkg, projectRoot)) return;
|
|
1324
|
+
let currentDir = path.dirname(projectRoot);
|
|
1325
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
1326
|
+
const resolved = tryResolveImportFromPackageRoot(pkg, currentDir);
|
|
1327
|
+
if (resolved) return resolved;
|
|
1328
|
+
currentDir = path.dirname(currentDir);
|
|
1329
|
+
}
|
|
1330
|
+
return tryResolveImportFromPackageRoot(pkg, currentDir);
|
|
1331
|
+
}
|
|
1146
1332
|
const preBuildCacheMap = {};
|
|
1333
|
+
const preBuildShareItemMap = {};
|
|
1147
1334
|
const PREBUILD_TAG = "__prebuild__";
|
|
1148
|
-
function writePreBuildLibPath(pkg) {
|
|
1335
|
+
function writePreBuildLibPath(pkg, shareItem) {
|
|
1149
1336
|
if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG);
|
|
1150
|
-
|
|
1337
|
+
preBuildShareItemMap[pkg] = shareItem;
|
|
1338
|
+
preBuildCacheMap[pkg].writeSync("", true);
|
|
1151
1339
|
}
|
|
1152
1340
|
function getPreBuildLibImportId(pkg) {
|
|
1153
1341
|
if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = new VirtualModule(pkg, PREBUILD_TAG);
|
|
1154
1342
|
return preBuildCacheMap[pkg].getImportId();
|
|
1155
1343
|
}
|
|
1344
|
+
function getPreBuildShareItem(pkg) {
|
|
1345
|
+
return preBuildShareItemMap[pkg];
|
|
1346
|
+
}
|
|
1347
|
+
function getSharedImportSource(pkg, shareItem) {
|
|
1348
|
+
return getConcreteSharedImportSource(pkg, shareItem) || getPreBuildLibImportId(pkg);
|
|
1349
|
+
}
|
|
1156
1350
|
const LOAD_SHARE_TAG = "__loadShare__";
|
|
1157
1351
|
const loadShareCacheMap = {};
|
|
1158
1352
|
function getLoadShareImportId(pkg, isRolldown, command) {
|
|
@@ -1170,22 +1364,25 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1170
1364
|
const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
1171
1365
|
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
1172
1366
|
const useSsrProviderFallback = hasPackageDependency("vinext") && command === "build" && pkg === "react";
|
|
1173
|
-
const
|
|
1367
|
+
const concreteSharedImportSource = getConcreteSharedImportSource(pkg, shareItem);
|
|
1368
|
+
const sharedImportSource = concreteSharedImportSource || getPreBuildLibImportId(pkg);
|
|
1369
|
+
const devImportSource = concreteSharedImportSource || pkg;
|
|
1370
|
+
const providerImportId = getLocalProviderImportPath(pkg) || concreteSharedImportSource || sharedImportSource;
|
|
1174
1371
|
const namedExports = getPackageNamedExports(pkg);
|
|
1175
1372
|
let exportLine;
|
|
1176
1373
|
if (namedExports.length > 0) {
|
|
1177
1374
|
const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
|
|
1178
1375
|
const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
|
|
1179
1376
|
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(", ")} });`;
|
|
1180
|
-
} else exportLine = useESM ? `export default exportModule.default ?? exportModule\n export * from ${
|
|
1377
|
+
} else exportLine = useESM ? `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}` : "module.exports = exportModule";
|
|
1181
1378
|
loadShareCacheMap[pkg].writeSync(`
|
|
1182
|
-
import ${
|
|
1183
|
-
${command !== "build" ? `;() => import(${
|
|
1379
|
+
import ${escapeGeneratedStringLiteral(sharedImportSource)};
|
|
1380
|
+
${command !== "build" ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : ""}
|
|
1184
1381
|
${importLine}
|
|
1185
1382
|
${useSsrProviderFallback ? `const providerModulePromise = typeof window === "undefined"
|
|
1186
|
-
? import(${
|
|
1383
|
+
? import(${escapeGeneratedStringLiteral(providerImportId)})
|
|
1187
1384
|
: undefined` : ""}
|
|
1188
|
-
const res = initPromise.then(runtime => runtime.loadShare(${
|
|
1385
|
+
const res = initPromise.then(runtime => runtime.loadShare(${escapeGeneratedStringLiteral(pkg)}, {
|
|
1189
1386
|
customShareInfo: {shareConfig:{
|
|
1190
1387
|
singleton: ${shareItem.shareConfig.singleton},
|
|
1191
1388
|
strictVersion: ${shareItem.shareConfig.strictVersion},
|
|
@@ -1196,7 +1393,7 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1196
1393
|
? ((await providerModulePromise)?.default ?? await providerModulePromise)
|
|
1197
1394
|
: ${awaitOrPlaceholder}res.then((factory) => (typeof factory === "function" ? factory() : factory)))` : `${awaitOrPlaceholder}res.then((factory) => (typeof factory === "function" ? factory() : factory))`}
|
|
1198
1395
|
${exportLine}
|
|
1199
|
-
|
|
1396
|
+
`, true);
|
|
1200
1397
|
}
|
|
1201
1398
|
//#endregion
|
|
1202
1399
|
//#region src/virtualModules/virtualRemoteEntry.ts
|
|
@@ -1230,7 +1427,7 @@ function generateLocalSharedImportMap() {
|
|
|
1230
1427
|
return `
|
|
1231
1428
|
${JSON.stringify(pkg)}: async () => {
|
|
1232
1429
|
${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(pkg)}}' must be provided by host\`);` : isVinext && pkg === "react" ? `let pkg = await import("react");
|
|
1233
|
-
return pkg;` : `let pkg = await import(
|
|
1430
|
+
return pkg;` : `let pkg = await import(${JSON.stringify(getSharedImportSource(pkg, shareItem))});
|
|
1234
1431
|
return pkg;`}
|
|
1235
1432
|
}
|
|
1236
1433
|
`;
|
|
@@ -1512,6 +1709,18 @@ const processModuleAssets = (bundle, filesMap, moduleMatcher) => {
|
|
|
1512
1709
|
}
|
|
1513
1710
|
};
|
|
1514
1711
|
/**
|
|
1712
|
+
* Adds global CSS assets to all module exports
|
|
1713
|
+
* @param filesMap - The preload map to update
|
|
1714
|
+
* @param cssAssets - Set of CSS asset filenames to add
|
|
1715
|
+
*/
|
|
1716
|
+
const addCssAssetsToAllExports = (filesMap, cssAssets) => {
|
|
1717
|
+
Object.keys(filesMap).forEach((key) => {
|
|
1718
|
+
cssAssets.forEach((cssAsset) => {
|
|
1719
|
+
trackAsset(filesMap, key, cssAsset, false, "css");
|
|
1720
|
+
});
|
|
1721
|
+
});
|
|
1722
|
+
};
|
|
1723
|
+
/**
|
|
1515
1724
|
* Deduplicates assets in the files map
|
|
1516
1725
|
* @param filesMap - The preload map to deduplicate
|
|
1517
1726
|
* @returns New deduplicated preload map
|
|
@@ -1837,12 +2046,13 @@ function pluginModuleParseEnd_default(excludeFn, options) {
|
|
|
1837
2046
|
//#region src/plugins/pluginProxyRemoteEntry.ts
|
|
1838
2047
|
const filter = createFilter();
|
|
1839
2048
|
function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
|
|
1840
|
-
let viteConfig, _command;
|
|
2049
|
+
let viteConfig, _command, root;
|
|
1841
2050
|
return {
|
|
1842
2051
|
name: "proxyRemoteEntry",
|
|
1843
2052
|
enforce: "post",
|
|
1844
2053
|
configResolved(config) {
|
|
1845
2054
|
viteConfig = config;
|
|
2055
|
+
root = config.root;
|
|
1846
2056
|
},
|
|
1847
2057
|
config(config, { command }) {
|
|
1848
2058
|
_command = command;
|
|
@@ -1897,6 +2107,51 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
|
|
|
1897
2107
|
return code;
|
|
1898
2108
|
}
|
|
1899
2109
|
})());
|
|
2110
|
+
},
|
|
2111
|
+
generateBundle(_, bundle) {
|
|
2112
|
+
if (_command !== "build") return;
|
|
2113
|
+
const filesMap = {};
|
|
2114
|
+
const exposeEntries = Object.entries(options.exposes);
|
|
2115
|
+
const allCssAssets = options.bundleAllCSS ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
|
|
2116
|
+
processModuleAssets(bundle, filesMap, (modulePath) => {
|
|
2117
|
+
const absoluteModulePath = path$1.resolve(root, modulePath);
|
|
2118
|
+
return exposeEntries.find(([_, exposeOptions]) => {
|
|
2119
|
+
const exposePath = path$1.resolve(root, exposeOptions.import);
|
|
2120
|
+
if (absoluteModulePath === exposePath) return true;
|
|
2121
|
+
const stripKnownJsExt = (filePath) => {
|
|
2122
|
+
const ext = path$1.extname(filePath);
|
|
2123
|
+
return [
|
|
2124
|
+
".ts",
|
|
2125
|
+
".tsx",
|
|
2126
|
+
".jsx",
|
|
2127
|
+
".mjs",
|
|
2128
|
+
".cjs"
|
|
2129
|
+
].includes(ext) ? path$1.join(path$1.dirname(filePath), path$1.basename(filePath, ext)) : filePath;
|
|
2130
|
+
};
|
|
2131
|
+
return stripKnownJsExt(absoluteModulePath) === stripKnownJsExt(exposePath);
|
|
2132
|
+
})?.[1].import;
|
|
2133
|
+
});
|
|
2134
|
+
if (options.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
|
|
2135
|
+
const ensureRelativeImportPath = (fromFile, toFile) => {
|
|
2136
|
+
let relativePath = path$1.relative(path$1.dirname(fromFile), toFile);
|
|
2137
|
+
if (!relativePath.startsWith(".")) relativePath = `./${relativePath}`;
|
|
2138
|
+
return relativePath;
|
|
2139
|
+
};
|
|
2140
|
+
const placeholderValue = getExposesCssMapPlaceholder();
|
|
2141
|
+
const placeholderPatterns = [
|
|
2142
|
+
JSON.stringify(placeholderValue),
|
|
2143
|
+
`'${placeholderValue}'`,
|
|
2144
|
+
`\`${placeholderValue}\``
|
|
2145
|
+
];
|
|
2146
|
+
for (const file of Object.values(bundle)) {
|
|
2147
|
+
if (file.type !== "chunk" || !file.code.includes(placeholderValue)) continue;
|
|
2148
|
+
const cssAssetMap = exposeEntries.reduce((acc, [exposeKey, expose]) => {
|
|
2149
|
+
const assets = filesMap[expose.import] || createEmptyAssetMap();
|
|
2150
|
+
acc[exposeKey] = [...assets.css.sync, ...assets.css.async].map((cssAsset) => ensureRelativeImportPath(file.fileName, cssAsset));
|
|
2151
|
+
return acc;
|
|
2152
|
+
}, {});
|
|
2153
|
+
for (const placeholderPattern of placeholderPatterns) file.code = file.code.replace(placeholderPattern, JSON.stringify(cssAssetMap));
|
|
2154
|
+
}
|
|
1900
2155
|
}
|
|
1901
2156
|
};
|
|
1902
2157
|
}
|
|
@@ -1959,6 +2214,9 @@ var PromiseStore = class {
|
|
|
1959
2214
|
};
|
|
1960
2215
|
//#endregion
|
|
1961
2216
|
//#region src/plugins/pluginProxySharedModule_preBuild.ts
|
|
2217
|
+
function getPrebuildResolutionSource(pkgName, shareItem) {
|
|
2218
|
+
return getConcreteSharedImportSource(pkgName, shareItem) || pkgName;
|
|
2219
|
+
}
|
|
1962
2220
|
function proxySharedModule(options) {
|
|
1963
2221
|
const { shared = {} } = options;
|
|
1964
2222
|
let _config;
|
|
@@ -1997,7 +2255,7 @@ function proxySharedModule(options) {
|
|
|
1997
2255
|
if (key.endsWith("/") && source !== key.slice(0, -1)) return;
|
|
1998
2256
|
const loadSharePath = getLoadShareModulePath(source, isRolldown, command);
|
|
1999
2257
|
writeLoadShareModule(source, shared[key], command, isRolldown);
|
|
2000
|
-
writePreBuildLibPath(source);
|
|
2258
|
+
writePreBuildLibPath(source, shared[key]);
|
|
2001
2259
|
addUsedShares(source);
|
|
2002
2260
|
writeLocalSharedImportMap();
|
|
2003
2261
|
return this.resolve(loadSharePath, importer);
|
|
@@ -2008,14 +2266,18 @@ function proxySharedModule(options) {
|
|
|
2008
2266
|
return command === "build" ? {
|
|
2009
2267
|
find: new RegExp(`(.*${PREBUILD_TAG}.*)`),
|
|
2010
2268
|
replacement: function($1) {
|
|
2011
|
-
|
|
2269
|
+
const pkgName = assertModuleFound(PREBUILD_TAG, $1).name;
|
|
2270
|
+
return getPrebuildResolutionSource(pkgName, getPreBuildShareItem(pkgName));
|
|
2012
2271
|
}
|
|
2013
2272
|
} : {
|
|
2014
2273
|
find: new RegExp(`(.*${PREBUILD_TAG}.*)`),
|
|
2015
2274
|
replacement: "$1",
|
|
2016
2275
|
async customResolver(source, importer) {
|
|
2017
2276
|
const pkgName = assertModuleFound(PREBUILD_TAG, source).name;
|
|
2018
|
-
const
|
|
2277
|
+
const importSource = getPrebuildResolutionSource(pkgName, getPreBuildShareItem(pkgName));
|
|
2278
|
+
const resolved = await this.resolve(importSource, importer);
|
|
2279
|
+
if (!resolved?.id) return;
|
|
2280
|
+
const result = resolved.id;
|
|
2019
2281
|
if (_config && !result.includes(_config.cacheDir)) savePrebuild.set(pkgName, Promise.resolve(result));
|
|
2020
2282
|
return await this.resolve(await savePrebuild.get(pkgName), importer);
|
|
2021
2283
|
}
|
|
@@ -2032,7 +2294,7 @@ function proxySharedModule(options) {
|
|
|
2032
2294
|
return;
|
|
2033
2295
|
}
|
|
2034
2296
|
writeLoadShareModule(key, shared[key], _command, isRolldown);
|
|
2035
|
-
writePreBuildLibPath(key);
|
|
2297
|
+
writePreBuildLibPath(key, shared[key]);
|
|
2036
2298
|
addUsedShares(key);
|
|
2037
2299
|
});
|
|
2038
2300
|
writeLocalSharedImportMap();
|
|
@@ -2154,14 +2416,19 @@ function stripEmptyPreloadCalls(code) {
|
|
|
2154
2416
|
while (cursor < nextCode.length) {
|
|
2155
2417
|
const char = nextCode[cursor];
|
|
2156
2418
|
if (char === "(") depth++;
|
|
2157
|
-
else if (char === ")")
|
|
2158
|
-
|
|
2419
|
+
else if (char === ")") {
|
|
2420
|
+
depth--;
|
|
2421
|
+
if (depth < 0) break;
|
|
2422
|
+
} else if (depth === 0 && nextCode.startsWith(",[],import.meta.url)", cursor)) {
|
|
2159
2423
|
replacementEnd = cursor;
|
|
2160
2424
|
break;
|
|
2161
2425
|
}
|
|
2162
2426
|
cursor++;
|
|
2163
2427
|
}
|
|
2164
|
-
if (replacementEnd === -1)
|
|
2428
|
+
if (replacementEnd === -1) {
|
|
2429
|
+
start = nextCode.indexOf(marker, start + marker.length);
|
|
2430
|
+
continue;
|
|
2431
|
+
}
|
|
2165
2432
|
const expression = nextCode.slice(exprStart, replacementEnd);
|
|
2166
2433
|
nextCode = nextCode.slice(0, start) + expression + nextCode.slice(replacementEnd + 20);
|
|
2167
2434
|
start = nextCode.indexOf(marker, start + expression.length);
|
|
@@ -2238,13 +2505,14 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
2238
2505
|
VirtualModule.setRoot(root);
|
|
2239
2506
|
VirtualModule.ensureVirtualPackageExists();
|
|
2240
2507
|
initVirtualModules(_command, getRemoteEntryId(options));
|
|
2241
|
-
if (_command !== "serve") return;
|
|
2242
2508
|
const isRolldown = getIsRolldown(this);
|
|
2243
2509
|
if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
|
|
2244
2510
|
if (shared && Object.keys(shared).length > 0) {
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2511
|
+
if (_command === "serve") {
|
|
2512
|
+
config.optimizeDeps = config.optimizeDeps || {};
|
|
2513
|
+
config.optimizeDeps.include = config.optimizeDeps.include || [];
|
|
2514
|
+
config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
|
|
2515
|
+
}
|
|
2248
2516
|
for (const key of Object.keys(shared)) {
|
|
2249
2517
|
if (key.endsWith("/")) continue;
|
|
2250
2518
|
const shareItem = shared[key];
|
|
@@ -2254,10 +2522,12 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
2254
2522
|
}
|
|
2255
2523
|
getLoadShareModulePath(key, isRolldown);
|
|
2256
2524
|
writeLoadShareModule(key, shareItem, _command, isRolldown);
|
|
2257
|
-
writePreBuildLibPath(key);
|
|
2525
|
+
writePreBuildLibPath(key, shareItem);
|
|
2258
2526
|
addUsedShares(key);
|
|
2259
|
-
|
|
2260
|
-
|
|
2527
|
+
if (_command === "serve") {
|
|
2528
|
+
if (!isRolldown) config.optimizeDeps.include.push(getLoadShareImportId(key, isRolldown, _command));
|
|
2529
|
+
config.optimizeDeps.include.push(getPreBuildLibImportId(key));
|
|
2530
|
+
}
|
|
2261
2531
|
}
|
|
2262
2532
|
writeLocalSharedImportMap();
|
|
2263
2533
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/vite",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.3",
|
|
4
4
|
"description": "Vite plugin for Module Federation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.cjs",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
"@module-federation/sdk": "2.2.3",
|
|
73
73
|
"@rollup/pluginutils": "^5.3.0",
|
|
74
74
|
"defu": "^6.1.4",
|
|
75
|
+
"es-module-lexer": "^1.7.0",
|
|
75
76
|
"estree-walker": "^3.0.3",
|
|
76
77
|
"magic-string": "^0.30.21",
|
|
77
78
|
"pathe": "^2.0.3"
|