@module-federation/vite 1.15.4 → 1.16.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/README.md +30 -1
- package/lib/index.cjs +1123 -870
- package/lib/index.d.cts +22 -6
- package/lib/index.d.mts +22 -6
- package/lib/index.mjs +1063 -793
- package/lib/packageUtils-CbbnJvKu.cjs +358 -0
- package/lib/packageUtils-DOekOsFz.mjs +250 -0
- package/lib/pluginDts-B5pcUmam.mjs +309 -0
- package/lib/pluginDts-BEOKyKQ-.cjs +311 -0
- package/lib/utils/ssrEntryLoader.cjs +301 -0
- package/lib/utils/ssrEntryLoader.d.cts +65 -0
- package/lib/utils/ssrEntryLoader.d.mts +66 -0
- package/lib/utils/ssrEntryLoader.mjs +301 -0
- package/package.json +13 -5
package/lib/index.cjs
CHANGED
|
@@ -1,34 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
-
key = keys[i];
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
-
get: ((k) => from[k]).bind(null, key),
|
|
14
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
-
value: mod,
|
|
21
|
-
enumerable: true
|
|
22
|
-
}) : target, mod));
|
|
23
|
-
//#endregion
|
|
2
|
+
const require_packageUtils = require("./packageUtils-CbbnJvKu.cjs");
|
|
24
3
|
let fs = require("fs");
|
|
25
|
-
fs = __toESM(fs);
|
|
4
|
+
fs = require_packageUtils.__toESM(fs);
|
|
26
5
|
let module$1 = require("module");
|
|
27
6
|
let pathe = require("pathe");
|
|
28
|
-
pathe = __toESM(pathe);
|
|
29
|
-
let
|
|
30
|
-
let _module_federation_dts_plugin = require("@module-federation/dts-plugin");
|
|
31
|
-
let _module_federation_dts_plugin_core = require("@module-federation/dts-plugin/core");
|
|
7
|
+
pathe = require_packageUtils.__toESM(pathe);
|
|
8
|
+
let vite = require("vite");
|
|
32
9
|
let url = require("url");
|
|
33
10
|
let es_module_lexer = require("es-module-lexer");
|
|
34
11
|
//#region src/utils/codeRewriter.ts
|
|
@@ -192,237 +169,6 @@ function injectEntryScript(html, initSrc) {
|
|
|
192
169
|
return html.replace("<head>", `<head><script type="module" src=${JSON.stringify(src)}><\/script>`);
|
|
193
170
|
}
|
|
194
171
|
//#endregion
|
|
195
|
-
//#region src/utils/logger.ts
|
|
196
|
-
const MODULE_FEDERATION_LOG_PREFIX = "[Module Federation]";
|
|
197
|
-
function formatModuleFederationMessage(message) {
|
|
198
|
-
return `${MODULE_FEDERATION_LOG_PREFIX} ${message}`;
|
|
199
|
-
}
|
|
200
|
-
function createModuleFederationError(message) {
|
|
201
|
-
return new Error(formatModuleFederationMessage(message));
|
|
202
|
-
}
|
|
203
|
-
function toConsoleArgs(message, rest = []) {
|
|
204
|
-
if (typeof message === "string") return [formatModuleFederationMessage(message), ...rest];
|
|
205
|
-
if (message === void 0) return [MODULE_FEDERATION_LOG_PREFIX, ...rest];
|
|
206
|
-
return [
|
|
207
|
-
MODULE_FEDERATION_LOG_PREFIX,
|
|
208
|
-
message,
|
|
209
|
-
...rest
|
|
210
|
-
];
|
|
211
|
-
}
|
|
212
|
-
const moduleFederationConsole = {
|
|
213
|
-
log(message, ...rest) {
|
|
214
|
-
console.log(...toConsoleArgs(message, rest));
|
|
215
|
-
},
|
|
216
|
-
warn(message, ...rest) {
|
|
217
|
-
console.warn(...toConsoleArgs(message, rest));
|
|
218
|
-
},
|
|
219
|
-
error(message, ...rest) {
|
|
220
|
-
console.error(...toConsoleArgs(message, rest));
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
moduleFederationConsole.log;
|
|
224
|
-
const mfWarn = moduleFederationConsole.warn;
|
|
225
|
-
const mfError = moduleFederationConsole.error;
|
|
226
|
-
//#endregion
|
|
227
|
-
//#region src/utils/packageUtils.ts
|
|
228
|
-
const dependencyPresenceCache = /* @__PURE__ */ new Map();
|
|
229
|
-
let packageDetectionCwd;
|
|
230
|
-
function getDependencyCacheKey(cwd, dependencyName) {
|
|
231
|
-
return `${cwd}:${dependencyName}`;
|
|
232
|
-
}
|
|
233
|
-
function setPackageDetectionCwd(cwd) {
|
|
234
|
-
packageDetectionCwd = cwd;
|
|
235
|
-
}
|
|
236
|
-
function getPackageDetectionCwd() {
|
|
237
|
-
return packageDetectionCwd || process.cwd();
|
|
238
|
-
}
|
|
239
|
-
const DEFAULT_EXPORT_CONDITIONS = [
|
|
240
|
-
"browser",
|
|
241
|
-
"import",
|
|
242
|
-
"module",
|
|
243
|
-
"default",
|
|
244
|
-
"require"
|
|
245
|
-
];
|
|
246
|
-
function resolveExportsEntry(exportsField, conditions = DEFAULT_EXPORT_CONDITIONS) {
|
|
247
|
-
if (typeof exportsField === "string") return exportsField;
|
|
248
|
-
if (!exportsField || typeof exportsField !== "object") return void 0;
|
|
249
|
-
const record = exportsField;
|
|
250
|
-
const rootExport = record["."];
|
|
251
|
-
if (rootExport) return resolveExportsEntry(rootExport);
|
|
252
|
-
for (const condition of conditions) {
|
|
253
|
-
const target = resolveExportsEntry(record[condition], conditions);
|
|
254
|
-
if (target) return target;
|
|
255
|
-
}
|
|
256
|
-
for (const target of Object.values(record)) {
|
|
257
|
-
const resolved = resolveExportsEntry(target, conditions);
|
|
258
|
-
if (resolved) return resolved;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
function getPackageExportsTarget(pkg, packageName, exportsField) {
|
|
262
|
-
if (typeof exportsField === "string") return pkg === packageName ? exportsField : void 0;
|
|
263
|
-
if (!exportsField || typeof exportsField !== "object") return void 0;
|
|
264
|
-
const record = exportsField;
|
|
265
|
-
const subpath = pkg === packageName ? "." : `.${pkg.slice(packageName.length)}`;
|
|
266
|
-
if (subpath !== ".") return record[subpath];
|
|
267
|
-
return record["."] ?? (!Object.keys(record).some((key) => key.startsWith(".")) ? record : void 0);
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Escaping rules:
|
|
271
|
-
* Convert using the format __${mapping}__, where _ and $ are not allowed in npm package names but can be used in variable names.
|
|
272
|
-
* @ => 1
|
|
273
|
-
* / => 2
|
|
274
|
-
* - => 3
|
|
275
|
-
* . => 4
|
|
276
|
-
*/
|
|
277
|
-
/**
|
|
278
|
-
* Encodes a package name into a valid file name.
|
|
279
|
-
* @param {string} name - The package name, e.g., "@scope/xx-xx.xx".
|
|
280
|
-
* @returns {string} - The encoded file name.
|
|
281
|
-
*/
|
|
282
|
-
function packageNameEncode(name) {
|
|
283
|
-
if (typeof name !== "string") throw createModuleFederationError("A string package name is required");
|
|
284
|
-
return name.replace(/@/g, "_mf_0_").replace(/\//g, "_mf_1_").replace(/-/g, "_mf_2_").replace(/\./g, "_mf_3_");
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Decodes an encoded file name back to the original package name.
|
|
288
|
-
* @param {string} encoded - The encoded file name, e.g., "_mf_0_scope_mf_1_xx_mf_2_xx_mf_3_xx".
|
|
289
|
-
* @returns {string} - The decoded package name.
|
|
290
|
-
*/
|
|
291
|
-
function packageNameDecode(encoded) {
|
|
292
|
-
if (typeof encoded !== "string") throw createModuleFederationError("A string encoded file name is required");
|
|
293
|
-
return encoded.replace(/_mf_0_/g, "@").replace(/_mf_1_/g, "/").replace(/_mf_2_/g, "-").replace(/_mf_3_/g, ".");
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* Removes any subpath from an npm package specifier and returns the package name only.
|
|
297
|
-
* @param {string} packageString - The package specifier, e.g., "@scope/pkg/runtime" or "react/jsx-runtime".
|
|
298
|
-
* @returns {string} - The base npm package name.
|
|
299
|
-
*/
|
|
300
|
-
function getPackageName(packageString) {
|
|
301
|
-
const match = packageString.match(/^(?:@[^/]+\/)?[^/]+/);
|
|
302
|
-
return match ? match[0] : packageString;
|
|
303
|
-
}
|
|
304
|
-
function getPackageNameFromNodeModulePath(source) {
|
|
305
|
-
const normalized = source.replace(/\\/g, "/");
|
|
306
|
-
const nodeModulesIndex = normalized.lastIndexOf("/node_modules/");
|
|
307
|
-
if (nodeModulesIndex < 0) return;
|
|
308
|
-
const parts = normalized.slice(nodeModulesIndex + 14).split("/");
|
|
309
|
-
if (!parts[0]) return;
|
|
310
|
-
if (parts[0].startsWith("@")) return parts[1] ? `${parts[0]}/${parts[1]}` : void 0;
|
|
311
|
-
return parts[0];
|
|
312
|
-
}
|
|
313
|
-
function getInstalledPackageJson(pkg, opts) {
|
|
314
|
-
const cwd = opts?.cwd || getPackageDetectionCwd();
|
|
315
|
-
const packageName = opts?.packageName || getPackageName(pkg);
|
|
316
|
-
const tryReadPackageJson = (packageJsonPath) => {
|
|
317
|
-
if (!(0, fs.existsSync)(packageJsonPath)) return void 0;
|
|
318
|
-
try {
|
|
319
|
-
return {
|
|
320
|
-
path: packageJsonPath,
|
|
321
|
-
dir: pathe.default.dirname(packageJsonPath),
|
|
322
|
-
packageJson: JSON.parse((0, fs.readFileSync)(packageJsonPath, "utf-8"))
|
|
323
|
-
};
|
|
324
|
-
} catch {
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
};
|
|
328
|
-
const findPackageInPnpmStore = (startDir) => {
|
|
329
|
-
let currentDir = startDir;
|
|
330
|
-
const rootDir = pathe.default.parse(currentDir).root;
|
|
331
|
-
while (true) {
|
|
332
|
-
const pnpmStoreDir = pathe.default.join(currentDir, "node_modules", ".pnpm");
|
|
333
|
-
if ((0, fs.existsSync)(pnpmStoreDir)) try {
|
|
334
|
-
for (const entry of (0, fs.readdirSync)(pnpmStoreDir, { withFileTypes: true })) {
|
|
335
|
-
if (!entry.isDirectory()) continue;
|
|
336
|
-
const candidate = tryReadPackageJson(pathe.default.join(pnpmStoreDir, entry.name, "node_modules", packageName, "package.json"));
|
|
337
|
-
if (candidate?.packageJson.name === packageName) return candidate;
|
|
338
|
-
}
|
|
339
|
-
} catch {}
|
|
340
|
-
if (currentDir === rootDir) break;
|
|
341
|
-
currentDir = pathe.default.dirname(currentDir);
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
try {
|
|
345
|
-
const projectRequire = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(cwd, "package.json")}`));
|
|
346
|
-
let resolvedPath;
|
|
347
|
-
if (opts?.fromResolvedEntry) resolvedPath = opts.fromResolvedEntry;
|
|
348
|
-
else try {
|
|
349
|
-
resolvedPath = projectRequire.resolve(pkg);
|
|
350
|
-
} catch {
|
|
351
|
-
resolvedPath = projectRequire.resolve(packageName);
|
|
352
|
-
}
|
|
353
|
-
let currentDir = pathe.default.dirname(resolvedPath);
|
|
354
|
-
const rootDir = pathe.default.parse(currentDir).root;
|
|
355
|
-
while (true) {
|
|
356
|
-
const packageJsonPath = pathe.default.join(currentDir, "package.json");
|
|
357
|
-
if ((0, fs.existsSync)(packageJsonPath)) {
|
|
358
|
-
const packageJsonContent = (0, fs.readFileSync)(packageJsonPath, "utf-8");
|
|
359
|
-
try {
|
|
360
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
361
|
-
if (packageJson.name === packageName) return {
|
|
362
|
-
path: packageJsonPath,
|
|
363
|
-
dir: currentDir,
|
|
364
|
-
packageJson
|
|
365
|
-
};
|
|
366
|
-
} catch (error) {
|
|
367
|
-
if (!(error instanceof SyntaxError)) throw error;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
if (currentDir === rootDir) break;
|
|
371
|
-
currentDir = pathe.default.dirname(currentDir);
|
|
372
|
-
}
|
|
373
|
-
} catch {
|
|
374
|
-
let currentDir = cwd;
|
|
375
|
-
const rootDir = pathe.default.parse(currentDir).root;
|
|
376
|
-
while (true) {
|
|
377
|
-
const directCandidate = tryReadPackageJson(pathe.default.join(currentDir, "node_modules", packageName, "package.json"));
|
|
378
|
-
if (directCandidate?.packageJson.name === packageName) return directCandidate;
|
|
379
|
-
if (currentDir === rootDir) break;
|
|
380
|
-
currentDir = pathe.default.dirname(currentDir);
|
|
381
|
-
}
|
|
382
|
-
return findPackageInPnpmStore(cwd);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
function getInstalledPackageEntry(pkg, opts) {
|
|
386
|
-
const installed = getInstalledPackageJson(pkg, opts);
|
|
387
|
-
if (!installed) return void 0;
|
|
388
|
-
const cwd = opts?.cwd || getPackageDetectionCwd();
|
|
389
|
-
const packageName = opts?.packageName || getPackageName(pkg);
|
|
390
|
-
if (pkg !== packageName && opts?.resolveSubpathWithRequire !== false) try {
|
|
391
|
-
return (0, module$1.createRequire)(new URL(`file://${pathe.default.join(cwd, "package.json")}`)).resolve(pkg);
|
|
392
|
-
} catch {}
|
|
393
|
-
const packageJson = installed.packageJson;
|
|
394
|
-
const explicitEntry = resolveExportsEntry(getPackageExportsTarget(pkg, packageName, packageJson.exports), opts?.conditions) || (typeof packageJson.module === "string" ? packageJson.module : void 0) || (typeof packageJson.main === "string" ? packageJson.main : void 0) || "index.js";
|
|
395
|
-
return pathe.default.join(installed.dir, explicitEntry);
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Detect whether the current runtime is Vite 8+ by checking for a Vite version flag
|
|
399
|
-
* on the plugin hook context, with Rolldown metadata kept as a compatibility fallback.
|
|
400
|
-
*/
|
|
401
|
-
function getIsRolldown(ctx) {
|
|
402
|
-
const viteVersion = ctx?.meta?.viteVersion;
|
|
403
|
-
const viteMajor = Number(String(viteVersion ?? "").split(".")[0]);
|
|
404
|
-
return Number.isFinite(viteMajor) && viteMajor >= 8 || !!ctx?.meta?.rolldownVersion;
|
|
405
|
-
}
|
|
406
|
-
function hasPackageDependency(dependencyName, cwd = packageDetectionCwd || process.cwd()) {
|
|
407
|
-
const cacheKey = getDependencyCacheKey(cwd, dependencyName);
|
|
408
|
-
const cached = dependencyPresenceCache.get(cacheKey);
|
|
409
|
-
if (cached !== void 0) return cached;
|
|
410
|
-
try {
|
|
411
|
-
const packageJson = JSON.parse((0, fs.readFileSync)(pathe.default.join(cwd, "package.json"), "utf8"));
|
|
412
|
-
const hasDependency = [
|
|
413
|
-
packageJson.dependencies,
|
|
414
|
-
packageJson.devDependencies,
|
|
415
|
-
packageJson.peerDependencies,
|
|
416
|
-
packageJson.optionalDependencies
|
|
417
|
-
].some((deps) => !!deps?.[dependencyName]);
|
|
418
|
-
dependencyPresenceCache.set(cacheKey, hasDependency);
|
|
419
|
-
return hasDependency;
|
|
420
|
-
} catch {
|
|
421
|
-
dependencyPresenceCache.set(cacheKey, false);
|
|
422
|
-
return false;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
//#endregion
|
|
426
172
|
//#region src/utils/normalizeModuleFederationOptions.ts
|
|
427
173
|
const INTERNAL_NAME_PREFIX = "__mfe_internal__";
|
|
428
174
|
function toInternalModuleFederationName(name) {
|
|
@@ -430,7 +176,7 @@ function toInternalModuleFederationName(name) {
|
|
|
430
176
|
}
|
|
431
177
|
function warnOnReservedInternalNamePrefix(name, kind) {
|
|
432
178
|
if (!name.startsWith(INTERNAL_NAME_PREFIX)) return;
|
|
433
|
-
mfWarn(`Reserved internal ${kind} prefix "${INTERNAL_NAME_PREFIX}" detected in public ${kind} "${name}". This prefix is reserved for internal module federation names and may cause conflicts.`);
|
|
179
|
+
require_packageUtils.mfWarn(`Reserved internal ${kind} prefix "${INTERNAL_NAME_PREFIX}" detected in public ${kind} "${name}". This prefix is reserved for internal module federation names and may cause conflicts.`);
|
|
434
180
|
}
|
|
435
181
|
function normalizeExposesItem(item) {
|
|
436
182
|
let importPath = "";
|
|
@@ -494,7 +240,7 @@ function normalizeRemoteItem(key, remote) {
|
|
|
494
240
|
* @returns {string | undefined}
|
|
495
241
|
*/
|
|
496
242
|
function searchPackageVersion(sharedName) {
|
|
497
|
-
const version = getInstalledPackageJson(sharedName
|
|
243
|
+
const version = require_packageUtils.getInstalledPackageJson(sharedName)?.packageJson.version;
|
|
498
244
|
return typeof version === "string" ? version : void 0;
|
|
499
245
|
}
|
|
500
246
|
function inferVersionFromRequiredVersion(requiredVersion) {
|
|
@@ -503,7 +249,7 @@ function inferVersionFromRequiredVersion(requiredVersion) {
|
|
|
503
249
|
}
|
|
504
250
|
function getLitExportSubpathShares(sharedName) {
|
|
505
251
|
if (sharedName !== "lit") return [];
|
|
506
|
-
const exportsField = getInstalledPackageJson(sharedName, { packageName: sharedName })?.packageJson.exports;
|
|
252
|
+
const exportsField = require_packageUtils.getInstalledPackageJson(sharedName, { packageName: sharedName })?.packageJson.exports;
|
|
507
253
|
if (!exportsField || typeof exportsField === "string") return [];
|
|
508
254
|
return Object.keys(exportsField).filter((key) => key.startsWith("./") && key !== "." && !key.includes("*")).map((key) => `${sharedName}/${key.slice(2)}`);
|
|
509
255
|
}
|
|
@@ -512,18 +258,18 @@ function normalizeShareItem(key, shareItem) {
|
|
|
512
258
|
const isImportFalse = typeof shareItem === "object" && shareItem.import === false;
|
|
513
259
|
try {
|
|
514
260
|
try {
|
|
515
|
-
version = require(pathe.join(getPackageName(key), "package.json")).version;
|
|
261
|
+
version = require(pathe.join(require_packageUtils.getPackageName(key), "package.json")).version;
|
|
516
262
|
} catch (e1) {
|
|
517
263
|
try {
|
|
518
|
-
const localPath = pathe.join(process.cwd(), "node_modules", getPackageName(key), "package.json");
|
|
264
|
+
const localPath = pathe.join(process.cwd(), "node_modules", require_packageUtils.getPackageName(key), "package.json");
|
|
519
265
|
version = require(localPath).version;
|
|
520
266
|
} catch (e2) {
|
|
521
267
|
version = searchPackageVersion(key);
|
|
522
|
-
if (!version && !isImportFalse) mfError(e1);
|
|
268
|
+
if (!version && !isImportFalse) require_packageUtils.mfError(e1);
|
|
523
269
|
}
|
|
524
270
|
}
|
|
525
271
|
} catch (e) {
|
|
526
|
-
if (!isImportFalse) mfError(`Unexpected error resolving version for ${key}:`, e);
|
|
272
|
+
if (!isImportFalse) require_packageUtils.mfError(`Unexpected error resolving version for ${key}:`, e);
|
|
527
273
|
}
|
|
528
274
|
if (typeof shareItem === "string") return {
|
|
529
275
|
name: shareItem,
|
|
@@ -553,7 +299,7 @@ function normalizeShared(shared) {
|
|
|
553
299
|
explicitSharedKeys = /* @__PURE__ */ new Set();
|
|
554
300
|
if (!shared) {
|
|
555
301
|
const result = {};
|
|
556
|
-
const packageJsonPath = pathe.join(getPackageDetectionCwd(), "package.json");
|
|
302
|
+
const packageJsonPath = pathe.join(require_packageUtils.getPackageDetectionCwd(), "package.json");
|
|
557
303
|
try {
|
|
558
304
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
559
305
|
if (packageJson.name === "@module-federation/vite") return result;
|
|
@@ -591,7 +337,7 @@ function normalizeShared(shared) {
|
|
|
591
337
|
return result;
|
|
592
338
|
}
|
|
593
339
|
function shouldAutoShareDependency(key) {
|
|
594
|
-
const pkg = getInstalledPackageJson(key)?.packageJson;
|
|
340
|
+
const pkg = require_packageUtils.getInstalledPackageJson(key)?.packageJson;
|
|
595
341
|
if (!pkg) return false;
|
|
596
342
|
if (!pkg.browser && !pkg.exports && typeof pkg.module !== "string") return false;
|
|
597
343
|
if (key === "@module-federation/vite") return false;
|
|
@@ -618,6 +364,18 @@ function normalizeManifest(manifest) {
|
|
|
618
364
|
}
|
|
619
365
|
let config;
|
|
620
366
|
let explicitSharedKeys = /* @__PURE__ */ new Set();
|
|
367
|
+
function resolveRuntimeImplementation() {
|
|
368
|
+
const fallback = require.resolve("@module-federation/runtime");
|
|
369
|
+
try {
|
|
370
|
+
const packageJsonPath = require.resolve("@module-federation/runtime/package.json");
|
|
371
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
372
|
+
const importExport = packageJson.exports?.["."];
|
|
373
|
+
const exportImport = typeof importExport === "object" ? typeof importExport.import === "string" ? importExport.import : importExport.import?.default : void 0;
|
|
374
|
+
const esmEntry = packageJson.module || exportImport;
|
|
375
|
+
if (esmEntry) return pathe.join(pathe.dirname(packageJsonPath), esmEntry);
|
|
376
|
+
} catch {}
|
|
377
|
+
return fallback;
|
|
378
|
+
}
|
|
621
379
|
function getNormalizeModuleFederationOptions() {
|
|
622
380
|
return config;
|
|
623
381
|
}
|
|
@@ -626,11 +384,11 @@ function isExplicitSharedKey(key) {
|
|
|
626
384
|
}
|
|
627
385
|
function getNormalizeShareItem(key) {
|
|
628
386
|
const options = getNormalizeModuleFederationOptions();
|
|
629
|
-
return options.shared[key] || options.shared[getPackageName(key)] || options.shared[getPackageName(key) + "/"];
|
|
387
|
+
return options.shared[key] || options.shared[require_packageUtils.getPackageName(key)] || options.shared[require_packageUtils.getPackageName(key) + "/"];
|
|
630
388
|
}
|
|
631
389
|
function normalizeModuleFederationOptions(options) {
|
|
632
390
|
warnOnReservedInternalNamePrefix(options.name, "containerName");
|
|
633
|
-
if (options.virtualModuleDir && options.virtualModuleDir.includes("/")) throw createModuleFederationError(`Invalid virtualModuleDir: "${options.virtualModuleDir}". The virtualModuleDir option cannot contain slashes (/). Please use a single directory name like '__mf__virtual__your_app_name'.`);
|
|
391
|
+
if (options.virtualModuleDir && options.virtualModuleDir.includes("/")) throw require_packageUtils.createModuleFederationError(`Invalid virtualModuleDir: "${options.virtualModuleDir}". The virtualModuleDir option cannot contain slashes (/). Please use a single directory name like '__mf__virtual__your_app_name'.`);
|
|
634
392
|
return config = {
|
|
635
393
|
exposes: normalizeExposes(options.exposes),
|
|
636
394
|
filename: options.filename || "remoteEntry-[hash]",
|
|
@@ -642,7 +400,7 @@ function normalizeModuleFederationOptions(options) {
|
|
|
642
400
|
shareScope: options.shareScope || "default",
|
|
643
401
|
shared: normalizeShared(options.shared),
|
|
644
402
|
runtimePlugins: options.runtimePlugins || [],
|
|
645
|
-
implementation: options.implementation ||
|
|
403
|
+
implementation: options.implementation || resolveRuntimeImplementation(),
|
|
646
404
|
manifest: normalizeManifest(options.manifest),
|
|
647
405
|
dev: options.dev,
|
|
648
406
|
dts: options.dts,
|
|
@@ -671,7 +429,7 @@ const patternMap = {};
|
|
|
671
429
|
const cacheMap = {};
|
|
672
430
|
function assertModuleFound(tag, str = "") {
|
|
673
431
|
const module = VirtualModule.findModule(tag, str);
|
|
674
|
-
if (!module) throw createModuleFederationError(`Module Federation shared module '${str}' not found. Please ensure it's installed as a dependency in your package.json.`);
|
|
432
|
+
if (!module) throw require_packageUtils.createModuleFederationError(`Module Federation shared module '${str}' not found. Please ensure it's installed as a dependency in your package.json.`);
|
|
675
433
|
return module;
|
|
676
434
|
}
|
|
677
435
|
var VirtualModule = class {
|
|
@@ -681,9 +439,9 @@ var VirtualModule = class {
|
|
|
681
439
|
inited = false;
|
|
682
440
|
code;
|
|
683
441
|
static findModule(tag, str = "") {
|
|
684
|
-
if (!patternMap[tag]) patternMap[tag] = new RegExp(`(.*${packageNameEncode(tag)}(.+?)${packageNameEncode(tag)}.*)`);
|
|
442
|
+
if (!patternMap[tag]) patternMap[tag] = new RegExp(`(.*${require_packageUtils.packageNameEncode(tag)}(.+?)${require_packageUtils.packageNameEncode(tag)}.*)`);
|
|
685
443
|
const moduleName = (str.match(patternMap[tag]) || [])[2];
|
|
686
|
-
if (moduleName) return cacheMap[tag][packageNameDecode(moduleName)];
|
|
444
|
+
if (moduleName) return cacheMap[tag][require_packageUtils.packageNameDecode(moduleName)];
|
|
687
445
|
}
|
|
688
446
|
static findById(id) {
|
|
689
447
|
const normalized = id.replace(/^\0+/, "").replace(/^\/@id\//, "").replace(/^__x00__/, "").replace(/[?#].*$/, "");
|
|
@@ -698,7 +456,7 @@ var VirtualModule = class {
|
|
|
698
456
|
}
|
|
699
457
|
getImportId() {
|
|
700
458
|
const { internalName: mfName } = getNormalizeModuleFederationOptions();
|
|
701
|
-
return `virtual:mf:${packageNameEncode(`${mfName}${this.tag}${this.name}${this.tag}`)}${this.suffix}`;
|
|
459
|
+
return `virtual:mf:${require_packageUtils.packageNameEncode(`${mfName}${this.tag}${this.name}${this.tag}`)}${this.suffix}`;
|
|
702
460
|
}
|
|
703
461
|
getResolvedId() {
|
|
704
462
|
return `\0${this.getImportId()}`;
|
|
@@ -856,11 +614,24 @@ function getDeferredInitPromiseCode() {
|
|
|
856
614
|
initReject = rj;
|
|
857
615
|
});`;
|
|
858
616
|
}
|
|
859
|
-
|
|
617
|
+
let _ssrRemotes = [];
|
|
618
|
+
function setSsrRemotes(remotes) {
|
|
619
|
+
_ssrRemotes = remotes;
|
|
620
|
+
}
|
|
621
|
+
function getSsrNoopResolveCode(enableSsrInit) {
|
|
622
|
+
if (!enableSsrInit) return "";
|
|
860
623
|
return `if (typeof window === 'undefined') {
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
624
|
+
var _noop = { loadRemote: function() { return Promise.resolve(undefined); }, loadShare: function() { return Promise.resolve(undefined); } };
|
|
625
|
+
import(/* @vite-ignore */ '@module-federation/runtime').then(function(runtimeMod) {
|
|
626
|
+
return import(/* @vite-ignore */ '@module-federation/vite/ssrEntryLoader').then(
|
|
627
|
+
function(loaderMod) { return [runtimeMod, [loaderMod.default()]]; },
|
|
628
|
+
function() { return [runtimeMod, []]; }
|
|
629
|
+
);
|
|
630
|
+
}).then(function(pair) {
|
|
631
|
+
var runtime = pair[0].init({ name: '__mf_ssr_host__', remotes: ${JSON.stringify(_ssrRemotes)}, shared: {}, plugins: pair[1] });
|
|
632
|
+
initResolve(runtime);
|
|
633
|
+
}, function() {
|
|
634
|
+
initResolve(_noop);
|
|
864
635
|
});
|
|
865
636
|
}`;
|
|
866
637
|
}
|
|
@@ -875,12 +646,12 @@ if (!${options.stateVar}) {
|
|
|
875
646
|
initResolve,
|
|
876
647
|
initReject,
|
|
877
648
|
};
|
|
878
|
-
${getSsrNoopResolveCode()}
|
|
649
|
+
${getSsrNoopResolveCode(options.enableSsrInit)}
|
|
879
650
|
}
|
|
880
651
|
const ${options.exposedConst} = ${options.stateVar}.${options.exposedProperty};
|
|
881
652
|
`;
|
|
882
653
|
}
|
|
883
|
-
function getRuntimeInitBootstrapCode() {
|
|
654
|
+
function getRuntimeInitBootstrapCode(enableSsrInit = false) {
|
|
884
655
|
return `
|
|
885
656
|
const globalKey = ${JSON.stringify(getRuntimeInitGlobalKey())};
|
|
886
657
|
const moduleCacheGlobalKey = ${JSON.stringify(MODULE_CACHE_GLOBAL_KEY)};
|
|
@@ -895,7 +666,7 @@ if (!globalThis[globalKey]) {
|
|
|
895
666
|
initReject,
|
|
896
667
|
moduleCache: globalThis[moduleCacheGlobalKey],
|
|
897
668
|
};
|
|
898
|
-
${getSsrNoopResolveCode()}
|
|
669
|
+
${getSsrNoopResolveCode(enableSsrInit)}
|
|
899
670
|
}
|
|
900
671
|
globalThis[globalKey].moduleCache ||= globalThis[moduleCacheGlobalKey];
|
|
901
672
|
globalThis[globalKey].moduleCache.share ||= {};
|
|
@@ -911,27 +682,29 @@ globalThis[__mfCacheGlobalKey].remote ||= {};
|
|
|
911
682
|
const __mfModuleCache = globalThis[__mfCacheGlobalKey];
|
|
912
683
|
`;
|
|
913
684
|
}
|
|
914
|
-
function getRuntimeInitPromiseBootstrapCode() {
|
|
685
|
+
function getRuntimeInitPromiseBootstrapCode(enableSsrInit = false) {
|
|
915
686
|
return getRuntimeInitStateBootstrapCode({
|
|
916
687
|
globalKeyVar: "__mfPromiseGlobalKey",
|
|
917
688
|
stateVar: "__mfPromiseState",
|
|
918
689
|
exposedConst: "initPromise",
|
|
919
|
-
exposedProperty: "initPromise"
|
|
690
|
+
exposedProperty: "initPromise",
|
|
691
|
+
enableSsrInit
|
|
920
692
|
});
|
|
921
693
|
}
|
|
922
|
-
function getRuntimeInitResolveBootstrapCode() {
|
|
694
|
+
function getRuntimeInitResolveBootstrapCode(enableSsrInit = false) {
|
|
923
695
|
return getRuntimeInitStateBootstrapCode({
|
|
924
696
|
globalKeyVar: "__mfResolveGlobalKey",
|
|
925
697
|
stateVar: "__mfResolveState",
|
|
926
698
|
exposedConst: "initResolve",
|
|
927
|
-
exposedProperty: "initResolve"
|
|
699
|
+
exposedProperty: "initResolve",
|
|
700
|
+
enableSsrInit
|
|
928
701
|
});
|
|
929
702
|
}
|
|
930
|
-
function writeRuntimeInitStatus(command) {
|
|
703
|
+
function writeRuntimeInitStatus(command, enableSsrInit = false) {
|
|
931
704
|
const exportStatement = command === "build" ? `const { initPromise, initResolve, initReject, moduleCache } = globalThis[globalKey];
|
|
932
705
|
export { initPromise, initResolve, initReject, moduleCache };` : `module.exports = globalThis[globalKey];`;
|
|
933
706
|
virtualRuntimeInitStatus.writeSync(`
|
|
934
|
-
${getRuntimeInitBootstrapCode()}
|
|
707
|
+
${getRuntimeInitBootstrapCode(enableSsrInit)}
|
|
935
708
|
${exportStatement}
|
|
936
709
|
`);
|
|
937
710
|
}
|
|
@@ -969,13 +742,13 @@ const JS_IDENTIFIER_PATTERN = `[\$_\\p{ID_Start}][\$_\\u200C\\u200D\\p{ID_Contin
|
|
|
969
742
|
const localRequire = (0, module$1.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
970
743
|
function resolvePackageEntryFromProjectRoot(pkg) {
|
|
971
744
|
try {
|
|
972
|
-
return (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`)).resolve(pkg);
|
|
745
|
+
return (0, module$1.createRequire)(new URL(`file://${pathe.default.join(require_packageUtils.getPackageDetectionCwd(), "package.json")}`)).resolve(pkg);
|
|
973
746
|
} catch {
|
|
974
747
|
return;
|
|
975
748
|
}
|
|
976
749
|
}
|
|
977
750
|
function getPackageEsmEntryPath(pkg) {
|
|
978
|
-
return getInstalledPackageEntry(pkg, {
|
|
751
|
+
return require_packageUtils.getInstalledPackageEntry(pkg, {
|
|
979
752
|
conditions: [
|
|
980
753
|
"browser",
|
|
981
754
|
"import",
|
|
@@ -1067,7 +840,7 @@ function getNamedExportsViaRegex(source, filePath, visited) {
|
|
|
1067
840
|
}
|
|
1068
841
|
function getPackageNamedExports(pkg) {
|
|
1069
842
|
try {
|
|
1070
|
-
const mod = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`))(pkg);
|
|
843
|
+
const mod = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(require_packageUtils.getPackageDetectionCwd(), "package.json")}`))(pkg);
|
|
1071
844
|
return Object.keys(mod).filter((k) => isValidEsmExportName(k));
|
|
1072
845
|
} catch {
|
|
1073
846
|
return getEsmNamedExports(pkg);
|
|
@@ -1075,10 +848,10 @@ function getPackageNamedExports(pkg) {
|
|
|
1075
848
|
}
|
|
1076
849
|
function getLocalProviderImportPath(pkg) {
|
|
1077
850
|
try {
|
|
1078
|
-
const resolved = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`)).resolve(pkg);
|
|
851
|
+
const resolved = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(require_packageUtils.getPackageDetectionCwd(), "package.json")}`)).resolve(pkg);
|
|
1079
852
|
return isWorkspaceFilePath(resolved) ? resolved : void 0;
|
|
1080
853
|
} catch {
|
|
1081
|
-
const resolved = getInstalledPackageEntry(pkg, {
|
|
854
|
+
const resolved = require_packageUtils.getInstalledPackageEntry(pkg, {
|
|
1082
855
|
conditions: [
|
|
1083
856
|
"browser",
|
|
1084
857
|
"import",
|
|
@@ -1091,12 +864,12 @@ function getLocalProviderImportPath(pkg) {
|
|
|
1091
864
|
}
|
|
1092
865
|
}
|
|
1093
866
|
function getProjectResolvedImportPath(pkg) {
|
|
1094
|
-
if (pkg === getPackageName(pkg)) {
|
|
867
|
+
if (pkg === require_packageUtils.getPackageName(pkg)) {
|
|
1095
868
|
const esmEntry = getPackageEsmEntryPath(pkg);
|
|
1096
869
|
if (esmEntry) return esmEntry;
|
|
1097
870
|
}
|
|
1098
871
|
try {
|
|
1099
|
-
return (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`)).resolve(pkg);
|
|
872
|
+
return (0, module$1.createRequire)(new URL(`file://${pathe.default.join(require_packageUtils.getPackageDetectionCwd(), "package.json")}`)).resolve(pkg);
|
|
1100
873
|
} catch {
|
|
1101
874
|
return;
|
|
1102
875
|
}
|
|
@@ -1111,8 +884,8 @@ function isWorkspaceFilePath(resolved) {
|
|
|
1111
884
|
}
|
|
1112
885
|
function isWorkspacePackageEntry(pkg, resolved) {
|
|
1113
886
|
if (!resolved || !pathe.default.isAbsolute(resolved) || !isWorkspaceFilePath(resolved)) return false;
|
|
1114
|
-
return !!getInstalledPackageJson(pkg, {
|
|
1115
|
-
packageName: getPackageName(pkg),
|
|
887
|
+
return !!require_packageUtils.getInstalledPackageJson(pkg, {
|
|
888
|
+
packageName: require_packageUtils.getPackageName(pkg),
|
|
1116
889
|
fromResolvedEntry: resolved
|
|
1117
890
|
});
|
|
1118
891
|
}
|
|
@@ -1126,7 +899,7 @@ function tryResolveImportFromPackageRoot(pkg, root) {
|
|
|
1126
899
|
function getConcreteSharedImportSource(pkg, shareItem) {
|
|
1127
900
|
const configuredImport = shareItem?.shareConfig.import;
|
|
1128
901
|
if (typeof configuredImport === "string") return configuredImport;
|
|
1129
|
-
const projectRoot = getPackageDetectionCwd();
|
|
902
|
+
const projectRoot = require_packageUtils.getPackageDetectionCwd();
|
|
1130
903
|
if (tryResolveImportFromPackageRoot(pkg, projectRoot)) return;
|
|
1131
904
|
let currentDir = pathe.default.dirname(projectRoot);
|
|
1132
905
|
while (currentDir !== pathe.default.dirname(currentDir)) {
|
|
@@ -1254,7 +1027,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
|
1254
1027
|
let exportLine;
|
|
1255
1028
|
if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg);
|
|
1256
1029
|
else {
|
|
1257
|
-
mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
|
|
1030
|
+
require_packageUtils.mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
|
|
1258
1031
|
exportLine = generateDeferredHostProvidedExports([], pkg);
|
|
1259
1032
|
}
|
|
1260
1033
|
loadShareCacheMap[pkg].writeSync(`
|
|
@@ -1317,7 +1090,7 @@ function addUsedShares(pkg) {
|
|
|
1317
1090
|
const LOCAL_SHARED_IMPORT_MAP_ID = "virtual:mf-localSharedImportMap";
|
|
1318
1091
|
function getLocalSharedImportMapPath() {
|
|
1319
1092
|
const { internalName, name } = getNormalizeModuleFederationOptions();
|
|
1320
|
-
return `${LOCAL_SHARED_IMPORT_MAP_ID}:${packageNameEncode(internalName || name)}`;
|
|
1093
|
+
return `${LOCAL_SHARED_IMPORT_MAP_ID}:${require_packageUtils.packageNameEncode(internalName || name)}`;
|
|
1321
1094
|
}
|
|
1322
1095
|
function getResolvedLocalSharedImportMapId() {
|
|
1323
1096
|
return `\0${getLocalSharedImportMapPath()}`;
|
|
@@ -1335,8 +1108,8 @@ function writeLocalSharedImportMap() {
|
|
|
1335
1108
|
}
|
|
1336
1109
|
}
|
|
1337
1110
|
function shouldUseDirectReactImport() {
|
|
1338
|
-
const isVinext = hasPackageDependency("vinext");
|
|
1339
|
-
const isAstro = hasPackageDependency("astro");
|
|
1111
|
+
const isVinext = require_packageUtils.hasPackageDependency("vinext");
|
|
1112
|
+
const isAstro = require_packageUtils.hasPackageDependency("astro");
|
|
1340
1113
|
return isVinext || isAstro;
|
|
1341
1114
|
}
|
|
1342
1115
|
function getLocalSharedPackagePath(pkg, shareItem) {
|
|
@@ -1471,7 +1244,7 @@ const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
|
|
|
1471
1244
|
let current = mod;
|
|
1472
1245
|
for (let i = 0; i < 5; i++) {
|
|
1473
1246
|
const defaultExport = current?.default;
|
|
1474
|
-
if (!defaultExport || typeof defaultExport !== "object") break;
|
|
1247
|
+
if (!defaultExport || typeof defaultExport !== "object" || Object.keys(defaultExport).length === 0) break;
|
|
1475
1248
|
const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
|
|
1476
1249
|
if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;
|
|
1477
1250
|
current = defaultExport;
|
|
@@ -1511,6 +1284,9 @@ const REMOTE_ENTRY_ID = "virtual:mf-REMOTE_ENTRY_ID";
|
|
|
1511
1284
|
function getRemoteEntryId(options) {
|
|
1512
1285
|
return `${REMOTE_ENTRY_ID}:${`${options.internalName}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
1513
1286
|
}
|
|
1287
|
+
const SSR_ONLY_PLUGIN_SPECIFIERS = new Set(["@module-federation/vite/ssrEntryLoader"]);
|
|
1288
|
+
const isSsrOnlyPlugin = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].some((s) => importStatement.includes(s));
|
|
1289
|
+
const getSsrOnlyPluginSpecifier = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].find((s) => importStatement.includes(s));
|
|
1514
1290
|
function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
|
|
1515
1291
|
const pluginImportNames = options.runtimePlugins.map((p, i) => {
|
|
1516
1292
|
if (typeof p === "string") return [
|
|
@@ -1534,7 +1310,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1534
1310
|
globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
|
|
1535
1311
|
}
|
|
1536
1312
|
import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
|
|
1537
|
-
${pluginImportNames.map((item) => item[1]).join("\n")}
|
|
1313
|
+
${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
|
|
1538
1314
|
${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
|
|
1539
1315
|
${getRuntimeModuleCacheBootstrapCode()}
|
|
1540
1316
|
const initTokens = {}
|
|
@@ -1582,11 +1358,19 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1582
1358
|
async function init(shared = {}, initScope = []) {
|
|
1583
1359
|
const {usedShared, usedRemotes} = await getLocalSharedImportMap()
|
|
1584
1360
|
${generateDirectSharedCacheSeedCode(command)}
|
|
1361
|
+
const __browserPlugins = [${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => `${item[0]}(${item[2]})`).join(", ")}];
|
|
1362
|
+
const __ssrPlugins = typeof globalThis.window === 'undefined'
|
|
1363
|
+
? await Promise.all([${pluginImportNames.filter((item) => isSsrOnlyPlugin(item[1])).map((item) => {
|
|
1364
|
+
const specifier = getSsrOnlyPluginSpecifier(item[1]);
|
|
1365
|
+
const opts = item[2];
|
|
1366
|
+
return `import(${JSON.stringify(specifier)}).then(m => (m.default ?? m)(${opts}))`;
|
|
1367
|
+
}).join(", ")}])
|
|
1368
|
+
: [];
|
|
1585
1369
|
const initRes = runtimeInit({
|
|
1586
1370
|
name: mfName,
|
|
1587
|
-
remotes: usedRemotes,
|
|
1371
|
+
remotes: ${options.shareStrategy === "loaded-first" ? "[]" : "usedRemotes"},
|
|
1588
1372
|
shared: usedShared,
|
|
1589
|
-
plugins: [
|
|
1373
|
+
plugins: [...__browserPlugins, ...__ssrPlugins],
|
|
1590
1374
|
${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
|
|
1591
1375
|
});
|
|
1592
1376
|
// handling circular init calls
|
|
@@ -1637,6 +1421,7 @@ const hostAutoInitModule = new VirtualModule("hostAutoInit", "__H_A_I__");
|
|
|
1637
1421
|
let currentHostAutoInitRemoteEntryId = REMOTE_ENTRY_ID;
|
|
1638
1422
|
let currentHostAutoInitCommand = "build";
|
|
1639
1423
|
function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
|
|
1424
|
+
const shouldPreloadShares = getNormalizeModuleFederationOptions().shareStrategy !== "loaded-first";
|
|
1640
1425
|
return `
|
|
1641
1426
|
${getRuntimeModuleCacheBootstrapCode()}
|
|
1642
1427
|
let hostInitPromise;
|
|
@@ -1648,6 +1433,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
|
|
|
1648
1433
|
const runtime = await remoteEntry.init();
|
|
1649
1434
|
const usedShared = ${generateUsedSharedPreloadConfig()};
|
|
1650
1435
|
${normalizeRuntimeShareCode}
|
|
1436
|
+
${shouldPreloadShares ? `
|
|
1651
1437
|
for (const [pkg, share] of Object.entries(usedShared)) {
|
|
1652
1438
|
if (__mfModuleCache.share[pkg] !== undefined) {
|
|
1653
1439
|
continue;
|
|
@@ -1661,6 +1447,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
|
|
|
1661
1447
|
});
|
|
1662
1448
|
});
|
|
1663
1449
|
}
|
|
1450
|
+
` : ""}
|
|
1664
1451
|
const __mfRemotePreloads = [];
|
|
1665
1452
|
await Promise.all(__mfRemotePreloads);
|
|
1666
1453
|
return runtime;
|
|
@@ -1692,12 +1479,13 @@ function getHostAutoInitPath() {
|
|
|
1692
1479
|
//#region src/virtualModules/virtualRemotes.ts
|
|
1693
1480
|
const cacheRemoteMap = {};
|
|
1694
1481
|
const LOAD_REMOTE_TAG = "__loadRemote__";
|
|
1695
|
-
function getRemoteVirtualModule(remote, command) {
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
cacheRemoteMap[
|
|
1482
|
+
function getRemoteVirtualModule(remote, command, enableSsrInit = false) {
|
|
1483
|
+
const cacheKey = `${remote}__${command}__${enableSsrInit ? "ssr" : "no-ssr"}`;
|
|
1484
|
+
if (!cacheRemoteMap[cacheKey]) {
|
|
1485
|
+
cacheRemoteMap[cacheKey] = new VirtualModule(remote, LOAD_REMOTE_TAG, ".mjs");
|
|
1486
|
+
cacheRemoteMap[cacheKey].writeSync(generateRemotes(remote, command, enableSsrInit));
|
|
1699
1487
|
}
|
|
1700
|
-
return cacheRemoteMap[
|
|
1488
|
+
return cacheRemoteMap[cacheKey];
|
|
1701
1489
|
}
|
|
1702
1490
|
const usedRemotesMap = {};
|
|
1703
1491
|
function addUsedRemote(remoteKey, remoteModule) {
|
|
@@ -1707,40 +1495,93 @@ function addUsedRemote(remoteKey, remoteModule) {
|
|
|
1707
1495
|
function getUsedRemotesMap() {
|
|
1708
1496
|
return usedRemotesMap;
|
|
1709
1497
|
}
|
|
1710
|
-
function
|
|
1711
|
-
const
|
|
1498
|
+
function getRemoteFromId(id, remotes) {
|
|
1499
|
+
const remoteName = Object.keys(remotes).filter((name) => id === name || id.startsWith(name + "/")).sort((a, b) => b.length - a.length)[0];
|
|
1500
|
+
return remoteName ? remotes[remoteName] : void 0;
|
|
1501
|
+
}
|
|
1502
|
+
function generateRemotes(id, command, enableSsrInit = false) {
|
|
1503
|
+
const useReactProxy = require_packageUtils.hasPackageDependency("react");
|
|
1504
|
+
const options = getNormalizeModuleFederationOptions();
|
|
1505
|
+
const isLoadedFirst = options.shareStrategy === "loaded-first";
|
|
1506
|
+
const remote = getRemoteFromId(id, options.remotes);
|
|
1507
|
+
const registerRemoteCode = isLoadedFirst && remote ? `runtime.registerRemotes([${JSON.stringify({
|
|
1508
|
+
entryGlobalName: remote.entryGlobalName,
|
|
1509
|
+
name: remote.name,
|
|
1510
|
+
type: remote.type,
|
|
1511
|
+
entry: remote.entry,
|
|
1512
|
+
shareScope: remote.shareScope ?? "default"
|
|
1513
|
+
})}]);` : "";
|
|
1712
1514
|
const reactImportLine = useReactProxy ? `import __mfReactDefault from "react";
|
|
1713
1515
|
import * as __mfReactNamespace from "react";
|
|
1714
1516
|
const __mfReact = __mfReactDefault ?? __mfReactNamespace.default ?? __mfReactNamespace;` : "";
|
|
1715
1517
|
const importLine = command === "build" ? `${getRuntimeModuleCacheBootstrapCode()}
|
|
1716
|
-
import { hostInitPromise as __mfHostInitPromise } from ${JSON.stringify(getHostAutoInitPath())};` : `${getRuntimeInitBootstrapCode()}
|
|
1717
|
-
const { initPromise, moduleCache: __mfModuleCache } = globalThis[globalKey]
|
|
1518
|
+
import { hostInitPromise as __mfHostInitPromise } from ${JSON.stringify(getHostAutoInitPath())};` : `${getRuntimeInitBootstrapCode(enableSsrInit)}
|
|
1519
|
+
const { initPromise, initResolve, initReject, moduleCache: __mfModuleCache } = globalThis[globalKey];
|
|
1520
|
+
if (typeof window !== "undefined") {
|
|
1521
|
+
import(${JSON.stringify(getHostAutoInitPath())})
|
|
1522
|
+
.then((mod) => mod.hostInitPromise)
|
|
1523
|
+
.then(initResolve, initReject);
|
|
1524
|
+
}`;
|
|
1718
1525
|
const exportLine = command === "serve" ? `if (__mfRemotePending) {
|
|
1719
|
-
|
|
1720
|
-
|
|
1526
|
+
__mfRemotePending = __mfRemotePending.then((mod) => {
|
|
1527
|
+
if (mod !== undefined) exportModule = mod;
|
|
1528
|
+
return exportModule;
|
|
1529
|
+
});
|
|
1721
1530
|
}
|
|
1722
|
-
export
|
|
1723
|
-
export const __mf_remote_pending = Promise.resolve(exportModule);
|
|
1531
|
+
export { exportModule as __moduleExports };
|
|
1532
|
+
export const __mf_remote_pending = __mfRemotePending || Promise.resolve(exportModule);
|
|
1724
1533
|
export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : command === "build" ? `if (__mfRemotePending) {
|
|
1725
|
-
|
|
1726
|
-
|
|
1534
|
+
__mfRemotePending = __mfRemotePending.then((mod) => {
|
|
1535
|
+
if (mod !== undefined) exportModule = mod;
|
|
1536
|
+
return exportModule;
|
|
1537
|
+
});
|
|
1727
1538
|
}
|
|
1728
|
-
export
|
|
1729
|
-
export const __mf_remote_pending = Promise.resolve(exportModule);
|
|
1539
|
+
export { exportModule as __moduleExports };
|
|
1540
|
+
export const __mf_remote_pending = __mfRemotePending || Promise.resolve(exportModule);
|
|
1730
1541
|
export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : "export default exportModule";
|
|
1542
|
+
const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise" : "initPromise";
|
|
1543
|
+
const remoteLoadFailureHandler = command === "build" ? `.catch((error) => {
|
|
1544
|
+
delete __mfModuleCache.remote[pendingKey];
|
|
1545
|
+
throw error;
|
|
1546
|
+
})` : `.catch(() => {
|
|
1547
|
+
delete __mfModuleCache.remote[pendingKey];
|
|
1548
|
+
})`;
|
|
1731
1549
|
return `
|
|
1732
1550
|
${reactImportLine}
|
|
1733
1551
|
${importLine}
|
|
1734
|
-
${
|
|
1552
|
+
${`
|
|
1553
|
+
function __mfStartRemoteLoad() {
|
|
1554
|
+
${`
|
|
1555
|
+
const pendingKey = ${JSON.stringify(`__mf_pending__${id}`)};
|
|
1556
|
+
if (!__mfModuleCache.remote[pendingKey]) {
|
|
1557
|
+
__mfModuleCache.remote[pendingKey] = ${remoteLoadRuntimePromise}
|
|
1558
|
+
.then((runtime) => {
|
|
1559
|
+
${registerRemoteCode}
|
|
1560
|
+
return runtime.loadRemote(${JSON.stringify(id)});
|
|
1561
|
+
})
|
|
1562
|
+
.then((mod) => {
|
|
1563
|
+
__mfModuleCache.remote[${JSON.stringify(id)}] = mod;
|
|
1564
|
+
delete __mfModuleCache.remote[pendingKey];
|
|
1565
|
+
return mod;
|
|
1566
|
+
})
|
|
1567
|
+
${remoteLoadFailureHandler};
|
|
1568
|
+
}
|
|
1569
|
+
return __mfModuleCache.remote[pendingKey];`}
|
|
1570
|
+
}
|
|
1735
1571
|
function __mfCreateRemoteProxy(pendingPromise) {
|
|
1736
1572
|
const listeners = new Set();
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1573
|
+
const ensurePending = () => {
|
|
1574
|
+
pendingPromise ||= __mfStartRemoteLoad();
|
|
1575
|
+
pendingPromise?.finally(() => {
|
|
1576
|
+
for (const listener of listeners) listener();
|
|
1577
|
+
});
|
|
1578
|
+
return pendingPromise;
|
|
1579
|
+
};
|
|
1740
1580
|
const getModule = () => __mfModuleCache.remote[${JSON.stringify(id)}];
|
|
1741
1581
|
const proxyTarget = function (...args) {
|
|
1742
1582
|
${useReactProxy ? `const [, setVersion] = __mfReact.useState(0);
|
|
1743
1583
|
__mfReact.useEffect(() => {
|
|
1584
|
+
ensurePending();
|
|
1744
1585
|
const listener = () => setVersion((value) => value + 1);
|
|
1745
1586
|
listeners.add(listener);
|
|
1746
1587
|
if (getModule()) listener();
|
|
@@ -1751,18 +1592,33 @@ export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?
|
|
|
1751
1592
|
if (fn !== undefined && fn !== null) {
|
|
1752
1593
|
${useReactProxy ? `return __mfReact.createElement(fn, args[0]);` : `return fn.apply(this, args);`}
|
|
1753
1594
|
}
|
|
1754
|
-
${useReactProxy ? `return null;` : `throw
|
|
1595
|
+
${useReactProxy ? `return null;` : `throw ensurePending();`}
|
|
1755
1596
|
};
|
|
1756
1597
|
return new Proxy(proxyTarget, {
|
|
1757
1598
|
get(_target, prop) {
|
|
1758
1599
|
if (prop === "__mf_is_remote_proxy") return true;
|
|
1759
1600
|
if (prop === "__esModule") return true;
|
|
1760
1601
|
if (prop === "then") return undefined;
|
|
1602
|
+
// Allow React's dev-mode console.warn to stringify the proxy without
|
|
1603
|
+
// throwing "Cannot convert object to primitive value".
|
|
1604
|
+
if (prop === Symbol.toPrimitive || prop === "toString")
|
|
1605
|
+
return () => "[MF remote proxy: pending]";
|
|
1761
1606
|
const mod = getModule();
|
|
1762
1607
|
if (mod) {
|
|
1763
1608
|
return prop in mod ? mod[prop] : mod.default?.[prop];
|
|
1764
1609
|
}
|
|
1765
|
-
|
|
1610
|
+
// When the module is pending and React.lazy() checks for "default",
|
|
1611
|
+
// return the proxy function itself so React renders it (returns null)
|
|
1612
|
+
// rather than crashing on undefined.
|
|
1613
|
+
${useReactProxy ? `if (prop === "default") return proxyTarget;
|
|
1614
|
+
return undefined;` : `throw ensurePending();`}
|
|
1615
|
+
},
|
|
1616
|
+
has(_target, prop) {
|
|
1617
|
+
const mod = getModule();
|
|
1618
|
+
if (mod) return prop in mod;
|
|
1619
|
+
// Tell React that "default" exists when module is pending so it
|
|
1620
|
+
// doesn't warn "lazy: Expected the result of a dynamic import()".
|
|
1621
|
+
${useReactProxy ? `return prop === "default" || prop === "__esModule" || prop === "__mf_is_remote_proxy";` : `return false;`}
|
|
1766
1622
|
},
|
|
1767
1623
|
ownKeys() {
|
|
1768
1624
|
const mod = getModule();
|
|
@@ -1790,40 +1646,12 @@ export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?
|
|
|
1790
1646
|
return target.apply(thisArg, args);
|
|
1791
1647
|
}
|
|
1792
1648
|
});
|
|
1793
|
-
}`
|
|
1649
|
+
}`}
|
|
1794
1650
|
let __mfRemotePending;
|
|
1795
1651
|
let exportModule = __mfModuleCache.remote[${JSON.stringify(id)}]
|
|
1796
1652
|
if (exportModule === undefined) {
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
__mfModuleCache.remote[pendingKey] = initPromise
|
|
1800
|
-
.then((runtime) => runtime.loadRemote(${JSON.stringify(id)}))
|
|
1801
|
-
.then((mod) => {
|
|
1802
|
-
__mfModuleCache.remote[${JSON.stringify(id)}] = mod;
|
|
1803
|
-
delete __mfModuleCache.remote[pendingKey];
|
|
1804
|
-
return mod;
|
|
1805
|
-
})
|
|
1806
|
-
.catch(() => {
|
|
1807
|
-
delete __mfModuleCache.remote[pendingKey];
|
|
1808
|
-
});
|
|
1809
|
-
}` : ""}
|
|
1810
|
-
${command !== "build" ? `__mfRemotePending = __mfModuleCache.remote[pendingKey];
|
|
1811
|
-
exportModule = __mfCreateRemoteProxy(__mfRemotePending);` : `const pendingKey = ${JSON.stringify(`__mf_pending__${id}`)};
|
|
1812
|
-
if (!__mfModuleCache.remote[pendingKey]) {
|
|
1813
|
-
__mfModuleCache.remote[pendingKey] = __mfHostInitPromise
|
|
1814
|
-
.then((runtime) => runtime.loadRemote(${JSON.stringify(id)}))
|
|
1815
|
-
.then((mod) => {
|
|
1816
|
-
__mfModuleCache.remote[${JSON.stringify(id)}] = mod;
|
|
1817
|
-
delete __mfModuleCache.remote[pendingKey];
|
|
1818
|
-
return mod;
|
|
1819
|
-
})
|
|
1820
|
-
.catch((error) => {
|
|
1821
|
-
delete __mfModuleCache.remote[pendingKey];
|
|
1822
|
-
throw error;
|
|
1823
|
-
});
|
|
1824
|
-
}
|
|
1825
|
-
__mfRemotePending = __mfModuleCache.remote[pendingKey];
|
|
1826
|
-
exportModule = {};`}
|
|
1653
|
+
__mfRemotePending = __mfStartRemoteLoad();
|
|
1654
|
+
exportModule = __mfCreateRemoteProxy(__mfRemotePending);
|
|
1827
1655
|
}
|
|
1828
1656
|
${exportLine}
|
|
1829
1657
|
`;
|
|
@@ -1833,7 +1661,38 @@ export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?
|
|
|
1833
1661
|
function getFirstHtmlEntryFile(entryFiles) {
|
|
1834
1662
|
return entryFiles.find((file) => file.endsWith(".html"));
|
|
1835
1663
|
}
|
|
1836
|
-
|
|
1664
|
+
function stripQueryAndHash(file) {
|
|
1665
|
+
return file.split(/[?#]/)[0];
|
|
1666
|
+
}
|
|
1667
|
+
function getBuildInput(config) {
|
|
1668
|
+
return config.build?.rollupOptions?.input ?? config.build?.rolldownOptions?.input;
|
|
1669
|
+
}
|
|
1670
|
+
function patchHashEntryFileName(output, entryName, fileName) {
|
|
1671
|
+
const originalEntryFileNames = output.entryFileNames;
|
|
1672
|
+
output.entryFileNames = (chunkInfo, ...args) => {
|
|
1673
|
+
if (chunkInfo?.name === entryName) return fileName;
|
|
1674
|
+
if (typeof originalEntryFileNames === "function") return originalEntryFileNames(chunkInfo, ...args);
|
|
1675
|
+
return originalEntryFileNames || "assets/[name]-[hash].js";
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
function patchHashEntryFileNames(config, entryName, fileName) {
|
|
1679
|
+
if (!fileName?.includes?.("[hash")) return;
|
|
1680
|
+
config.build ??= {};
|
|
1681
|
+
config.build.rollupOptions ??= {};
|
|
1682
|
+
config.build.rolldownOptions ??= {};
|
|
1683
|
+
const patchOutput = (output) => patchHashEntryFileName(output, entryName, fileName);
|
|
1684
|
+
const patchBundlerOutput = (bundlerOptions) => {
|
|
1685
|
+
const output = bundlerOptions.output;
|
|
1686
|
+
if (Array.isArray(output)) {
|
|
1687
|
+
output.forEach(patchOutput);
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1690
|
+
patchOutput(bundlerOptions.output ??= {});
|
|
1691
|
+
};
|
|
1692
|
+
patchBundlerOutput(config.build.rollupOptions);
|
|
1693
|
+
patchBundlerOutput(config.build.rolldownOptions);
|
|
1694
|
+
}
|
|
1695
|
+
const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClientInjected, skipTransformFor = [] }) => {
|
|
1837
1696
|
const DEV_HTML_PROXY_PREFIX = "virtual:mf-html-entry-proxy?";
|
|
1838
1697
|
const ENTRY_BOOTSTRAP_QUERY = "?mf-entry-bootstrap";
|
|
1839
1698
|
const waitsForInit = entryName === "hostInit";
|
|
@@ -1846,11 +1705,12 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
1846
1705
|
let viteConfig;
|
|
1847
1706
|
let clientInjected = forceClientInjected ?? false;
|
|
1848
1707
|
let emittedFileName;
|
|
1708
|
+
let skipTransformIds = /* @__PURE__ */ new Set();
|
|
1849
1709
|
function skipSvelteKitSsrBuild() {
|
|
1850
|
-
return (_command === "build" || viteConfig?.command === "build") && viteConfig?.build?.ssr && hasPackageDependency("@sveltejs/kit");
|
|
1710
|
+
return (_command === "build" || viteConfig?.command === "build") && viteConfig?.build?.ssr && require_packageUtils.hasPackageDependency("@sveltejs/kit");
|
|
1851
1711
|
}
|
|
1852
1712
|
function isSvelteKitServerModule(id) {
|
|
1853
|
-
return hasPackageDependency("@sveltejs/kit") && (id.includes(".svelte-kit/generated/") || id.includes("/@sveltejs/kit/src/runtime/server/"));
|
|
1713
|
+
return require_packageUtils.hasPackageDependency("@sveltejs/kit") && (id.includes(".svelte-kit/generated/") || id.includes("/@sveltejs/kit/src/runtime/server/"));
|
|
1854
1714
|
}
|
|
1855
1715
|
function rewriteSvelteKitInlineStart(html, initPath) {
|
|
1856
1716
|
return html.replace(/<script>([\s\S]*?)<\/script>/gi, (scriptTag, body) => {
|
|
@@ -1901,35 +1761,81 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
1901
1761
|
return patched;
|
|
1902
1762
|
}
|
|
1903
1763
|
function getBootstrapSource(initSrc, entrySrc, useSystemImportFallback = false) {
|
|
1904
|
-
const remotePreloads = Object.entries(getUsedRemotesMap()).flatMap(([remoteKey, remotes]) => Array.from(remotes).filter((remote) => remote !== remoteKey)).sort().map((remote) => `runtime.loadRemote(${JSON.stringify(remote)})`).join(",");
|
|
1905
1764
|
const importHelper = useSystemImportFallback ? `const __mfImport = (src) =>
|
|
1906
1765
|
globalThis.System && typeof globalThis.System.import === 'function'
|
|
1907
1766
|
? globalThis.System.import(src)
|
|
1908
1767
|
: import(src);
|
|
1909
1768
|
` : "";
|
|
1910
1769
|
const importExpression = (src) => useSystemImportFallback ? `__mfImport(${JSON.stringify(src)})` : `import(${JSON.stringify(src)})`;
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
const { initHost } = await ${importExpression(initSrc)};
|
|
1770
|
+
const remotePreloads = getNormalizeModuleFederationOptions()?.shareStrategy !== "loaded-first" ? Object.entries(getUsedRemotesMap()).flatMap(([remoteKey, remotes]) => Array.from(remotes).filter((remote) => remote !== remoteKey)).sort().map((remote) => `__mfPreloadRemote(${JSON.stringify(remote)})`).join(",") : "";
|
|
1771
|
+
const preloadBlock = remotePreloads ? `
|
|
1914
1772
|
const runtime = await initHost();
|
|
1773
|
+
const __mfPreloadRemote = (remote) => {
|
|
1774
|
+
const pendingKey = "__mf_pending__" + remote;
|
|
1775
|
+
if (!__mfModuleCache.remote[pendingKey]) {
|
|
1776
|
+
__mfModuleCache.remote[pendingKey] = runtime.loadRemote(remote)
|
|
1777
|
+
.then((mod) => {
|
|
1778
|
+
__mfModuleCache.remote[remote] = mod;
|
|
1779
|
+
delete __mfModuleCache.remote[pendingKey];
|
|
1780
|
+
return mod;
|
|
1781
|
+
})
|
|
1782
|
+
.catch((error) => {
|
|
1783
|
+
delete __mfModuleCache.remote[pendingKey];
|
|
1784
|
+
throw error;
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1787
|
+
return __mfModuleCache.remote[pendingKey];
|
|
1788
|
+
};
|
|
1915
1789
|
const __mfRemotePreloads = [${remotePreloads}];
|
|
1916
|
-
await Promise.
|
|
1790
|
+
await Promise.allSettled(__mfRemotePreloads);` : `await initHost();`;
|
|
1791
|
+
const importCode = `
|
|
1792
|
+
(async () => {
|
|
1793
|
+
const { initHost } = await ${importExpression(initSrc)};
|
|
1794
|
+
${preloadBlock}
|
|
1917
1795
|
})().then(() => ${importExpression(entrySrc)});
|
|
1918
1796
|
`;
|
|
1797
|
+
return [
|
|
1798
|
+
getRuntimeModuleCacheBootstrapCode(),
|
|
1799
|
+
importHelper,
|
|
1800
|
+
importCode
|
|
1801
|
+
].join("\n");
|
|
1919
1802
|
}
|
|
1920
1803
|
function getSystemBootstrapSource(initSrc, entrySrc) {
|
|
1921
1804
|
return getBootstrapSource(initSrc, entrySrc, true);
|
|
1922
1805
|
}
|
|
1923
1806
|
function injectHtml() {
|
|
1924
|
-
return inject === "html" && (htmlFilePath || hasPackageDependency("@sveltejs/kit"));
|
|
1807
|
+
return inject === "html" && (htmlFilePath || require_packageUtils.hasPackageDependency("@sveltejs/kit"));
|
|
1925
1808
|
}
|
|
1926
1809
|
function injectEntry() {
|
|
1927
|
-
if (inject === "html" && hasPackageDependency("@sveltejs/kit")) return false;
|
|
1810
|
+
if (inject === "html" && require_packageUtils.hasPackageDependency("@sveltejs/kit")) return false;
|
|
1928
1811
|
return inject === "entry" || !htmlFilePath;
|
|
1929
1812
|
}
|
|
1930
1813
|
function normalizeDevHtmlProxyId(id) {
|
|
1931
1814
|
return id.replace(/^\0/, "").replace(/^\/@id\//, "").replace(/^__x00__/, "");
|
|
1932
1815
|
}
|
|
1816
|
+
function normalizeModuleId(id) {
|
|
1817
|
+
return id.split("?")[0].replace(/\\/g, "/");
|
|
1818
|
+
}
|
|
1819
|
+
function resolveProjectId(id) {
|
|
1820
|
+
if (id.startsWith("\0") || id.startsWith("virtual:")) return normalizeModuleId(id);
|
|
1821
|
+
return normalizeModuleId(pathe.isAbsolute(id) ? id : pathe.resolve(viteConfig.root, id));
|
|
1822
|
+
}
|
|
1823
|
+
function addEntryFile(file) {
|
|
1824
|
+
const normalized = normalizeModuleId(file);
|
|
1825
|
+
if (!entryFiles.includes(normalized)) entryFiles.push(normalized);
|
|
1826
|
+
}
|
|
1827
|
+
function addHtmlScriptEntries(htmlPath) {
|
|
1828
|
+
if (!fs.existsSync(htmlPath)) return;
|
|
1829
|
+
const htmlContent = fs.readFileSync(htmlPath, "utf-8");
|
|
1830
|
+
const scriptRegex = /<script\b(?=[^>]*\btype=["']module["'])(?=[^>]*\bsrc=["']([^"']+)["'])[^>]*>/gi;
|
|
1831
|
+
let match;
|
|
1832
|
+
while ((match = scriptRegex.exec(htmlContent)) !== null) {
|
|
1833
|
+
const scriptSrc = stripQueryAndHash(match[1]);
|
|
1834
|
+
if (/^(?:[a-z]+:)?\/\//i.test(scriptSrc)) continue;
|
|
1835
|
+
addEntryFile(scriptSrc);
|
|
1836
|
+
addEntryFile(scriptSrc.startsWith("/") ? pathe.resolve(viteConfig.root, scriptSrc.slice(1)) : pathe.resolve(pathe.dirname(htmlPath), scriptSrc));
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1933
1839
|
return [{
|
|
1934
1840
|
name: "add-entry",
|
|
1935
1841
|
apply: "serve",
|
|
@@ -1946,6 +1852,7 @@ ${importHelper}(async () => {
|
|
|
1946
1852
|
const relativePath = normalized.startsWith(root + "/") ? normalized.slice(root.length) : "/" + normalized.replace(/^[A-Za-z]:[\\/]/, "");
|
|
1947
1853
|
devEntryPath = config.base + relativePath.replace(/^\//, "");
|
|
1948
1854
|
}
|
|
1855
|
+
skipTransformIds = new Set(skipTransformFor.map(resolveProjectId));
|
|
1949
1856
|
},
|
|
1950
1857
|
configureServer(server) {
|
|
1951
1858
|
server.middlewares.use((req, res, next) => {
|
|
@@ -1973,7 +1880,8 @@ ${importHelper}(async () => {
|
|
|
1973
1880
|
transformIndexHtml: {
|
|
1974
1881
|
order: "pre",
|
|
1975
1882
|
handler(c) {
|
|
1976
|
-
|
|
1883
|
+
const shouldWrapEntryHtml = _command === "serve" && inject === "entry" && waitsForInit;
|
|
1884
|
+
if (!injectHtml() && !shouldWrapEntryHtml) return;
|
|
1977
1885
|
clientInjected = true;
|
|
1978
1886
|
const base = viteConfig.base.replace(/\/$/, "");
|
|
1979
1887
|
const stripBase = (p) => base && p.startsWith(base + "/") ? p.slice(base.length) : p;
|
|
@@ -2005,24 +1913,30 @@ ${importHelper}(async () => {
|
|
|
2005
1913
|
}, {
|
|
2006
1914
|
name: "add-entry",
|
|
2007
1915
|
enforce: "post",
|
|
1916
|
+
applyToEnvironment() {
|
|
1917
|
+
return true;
|
|
1918
|
+
},
|
|
1919
|
+
config(config) {
|
|
1920
|
+
patchHashEntryFileNames(config, entryName, fileName);
|
|
1921
|
+
},
|
|
2008
1922
|
configResolved(config) {
|
|
2009
1923
|
viteConfig = config;
|
|
2010
|
-
|
|
1924
|
+
skipTransformIds = new Set(skipTransformFor.map(resolveProjectId));
|
|
1925
|
+
const ctx = this;
|
|
1926
|
+
const envName = ctx != null && typeof ctx === "object" ? ctx["environment"] : void 0;
|
|
1927
|
+
if (envName?.name && envName.name !== "client") return;
|
|
1928
|
+
const inputOptions = getBuildInput(config);
|
|
2011
1929
|
if (!inputOptions) htmlFilePath = pathe.resolve(config.root, "index.html");
|
|
2012
|
-
else if (typeof inputOptions === "string") entryFiles = [inputOptions];
|
|
2013
|
-
else if (Array.isArray(inputOptions)) entryFiles = inputOptions;
|
|
2014
|
-
else if (typeof inputOptions === "object") entryFiles = Object.values(inputOptions);
|
|
1930
|
+
else if (typeof inputOptions === "string") entryFiles = [normalizeModuleId(inputOptions)];
|
|
1931
|
+
else if (Array.isArray(inputOptions)) entryFiles = inputOptions.map(normalizeModuleId);
|
|
1932
|
+
else if (typeof inputOptions === "object") entryFiles = Object.values(inputOptions).map((input) => normalizeModuleId(String(input)));
|
|
2015
1933
|
if (entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles);
|
|
2016
|
-
if (
|
|
2017
|
-
const htmlContent = fs.readFileSync(htmlFilePath, "utf-8");
|
|
2018
|
-
const scriptRegex = /<script\s+[^>]*src=["']([^"']+)["'][^>]*>/gi;
|
|
2019
|
-
let match;
|
|
2020
|
-
while ((match = scriptRegex.exec(htmlContent)) !== null) entryFiles.push(match[1]);
|
|
2021
|
-
}
|
|
1934
|
+
if (htmlFilePath) addHtmlScriptEntries(htmlFilePath);
|
|
2022
1935
|
},
|
|
2023
1936
|
buildStart() {
|
|
2024
1937
|
if (_command === "serve") return;
|
|
2025
1938
|
if (skipSvelteKitSsrBuild()) return;
|
|
1939
|
+
if (this.environment?.name === "ssr") return;
|
|
2026
1940
|
const hasHash = fileName?.includes?.("[hash");
|
|
2027
1941
|
const emitFileOptions = {
|
|
2028
1942
|
name: entryName,
|
|
@@ -2032,16 +1946,14 @@ ${importHelper}(async () => {
|
|
|
2032
1946
|
};
|
|
2033
1947
|
if (!hasHash) emitFileOptions.fileName = fileName;
|
|
2034
1948
|
emitFileId = this.emitFile(emitFileOptions);
|
|
2035
|
-
if (htmlFilePath
|
|
2036
|
-
const htmlContent = fs.readFileSync(htmlFilePath, "utf-8");
|
|
2037
|
-
const scriptRegex = /<script\s+[^>]*src=["']([^"']+)["'][^>]*>/gi;
|
|
2038
|
-
let match;
|
|
2039
|
-
while ((match = scriptRegex.exec(htmlContent)) !== null) entryFiles.push(match[1]);
|
|
2040
|
-
}
|
|
1949
|
+
if (htmlFilePath) addHtmlScriptEntries(htmlFilePath);
|
|
2041
1950
|
},
|
|
2042
1951
|
generateBundle(_options, bundle) {
|
|
2043
1952
|
if (skipSvelteKitSsrBuild()) return;
|
|
2044
1953
|
if (!injectHtml()) return;
|
|
1954
|
+
if (!emitFileId) return;
|
|
1955
|
+
const htmlFileNames = Object.keys(bundle).filter((fileName) => fileName.endsWith(".html"));
|
|
1956
|
+
if (htmlFileNames.length === 0) return;
|
|
2045
1957
|
const file = this.getFileName(emitFileId);
|
|
2046
1958
|
emittedFileName = file;
|
|
2047
1959
|
const resolvePath = (htmlFileName) => {
|
|
@@ -2055,7 +1967,7 @@ ${importHelper}(async () => {
|
|
|
2055
1967
|
if (typeof result === "string") return result;
|
|
2056
1968
|
if (result && typeof result === "object") {
|
|
2057
1969
|
if ("runtime" in result) {
|
|
2058
|
-
mfWarn("renderBuiltUrl returned runtime code for HTML injection. Runtime code cannot be used in <script src=\"\">. Falling back to base path.");
|
|
1970
|
+
require_packageUtils.mfWarn("renderBuiltUrl returned runtime code for HTML injection. Runtime code cannot be used in <script src=\"\">. Falling back to base path.");
|
|
2059
1971
|
return viteConfig.base + file;
|
|
2060
1972
|
}
|
|
2061
1973
|
if (result.relative) return file;
|
|
@@ -2063,7 +1975,7 @@ ${importHelper}(async () => {
|
|
|
2063
1975
|
return viteConfig.base + file;
|
|
2064
1976
|
};
|
|
2065
1977
|
let bootstrapIndex = 0;
|
|
2066
|
-
for (const fileName
|
|
1978
|
+
for (const fileName of htmlFileNames) {
|
|
2067
1979
|
let htmlAsset = bundle[fileName];
|
|
2068
1980
|
if (htmlAsset.type === "chunk") return;
|
|
2069
1981
|
let htmlContent = htmlAsset.source.toString() || "";
|
|
@@ -2108,7 +2020,12 @@ ${importHelper}(async () => {
|
|
|
2108
2020
|
if (skipSvelteKitSsrBuild()) return;
|
|
2109
2021
|
if (isSvelteKitServerModule(id)) return;
|
|
2110
2022
|
if (id.includes(ENTRY_BOOTSTRAP_QUERY)) return;
|
|
2111
|
-
|
|
2023
|
+
if (normalizeModuleId(id).endsWith(".html")) return;
|
|
2024
|
+
if (skipTransformIds.has(resolveProjectId(id))) return;
|
|
2025
|
+
const transformCtx = this;
|
|
2026
|
+
const transformEnv = transformCtx != null && typeof transformCtx === "object" ? transformCtx["environment"] : void 0;
|
|
2027
|
+
if (transformEnv?.name && transformEnv.name !== "client") return;
|
|
2028
|
+
const isVinext = require_packageUtils.hasPackageDependency("vinext");
|
|
2112
2029
|
if (isVinext && inject === "html" && id.includes("virtual:vite-rsc/remove-duplicate-server-css")) {
|
|
2113
2030
|
const namespaceReactImport = `import * as React from 'react';`;
|
|
2114
2031
|
if (code.includes(namespaceReactImport)) return;
|
|
@@ -2124,9 +2041,16 @@ ${importHelper}(async () => {
|
|
|
2124
2041
|
clientInjected = true;
|
|
2125
2042
|
return mapCodeToCodeWithSourcemap(injection + code);
|
|
2126
2043
|
}
|
|
2127
|
-
if (
|
|
2044
|
+
if (_command === "serve" && inject === "entry" && waitsForInit && !clientInjected && /(?:^|\/)nuxt\/dist\/app\/entry\.js(?:\?|$)/.test(id) && code.includes("vueApp.mount(vueAppRootContainer);")) {
|
|
2128
2045
|
clientInjected = true;
|
|
2129
|
-
|
|
2046
|
+
const injection = `await import(${JSON.stringify(getEntryPath())}).then(({ initHost }) => initHost());\n `;
|
|
2047
|
+
return mapCodeToCodeWithSourcemap(code.replace("vueApp.mount(vueAppRootContainer);", `${injection}vueApp.mount(vueAppRootContainer);`));
|
|
2048
|
+
}
|
|
2049
|
+
const isHydrationEntryFallback = inject === "entry" && entryFiles.length === 0 && (!htmlFilePath || !fs.existsSync(htmlFilePath)) && !clientInjected && !id.includes("node_modules") && (id.startsWith("\0") || /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id)) && /hydrateRoot|createRoot|ReactDOM\.render/.test(code);
|
|
2050
|
+
const isNuxtClientEntryFallback = _command === "serve" && inject === "entry" && entryFiles.length === 0 && (!htmlFilePath || !fs.existsSync(htmlFilePath)) && !clientInjected && !id.includes("node_modules/.vite") && /(?:^|\/)nuxt\/dist\/app\/entry\.async\.js(?:\?|$)/.test(id) && code.includes("entry();");
|
|
2051
|
+
if (injectEntry() && entryFiles.some((file) => resolveProjectId(id) === file) || _command === "serve" && inject === "html" && !isVinext && !clientInjected && !id.startsWith("\0") && !id.includes("node_modules") && /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id) || isHydrationEntryFallback || isNuxtClientEntryFallback) {
|
|
2052
|
+
clientInjected = true;
|
|
2053
|
+
if (!waitsForInit || _command === "serve" && inject === "entry" && isHydrationEntryFallback) return mapCodeToCodeWithSourcemap(`import ${JSON.stringify(getEntryPath())};\n` + code);
|
|
2130
2054
|
const entrySrc = id.includes("?") ? `${id}&${ENTRY_BOOTSTRAP_QUERY.slice(1)}` : `${id}${ENTRY_BOOTSTRAP_QUERY}`;
|
|
2131
2055
|
return mapCodeToCodeWithSourcemap(getBootstrapSource(getEntryPath(), entrySrc));
|
|
2132
2056
|
}
|
|
@@ -2159,7 +2083,7 @@ function checkAliasConflicts(options) {
|
|
|
2159
2083
|
if (!matchesSharedKey(aliasEntry, sharedKey)) continue;
|
|
2160
2084
|
if (replacement === "$1") break;
|
|
2161
2085
|
if (typeof replacement === "string") {
|
|
2162
|
-
if (getPackageNameFromNodeModulePath(replacement) === (sharedKey.endsWith("/") ? sharedKey.slice(0, -1) : sharedKey)) continue;
|
|
2086
|
+
if (require_packageUtils.getPackageNameFromNodeModulePath(replacement) === (sharedKey.endsWith("/") ? sharedKey.slice(0, -1) : sharedKey)) continue;
|
|
2163
2087
|
conflicts.push({
|
|
2164
2088
|
sharedModule: sharedKey,
|
|
2165
2089
|
alias: String(aliasEntry.find),
|
|
@@ -2168,21 +2092,17 @@ function checkAliasConflicts(options) {
|
|
|
2168
2092
|
}
|
|
2169
2093
|
}
|
|
2170
2094
|
if (conflicts.length > 0) {
|
|
2171
|
-
mfWarn("Detected alias conflicts with shared modules:");
|
|
2095
|
+
require_packageUtils.mfWarn("Detected alias conflicts with shared modules:");
|
|
2172
2096
|
conflicts.forEach(({ sharedModule, alias, target }) => {
|
|
2173
|
-
mfWarn(`Shared module "${sharedModule}" is aliased by "${alias}" to "${target}"`);
|
|
2097
|
+
require_packageUtils.mfWarn(`Shared module "${sharedModule}" is aliased by "${alias}" to "${target}"`);
|
|
2174
2098
|
});
|
|
2175
|
-
mfWarn("This may cause runtime errors as the shared module will bypass Module Federation's sharing mechanism.");
|
|
2099
|
+
require_packageUtils.mfWarn("This may cause runtime errors as the shared module will bypass Module Federation's sharing mechanism.");
|
|
2176
2100
|
}
|
|
2177
2101
|
}
|
|
2178
2102
|
};
|
|
2179
2103
|
}
|
|
2180
2104
|
//#endregion
|
|
2181
|
-
//#region src/plugins/
|
|
2182
|
-
const REMOTE_HMR_ENDPOINT = "__mf_hmr";
|
|
2183
|
-
const REMOTE_HMR_EVENT = "mf:remote-update";
|
|
2184
|
-
const REMOTE_HMR_CONNECT_RETRY_DELAY_MS = 1e3;
|
|
2185
|
-
const REMOTE_HMR_CONNECT_MAX_RETRIES = 10;
|
|
2105
|
+
//#region src/plugins/hmr/react.ts
|
|
2186
2106
|
/**
|
|
2187
2107
|
* Proxy module served for `/@react-refresh` on MF remote dev servers.
|
|
2188
2108
|
* Delegates to the host page's RefreshRuntime instance via
|
|
@@ -2202,6 +2122,112 @@ const REACT_REFRESH_PROXY_MODULE = [
|
|
|
2202
2122
|
`export const __hmr_import = __rt.__hmr_import;`,
|
|
2203
2123
|
`export default __rt.default || __rt;`
|
|
2204
2124
|
].join("\n");
|
|
2125
|
+
const reactAdapter = {
|
|
2126
|
+
name: "react",
|
|
2127
|
+
pluginNames: ["vite:react-refresh", "vite:react-swc:refresh"],
|
|
2128
|
+
remote: { configureServer({ server }) {
|
|
2129
|
+
server.middlewares.use((req, res, next) => {
|
|
2130
|
+
if (req.url?.replace(/\?.*$/, "") !== "/@react-refresh") return next();
|
|
2131
|
+
res.setHeader("Content-Type", "application/javascript; charset=utf-8");
|
|
2132
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
2133
|
+
res.end(REACT_REFRESH_PROXY_MODULE);
|
|
2134
|
+
});
|
|
2135
|
+
} }
|
|
2136
|
+
};
|
|
2137
|
+
//#endregion
|
|
2138
|
+
//#region src/plugins/hmr/vue.ts
|
|
2139
|
+
/**
|
|
2140
|
+
* In dev mode each Vite dev server serves its own copy of Vue
|
|
2141
|
+
* (`/node_modules/.vite/deps/vue.js`). When a remote module is loaded into the
|
|
2142
|
+
* host page, the remote's Vue copy evaluates and runs:
|
|
2143
|
+
*
|
|
2144
|
+
* globalThis.__VUE_HMR_RUNTIME__ = createHotReloadAPI()
|
|
2145
|
+
*
|
|
2146
|
+
* which silently overwrites the host's runtime. After that, `createRecord` for
|
|
2147
|
+
* host components lives in the orphaned first runtime, but `reload(hmrId, ...)`
|
|
2148
|
+
* goes through the second runtime — the lookup misses and HMR stops working.
|
|
2149
|
+
*
|
|
2150
|
+
* This guard pins `__VUE_HMR_RUNTIME__` to the first writer (the host's Vue)
|
|
2151
|
+
* via a property trap on `globalThis`. Subsequent writes from remote-side Vue
|
|
2152
|
+
* copies are silently dropped. Must execute before any Vue module loads —
|
|
2153
|
+
* injected as a plain (non-module) script at `head-prepend`.
|
|
2154
|
+
*
|
|
2155
|
+
* `singleton: true` in `shared` is not sufficient: in dev mode MF's share-scope
|
|
2156
|
+
* does not actually dedupe Vue across dev servers, so without this guard the
|
|
2157
|
+
* last-loaded copy wins.
|
|
2158
|
+
*/
|
|
2159
|
+
const VUE_HMR_RUNTIME_GUARD_SCRIPT = `
|
|
2160
|
+
(function () {
|
|
2161
|
+
var h = null;
|
|
2162
|
+
Object.defineProperty(globalThis, '__VUE_HMR_RUNTIME__', {
|
|
2163
|
+
get: function () { return h; },
|
|
2164
|
+
set: function (v) { if (h === null) h = v; },
|
|
2165
|
+
configurable: true,
|
|
2166
|
+
enumerable: true,
|
|
2167
|
+
});
|
|
2168
|
+
})();`;
|
|
2169
|
+
/**
|
|
2170
|
+
* `@vitejs/plugin-vue` derives an SFC's `__hmrId` from a hash of the file path
|
|
2171
|
+
* relative to Vite's `root`. With module federation, host and remote are
|
|
2172
|
+
* separate Vite projects with independent roots — so an SFC at `src/App.vue`
|
|
2173
|
+
* in both will hash to the same id. Once both copies of Vue collapse onto the
|
|
2174
|
+
* shared `__VUE_HMR_RUNTIME__` (see the guard above), the host's instance and
|
|
2175
|
+
* the remote's instance both register under that single id. A remote-only
|
|
2176
|
+
* file change then calls `rerender(id, newRender)`, which iterates *every*
|
|
2177
|
+
* instance under that id — including the host one — and applies the remote's
|
|
2178
|
+
* render function to the host instance. The host's `setupState` doesn't have
|
|
2179
|
+
* the remote's bindings, so the render throws and Vue falls back to a full
|
|
2180
|
+
* reload required warning.
|
|
2181
|
+
*
|
|
2182
|
+
* Fix: rewrite the remote's emitted `__hmrId` literal to be prefixed with the
|
|
2183
|
+
* federation `name`, so the remote's instances live under a distinct key. The
|
|
2184
|
+
* accept callback emitted by plugin-vue reads `_sfc_main.__hmrId` /
|
|
2185
|
+
* `updated.__hmrId` at runtime, so rewriting the literal once is enough.
|
|
2186
|
+
*/
|
|
2187
|
+
const SFC_HMR_ID_LITERAL_RE = /(\.__hmrId\s*=\s*["'`])([^"'`]+)(["'`])/g;
|
|
2188
|
+
function rewriteSfcHmrId(code, federationName) {
|
|
2189
|
+
let matched = false;
|
|
2190
|
+
return {
|
|
2191
|
+
code: code.replace(SFC_HMR_ID_LITERAL_RE, (_match, prefix, id, suffix) => {
|
|
2192
|
+
matched = true;
|
|
2193
|
+
if (id.startsWith(`${federationName}-`)) return `${prefix}${id}${suffix}`;
|
|
2194
|
+
return `${prefix}${federationName}-${id}${suffix}`;
|
|
2195
|
+
}),
|
|
2196
|
+
matched
|
|
2197
|
+
};
|
|
2198
|
+
}
|
|
2199
|
+
let pluginVueRegressionWarned = false;
|
|
2200
|
+
function warnPluginVueRegression() {
|
|
2201
|
+
if (pluginVueRegressionWarned) return;
|
|
2202
|
+
pluginVueRegressionWarned = true;
|
|
2203
|
+
require_packageUtils.mfWarn("Detected a Vue SFC module that calls `__VUE_HMR_RUNTIME__.createRecord(` but no `.__hmrId = \"...\"` literal could be rewritten. @vitejs/plugin-vue may have changed its output format — without the rewrite, host and remote SFCs that share a path will collide on the shared HMR runtime. Please report this to @module-federation/vite.");
|
|
2204
|
+
}
|
|
2205
|
+
const vueAdapter = {
|
|
2206
|
+
name: "vue",
|
|
2207
|
+
pluginNames: ["vite:vue", "vite:vue-jsx"],
|
|
2208
|
+
host: { transformIndexHtml() {
|
|
2209
|
+
return [{
|
|
2210
|
+
tag: "script",
|
|
2211
|
+
children: VUE_HMR_RUNTIME_GUARD_SCRIPT,
|
|
2212
|
+
injectTo: "head-prepend"
|
|
2213
|
+
}];
|
|
2214
|
+
} },
|
|
2215
|
+
remote: { transform(code, _id, ctx) {
|
|
2216
|
+
if (!code.includes("__VUE_HMR_RUNTIME__.createRecord(")) return;
|
|
2217
|
+
const { code: rewritten, matched } = rewriteSfcHmrId(code, ctx.options.name);
|
|
2218
|
+
if (!matched) {
|
|
2219
|
+
warnPluginVueRegression();
|
|
2220
|
+
return;
|
|
2221
|
+
}
|
|
2222
|
+
return rewritten === code ? void 0 : rewritten;
|
|
2223
|
+
} }
|
|
2224
|
+
};
|
|
2225
|
+
//#endregion
|
|
2226
|
+
//#region src/plugins/hmr/fullReload.ts
|
|
2227
|
+
const REMOTE_HMR_ENDPOINT = "__mf_hmr";
|
|
2228
|
+
const REMOTE_HMR_EVENT = "mf:remote-update";
|
|
2229
|
+
const REMOTE_HMR_CONNECT_RETRY_DELAY_MS = 1e3;
|
|
2230
|
+
const REMOTE_HMR_CONNECT_MAX_RETRIES = 10;
|
|
2205
2231
|
function getBasePath$1(base) {
|
|
2206
2232
|
if (!base) return "/";
|
|
2207
2233
|
if (base.startsWith("http://") || base.startsWith("https://")) try {
|
|
@@ -2220,9 +2246,6 @@ function getHmrWsPath(base, hmrPath) {
|
|
|
2220
2246
|
if (!normalizedPath || normalizedPath === "/") return normalizedBase;
|
|
2221
2247
|
return `${normalizedBase.endsWith("/") ? normalizedBase.slice(0, -1) : normalizedBase}/${normalizedPath.startsWith("/") ? normalizedPath.slice(1) : normalizedPath}`;
|
|
2222
2248
|
}
|
|
2223
|
-
function shouldIgnoreFile(file, options) {
|
|
2224
|
-
return file.includes("/node_modules/") || file.includes("\\node_modules\\") || file.includes(`/${options.virtualModuleDir}/`) || file.includes(`\\${options.virtualModuleDir}\\`) || file.includes("/.vite/") || file.includes("\\.vite\\") || file.includes("/.mf/") || file.includes("\\.mf\\") || file.includes("/mf-manifest.json") || file.includes("\\mf-manifest.json") || file.includes("/mf-stats.json") || file.includes("\\mf-stats.json");
|
|
2225
|
-
}
|
|
2226
2249
|
function getRemoteHmrWsUrl(server) {
|
|
2227
2250
|
const hmr = server.config.server.hmr;
|
|
2228
2251
|
return `${hmr && typeof hmr === "object" && hmr.protocol ? hmr.protocol : server.config.server.https ? "wss" : "ws"}://${hmr && typeof hmr === "object" && hmr.host ? hmr.host : typeof server.config.server.host === "string" && server.config.server.host !== "0.0.0.0" ? server.config.server.host : "localhost"}:${hmr && typeof hmr === "object" && (hmr.clientPort || hmr.port) ? hmr.clientPort || hmr.port : server.config.server.port}${getHmrWsPath(server.config.base, hmr && typeof hmr === "object" ? hmr.path : "")}?token=${server.config.webSocketToken}`;
|
|
@@ -2261,466 +2284,275 @@ function getStringPreview(value, max = 180) {
|
|
|
2261
2284
|
} catch {}
|
|
2262
2285
|
return rawValue.slice(0, max);
|
|
2263
2286
|
}
|
|
2264
|
-
|
|
2265
|
-
|
|
2287
|
+
/**
|
|
2288
|
+
* Installs the `/__mf_hmr` metadata endpoint on a remote dev server. The host
|
|
2289
|
+
* fetches this to discover the remote's HMR WebSocket URL before opening a
|
|
2290
|
+
* Node-to-Node relay socket. Always installed on remotes when `remoteHmr` is
|
|
2291
|
+
* enabled — under `'native'` strategy the endpoint is unused but harmless;
|
|
2292
|
+
* under `'full-reload'` it's the discovery hop for the host relay.
|
|
2293
|
+
*/
|
|
2294
|
+
function setupRemoteMetadataEndpoint(server, options) {
|
|
2295
|
+
const endpointPath = getRemoteHmrPath(server.config.base);
|
|
2296
|
+
const wsUrl = getRemoteHmrWsUrl(server);
|
|
2297
|
+
server.middlewares.use((req, res, next) => {
|
|
2298
|
+
if (req.url?.replace(/\?.*/, "") !== endpointPath) {
|
|
2299
|
+
next();
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
res.setHeader("Content-Type", "application/json");
|
|
2303
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
2304
|
+
res.end(JSON.stringify({
|
|
2305
|
+
remote: options.name,
|
|
2306
|
+
event: REMOTE_HMR_EVENT,
|
|
2307
|
+
wsUrl
|
|
2308
|
+
}));
|
|
2309
|
+
});
|
|
2266
2310
|
}
|
|
2267
2311
|
/**
|
|
2268
|
-
*
|
|
2269
|
-
*
|
|
2270
|
-
*
|
|
2312
|
+
* Installs file-watcher broadcasts on a remote dev server. Every non-ignored
|
|
2313
|
+
* change/add/unlink emits a `mf:remote-update` custom event on the remote's
|
|
2314
|
+
* own WS channel. The host relay (see `setupHostFullReloadRelay`) listens
|
|
2315
|
+
* for these events and triggers a host-side full reload in response.
|
|
2271
2316
|
*
|
|
2272
|
-
*
|
|
2317
|
+
* Only called under the `'full-reload'` strategy.
|
|
2273
2318
|
*/
|
|
2274
|
-
function
|
|
2275
|
-
const
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
name: "module-federation-dev-remote-hmr",
|
|
2285
|
-
apply: "serve",
|
|
2286
|
-
configureServer(server) {
|
|
2287
|
-
if (!isRemoteHmrEnabled(options.dev)) return;
|
|
2288
|
-
const isRemote = Object.keys(options.exposes).length > 0;
|
|
2289
|
-
const isHost = Object.keys(options.remotes).length > 0;
|
|
2290
|
-
const strategy = resolveHmrStrategy(options.dev, server.config.plugins);
|
|
2291
|
-
if (isRemote) {
|
|
2292
|
-
const endpointPath = getRemoteHmrPath(server.config.base);
|
|
2293
|
-
const wsUrl = getRemoteHmrWsUrl(server);
|
|
2294
|
-
server.middlewares.use((req, res, next) => {
|
|
2295
|
-
if (req.url?.replace(/\?.*$/, "") !== "/@react-refresh") return next();
|
|
2296
|
-
res.setHeader("Content-Type", "application/javascript; charset=utf-8");
|
|
2297
|
-
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
2298
|
-
res.end(REACT_REFRESH_PROXY_MODULE);
|
|
2299
|
-
});
|
|
2300
|
-
server.middlewares.use((req, res, next) => {
|
|
2301
|
-
if (req.url?.replace(/\?.*/, "") !== endpointPath) {
|
|
2302
|
-
next();
|
|
2303
|
-
return;
|
|
2304
|
-
}
|
|
2305
|
-
res.setHeader("Content-Type", "application/json");
|
|
2306
|
-
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
2307
|
-
res.end(JSON.stringify({
|
|
2308
|
-
remote: options.name,
|
|
2309
|
-
event: REMOTE_HMR_EVENT,
|
|
2310
|
-
wsUrl
|
|
2311
|
-
}));
|
|
2312
|
-
});
|
|
2313
|
-
const broadcast = (file) => {
|
|
2314
|
-
if (strategy === "native") return;
|
|
2315
|
-
if (shouldIgnoreFile(file, options)) return;
|
|
2316
|
-
server.ws.send({
|
|
2317
|
-
type: "custom",
|
|
2318
|
-
event: REMOTE_HMR_EVENT,
|
|
2319
|
-
data: {
|
|
2320
|
-
remote: options.name,
|
|
2321
|
-
file,
|
|
2322
|
-
ts: Date.now()
|
|
2323
|
-
}
|
|
2324
|
-
});
|
|
2325
|
-
};
|
|
2326
|
-
server.watcher.on("change", broadcast);
|
|
2327
|
-
server.watcher.on("add", broadcast);
|
|
2328
|
-
server.watcher.on("unlink", broadcast);
|
|
2329
|
-
server.httpServer?.once("close", () => {
|
|
2330
|
-
server.watcher.off("change", broadcast);
|
|
2331
|
-
server.watcher.off("add", broadcast);
|
|
2332
|
-
server.watcher.off("unlink", broadcast);
|
|
2333
|
-
});
|
|
2334
|
-
}
|
|
2335
|
-
if (isHost) {
|
|
2336
|
-
const connections = [];
|
|
2337
|
-
const reconnectTimers = /* @__PURE__ */ new Map();
|
|
2338
|
-
let isTearingDown = false;
|
|
2339
|
-
const clearReconnectTimer = (remoteName) => {
|
|
2340
|
-
const timer = reconnectTimers.get(remoteName);
|
|
2341
|
-
if (!timer) return;
|
|
2342
|
-
clearTimeout(timer);
|
|
2343
|
-
reconnectTimers.delete(remoteName);
|
|
2344
|
-
};
|
|
2345
|
-
const scheduleReconnect = (remoteName, remote, attempt, reason) => {
|
|
2346
|
-
if (isTearingDown) return;
|
|
2347
|
-
if (attempt >= REMOTE_HMR_CONNECT_MAX_RETRIES) {
|
|
2348
|
-
mfWarn(`Remote "${remoteName}" full HMR reconnect skipped after ${REMOTE_HMR_CONNECT_MAX_RETRIES} attempts: ${reason}`);
|
|
2349
|
-
return;
|
|
2350
|
-
}
|
|
2351
|
-
clearReconnectTimer(remoteName);
|
|
2352
|
-
const timer = setTimeout(() => {
|
|
2353
|
-
reconnectTimers.delete(remoteName);
|
|
2354
|
-
connectRemote(remoteName, remote, attempt + 1);
|
|
2355
|
-
}, REMOTE_HMR_CONNECT_RETRY_DELAY_MS);
|
|
2356
|
-
reconnectTimers.set(remoteName, timer);
|
|
2357
|
-
};
|
|
2358
|
-
const connectRemote = async (remoteName, remote, attempt = 0) => {
|
|
2359
|
-
if (isTearingDown) return;
|
|
2360
|
-
const endpoint = getRemoteHmrEndpoint(remote.entry, server);
|
|
2361
|
-
if (!endpoint) {
|
|
2362
|
-
mfWarn(`Failed to build HMR endpoint URL for remote "${remoteName}"`);
|
|
2363
|
-
return;
|
|
2364
|
-
}
|
|
2365
|
-
try {
|
|
2366
|
-
const metadataResponse = await fetch(endpoint);
|
|
2367
|
-
if (!metadataResponse.ok) {
|
|
2368
|
-
mfWarn(`Failed to fetch remote HMR metadata from "${remoteName}": ${metadataResponse.status}`);
|
|
2369
|
-
scheduleReconnect(remoteName, remote, attempt, `HTTP ${metadataResponse.status}`);
|
|
2370
|
-
return;
|
|
2371
|
-
}
|
|
2372
|
-
const metadata = await metadataResponse.json();
|
|
2373
|
-
if (metadata.event !== REMOTE_HMR_EVENT || !metadata.wsUrl) {
|
|
2374
|
-
mfWarn(`Remote "${remoteName}" returned unexpected HMR metadata shape`);
|
|
2375
|
-
return;
|
|
2376
|
-
}
|
|
2377
|
-
const ws = new WebSocket(metadata.wsUrl, "vite-hmr");
|
|
2378
|
-
ws.onmessage = (rawEvent) => {
|
|
2379
|
-
if (strategy === "native") return;
|
|
2380
|
-
const message = parseRemoteHmrMessage(rawEvent.data);
|
|
2381
|
-
if (!message || message.event !== REMOTE_HMR_EVENT) return;
|
|
2382
|
-
server.ws.send({ type: "full-reload" });
|
|
2383
|
-
};
|
|
2384
|
-
ws.onopen = () => clearReconnectTimer(remoteName);
|
|
2385
|
-
ws.onerror = (error) => mfWarn(`Remote HMR socket error for "${remoteName}":`, error);
|
|
2386
|
-
ws.onclose = () => scheduleReconnect(remoteName, remote, attempt, "socket closed");
|
|
2387
|
-
connections.push(ws);
|
|
2388
|
-
} catch (error) {
|
|
2389
|
-
mfWarn(`Failed to connect remote HMR for "${remoteName}" on attempt ${attempt + 1}: ${getStringPreview(error)}`);
|
|
2390
|
-
scheduleReconnect(remoteName, remote, attempt, getStringPreview(error));
|
|
2391
|
-
}
|
|
2392
|
-
};
|
|
2393
|
-
const teardown = () => {
|
|
2394
|
-
isTearingDown = true;
|
|
2395
|
-
reconnectTimers.forEach((timer) => clearTimeout(timer));
|
|
2396
|
-
reconnectTimers.clear();
|
|
2397
|
-
connections.forEach((connection) => {
|
|
2398
|
-
if (connection.readyState !== connection.CLOSING && connection.readyState !== connection.CLOSED) connection.close();
|
|
2399
|
-
});
|
|
2400
|
-
connections.length = 0;
|
|
2401
|
-
};
|
|
2402
|
-
for (const [remoteName, remote] of Object.entries(options.remotes)) connectRemote(remoteName, remote);
|
|
2403
|
-
const triggerHostReload = (file) => {
|
|
2404
|
-
if (strategy === "native") return;
|
|
2405
|
-
if (shouldIgnoreFile(file, options)) return;
|
|
2406
|
-
server.ws.send({ type: "full-reload" });
|
|
2407
|
-
};
|
|
2408
|
-
server.watcher.on("change", triggerHostReload);
|
|
2409
|
-
server.watcher.on("add", triggerHostReload);
|
|
2410
|
-
server.watcher.on("unlink", triggerHostReload);
|
|
2411
|
-
server.httpServer?.once("close", teardown);
|
|
2319
|
+
function setupRemoteBroadcast(server, options) {
|
|
2320
|
+
const broadcast = (file) => {
|
|
2321
|
+
if (shouldIgnoreFile(file, options)) return;
|
|
2322
|
+
server.ws.send({
|
|
2323
|
+
type: "custom",
|
|
2324
|
+
event: REMOTE_HMR_EVENT,
|
|
2325
|
+
data: {
|
|
2326
|
+
remote: options.name,
|
|
2327
|
+
file,
|
|
2328
|
+
ts: Date.now()
|
|
2412
2329
|
}
|
|
2413
|
-
}
|
|
2414
|
-
};
|
|
2415
|
-
}
|
|
2416
|
-
//#endregion
|
|
2417
|
-
//#region src/plugins/pluginDts.ts
|
|
2418
|
-
const DEFAULT_DEV_OPTIONS = {
|
|
2419
|
-
disableLiveReload: true,
|
|
2420
|
-
disableHotTypesReload: false,
|
|
2421
|
-
disableDynamicRemoteTypeHints: false
|
|
2422
|
-
};
|
|
2423
|
-
const DYNAMIC_HINTS_PLUGIN = "@module-federation/dts-plugin/dynamic-remote-type-hints-plugin";
|
|
2424
|
-
const getIPv4 = () => process.env["FEDERATION_IPV4"] || "127.0.0.1";
|
|
2425
|
-
const DEV_TYPES_FOLDER = ".dev-server";
|
|
2426
|
-
const DEFAULT_PUBLIC_TYPES_FOLDER = "@mf-types";
|
|
2427
|
-
const forkDevWorkerPath = require.resolve("@module-federation/dts-plugin/dist/fork-dev-worker.js");
|
|
2428
|
-
var DevWorker = class {
|
|
2429
|
-
worker = _module_federation_dts_plugin_core.rpc.createRpcWorker(forkDevWorkerPath, {}, void 0, false);
|
|
2430
|
-
constructor(options) {
|
|
2431
|
-
this.worker.connect(options);
|
|
2432
|
-
}
|
|
2433
|
-
update() {
|
|
2434
|
-
this.worker.process?.send?.({
|
|
2435
|
-
type: _module_federation_dts_plugin_core.rpc.RpcGMCallTypes.CALL,
|
|
2436
|
-
id: this.worker.id,
|
|
2437
|
-
args: [void 0, "update"]
|
|
2438
2330
|
});
|
|
2439
|
-
}
|
|
2440
|
-
exit() {
|
|
2441
|
-
this.worker.terminate();
|
|
2442
|
-
}
|
|
2443
|
-
};
|
|
2444
|
-
const normalizeDevOptions = (dev) => {
|
|
2445
|
-
if (dev === false) return false;
|
|
2446
|
-
if (dev === true || typeof dev === "undefined") return { ...DEFAULT_DEV_OPTIONS };
|
|
2447
|
-
return {
|
|
2448
|
-
...DEFAULT_DEV_OPTIONS,
|
|
2449
|
-
...dev
|
|
2450
2331
|
};
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
Object.entries(options.remotes).forEach(([key, remote]) => {
|
|
2459
|
-
if (!remote.entry) return;
|
|
2460
|
-
remotes[key] = `${remote.entryGlobalName?.startsWith("http") || remote.entryGlobalName?.includes(".json") ? remote.name || key : remote.entryGlobalName || remote.name || key}@${remote.entry}`;
|
|
2332
|
+
server.watcher.on("change", broadcast);
|
|
2333
|
+
server.watcher.on("add", broadcast);
|
|
2334
|
+
server.watcher.on("unlink", broadcast);
|
|
2335
|
+
server.httpServer?.once("close", () => {
|
|
2336
|
+
server.watcher.off("change", broadcast);
|
|
2337
|
+
server.watcher.off("add", broadcast);
|
|
2338
|
+
server.watcher.off("unlink", broadcast);
|
|
2461
2339
|
});
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
}
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
const
|
|
2480
|
-
|
|
2481
|
-
return
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
const usesVueSfcExposes = (options) => {
|
|
2485
|
-
return getExposeImportPaths(options).some((value) => value.endsWith(".vue"));
|
|
2486
|
-
};
|
|
2487
|
-
const resolveDtsPluginOptions = (dts, options, context) => {
|
|
2488
|
-
if (dts === false) return false;
|
|
2489
|
-
const inferredGenerateTypesDefaults = { generateAPITypes: true };
|
|
2490
|
-
if (usesVueSfcExposes(options) && hasPackageDependency("vue-tsc", context)) inferredGenerateTypesDefaults.compilerInstance = "vue-tsc";
|
|
2491
|
-
if (dts === true || typeof dts === "undefined") return { generateTypes: inferredGenerateTypesDefaults };
|
|
2492
|
-
const generateTypes = dts.generateTypes;
|
|
2493
|
-
return {
|
|
2494
|
-
...dts,
|
|
2495
|
-
generateTypes: generateTypes === false ? false : {
|
|
2496
|
-
...inferredGenerateTypesDefaults,
|
|
2497
|
-
...generateTypes === true || typeof generateTypes === "undefined" ? {} : generateTypes
|
|
2498
|
-
}
|
|
2499
|
-
};
|
|
2500
|
-
};
|
|
2501
|
-
const getBasePath = (base) => {
|
|
2502
|
-
if (base.startsWith("http://") || base.startsWith("https://")) return new URL(base).pathname.replace(/\/$/, "") || "/";
|
|
2503
|
-
return base.replace(/\/$/, "") || "/";
|
|
2504
|
-
};
|
|
2505
|
-
const joinBaseAndAsset = (base, assetFileName) => {
|
|
2506
|
-
const basePath = getBasePath(base);
|
|
2507
|
-
return `${basePath === "/" ? "" : basePath}/${assetFileName}`.replace(/\/{2,}/g, "/");
|
|
2508
|
-
};
|
|
2509
|
-
const getDevDtsAssetPaths = (options) => {
|
|
2510
|
-
const { outputDir, publicTypesFolder, root, base } = options;
|
|
2511
|
-
return {
|
|
2512
|
-
apiFilePath: pathe.resolve(root, outputDir, `${DEV_TYPES_FOLDER}.d.ts`),
|
|
2513
|
-
apiRequestPath: joinBaseAndAsset(base, `${publicTypesFolder}.d.ts`),
|
|
2514
|
-
zipFilePath: pathe.resolve(root, outputDir, `${DEV_TYPES_FOLDER}.zip`),
|
|
2515
|
-
zipRequestPath: joinBaseAndAsset(base, `${publicTypesFolder}.zip`)
|
|
2340
|
+
}
|
|
2341
|
+
/**
|
|
2342
|
+
* Installs the host-side full-reload relay. For each configured remote:
|
|
2343
|
+
* 1. Fetches the remote's `/__mf_hmr` metadata to get its WS URL.
|
|
2344
|
+
* 2. Opens a Node-to-Node WebSocket to that URL.
|
|
2345
|
+
* 3. On any `mf:remote-update` message, broadcasts `{ type: 'full-reload' }`
|
|
2346
|
+
* to the host's own browser-facing WS.
|
|
2347
|
+
*
|
|
2348
|
+
* Also reloads on local host file changes. Retries failed connections up to
|
|
2349
|
+
* `REMOTE_HMR_CONNECT_MAX_RETRIES` times with a fixed delay.
|
|
2350
|
+
*
|
|
2351
|
+
* Only called under the `'full-reload'` strategy.
|
|
2352
|
+
*/
|
|
2353
|
+
function setupHostFullReloadRelay(server, options) {
|
|
2354
|
+
const connections = [];
|
|
2355
|
+
const reconnectTimers = /* @__PURE__ */ new Map();
|
|
2356
|
+
let isTearingDown = false;
|
|
2357
|
+
const clearReconnectTimer = (remoteName) => {
|
|
2358
|
+
const timer = reconnectTimers.get(remoteName);
|
|
2359
|
+
if (!timer) return;
|
|
2360
|
+
clearTimeout(timer);
|
|
2361
|
+
reconnectTimers.delete(remoteName);
|
|
2516
2362
|
};
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
const isZipRequest = requestPath === assetPaths.zipRequestPath;
|
|
2522
|
-
const isApiRequest = requestPath === assetPaths.apiRequestPath;
|
|
2523
|
-
if (!isZipRequest && !isApiRequest) {
|
|
2524
|
-
next();
|
|
2363
|
+
const scheduleReconnect = (remoteName, remote, attempt, reason) => {
|
|
2364
|
+
if (isTearingDown) return;
|
|
2365
|
+
if (attempt >= REMOTE_HMR_CONNECT_MAX_RETRIES) {
|
|
2366
|
+
require_packageUtils.mfWarn(`Remote "${remoteName}" full HMR reconnect skipped after ${REMOTE_HMR_CONNECT_MAX_RETRIES} attempts: ${reason}`);
|
|
2525
2367
|
return;
|
|
2526
2368
|
}
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2369
|
+
clearReconnectTimer(remoteName);
|
|
2370
|
+
const timer = setTimeout(() => {
|
|
2371
|
+
reconnectTimers.delete(remoteName);
|
|
2372
|
+
connectRemote(remoteName, remote, attempt + 1);
|
|
2373
|
+
}, REMOTE_HMR_CONNECT_RETRY_DELAY_MS);
|
|
2374
|
+
reconnectTimers.set(remoteName, timer);
|
|
2375
|
+
};
|
|
2376
|
+
const connectRemote = async (remoteName, remote, attempt = 0) => {
|
|
2377
|
+
if (isTearingDown) return;
|
|
2378
|
+
const endpoint = getRemoteHmrEndpoint(remote.entry, server);
|
|
2379
|
+
if (!endpoint) {
|
|
2380
|
+
require_packageUtils.mfWarn(`Failed to build HMR endpoint URL for remote "${remoteName}"`);
|
|
2531
2381
|
return;
|
|
2532
2382
|
}
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2383
|
+
try {
|
|
2384
|
+
const metadataResponse = await fetch(endpoint);
|
|
2385
|
+
if (!metadataResponse.ok) {
|
|
2386
|
+
require_packageUtils.mfWarn(`Failed to fetch remote HMR metadata from "${remoteName}": ${metadataResponse.status}`);
|
|
2387
|
+
scheduleReconnect(remoteName, remote, attempt, `HTTP ${metadataResponse.status}`);
|
|
2388
|
+
return;
|
|
2389
|
+
}
|
|
2390
|
+
const metadata = await metadataResponse.json();
|
|
2391
|
+
if (metadata.event !== "mf:remote-update" || !metadata.wsUrl) {
|
|
2392
|
+
require_packageUtils.mfWarn(`Remote "${remoteName}" returned unexpected HMR metadata shape`);
|
|
2393
|
+
return;
|
|
2394
|
+
}
|
|
2395
|
+
const ws = new WebSocket(metadata.wsUrl, "vite-hmr");
|
|
2396
|
+
ws.onmessage = (rawEvent) => {
|
|
2397
|
+
const message = parseRemoteHmrMessage(rawEvent.data);
|
|
2398
|
+
if (!message || message.event !== "mf:remote-update") return;
|
|
2399
|
+
server.ws.send({ type: "full-reload" });
|
|
2400
|
+
};
|
|
2401
|
+
ws.onopen = () => clearReconnectTimer(remoteName);
|
|
2402
|
+
ws.onerror = (error) => require_packageUtils.mfWarn(`Remote HMR socket error for "${remoteName}":`, error);
|
|
2403
|
+
ws.onclose = () => scheduleReconnect(remoteName, remote, attempt, "socket closed");
|
|
2404
|
+
connections.push(ws);
|
|
2405
|
+
} catch (error) {
|
|
2406
|
+
require_packageUtils.mfWarn(`Failed to connect remote HMR for "${remoteName}" on attempt ${attempt + 1}: ${getStringPreview(error)}`);
|
|
2407
|
+
scheduleReconnect(remoteName, remote, attempt, getStringPreview(error));
|
|
2538
2408
|
}
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2409
|
+
};
|
|
2410
|
+
const teardown = () => {
|
|
2411
|
+
isTearingDown = true;
|
|
2412
|
+
reconnectTimers.forEach((timer) => clearTimeout(timer));
|
|
2413
|
+
reconnectTimers.clear();
|
|
2414
|
+
connections.forEach((connection) => {
|
|
2415
|
+
if (connection.readyState !== connection.CLOSING && connection.readyState !== connection.CLOSED) connection.close();
|
|
2546
2416
|
});
|
|
2547
|
-
|
|
2417
|
+
connections.length = 0;
|
|
2548
2418
|
};
|
|
2549
|
-
|
|
2550
|
-
const
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2419
|
+
for (const [remoteName, remote] of Object.entries(options.remotes)) connectRemote(remoteName, remote);
|
|
2420
|
+
const triggerHostReload = (file) => {
|
|
2421
|
+
if (shouldIgnoreFile(file, options)) return;
|
|
2422
|
+
server.ws.send({ type: "full-reload" });
|
|
2423
|
+
};
|
|
2424
|
+
server.watcher.on("change", triggerHostReload);
|
|
2425
|
+
server.watcher.on("add", triggerHostReload);
|
|
2426
|
+
server.watcher.on("unlink", triggerHostReload);
|
|
2427
|
+
server.httpServer?.once("close", teardown);
|
|
2428
|
+
}
|
|
2429
|
+
//#endregion
|
|
2430
|
+
//#region src/plugins/pluginDevRemoteHmr.ts
|
|
2431
|
+
/**
|
|
2432
|
+
* Clears the federation runtime's `moduleCache` on every Vite `vite:beforeUpdate`
|
|
2433
|
+
* event. Without this, after a remote SFC change Vite would patch the in-memory
|
|
2434
|
+
* component, but `loadRemote()` would still return the cached stale module on
|
|
2435
|
+
* the next call (e.g. after route navigation), making the patched version
|
|
2436
|
+
* effectively unreachable.
|
|
2437
|
+
*/
|
|
2438
|
+
const FEDERATION_MODULE_CACHE_CLEAR_SCRIPT = `
|
|
2439
|
+
if (import.meta.hot) {
|
|
2440
|
+
import.meta.hot.on('vite:beforeUpdate', function () {
|
|
2441
|
+
try {
|
|
2442
|
+
var f = globalThis.__FEDERATION__ || globalThis.__VMOK__;
|
|
2443
|
+
if (!f || !f.__INSTANCES__) return;
|
|
2444
|
+
for (var i = 0; i < f.__INSTANCES__.length; i++) {
|
|
2445
|
+
if (f.__INSTANCES__[i] && f.__INSTANCES__[i].moduleCache)
|
|
2446
|
+
f.__INSTANCES__[i].moduleCache.clear();
|
|
2447
|
+
}
|
|
2448
|
+
} catch (e) {}
|
|
2449
|
+
});
|
|
2450
|
+
}`;
|
|
2451
|
+
const HMR_ADAPTERS = [reactAdapter, vueAdapter];
|
|
2452
|
+
function resolveAdapters(plugins) {
|
|
2453
|
+
const pluginNames = new Set(plugins.map((p) => p.name));
|
|
2454
|
+
return HMR_ADAPTERS.filter((adapter) => adapter.pluginNames.some((name) => pluginNames.has(name)));
|
|
2455
|
+
}
|
|
2456
|
+
function hasCrossFederationHmr(plugins) {
|
|
2457
|
+
return resolveAdapters(plugins).length > 0;
|
|
2458
|
+
}
|
|
2459
|
+
function isRemoteHmrEnabled(dev) {
|
|
2460
|
+
return typeof dev === "object" && dev !== null && !!dev.remoteHmr;
|
|
2461
|
+
}
|
|
2462
|
+
/**
|
|
2463
|
+
* `'native'` — a matched framework adapter owns HMR through Vite's native
|
|
2464
|
+
* channel (e.g. React Fast Refresh via the `/@react-refresh` proxy, Vue's
|
|
2465
|
+
* patched `__VUE_HMR_RUNTIME__`). The broadcast/relay path stays idle.
|
|
2466
|
+
*
|
|
2467
|
+
* `'full-reload'` — no adapter matched, or the user explicitly opted in with
|
|
2468
|
+
* `remoteHmr: 'full-reload'` to bypass adapters: the plugin's broadcast/relay
|
|
2469
|
+
* machinery triggers a page reload on every remote file change.
|
|
2470
|
+
*/
|
|
2471
|
+
function resolveHmrStrategy(dev, plugins) {
|
|
2472
|
+
if (typeof dev === "object" && dev !== null && dev.remoteHmr === "full-reload") return "full-reload";
|
|
2473
|
+
return hasCrossFederationHmr(plugins) ? "native" : "full-reload";
|
|
2474
|
+
}
|
|
2475
|
+
function shouldIgnoreFile(file, options) {
|
|
2476
|
+
return file.includes("/node_modules/") || file.includes("\\node_modules\\") || file.includes(`/${options.virtualModuleDir}/`) || file.includes(`\\${options.virtualModuleDir}\\`) || file.includes("/.vite/") || file.includes("\\.vite\\") || file.includes("/.mf/") || file.includes("\\.mf\\") || file.includes("/mf-manifest.json") || file.includes("\\mf-manifest.json") || file.includes("/mf-stats.json") || file.includes("\\mf-stats.json");
|
|
2477
|
+
}
|
|
2478
|
+
function collectHostTags(server, options, adapters) {
|
|
2479
|
+
const ctx = {
|
|
2480
|
+
server,
|
|
2481
|
+
options
|
|
2482
|
+
};
|
|
2483
|
+
const tags = [];
|
|
2484
|
+
for (const adapter of adapters) {
|
|
2485
|
+
const adapterTags = adapter.host?.transformIndexHtml?.(ctx);
|
|
2486
|
+
if (adapterTags) tags.push(...adapterTags);
|
|
2487
|
+
}
|
|
2488
|
+
tags.push({
|
|
2489
|
+
tag: "script",
|
|
2490
|
+
attrs: { type: "module" },
|
|
2491
|
+
children: FEDERATION_MODULE_CACHE_CLEAR_SCRIPT,
|
|
2492
|
+
injectTo: "head"
|
|
2569
2493
|
});
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2494
|
+
return tags;
|
|
2495
|
+
}
|
|
2496
|
+
function pluginDevRemoteHmr(options) {
|
|
2497
|
+
const isHost = Object.keys(options.remotes).length > 0;
|
|
2498
|
+
const isRemote = Object.keys(options.exposes).length > 0;
|
|
2499
|
+
let adapters = [];
|
|
2500
|
+
let strategy = "full-reload";
|
|
2501
|
+
return {
|
|
2502
|
+
name: "module-federation-dev-remote-hmr",
|
|
2576
2503
|
apply: "serve",
|
|
2577
|
-
config(config) {
|
|
2578
|
-
normalizedDevOptions = normalizeDevOptions(options.dev);
|
|
2579
|
-
if (!normalizedDevOptions) return;
|
|
2580
|
-
if (normalizedDevOptions.disableDynamicRemoteTypeHints) return;
|
|
2581
|
-
ensureRuntimePlugin(options, DYNAMIC_HINTS_PLUGIN);
|
|
2582
|
-
const define = config.define ? { ...config.define } : {};
|
|
2583
|
-
if (!("FEDERATION_IPV4" in define)) define.FEDERATION_IPV4 = JSON.stringify(getIPv4());
|
|
2584
|
-
config.define = define;
|
|
2585
|
-
},
|
|
2586
2504
|
configResolved(config) {
|
|
2587
|
-
|
|
2505
|
+
adapters = resolveAdapters(config.plugins);
|
|
2506
|
+
strategy = resolveHmrStrategy(options.dev, config.plugins);
|
|
2588
2507
|
},
|
|
2589
2508
|
configureServer(server) {
|
|
2590
|
-
if (!
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
const dtsModuleFederationConfig = getDtsModuleFederationConfig(resolvedConfig.root);
|
|
2596
|
-
const normalizedDtsOptions = normalizeDevDtsOptions(dtsModuleFederationConfig.dts, resolvedConfig.root);
|
|
2597
|
-
if (typeof normalizedDtsOptions !== "object") return;
|
|
2598
|
-
const normalizedGenerateTypes = (0, _module_federation_sdk.normalizeOptions)(Boolean(normalizedDtsOptions), { compileInChildProcess: true }, "mfOptions.dts.generateTypes")(normalizedDtsOptions.generateTypes);
|
|
2599
|
-
const remote = normalizedGenerateTypes === false ? void 0 : {
|
|
2600
|
-
implementation: normalizedDtsOptions.implementation,
|
|
2601
|
-
context: resolvedConfig.root,
|
|
2602
|
-
outputDir,
|
|
2603
|
-
moduleFederationConfig: { ...dtsModuleFederationConfig },
|
|
2604
|
-
hostRemoteTypesFolder: normalizedGenerateTypes.typesFolder || DEFAULT_PUBLIC_TYPES_FOLDER,
|
|
2605
|
-
...normalizedGenerateTypes,
|
|
2606
|
-
typesFolder: DEV_TYPES_FOLDER
|
|
2607
|
-
};
|
|
2608
|
-
if (remote) server.middlewares.use(createDevDtsAssetMiddleware(getDevDtsAssetPaths({
|
|
2609
|
-
outputDir,
|
|
2610
|
-
publicTypesFolder: remote.hostRemoteTypesFolder || DEFAULT_PUBLIC_TYPES_FOLDER,
|
|
2611
|
-
root: resolvedConfig.root,
|
|
2612
|
-
base: resolvedConfig.base
|
|
2613
|
-
})));
|
|
2614
|
-
if (remote && !remote.tsConfigPath && normalizedDtsOptions.tsConfigPath) remote.tsConfigPath = normalizedDtsOptions.tsConfigPath;
|
|
2615
|
-
const normalizedConsumeTypes = (0, _module_federation_sdk.normalizeOptions)(Boolean(normalizedDtsOptions), { consumeAPITypes: true }, "mfOptions.dts.consumeTypes")(normalizedDtsOptions.consumeTypes);
|
|
2616
|
-
const host = normalizedConsumeTypes === false ? void 0 : {
|
|
2617
|
-
implementation: normalizedDtsOptions.implementation,
|
|
2618
|
-
context: resolvedConfig.root,
|
|
2619
|
-
moduleFederationConfig: dtsModuleFederationConfig,
|
|
2620
|
-
typesFolder: normalizedConsumeTypes.typesFolder || "@mf-types",
|
|
2621
|
-
abortOnError: false,
|
|
2622
|
-
...normalizedConsumeTypes
|
|
2623
|
-
};
|
|
2624
|
-
const extraOptions = normalizedDtsOptions.extraOptions || {};
|
|
2625
|
-
if (!remote && !host && devOptions.disableLiveReload) return;
|
|
2626
|
-
const startDevWorker = async () => {
|
|
2627
|
-
let remoteTypeUrls;
|
|
2628
|
-
if (host) remoteTypeUrls = await new Promise((resolve) => {
|
|
2629
|
-
(0, _module_federation_dts_plugin.consumeTypesAPI)({
|
|
2630
|
-
host,
|
|
2631
|
-
extraOptions,
|
|
2632
|
-
displayErrorInTerminal: normalizedDtsOptions.displayErrorInTerminal
|
|
2633
|
-
}, resolve);
|
|
2634
|
-
});
|
|
2635
|
-
devWorker = new DevWorker({
|
|
2636
|
-
name: options.name,
|
|
2637
|
-
remote,
|
|
2638
|
-
host: host ? {
|
|
2639
|
-
...host,
|
|
2640
|
-
remoteTypeUrls
|
|
2641
|
-
} : void 0,
|
|
2642
|
-
extraOptions,
|
|
2643
|
-
disableLiveReload: devOptions.disableLiveReload,
|
|
2644
|
-
disableHotTypesReload: devOptions.disableHotTypesReload
|
|
2645
|
-
});
|
|
2646
|
-
const update = () => devWorker?.update();
|
|
2647
|
-
server.watcher.on("change", update);
|
|
2648
|
-
server.watcher.on("add", update);
|
|
2649
|
-
server.watcher.on("unlink", update);
|
|
2650
|
-
server.httpServer?.once("close", () => {
|
|
2651
|
-
devWorker?.exit();
|
|
2652
|
-
server.watcher.off("change", update);
|
|
2653
|
-
server.watcher.off("add", update);
|
|
2654
|
-
server.watcher.off("unlink", update);
|
|
2509
|
+
if (!isRemoteHmrEnabled(options.dev)) return;
|
|
2510
|
+
if (isRemote) {
|
|
2511
|
+
for (const adapter of adapters) adapter.remote?.configureServer?.({
|
|
2512
|
+
server,
|
|
2513
|
+
options
|
|
2655
2514
|
});
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
logDtsError(error, normalizedDtsOptions);
|
|
2659
|
-
});
|
|
2660
|
-
}
|
|
2661
|
-
}, {
|
|
2662
|
-
name: "module-federation-dts-build",
|
|
2663
|
-
apply: "build",
|
|
2664
|
-
configResolved(config) {
|
|
2665
|
-
resolvedConfig = config;
|
|
2666
|
-
},
|
|
2667
|
-
async generateBundle() {
|
|
2668
|
-
if (hasGeneratedBundle) return;
|
|
2669
|
-
hasGeneratedBundle = true;
|
|
2670
|
-
if (!resolvedConfig) return;
|
|
2671
|
-
let normalizedDtsOptions;
|
|
2672
|
-
try {
|
|
2673
|
-
normalizedDtsOptions = (0, _module_federation_dts_plugin.normalizeDtsOptions)(getDtsModuleFederationConfig(resolvedConfig.root), resolvedConfig.root);
|
|
2674
|
-
} catch (error) {
|
|
2675
|
-
logDtsError(error, options.dts);
|
|
2676
|
-
return;
|
|
2515
|
+
setupRemoteMetadataEndpoint(server, options);
|
|
2516
|
+
if (strategy === "full-reload") setupRemoteBroadcast(server, options);
|
|
2677
2517
|
}
|
|
2678
|
-
if (
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
try {
|
|
2683
|
-
consumeOptions = (0, _module_federation_dts_plugin.normalizeConsumeTypesOptions)({
|
|
2684
|
-
context,
|
|
2685
|
-
dtsOptions: normalizedDtsOptions,
|
|
2686
|
-
pluginOptions: getDtsModuleFederationConfig(resolvedConfig.root)
|
|
2518
|
+
if (isHost) {
|
|
2519
|
+
for (const adapter of adapters) adapter.host?.configureServer?.({
|
|
2520
|
+
server,
|
|
2521
|
+
options
|
|
2687
2522
|
});
|
|
2688
|
-
|
|
2689
|
-
logDtsError(error, normalizedDtsOptions);
|
|
2690
|
-
return;
|
|
2691
|
-
}
|
|
2692
|
-
if (consumeOptions?.host?.typesOnBuild) try {
|
|
2693
|
-
await (0, _module_federation_dts_plugin.consumeTypesAPI)(consumeOptions);
|
|
2694
|
-
} catch (error) {
|
|
2695
|
-
logDtsError(error, normalizedDtsOptions);
|
|
2523
|
+
if (strategy === "full-reload") setupHostFullReloadRelay(server, options);
|
|
2696
2524
|
}
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2525
|
+
},
|
|
2526
|
+
transform: {
|
|
2527
|
+
order: "post",
|
|
2528
|
+
handler(code, id) {
|
|
2529
|
+
if (!isRemote || !isRemoteHmrEnabled(options.dev)) return;
|
|
2530
|
+
if (!adapters.length) return;
|
|
2531
|
+
let result = code;
|
|
2532
|
+
const adapterCtx = { options };
|
|
2533
|
+
for (const adapter of adapters) {
|
|
2534
|
+
const next = adapter.remote?.transform?.(result, id, adapterCtx);
|
|
2535
|
+
if (typeof next === "string") result = next;
|
|
2536
|
+
}
|
|
2537
|
+
return result === code ? void 0 : result;
|
|
2708
2538
|
}
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2539
|
+
},
|
|
2540
|
+
transformIndexHtml: {
|
|
2541
|
+
order: "pre",
|
|
2542
|
+
handler(_html, ctx) {
|
|
2543
|
+
if (!isRemoteHmrEnabled(options.dev)) return;
|
|
2544
|
+
if (!isHost || !ctx.server) return;
|
|
2545
|
+
return collectHostTags(ctx.server, options, adapters);
|
|
2714
2546
|
}
|
|
2715
2547
|
}
|
|
2716
|
-
}
|
|
2548
|
+
};
|
|
2717
2549
|
}
|
|
2718
2550
|
//#endregion
|
|
2719
2551
|
//#region src/virtualModules/index.ts
|
|
2720
|
-
function initVirtualModules(command, remoteEntryId) {
|
|
2552
|
+
function initVirtualModules(command, remoteEntryId, enableSsrInit = false) {
|
|
2721
2553
|
writeLocalSharedImportMap();
|
|
2722
2554
|
writeHostAutoInit(remoteEntryId, command);
|
|
2723
|
-
writeRuntimeInitStatus(command);
|
|
2555
|
+
writeRuntimeInitStatus(command, enableSsrInit);
|
|
2724
2556
|
}
|
|
2725
2557
|
//#endregion
|
|
2726
2558
|
//#region src/utils/bundleHelpers.ts
|
|
@@ -3070,6 +2902,12 @@ function removeTrailingSlash(value) {
|
|
|
3070
2902
|
function ensureTrailingSlash(value) {
|
|
3071
2903
|
return `${removeTrailingSlash(value)}/`;
|
|
3072
2904
|
}
|
|
2905
|
+
function getBasePath(base) {
|
|
2906
|
+
return removeTrailingSlash(base || "/");
|
|
2907
|
+
}
|
|
2908
|
+
function isNuxtClientBase(base) {
|
|
2909
|
+
return getBasePath(base).endsWith("/_nuxt");
|
|
2910
|
+
}
|
|
3073
2911
|
function normalizeNodeModulePath(source) {
|
|
3074
2912
|
return source.replace(/\\/g, "/").replace(/\?.*$/, "");
|
|
3075
2913
|
}
|
|
@@ -3103,6 +2941,116 @@ function resolvePublicPath(options, viteBase, originalBase) {
|
|
|
3103
2941
|
return "auto";
|
|
3104
2942
|
}
|
|
3105
2943
|
//#endregion
|
|
2944
|
+
//#region src/virtualModules/virtualExposesSSR.ts
|
|
2945
|
+
/**
|
|
2946
|
+
* Virtual module ID for the SSR exposes map.
|
|
2947
|
+
* Separate from the browser exposes: no CSS injection, no document references,
|
|
2948
|
+
* and shared packages are imported as bare specifiers (externals in the SSR build).
|
|
2949
|
+
*/
|
|
2950
|
+
function getVirtualExposesSSRId(options) {
|
|
2951
|
+
return `virtual:mf-exposes-ssr:${`${options.internalName}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
2952
|
+
}
|
|
2953
|
+
/**
|
|
2954
|
+
* Generates the SSR exposes map module.
|
|
2955
|
+
*
|
|
2956
|
+
* Differences from the browser version (virtualExposes.ts):
|
|
2957
|
+
* - No CSS asset injection (document APIs unavailable on Node)
|
|
2958
|
+
* - Shared packages (react, react-dom, etc.) must be externals in the SSR
|
|
2959
|
+
* build so Node resolves them via its own module cache — this is what
|
|
2960
|
+
* guarantees the React singleton is shared with react-dom/server.
|
|
2961
|
+
*/
|
|
2962
|
+
function generateExposesSSR(options) {
|
|
2963
|
+
return `
|
|
2964
|
+
export default {
|
|
2965
|
+
${Object.keys(options.exposes).map((key) => {
|
|
2966
|
+
return `
|
|
2967
|
+
${JSON.stringify(key)}: async () => {
|
|
2968
|
+
const importModule = await import(${JSON.stringify(options.exposes[key].import)})
|
|
2969
|
+
const exportModule = {}
|
|
2970
|
+
Object.assign(exportModule, importModule)
|
|
2971
|
+
Object.defineProperty(exportModule, "__esModule", {
|
|
2972
|
+
value: true,
|
|
2973
|
+
enumerable: false
|
|
2974
|
+
})
|
|
2975
|
+
return exportModule
|
|
2976
|
+
}
|
|
2977
|
+
`;
|
|
2978
|
+
}).join(",")}
|
|
2979
|
+
}
|
|
2980
|
+
`;
|
|
2981
|
+
}
|
|
2982
|
+
//#endregion
|
|
2983
|
+
//#region src/virtualModules/virtualRemoteEntrySSR.ts
|
|
2984
|
+
const REMOTE_ENTRY_SSR_ID = "virtual:mf-REMOTE_ENTRY_SSR_ID";
|
|
2985
|
+
function getRemoteEntrySSRId(options) {
|
|
2986
|
+
return `${REMOTE_ENTRY_SSR_ID}:${`${options.internalName}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
2987
|
+
}
|
|
2988
|
+
function getSsrRemoteEntryFileName(browserFilename) {
|
|
2989
|
+
const ext = browserFilename.match(/\.[^.]+$/)?.[0] || ".js";
|
|
2990
|
+
return `${browserFilename.slice(0, browserFilename.length - ext.length)}.ssr${ext}`;
|
|
2991
|
+
}
|
|
2992
|
+
/**
|
|
2993
|
+
* Generates the SSR remote entry module.
|
|
2994
|
+
*
|
|
2995
|
+
* This is intentionally minimal — no HMR shim, no loadShare virtual modules,
|
|
2996
|
+
* no browser globals. Shared packages (react, react-dom, etc.) are imported
|
|
2997
|
+
* as externals by the SSR build, so Node's require cache provides the singleton.
|
|
2998
|
+
*
|
|
2999
|
+
* The container API (init / get) mirrors the browser entry so the MF runtime
|
|
3000
|
+
* can call it the same way on the server.
|
|
3001
|
+
*/
|
|
3002
|
+
function generateRemoteEntrySSR(options) {
|
|
3003
|
+
const virtualExposesSSRId = getVirtualExposesSSRId(options);
|
|
3004
|
+
return `
|
|
3005
|
+
import { init as runtimeInit } from "@module-federation/runtime";
|
|
3006
|
+
|
|
3007
|
+
let exposesMapPromise;
|
|
3008
|
+
|
|
3009
|
+
async function getExposesMap() {
|
|
3010
|
+
exposesMapPromise ??= import(${JSON.stringify(virtualExposesSSRId)}).then((mod) => mod.default ?? mod);
|
|
3011
|
+
return exposesMapPromise;
|
|
3012
|
+
}
|
|
3013
|
+
|
|
3014
|
+
/**
|
|
3015
|
+
* Called by the MF runtime on the host to register this remote's share scope.
|
|
3016
|
+
* On the server the host has already initialised the runtime, so we just need
|
|
3017
|
+
* to set up a minimal runtime instance for the remote container.
|
|
3018
|
+
*/
|
|
3019
|
+
async function init(shared = {}, initScope = []) {
|
|
3020
|
+
const initRes = runtimeInit({
|
|
3021
|
+
name: ${JSON.stringify(options.internalName)},
|
|
3022
|
+
remotes: [],
|
|
3023
|
+
shared: {},
|
|
3024
|
+
});
|
|
3025
|
+
const initToken = { from: ${JSON.stringify(options.internalName)} };
|
|
3026
|
+
if (initScope.indexOf(initToken) >= 0) return;
|
|
3027
|
+
initScope.push(initToken);
|
|
3028
|
+
initRes.initShareScopeMap(${JSON.stringify(options.shareScope)}, shared);
|
|
3029
|
+
try {
|
|
3030
|
+
await Promise.all(
|
|
3031
|
+
await initRes.initializeSharing(${JSON.stringify(options.shareScope)}, {
|
|
3032
|
+
strategy: ${JSON.stringify(options.shareStrategy ?? "version-first")},
|
|
3033
|
+
from: 'build',
|
|
3034
|
+
initScope,
|
|
3035
|
+
})
|
|
3036
|
+
);
|
|
3037
|
+
} catch (e) {
|
|
3038
|
+
console.error('[Module Federation SSR]', e);
|
|
3039
|
+
}
|
|
3040
|
+
return initRes;
|
|
3041
|
+
}
|
|
3042
|
+
|
|
3043
|
+
async function getExposes(moduleName) {
|
|
3044
|
+
const exposesMap = await getExposesMap();
|
|
3045
|
+
if (!(moduleName in exposesMap))
|
|
3046
|
+
throw new Error(\`[Module Federation] Module \${moduleName} does not exist in container.\`);
|
|
3047
|
+
return exposesMap[moduleName]().then((res) => () => res);
|
|
3048
|
+
}
|
|
3049
|
+
|
|
3050
|
+
export { init, getExposes as get };
|
|
3051
|
+
`;
|
|
3052
|
+
}
|
|
3053
|
+
//#endregion
|
|
3106
3054
|
//#region src/plugins/pluginMFManifest.ts
|
|
3107
3055
|
/**
|
|
3108
3056
|
* Resolves the build version for the module federation manifest.
|
|
@@ -3133,6 +3081,7 @@ const Manifest = () => {
|
|
|
3133
3081
|
};
|
|
3134
3082
|
let root;
|
|
3135
3083
|
let remoteEntryFile;
|
|
3084
|
+
let ssrRemoteEntryFile;
|
|
3136
3085
|
let publicPath;
|
|
3137
3086
|
let _command;
|
|
3138
3087
|
let _originalConfigBase;
|
|
@@ -3169,8 +3118,8 @@ const Manifest = () => {
|
|
|
3169
3118
|
type: "module"
|
|
3170
3119
|
},
|
|
3171
3120
|
ssrRemoteEntry: {
|
|
3172
|
-
name: filename,
|
|
3173
|
-
path: "",
|
|
3121
|
+
name: getSsrRemoteEntryFileName(filename),
|
|
3122
|
+
path: "/__mf_ssr__/",
|
|
3174
3123
|
type: "module"
|
|
3175
3124
|
},
|
|
3176
3125
|
varRemoteEntry: varFilename ? {
|
|
@@ -3201,6 +3150,7 @@ const Manifest = () => {
|
|
|
3201
3150
|
_originalConfigBase = config.base;
|
|
3202
3151
|
},
|
|
3203
3152
|
configResolved(config) {
|
|
3153
|
+
viteConfig = config;
|
|
3204
3154
|
root = config.root;
|
|
3205
3155
|
let base = config.base;
|
|
3206
3156
|
if (_command === "serve") base = (config.server.origin || "") + config.base;
|
|
@@ -3210,7 +3160,10 @@ const Manifest = () => {
|
|
|
3210
3160
|
if (!mfManifestName) return;
|
|
3211
3161
|
let filesMap = {};
|
|
3212
3162
|
const foundRemoteEntryFile = findRemoteEntryFile(mfOptions.filename, bundle);
|
|
3163
|
+
const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions.filename);
|
|
3164
|
+
const foundSsrRemoteEntryFile = Object.values(bundle).find((file) => file.fileName === expectedSsrRemoteEntryFile)?.fileName;
|
|
3213
3165
|
if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
|
|
3166
|
+
ssrRemoteEntryFile = foundSsrRemoteEntryFile || expectedSsrRemoteEntryFile;
|
|
3214
3167
|
const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
|
|
3215
3168
|
if (!disableAssetsAnalyze) {
|
|
3216
3169
|
const exposesModules = Object.keys(mfOptions.exposes).map((item) => mfOptions.exposes[item].import);
|
|
@@ -3252,6 +3205,11 @@ const Manifest = () => {
|
|
|
3252
3205
|
path: "",
|
|
3253
3206
|
type: "module"
|
|
3254
3207
|
};
|
|
3208
|
+
const ssrRemoteEntry = {
|
|
3209
|
+
name: ssrRemoteEntryFile || getSsrRemoteEntryFileName(filename),
|
|
3210
|
+
path: _command === "serve" ? "/__mf_ssr__/" : "",
|
|
3211
|
+
type: "module"
|
|
3212
|
+
};
|
|
3255
3213
|
const varRemoteEntry = varFilename ? {
|
|
3256
3214
|
name: varFilename,
|
|
3257
3215
|
path: "",
|
|
@@ -3315,7 +3273,7 @@ const Manifest = () => {
|
|
|
3315
3273
|
buildName: name
|
|
3316
3274
|
},
|
|
3317
3275
|
remoteEntry,
|
|
3318
|
-
ssrRemoteEntry
|
|
3276
|
+
ssrRemoteEntry,
|
|
3319
3277
|
varRemoteEntry,
|
|
3320
3278
|
types: {
|
|
3321
3279
|
path: "",
|
|
@@ -3382,14 +3340,14 @@ function resetParseState() {
|
|
|
3382
3340
|
}
|
|
3383
3341
|
function setParseTimeout(timeout) {
|
|
3384
3342
|
if (!_parseTimeout) _parseTimeout = setTimeout(() => {
|
|
3385
|
-
mfWarn(`Parse timeout (${timeout}s) - forcing resolve`);
|
|
3343
|
+
require_packageUtils.mfWarn(`Parse timeout (${timeout}s) - forcing resolve`);
|
|
3386
3344
|
_resolve?.(1);
|
|
3387
3345
|
}, timeout * 1e3);
|
|
3388
3346
|
}
|
|
3389
3347
|
function resetIdleTimeout(timeout) {
|
|
3390
3348
|
clearParseTimeout();
|
|
3391
3349
|
_parseTimeout = setTimeout(() => {
|
|
3392
|
-
mfWarn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout.`);
|
|
3350
|
+
require_packageUtils.mfWarn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout.`);
|
|
3393
3351
|
_resolve?.(1);
|
|
3394
3352
|
}, timeout * 1e3);
|
|
3395
3353
|
}
|
|
@@ -3554,13 +3512,14 @@ function appendAlias(config, alias) {
|
|
|
3554
3512
|
function pluginProxyRemotes_default(options) {
|
|
3555
3513
|
let command;
|
|
3556
3514
|
let root = process.cwd();
|
|
3515
|
+
let enableSsrInit = false;
|
|
3557
3516
|
const { remotes } = options;
|
|
3558
3517
|
function resolveRemoteId(source, importer, remoteName) {
|
|
3559
3518
|
if (source === remoteName) {
|
|
3560
|
-
const installedPackageEntry = getInstalledPackageEntry(source, { cwd: root });
|
|
3519
|
+
const installedPackageEntry = require_packageUtils.getInstalledPackageEntry(source, { cwd: root });
|
|
3561
3520
|
if (installedPackageEntry && (importer === void 0 || isNodeModulesImporter(importer))) return installedPackageEntry;
|
|
3562
3521
|
}
|
|
3563
|
-
const remoteModule = getRemoteVirtualModule(source, command);
|
|
3522
|
+
const remoteModule = getRemoteVirtualModule(source, command, enableSsrInit);
|
|
3564
3523
|
addUsedRemote(remoteName, source);
|
|
3565
3524
|
refreshHostAutoInit();
|
|
3566
3525
|
return remoteModule.getImportId();
|
|
@@ -3579,6 +3538,9 @@ function pluginProxyRemotes_default(options) {
|
|
|
3579
3538
|
});
|
|
3580
3539
|
});
|
|
3581
3540
|
},
|
|
3541
|
+
configResolved() {
|
|
3542
|
+
enableSsrInit = command === "serve" && parseInt(vite.version, 10) >= 8;
|
|
3543
|
+
},
|
|
3582
3544
|
resolveId(source, importer) {
|
|
3583
3545
|
if (!filterId(source)) return;
|
|
3584
3546
|
for (const remote of Object.values(remotes)) {
|
|
@@ -3626,10 +3588,10 @@ function getPrebuildResolutionSource(pkgName, shareItem) {
|
|
|
3626
3588
|
}
|
|
3627
3589
|
function tryResolveFromProjectRoot(source) {
|
|
3628
3590
|
if (pathe.default.isAbsolute(source) || source.startsWith(".") || source.startsWith("/")) return source;
|
|
3629
|
-
const browserEntry = getInstalledPackageEntry(source, { cwd: getPackageDetectionCwd() });
|
|
3591
|
+
const browserEntry = require_packageUtils.getInstalledPackageEntry(source, { cwd: require_packageUtils.getPackageDetectionCwd() });
|
|
3630
3592
|
if (browserEntry) return browserEntry;
|
|
3631
3593
|
try {
|
|
3632
|
-
return (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`)).resolve(source);
|
|
3594
|
+
return (0, module$1.createRequire)(new URL(`file://${pathe.default.join(require_packageUtils.getPackageDetectionCwd(), "package.json")}`)).resolve(source);
|
|
3633
3595
|
} catch {
|
|
3634
3596
|
return;
|
|
3635
3597
|
}
|
|
@@ -3655,15 +3617,15 @@ function findSharedKeyForSource(source, shared) {
|
|
|
3655
3617
|
const explicitSubpathKey = getMatchingNodeModuleSubpath(source, Object.keys(shared || {}).filter((sharedKey) => sharedKey.includes("/") && !sharedKey.endsWith("/")));
|
|
3656
3618
|
if (explicitSubpathKey) return explicitSubpathKey;
|
|
3657
3619
|
}
|
|
3658
|
-
const packageName = getPackageNameFromNodeModulePath(source);
|
|
3620
|
+
const packageName = require_packageUtils.getPackageNameFromNodeModulePath(source);
|
|
3659
3621
|
return packageName ? findSharedKey(packageName, shared) : void 0;
|
|
3660
3622
|
}
|
|
3661
3623
|
/**
|
|
3662
3624
|
* Reads the dependencies of an installed package from its package.json.
|
|
3663
3625
|
*/
|
|
3664
3626
|
function getPackageDependencies(pkg) {
|
|
3665
|
-
const packageName = getPackageName(pkg);
|
|
3666
|
-
const installed = getInstalledPackageJson(packageName, { packageName });
|
|
3627
|
+
const packageName = require_packageUtils.getPackageName(pkg);
|
|
3628
|
+
const installed = require_packageUtils.getInstalledPackageJson(packageName, { packageName });
|
|
3667
3629
|
return Object.keys(installed?.packageJson.dependencies || {});
|
|
3668
3630
|
}
|
|
3669
3631
|
/**
|
|
@@ -3682,7 +3644,7 @@ function excludeSharedSubDependencies(shared) {
|
|
|
3682
3644
|
const depKey = sharedKeyByBase.get(dep);
|
|
3683
3645
|
if (depKey && depKey !== parentKey) {
|
|
3684
3646
|
if (shared[depKey]?.shareConfig.singleton === true || shared[depKey]?.shareConfig.import === false) continue;
|
|
3685
|
-
mfWarn(`"${dep}" is a dependency of shared package "${parentKey}" and is also shared separately. This may cause initialization order issues in dev mode. Consider sharing only "${parentKey}".\n Auto-excluding "${dep}" from shared modules for dev mode.`);
|
|
3647
|
+
require_packageUtils.mfWarn(`"${dep}" is a dependency of shared package "${parentKey}" and is also shared separately. This may cause initialization order issues in dev mode. Consider sharing only "${parentKey}".\n Auto-excluding "${dep}" from shared modules for dev mode.`);
|
|
3686
3648
|
delete shared[depKey];
|
|
3687
3649
|
sharedKeys.delete(depKey);
|
|
3688
3650
|
sharedKeyByBase.delete(dep);
|
|
@@ -3724,10 +3686,10 @@ function proxySharedModule(options) {
|
|
|
3724
3686
|
name: "proxyPreBuildShared",
|
|
3725
3687
|
enforce: "post",
|
|
3726
3688
|
config(config, { command }) {
|
|
3727
|
-
setPackageDetectionCwd(config.root || process.cwd());
|
|
3728
|
-
const isVinext = hasPackageDependency("vinext");
|
|
3729
|
-
const isAstro = hasPackageDependency("astro");
|
|
3730
|
-
const isRolldown = getIsRolldown(this);
|
|
3689
|
+
require_packageUtils.setPackageDetectionCwd(config.root || process.cwd());
|
|
3690
|
+
const isVinext = require_packageUtils.hasPackageDependency("vinext");
|
|
3691
|
+
const isAstro = require_packageUtils.hasPackageDependency("astro");
|
|
3692
|
+
const isRolldown = require_packageUtils.getIsRolldown(this);
|
|
3731
3693
|
_command = command;
|
|
3732
3694
|
useRolldown = isRolldown;
|
|
3733
3695
|
useDirectReactImport = isVinext || isAstro;
|
|
@@ -3735,7 +3697,7 @@ function proxySharedModule(options) {
|
|
|
3735
3697
|
},
|
|
3736
3698
|
configResolved(config) {
|
|
3737
3699
|
_config = config;
|
|
3738
|
-
const isRolldown = getIsRolldown(this);
|
|
3700
|
+
const isRolldown = require_packageUtils.getIsRolldown(this);
|
|
3739
3701
|
Object.keys(shared).forEach((key) => {
|
|
3740
3702
|
if (key.endsWith("/")) return;
|
|
3741
3703
|
if (useDirectReactImport && key === "react") {
|
|
@@ -3860,9 +3822,37 @@ function applyRewrites(code, imports, id) {
|
|
|
3860
3822
|
const importParts = [];
|
|
3861
3823
|
if (imp.defaultLocal) importParts.push(`default as ${imp.defaultLocal}`);
|
|
3862
3824
|
importParts.push(`__moduleExports as ${nsId}`);
|
|
3863
|
-
const destructParts = imp.named.map((s) => s.imported === s.local ? s.local : `${s.imported}: ${s.local}`);
|
|
3864
3825
|
let rewrite = `import { ${importParts.join(", ")} } from ${src};`;
|
|
3865
|
-
if (
|
|
3826
|
+
if (imp.named.length > 0) {
|
|
3827
|
+
const isProxyId = `__mf_is_proxy_${counter++}`;
|
|
3828
|
+
const namedProxyHelper = `function __mfCreateNamedRemoteProxy(ns, key) {
|
|
3829
|
+
const target = function (...args) {
|
|
3830
|
+
const value = ns[key];
|
|
3831
|
+
return typeof value === "function" ? value.apply(this, args) : value;
|
|
3832
|
+
};
|
|
3833
|
+
return new Proxy(target, {
|
|
3834
|
+
get(_target, prop) {
|
|
3835
|
+
if (prop === "then") return undefined;
|
|
3836
|
+
const value = ns[key];
|
|
3837
|
+
if (prop === Symbol.toPrimitive) return () => value;
|
|
3838
|
+
const item = value == null ? undefined : value[prop];
|
|
3839
|
+
return typeof item === "function" ? item.bind(value) : item;
|
|
3840
|
+
},
|
|
3841
|
+
apply(target, thisArg, args) {
|
|
3842
|
+
return target.apply(thisArg, args);
|
|
3843
|
+
}
|
|
3844
|
+
});
|
|
3845
|
+
}`;
|
|
3846
|
+
const tempNames = imp.named.map((_s) => `__mf_named_${counter++}`);
|
|
3847
|
+
const destructParts = imp.named.map((s, index) => `${s.imported}: ${tempNames[index]}`);
|
|
3848
|
+
const bindingLines = imp.named.map((s, index) => {
|
|
3849
|
+
const temp = tempNames[index];
|
|
3850
|
+
return `const ${s.local} = ${isProxyId} ? __mfCreateNamedRemoteProxy(${nsId}, ${JSON.stringify(s.imported)}) : ${temp};`;
|
|
3851
|
+
});
|
|
3852
|
+
rewrite += `\n${namedProxyHelper}\nconst ${isProxyId} = ${nsId} && ${nsId}.__mf_is_remote_proxy;`;
|
|
3853
|
+
rewrite += `\nconst { ${destructParts.join(", ")} } = ${isProxyId} ? {} : ${nsId};`;
|
|
3854
|
+
rewrite += `\n${bindingLines.join("\n")}`;
|
|
3855
|
+
}
|
|
3866
3856
|
ms.overwrite(imp.start, imp.end, rewrite);
|
|
3867
3857
|
}
|
|
3868
3858
|
changed = true;
|
|
@@ -4138,6 +4128,205 @@ function pluginRemoteNamedExports(options) {
|
|
|
4138
4128
|
};
|
|
4139
4129
|
}
|
|
4140
4130
|
//#endregion
|
|
4131
|
+
//#region src/plugins/pluginSSRRemoteEntry.ts
|
|
4132
|
+
/**
|
|
4133
|
+
* Emits a Node-compatible SSR remote entry alongside the browser entry.
|
|
4134
|
+
*
|
|
4135
|
+
* Format strategy:
|
|
4136
|
+
* - Emit a dedicated ESM SSR entry alongside the browser entry.
|
|
4137
|
+
* - Keep the SSR entry out of the browser remote graph for Rollup builds by
|
|
4138
|
+
* emitting it as a generated asset.
|
|
4139
|
+
*
|
|
4140
|
+
* In both cases shared packages (react, react-dom, etc.) are marked as external
|
|
4141
|
+
* so Node resolves them through its own module cache, guaranteeing the singleton
|
|
4142
|
+
* is shared with react-dom/server.
|
|
4143
|
+
*/
|
|
4144
|
+
function pluginSSRRemoteEntry(options) {
|
|
4145
|
+
const remoteEntrySSRId = getRemoteEntrySSRId(options);
|
|
4146
|
+
const virtualExposesSSRId = getVirtualExposesSSRId(options);
|
|
4147
|
+
let isRolldown = false;
|
|
4148
|
+
let ssrOutputFilename = "";
|
|
4149
|
+
const ssrOnlyExternals = [
|
|
4150
|
+
"@module-federation/runtime",
|
|
4151
|
+
"@module-federation/runtime-core",
|
|
4152
|
+
"@module-federation/sdk",
|
|
4153
|
+
...options.ssrExternals ?? []
|
|
4154
|
+
];
|
|
4155
|
+
const ssrOnlyExternalPattern = new RegExp(`^(${ssrOnlyExternals.map((e) => e.replace(/[/\\^$*+?.()|[\]{}]/g, "\\$&")).join("|")})(\\/.*)?$`);
|
|
4156
|
+
const ssrModuleIds = new Set([remoteEntrySSRId, virtualExposesSSRId]);
|
|
4157
|
+
const resolvedAbsToPackage = /* @__PURE__ */ new Map();
|
|
4158
|
+
let isServe = false;
|
|
4159
|
+
let viteConfig;
|
|
4160
|
+
let isNuxtProject = false;
|
|
4161
|
+
const findNuxtExposesChunk = (bundle) => {
|
|
4162
|
+
const exposeKeys = Object.keys(options.exposes);
|
|
4163
|
+
if (exposeKeys.length === 0) return;
|
|
4164
|
+
return Object.values(bundle).find((file) => {
|
|
4165
|
+
if (file.type !== "chunk" || !file.fileName.startsWith("_nuxt/") || !file.fileName.endsWith(".js")) return false;
|
|
4166
|
+
const code = file.code || "";
|
|
4167
|
+
return exposeKeys.every((key) => code.includes(JSON.stringify(key)));
|
|
4168
|
+
})?.fileName;
|
|
4169
|
+
};
|
|
4170
|
+
return [{
|
|
4171
|
+
name: "mf:ssr-remote-entry:pre",
|
|
4172
|
+
enforce: "pre",
|
|
4173
|
+
configResolved(config) {
|
|
4174
|
+
isServe = config.command === "serve";
|
|
4175
|
+
for (const pkg of ssrOnlyExternals) {
|
|
4176
|
+
const aliasEntry = (config.resolve?.alias)?.find((a) => a.find === pkg || a.find instanceof RegExp && a.find.test(pkg));
|
|
4177
|
+
if (aliasEntry?.replacement) resolvedAbsToPackage.set(aliasEntry.replacement, pkg);
|
|
4178
|
+
}
|
|
4179
|
+
},
|
|
4180
|
+
resolveId(id, importer) {
|
|
4181
|
+
if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
|
|
4182
|
+
if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
|
|
4183
|
+
if (!importer || !ssrModuleIds.has(importer)) return;
|
|
4184
|
+
if (ssrOnlyExternalPattern.test(id)) return {
|
|
4185
|
+
id,
|
|
4186
|
+
external: true
|
|
4187
|
+
};
|
|
4188
|
+
const pkg = resolvedAbsToPackage.get(id);
|
|
4189
|
+
if (pkg) return {
|
|
4190
|
+
id: pkg,
|
|
4191
|
+
external: true
|
|
4192
|
+
};
|
|
4193
|
+
if (id.startsWith(".") || id.startsWith("/") || id.startsWith("file:")) return this.resolve(id, importer, { skipSelf: true }).then((resolved) => {
|
|
4194
|
+
if (resolved) ssrModuleIds.add(resolved.id);
|
|
4195
|
+
return resolved;
|
|
4196
|
+
});
|
|
4197
|
+
}
|
|
4198
|
+
}, {
|
|
4199
|
+
name: "mf:ssr-remote-entry",
|
|
4200
|
+
configResolved(config) {
|
|
4201
|
+
viteConfig = config;
|
|
4202
|
+
isNuxtProject = require_packageUtils.isNuxtProjectRoot(config.root);
|
|
4203
|
+
},
|
|
4204
|
+
configureServer(server) {
|
|
4205
|
+
const base = "/__mf_ssr__";
|
|
4206
|
+
const basePath = getBasePath(viteConfig?.base);
|
|
4207
|
+
const ssrEntryFileName = getSsrRemoteEntryFileName(options.filename);
|
|
4208
|
+
if (isNuxtProject || isNuxtClientBase(basePath)) server.middlewares.use((req, _res, next) => {
|
|
4209
|
+
if (req.url?.replace(/\?.*/, "") === `${basePath}/${ssrEntryFileName}`) req.url = `${basePath}/__mf_ssr__/${ssrEntryFileName}`;
|
|
4210
|
+
next();
|
|
4211
|
+
});
|
|
4212
|
+
const ssrEnv = server.environments?.ssr;
|
|
4213
|
+
const clientEnv = server.environments?.client;
|
|
4214
|
+
if (typeof (ssrEnv?.fetchModule ?? clientEnv?.fetchModule) === "function") server.middlewares.use("/__mf_runner__", async (req, res) => {
|
|
4215
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
4216
|
+
if (req.method === "OPTIONS") {
|
|
4217
|
+
res.setHeader("Access-Control-Allow-Methods", "POST");
|
|
4218
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
4219
|
+
res.statusCode = 204;
|
|
4220
|
+
res.end();
|
|
4221
|
+
return;
|
|
4222
|
+
}
|
|
4223
|
+
if (req.method !== "POST") {
|
|
4224
|
+
res.statusCode = 405;
|
|
4225
|
+
res.end("Method not allowed");
|
|
4226
|
+
return;
|
|
4227
|
+
}
|
|
4228
|
+
try {
|
|
4229
|
+
const chunks = [];
|
|
4230
|
+
await new Promise((resolve, reject) => {
|
|
4231
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
4232
|
+
req.on("end", resolve);
|
|
4233
|
+
req.on("error", reject);
|
|
4234
|
+
});
|
|
4235
|
+
const body = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
4236
|
+
if (body.name === "getBuiltins") {
|
|
4237
|
+
const builtins = (clientEnv ?? ssrEnv)?.config?.resolve?.builtins ?? [];
|
|
4238
|
+
res.setHeader("Content-Type", "application/json");
|
|
4239
|
+
res.end(JSON.stringify({ result: builtins }));
|
|
4240
|
+
return;
|
|
4241
|
+
}
|
|
4242
|
+
if (body.name !== "fetchModule") {
|
|
4243
|
+
res.statusCode = 400;
|
|
4244
|
+
res.end(JSON.stringify({ error: { message: `Unsupported invoke: ${body.name}` } }));
|
|
4245
|
+
return;
|
|
4246
|
+
}
|
|
4247
|
+
const [id, importer, opts] = body.data;
|
|
4248
|
+
const fetchEnv = ssrEnv ?? clientEnv;
|
|
4249
|
+
const fetchFn = fetchEnv.fetchModule.bind(fetchEnv);
|
|
4250
|
+
let result;
|
|
4251
|
+
try {
|
|
4252
|
+
result = await fetchFn(id, importer, opts);
|
|
4253
|
+
} catch (fetchErr) {
|
|
4254
|
+
const bareId = id.startsWith("/@id/") ? id.slice(5).replace(/^__x00__/, "\0") : id;
|
|
4255
|
+
try {
|
|
4256
|
+
const { createRequire } = await import("module");
|
|
4257
|
+
const resolved = createRequire(new URL(`file://${server.config.root}/package.json`)).resolve(bareId.replace(/^\0/, ""));
|
|
4258
|
+
const { pathToFileURL } = await import("url");
|
|
4259
|
+
result = {
|
|
4260
|
+
externalize: pathToFileURL(resolved).href,
|
|
4261
|
+
type: "module"
|
|
4262
|
+
};
|
|
4263
|
+
} catch {
|
|
4264
|
+
throw fetchErr;
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
res.setHeader("Content-Type", "application/json");
|
|
4268
|
+
res.end(JSON.stringify({ result }));
|
|
4269
|
+
} catch (e) {
|
|
4270
|
+
res.setHeader("Content-Type", "application/json");
|
|
4271
|
+
res.end(JSON.stringify({ error: { message: String(e instanceof Error ? e.message : e) } }));
|
|
4272
|
+
}
|
|
4273
|
+
});
|
|
4274
|
+
const ssrPath = `${base}/${ssrEntryFileName}`;
|
|
4275
|
+
server.middlewares.use(ssrPath, (_req, res) => {
|
|
4276
|
+
const exposesUrl = `${base}/${options.filename.replace(/\.[^.]+$/, "")}.exposes.js`;
|
|
4277
|
+
const code = generateRemoteEntrySSR(options).replace(JSON.stringify(virtualExposesSSRId), JSON.stringify(exposesUrl));
|
|
4278
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
4279
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
4280
|
+
res.end(code);
|
|
4281
|
+
});
|
|
4282
|
+
},
|
|
4283
|
+
resolveId(id) {
|
|
4284
|
+
if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
|
|
4285
|
+
if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
|
|
4286
|
+
if (id === `/__mf_ssr__/${getSsrRemoteEntryFileName(options.filename)}`) return remoteEntrySSRId;
|
|
4287
|
+
if (id === `/__mf_ssr__/${options.filename.replace(/\.[^.]+$/, "")}.exposes.js`) return virtualExposesSSRId;
|
|
4288
|
+
},
|
|
4289
|
+
load(id) {
|
|
4290
|
+
if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return generateRemoteEntrySSR(options);
|
|
4291
|
+
if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return generateExposesSSR(options);
|
|
4292
|
+
},
|
|
4293
|
+
buildStart() {
|
|
4294
|
+
if (isServe) return;
|
|
4295
|
+
isRolldown = require_packageUtils.getIsRolldown(this);
|
|
4296
|
+
ssrOutputFilename = getSsrRemoteEntryFileName(options.filename);
|
|
4297
|
+
const environmentName = this.environment?.name;
|
|
4298
|
+
const hasSsrEnvironment = Boolean(viteConfig?.environments?.ssr);
|
|
4299
|
+
const isLegacySsrBuild = Boolean(this.environment?.config?.build?.ssr);
|
|
4300
|
+
if (hasSsrEnvironment) {
|
|
4301
|
+
if (isNuxtProject) {
|
|
4302
|
+
if (environmentName === "ssr") return;
|
|
4303
|
+
} else if (environmentName !== "ssr") return;
|
|
4304
|
+
} else if (isLegacySsrBuild) {} else if (environmentName && environmentName !== "client") return;
|
|
4305
|
+
if (Object.keys(options.exposes).length === 0) return;
|
|
4306
|
+
if (isRolldown) this.emitFile({
|
|
4307
|
+
type: "chunk",
|
|
4308
|
+
id: remoteEntrySSRId,
|
|
4309
|
+
name: "ssrRemoteEntry",
|
|
4310
|
+
fileName: ssrOutputFilename,
|
|
4311
|
+
preserveSignature: "strict"
|
|
4312
|
+
});
|
|
4313
|
+
else this.emitFile({
|
|
4314
|
+
type: "asset",
|
|
4315
|
+
fileName: ssrOutputFilename,
|
|
4316
|
+
source: generateRemoteEntrySSR(options)
|
|
4317
|
+
});
|
|
4318
|
+
},
|
|
4319
|
+
generateBundle(_options, bundle) {
|
|
4320
|
+
const exposesChunk = findNuxtExposesChunk(bundle);
|
|
4321
|
+
const ssrAsset = bundle[ssrOutputFilename];
|
|
4322
|
+
if (exposesChunk && ssrAsset?.type === "asset" && typeof ssrAsset.source === "string") ssrAsset.source = ssrAsset.source.replace(/import\("virtual:mf-exposes-ssr:[^"]+"\)/g, `import("./${exposesChunk}")`);
|
|
4323
|
+
if (!isRolldown) return;
|
|
4324
|
+
const chunk = bundle[ssrOutputFilename];
|
|
4325
|
+
if (!chunk || chunk.type !== "chunk") return;
|
|
4326
|
+
}
|
|
4327
|
+
}];
|
|
4328
|
+
}
|
|
4329
|
+
//#endregion
|
|
4141
4330
|
//#region src/plugins/pluginVarRemoteEntry.ts
|
|
4142
4331
|
const VarRemoteEntry = () => {
|
|
4143
4332
|
const mfOptions = getNormalizeModuleFederationOptions();
|
|
@@ -4173,9 +4362,9 @@ const VarRemoteEntry = () => {
|
|
|
4173
4362
|
},
|
|
4174
4363
|
async generateBundle(_options, bundle) {
|
|
4175
4364
|
if (!varFilename) return;
|
|
4176
|
-
if (!isValidVarName(name)) mfWarn(`Provided remote name "${name}" is not valid for "var" remoteEntry type, thus it's placed in globalThis['${name}'].\nIt may cause problems, so you would better want to use valid var name (see https://www.w3schools.com/js/js_variables.asp).`);
|
|
4365
|
+
if (!isValidVarName(name)) require_packageUtils.mfWarn(`Provided remote name "${name}" is not valid for "var" remoteEntry type, thus it's placed in globalThis['${name}'].\nIt may cause problems, so you would better want to use valid var name (see https://www.w3schools.com/js/js_variables.asp).`);
|
|
4177
4366
|
const remoteEntryFile = findRemoteEntryFile(mfOptions.filename, bundle);
|
|
4178
|
-
if (!remoteEntryFile) throw createModuleFederationError(`Couldn't find a remoteEntry chunk file for ${mfOptions.filename}, can't generate varRemoteEntry file`);
|
|
4367
|
+
if (!remoteEntryFile) throw require_packageUtils.createModuleFederationError(`Couldn't find a remoteEntry chunk file for ${mfOptions.filename}, can't generate varRemoteEntry file`);
|
|
4179
4368
|
this.emitFile({
|
|
4180
4369
|
type: "asset",
|
|
4181
4370
|
fileName: varFilename,
|
|
@@ -4398,10 +4587,15 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
4398
4587
|
config(config, { command: _command }) {
|
|
4399
4588
|
if (_command === "serve") ignoreFederationGeneratedFiles(config, options);
|
|
4400
4589
|
const root = config.root || process.cwd();
|
|
4401
|
-
setPackageDetectionCwd(root);
|
|
4402
|
-
const isVinext = hasPackageDependency("vinext");
|
|
4590
|
+
require_packageUtils.setPackageDetectionCwd(root);
|
|
4591
|
+
const isVinext = require_packageUtils.hasPackageDependency("vinext");
|
|
4592
|
+
setSsrRemotes(Object.entries(options.remotes).map(([key, r]) => ({
|
|
4593
|
+
name: key,
|
|
4594
|
+
entry: r.entry,
|
|
4595
|
+
type: r.type ?? "module"
|
|
4596
|
+
})));
|
|
4403
4597
|
initVirtualModules(_command, getRemoteEntryId(options));
|
|
4404
|
-
const isRolldown = getIsRolldown(this);
|
|
4598
|
+
const isRolldown = require_packageUtils.getIsRolldown(this);
|
|
4405
4599
|
if (remotes && Object.keys(remotes).length > 0) {
|
|
4406
4600
|
for (const key of Object.keys(remotes)) addUsedRemote(key, key);
|
|
4407
4601
|
if (_command === "serve") {
|
|
@@ -4509,22 +4703,62 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
4509
4703
|
if (isLitShare(key)) optimizeDeps.exclude.push(key);
|
|
4510
4704
|
else optimizeDeps.include.push(key);
|
|
4511
4705
|
for (const subpath of getCommonSharedSubpaths(key)) {
|
|
4706
|
+
getLoadShareModulePath(subpath, isRolldown);
|
|
4707
|
+
writeLoadShareModule(subpath, shareItem, _command, isRolldown);
|
|
4512
4708
|
writePreBuildLibPath(subpath, shareItem);
|
|
4709
|
+
addUsedShares(subpath);
|
|
4513
4710
|
optimizeDeps.include.push(subpath);
|
|
4514
4711
|
}
|
|
4515
4712
|
}
|
|
4516
4713
|
}
|
|
4517
4714
|
writeLocalSharedImportMap();
|
|
4518
4715
|
}
|
|
4716
|
+
},
|
|
4717
|
+
configResolved(config) {
|
|
4718
|
+
if (parseInt(vite.version, 10) < 8) return;
|
|
4719
|
+
if (!(Object.keys(options.exposes).length > 0 || Object.keys(options.remotes).length > 0)) return;
|
|
4720
|
+
if (options.runtimePlugins.some((p) => {
|
|
4721
|
+
return (typeof p === "string" ? p : p[0]) === "@module-federation/vite/ssrEntryLoader";
|
|
4722
|
+
})) return;
|
|
4723
|
+
const pluginRequire = (0, module$1.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
4724
|
+
const projectRequire = (0, module$1.createRequire)(new URL(`file://${config.root}/package.json`));
|
|
4725
|
+
const sharedKeys = Object.keys(options.shared ?? {});
|
|
4726
|
+
const commonSharedPkgs = [
|
|
4727
|
+
"react",
|
|
4728
|
+
"react-dom",
|
|
4729
|
+
"react/jsx-runtime",
|
|
4730
|
+
"react/jsx-dev-runtime",
|
|
4731
|
+
"@module-federation/runtime",
|
|
4732
|
+
"@module-federation/runtime-core",
|
|
4733
|
+
"@module-federation/sdk"
|
|
4734
|
+
];
|
|
4735
|
+
const resolvedShared = {};
|
|
4736
|
+
for (const pkg of [...commonSharedPkgs, ...sharedKeys]) try {
|
|
4737
|
+
resolvedShared[pkg] = projectRequire.resolve(pkg);
|
|
4738
|
+
} catch {
|
|
4739
|
+
try {
|
|
4740
|
+
resolvedShared[pkg] = pluginRequire.resolve(pkg);
|
|
4741
|
+
} catch {}
|
|
4742
|
+
}
|
|
4743
|
+
const ssrEntryLoaderSpecifier = "@module-federation/vite/ssrEntryLoader";
|
|
4744
|
+
try {
|
|
4745
|
+
pluginRequire.resolve(ssrEntryLoaderSpecifier);
|
|
4746
|
+
options.runtimePlugins.push([ssrEntryLoaderSpecifier, { resolvedShared }]);
|
|
4747
|
+
} catch {}
|
|
4519
4748
|
}
|
|
4520
4749
|
};
|
|
4521
4750
|
}
|
|
4751
|
+
const SSR_ONLY_PLUGINS = new Set(["@module-federation/vite/ssrEntryLoader"]);
|
|
4752
|
+
function loadPluginDts(options) {
|
|
4753
|
+
if (options.dts === false) return [];
|
|
4754
|
+
return [Promise.resolve().then(() => require("./pluginDts-BEOKyKQ-.cjs")).then(({ default: pluginDts }) => pluginDts(options))];
|
|
4755
|
+
}
|
|
4522
4756
|
function federation(mfUserOptions) {
|
|
4523
4757
|
if (isTestEnv()) return [];
|
|
4524
4758
|
const options = normalizeModuleFederationOptions(mfUserOptions);
|
|
4525
|
-
const isVinext = hasPackageDependency("vinext");
|
|
4759
|
+
const isVinext = require_packageUtils.hasPackageDependency("vinext");
|
|
4526
4760
|
const { name, shared, filename, hostInitInjectLocation } = options;
|
|
4527
|
-
if (!name) throw createModuleFederationError("name is required");
|
|
4761
|
+
if (!name) throw require_packageUtils.createModuleFederationError("name is required");
|
|
4528
4762
|
const remoteEntryId = getRemoteEntryId(options);
|
|
4529
4763
|
const virtualExposesId = getVirtualExposesId(options);
|
|
4530
4764
|
let command;
|
|
@@ -4570,14 +4804,26 @@ function federation(mfUserOptions) {
|
|
|
4570
4804
|
command = env.command;
|
|
4571
4805
|
},
|
|
4572
4806
|
configResolved() {
|
|
4573
|
-
initVirtualModules(command, remoteEntryId);
|
|
4807
|
+
initVirtualModules(command, remoteEntryId, parseInt(vite.version, 10) >= 8);
|
|
4574
4808
|
}
|
|
4575
4809
|
},
|
|
4576
4810
|
aliasToArrayPlugin_default,
|
|
4577
4811
|
checkAliasConflicts({ shared }),
|
|
4578
4812
|
normalizeOptimizeDeps_default,
|
|
4579
|
-
...
|
|
4813
|
+
...loadPluginDts(options),
|
|
4580
4814
|
pluginDevRemoteHmr(options),
|
|
4815
|
+
{
|
|
4816
|
+
name: "mf:normalize-entry-chunks",
|
|
4817
|
+
enforce: "pre",
|
|
4818
|
+
apply: "build",
|
|
4819
|
+
generateBundle(_options, bundle) {
|
|
4820
|
+
for (const chunk of Object.values(bundle)) {
|
|
4821
|
+
if (typeof chunk !== "object" || chunk === null || chunk.type !== "chunk" || !chunk.isEntry) continue;
|
|
4822
|
+
const facadeId = chunk.facadeModuleId ?? "";
|
|
4823
|
+
if (facadeId.includes("__mf__virtual") || facadeId.startsWith("virtual:mf-") || facadeId.startsWith("virtual:mf:") || facadeId.startsWith("\0virtual:mf-") || facadeId.startsWith("\0virtual:mf:")) chunk.isEntry = false;
|
|
4824
|
+
}
|
|
4825
|
+
}
|
|
4826
|
+
},
|
|
4581
4827
|
...addEntry({
|
|
4582
4828
|
entryName: "remoteEntry",
|
|
4583
4829
|
entryPath: remoteEntryId,
|
|
@@ -4587,7 +4833,8 @@ function federation(mfUserOptions) {
|
|
|
4587
4833
|
entryName: "hostInit",
|
|
4588
4834
|
entryPath: () => getHostAutoInitPath(),
|
|
4589
4835
|
inject: hostInitInjectLocation,
|
|
4590
|
-
forceClientInjected: Object.keys(options.exposes).length > 0
|
|
4836
|
+
forceClientInjected: Object.keys(options.exposes).length > 0,
|
|
4837
|
+
skipTransformFor: Object.values(options.exposes).map((expose) => expose.import)
|
|
4591
4838
|
}),
|
|
4592
4839
|
...addEntry({
|
|
4593
4840
|
entryName: "virtualExposes",
|
|
@@ -4637,7 +4884,7 @@ function federation(mfUserOptions) {
|
|
|
4637
4884
|
delete output.codeSplitting;
|
|
4638
4885
|
if (warnedAboutCodeSplitting) return;
|
|
4639
4886
|
warnedAboutCodeSplitting = true;
|
|
4640
|
-
mfWarn("Ignoring `output.codeSplitting = false` because module federation requires chunk splitting.");
|
|
4887
|
+
require_packageUtils.mfWarn("Ignoring `output.codeSplitting = false` because module federation requires chunk splitting.");
|
|
4641
4888
|
return;
|
|
4642
4889
|
}
|
|
4643
4890
|
if (!output?.codeSplitting || typeof output.codeSplitting !== "object") return;
|
|
@@ -4646,7 +4893,7 @@ function federation(mfUserOptions) {
|
|
|
4646
4893
|
if (Object.keys(output.codeSplitting).length === 0) delete output.codeSplitting;
|
|
4647
4894
|
if (warnedAboutCodeSplittingGroups) return;
|
|
4648
4895
|
warnedAboutCodeSplittingGroups = true;
|
|
4649
|
-
mfWarn("Ignoring `output.codeSplitting.groups` because it conflicts with module federation. Grouping shared dependency init wrappers with their dependent modules can break runtime init order and cause standalone remotes to fail before mount.");
|
|
4896
|
+
require_packageUtils.mfWarn("Ignoring `output.codeSplitting.groups` because it conflicts with module federation. Grouping shared dependency init wrappers with their dependent modules can break runtime init order and cause standalone remotes to fail before mount.");
|
|
4650
4897
|
};
|
|
4651
4898
|
let warnedAboutManualChunks = false;
|
|
4652
4899
|
const applyManualChunks = (output) => {
|
|
@@ -4654,7 +4901,7 @@ function federation(mfUserOptions) {
|
|
|
4654
4901
|
const isPatchedByPlugin = typeof output.manualChunks === "function" && patchedManualChunks.has(output.manualChunks);
|
|
4655
4902
|
if (output.manualChunks && !isPatchedByPlugin && !warnedAboutManualChunks) {
|
|
4656
4903
|
warnedAboutManualChunks = true;
|
|
4657
|
-
mfWarn("Ignoring `output.manualChunks` because it conflicts with module federation. Module federation transforms shared dependency imports with async init wrappers, and grouping these transformed modules into a single chunk creates circular async dependencies that cause the application to silently hang.");
|
|
4904
|
+
require_packageUtils.mfWarn("Ignoring `output.manualChunks` because it conflicts with module federation. Module federation transforms shared dependency imports with async init wrappers, and grouping these transformed modules into a single chunk creates circular async dependencies that cause the application to silently hang.");
|
|
4658
4905
|
}
|
|
4659
4906
|
const mfManualChunks = function(id) {
|
|
4660
4907
|
if (id.includes(runtimeInitId)) return "runtimeInit";
|
|
@@ -4732,11 +4979,11 @@ function federation(mfUserOptions) {
|
|
|
4732
4979
|
*
|
|
4733
4980
|
* @see https://rollupjs.org/plugin-development/#synthetic-named-exports
|
|
4734
4981
|
*/
|
|
4735
|
-
if (!/\bexport\s+const\s+__moduleExports\b/.test(code)) {
|
|
4982
|
+
if (!/\bexport\s+const\s+__moduleExports\b/.test(code) && !/\bexport\s*\{[^}]*__moduleExports/.test(code)) {
|
|
4736
4983
|
const nextCode = code.replace("export default exportModule", "export const __moduleExports = exportModule;\nexport default exportModule.__esModule ? exportModule.default : exportModule");
|
|
4737
4984
|
code = nextCode === code ? `${code}\nexport const __moduleExports = exportModule;\n` : nextCode;
|
|
4738
4985
|
}
|
|
4739
|
-
if (getIsRolldown(this)) return { code };
|
|
4986
|
+
if (require_packageUtils.getIsRolldown(this)) return { code };
|
|
4740
4987
|
return {
|
|
4741
4988
|
code,
|
|
4742
4989
|
syntheticNamedExports: "__moduleExports"
|
|
@@ -4790,7 +5037,7 @@ function federation(mfUserOptions) {
|
|
|
4790
5037
|
enforce: "post",
|
|
4791
5038
|
_options: options,
|
|
4792
5039
|
config(config, { command: _command }) {
|
|
4793
|
-
const isRolldown = getIsRolldown(this);
|
|
5040
|
+
const isRolldown = require_packageUtils.getIsRolldown(this);
|
|
4794
5041
|
let implementation = options.implementation;
|
|
4795
5042
|
if (isRolldown) implementation = implementation.replace(/\.cjs(\.js)?$/, ".js");
|
|
4796
5043
|
appendResolveAlias(config, {
|
|
@@ -4805,27 +5052,29 @@ function federation(mfUserOptions) {
|
|
|
4805
5052
|
config.optimizeDeps.include.push("@module-federation/runtime");
|
|
4806
5053
|
options.runtimePlugins.forEach((p) => {
|
|
4807
5054
|
const pluginPath = typeof p === "string" ? p : p[0];
|
|
5055
|
+
if (SSR_ONLY_PLUGINS.has(pluginPath)) return;
|
|
4808
5056
|
if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) config.optimizeDeps.include.push(pluginPath);
|
|
4809
5057
|
});
|
|
4810
5058
|
if (isRolldown) {
|
|
4811
5059
|
config.build ??= {};
|
|
4812
5060
|
config.build.target ??= "esnext";
|
|
4813
5061
|
}
|
|
4814
|
-
const isAstro = hasPackageDependency("astro");
|
|
5062
|
+
const isAstro = require_packageUtils.hasPackageDependency("astro");
|
|
4815
5063
|
const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
|
|
4816
5064
|
const envTargetDefineValue = !options.target && isAstro ? "undefined" : JSON.stringify(resolvedTarget);
|
|
4817
5065
|
if (!config.define) config.define = {};
|
|
4818
5066
|
if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] = envTargetDefineValue;
|
|
4819
|
-
if (options.target && "ENV_TARGET" in config.define && config.define["ENV_TARGET"] !== JSON.stringify(options.target)) mfWarn(`ENV_TARGET define (${config.define["ENV_TARGET"]}) differs from target option ("${options.target}"). ENV_TARGET will not be overridden.`);
|
|
5067
|
+
if (options.target && "ENV_TARGET" in config.define && config.define["ENV_TARGET"] !== JSON.stringify(options.target)) require_packageUtils.mfWarn(`ENV_TARGET define (${config.define["ENV_TARGET"]}) differs from target option ("${options.target}"). ENV_TARGET will not be overridden.`);
|
|
4820
5068
|
}
|
|
4821
5069
|
},
|
|
4822
5070
|
...Manifest(),
|
|
5071
|
+
...pluginSSRRemoteEntry(options),
|
|
4823
5072
|
...VarRemoteEntry(),
|
|
4824
5073
|
{
|
|
4825
5074
|
name: "module-federation-vinext-fix-rsc-preload-as",
|
|
4826
5075
|
enforce: "post",
|
|
4827
5076
|
configureServer(server) {
|
|
4828
|
-
if (!hasPackageDependency("vinext")) return;
|
|
5077
|
+
if (!require_packageUtils.hasPackageDependency("vinext")) return;
|
|
4829
5078
|
server.middlewares.use((req, res, next) => {
|
|
4830
5079
|
if (!req.headers.accept?.includes("text/html")) {
|
|
4831
5080
|
next();
|
|
@@ -4845,7 +5094,7 @@ function federation(mfUserOptions) {
|
|
|
4845
5094
|
});
|
|
4846
5095
|
},
|
|
4847
5096
|
generateBundle(_, bundle, _isWrite) {
|
|
4848
|
-
if (!hasPackageDependency("vinext")) return;
|
|
5097
|
+
if (!require_packageUtils.hasPackageDependency("vinext")) return;
|
|
4849
5098
|
for (const chunk of Object.values(bundle)) {
|
|
4850
5099
|
if (!isOutputChunk(chunk)) continue;
|
|
4851
5100
|
if (!chunk.code.includes("case\"L\"")) continue;
|
|
@@ -4893,5 +5142,9 @@ function federation(mfUserOptions) {
|
|
|
4893
5142
|
})()
|
|
4894
5143
|
];
|
|
4895
5144
|
}
|
|
5145
|
+
function createModuleFederationConfig(options) {
|
|
5146
|
+
return options;
|
|
5147
|
+
}
|
|
4896
5148
|
//#endregion
|
|
5149
|
+
exports.createModuleFederationConfig = createModuleFederationConfig;
|
|
4897
5150
|
exports.federation = federation;
|