@module-federation/vite 1.22.1 → 1.23.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 +19 -0
- package/lib/{dtsConstants-dDsHZFC1.js → dtsConstants-DEMpRfBz.js} +231 -59
- package/lib/index.d.ts +14 -1
- package/lib/index.js +1076 -366
- package/lib/{pluginDts-CQ088qGF.js → pluginDts-VSLhAx6d.js} +1 -1
- package/lib/{sharedKeyMatcher-BRzBCbuR.js → sharedKeyMatcher-Od_nYxJA.js} +39 -10
- package/lib/{ssrEntryLoader-BUXUQi0P.js → ssrEntryLoader-BvAkpCyi.js} +1 -1
- package/lib/{ssrVmStrategy-Ud06y3Xf.js → ssrVmStrategy-CDbcwMnf.js} +2 -2
- package/lib/utils/ssrEntryLoader.js +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -119,6 +119,9 @@ export default defineConfig({
|
|
|
119
119
|
// optional: additional "var" remoteEntry file
|
|
120
120
|
// needed only for legacy hosts with "var" usage (remote.type = 'var')
|
|
121
121
|
varFilename: "varRemoteEntry.js",
|
|
122
|
+
// optional: exact name of the SSR remote entry
|
|
123
|
+
// default: "<filename base>.ssr.js" (e.g. remoteEntry.ssr.js)
|
|
124
|
+
ssrFilename: "remoteEntry.ssr.js",
|
|
122
125
|
exposes: {
|
|
123
126
|
"./remote-app": "./src/App.vue",
|
|
124
127
|
},
|
|
@@ -151,6 +154,18 @@ shared: {
|
|
|
151
154
|
|
|
152
155
|
`suppressMissingImportWarning` defaults to `false`. Enable it only when the host is guaranteed to provide the dependency and local named-export detection is unnecessary.
|
|
153
156
|
|
|
157
|
+
In a production build, a host-only dependency that the exposed modules reach only through a dynamic `import()` is not fetched while the remote initializes. It is loaded from the host's provider when that `import()` runs, before the imported chunk evaluates. A dependency imported statically by an exposed module, or configured with `eager: true`, is still loaded during initialization.
|
|
158
|
+
|
|
159
|
+
### Shared dependencies installed in several places
|
|
160
|
+
|
|
161
|
+
An absolute import that resolves inside a different `node_modules` directory than the one the share itself resolves to, for example a workspace package with its own nested copy, is not treated as the shared module by default. Set `allowNodeModulesSuffixMatch: true` on the share to match it by the path after `node_modules/`, as webpack and rspack do with the same option:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
shared: {
|
|
165
|
+
react: { singleton: true, allowNodeModulesSuffixMatch: true },
|
|
166
|
+
},
|
|
167
|
+
```
|
|
168
|
+
|
|
154
169
|
## The Host Application configuration
|
|
155
170
|
|
|
156
171
|
file **host/vite.config.ts**
|
|
@@ -263,6 +278,8 @@ federation({
|
|
|
263
278
|
|
|
264
279
|
The `"vm"` strategy requires Node.js to run with `--experimental-vm-modules`. When unavailable, the loader warns once and falls back to `"temp-file"`. Vite 8 development uses `ModuleRunner`; this option primarily affects build and preview SSR entry loading.
|
|
265
280
|
|
|
281
|
+
The SSR remote entry is emitted as `<filename base>.ssr.js` next to the browser entry, or under the exact name given by `ssrFilename`, and is advertised as `metaData.ssrRemoteEntry` in `mf-manifest.json`. It keeps `@module-federation/runtime`, `@module-federation/runtime-core` and `@module-federation/sdk` external by default so Node resolves them from the host. Hosts that cannot resolve those packages, such as a plain `@module-federation/enhanced` host using the SDK's reference Node loader, need a self-contained entry: opt the packages back in with Vite's `ssr.noExternal` (for example `ssr: { noExternal: true }`) on the remote.
|
|
282
|
+
|
|
266
283
|
## Runtime capability optimization
|
|
267
284
|
|
|
268
285
|
Runtime features that a build never uses can be removed at build time:
|
|
@@ -391,6 +408,8 @@ Do not set `build.rollupOptions.output.codeSplitting` or
|
|
|
391
408
|
`build.rolldownOptions.output.codeSplitting` to `false` — it will be **ignored** (with a warning).
|
|
392
409
|
Module Federation requires chunk splitting so `runtimeInitStatus` and deferred `loadShare` wrappers stay isolated for correct bootstrap order. Eager `loadShare` wrappers are coalesced into one `loadShare-eager` chunk to reduce startup requests, on both Rolldown (Vite 8+) and Rollup (Vite 5–7).
|
|
393
410
|
|
|
411
|
+
Non-eager `loadShare` wrappers that reach their local `__prebuild__` fallback only through `import()` are merged into one `__loadShare__shared` chunk per `federation()` instance, with the shared-cache helpers included once. A wrapper that statically imports its local payload keeps its own chunk, since merging it could close a top-level-await cycle. `__prebuild__` fallbacks stay in separate lazily imported chunks, so a consumer never downloads its local copy when a peer already provides the share. The plugin warns at build time if a fallback ends up inside the merged chunk.
|
|
412
|
+
|
|
394
413
|
### `codeSplitting.groups` (Vite 8+ / Rolldown)
|
|
395
414
|
|
|
396
415
|
User groups are now **preserved**. The plugin installs its own federation groups at the highest priority and appends your groups below them, so your groups can only claim modules the federation groups didn't.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
1
|
+
import { d as getNodeModulesSuffix, r as getSharedRuntimeKey } from "./sharedKeyMatcher-Od_nYxJA.js";
|
|
2
|
+
import { existsSync, readFileSync, readdirSync, realpathSync } from "fs";
|
|
3
3
|
import { createRequire } from "module";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
@@ -35,6 +35,29 @@ const moduleFederationConsole = {
|
|
|
35
35
|
const mfWarn = moduleFederationConsole.warn;
|
|
36
36
|
const mfError = moduleFederationConsole.error;
|
|
37
37
|
//#endregion
|
|
38
|
+
//#region src/utils/reactShares.ts
|
|
39
|
+
/** Property under which React 19 exposes its internals object. */
|
|
40
|
+
const REACT_CLIENT_INTERNALS_KEY = "__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE";
|
|
41
|
+
/**
|
|
42
|
+
* Every property React has used for its internals object, newest first. Two
|
|
43
|
+
* module objects that expose the same internals are the same React instance.
|
|
44
|
+
*/
|
|
45
|
+
const REACT_INTERNALS_KEYS = [
|
|
46
|
+
REACT_CLIENT_INTERNALS_KEY,
|
|
47
|
+
"__TEST_INTERNALS",
|
|
48
|
+
"__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED"
|
|
49
|
+
];
|
|
50
|
+
/**
|
|
51
|
+
* Importing this share's local fallback registers a DOM renderer as a side
|
|
52
|
+
* effect. An entry-injected leaf must not evaluate its own copy while the host
|
|
53
|
+
* renderer already owns the root, so its wrapper waits for the cache or init.
|
|
54
|
+
*/
|
|
55
|
+
const REACT_DOM_CLIENT_SHARE = "react-dom/client";
|
|
56
|
+
/** React and its subpath exports must bind synchronously for CJS consumers. */
|
|
57
|
+
function isReactCoreShare(pkg) {
|
|
58
|
+
return pkg === "react" || pkg.startsWith("react/");
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
38
61
|
//#region src/utils/packageUtils.ts
|
|
39
62
|
const dependencyPresenceCache = /* @__PURE__ */ new Map();
|
|
40
63
|
let packageDetectionCwd;
|
|
@@ -42,6 +65,7 @@ function getDependencyCacheKey(cwd, dependencyName) {
|
|
|
42
65
|
return `${cwd}:${dependencyName}`;
|
|
43
66
|
}
|
|
44
67
|
const installedPackageJsonCache = /* @__PURE__ */ new Map();
|
|
68
|
+
const dependentsLookupCache = /* @__PURE__ */ new Map();
|
|
45
69
|
function setPackageDetectionCwd(cwd) {
|
|
46
70
|
packageDetectionCwd = cwd;
|
|
47
71
|
}
|
|
@@ -213,7 +237,7 @@ function getSharedCacheKeyParts(input) {
|
|
|
213
237
|
}
|
|
214
238
|
function getSharedCacheDescriptor(pkg, shareItem) {
|
|
215
239
|
const parts = getSharedCacheKeyParts({
|
|
216
|
-
pkg,
|
|
240
|
+
pkg: shareItem.shareConfig.request !== void 0 || shareItem.shareConfig.shareKey !== void 0 ? getSharedRuntimeKey(pkg, shareItem) : pkg,
|
|
217
241
|
singleton: shareItem.shareConfig.singleton,
|
|
218
242
|
version: shareItem.version,
|
|
219
243
|
scope: shareItem.scope
|
|
@@ -279,7 +303,47 @@ const sharedCacheHelperCode = `const __mfGetSharedCacheDescriptor = (pkg, single
|
|
|
279
303
|
};
|
|
280
304
|
const __mfReadSharedCacheOwner = (cache, descriptor) =>
|
|
281
305
|
cache[__mfSharedCacheOwnersKey]?.[descriptor.canonical];
|
|
306
|
+
const __mfGetSharedModuleIdentity = (value) => {
|
|
307
|
+
const candidates = [value, value?.default];
|
|
308
|
+
for (const candidate of candidates) {
|
|
309
|
+
if (!candidate || typeof candidate !== "object") continue;
|
|
310
|
+
for (const key of ${JSON.stringify(REACT_INTERNALS_KEYS)}) {
|
|
311
|
+
const internals = candidate[key];
|
|
312
|
+
if (internals && typeof internals === "object") {
|
|
313
|
+
return { internals };
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (typeof candidate.useState === "function") return { hook: candidate.useState };
|
|
317
|
+
}
|
|
318
|
+
return undefined;
|
|
319
|
+
};
|
|
320
|
+
const __mfIsSameSharedModule = (current, next) => {
|
|
321
|
+
if (current === next) return true;
|
|
322
|
+
const currentIdentity = __mfGetSharedModuleIdentity(current);
|
|
323
|
+
const nextIdentity = __mfGetSharedModuleIdentity(next);
|
|
324
|
+
if (!currentIdentity || !nextIdentity) return false;
|
|
325
|
+
const currentInternals = currentIdentity.internals;
|
|
326
|
+
const nextInternals = nextIdentity.internals;
|
|
327
|
+
// Internals identity is authoritative when either side exposes it.
|
|
328
|
+
// Never treat absent fields as equal (undefined === undefined).
|
|
329
|
+
if (currentInternals !== undefined || nextInternals !== undefined) {
|
|
330
|
+
return (
|
|
331
|
+
currentInternals !== undefined &&
|
|
332
|
+
currentInternals === nextInternals
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
// Hook identity is only a fallback when neither side exposes internals.
|
|
336
|
+
return (
|
|
337
|
+
typeof currentIdentity.hook === "function" &&
|
|
338
|
+
currentIdentity.hook === nextIdentity.hook
|
|
339
|
+
);
|
|
340
|
+
};
|
|
282
341
|
const __mfWriteSharedCache = (cache, descriptor, value, owner) => {
|
|
342
|
+
// Rewriting the same instance is a no-op on purpose: the first
|
|
343
|
+
// provider keeps ownership and subscribers are not re-notified, so
|
|
344
|
+
// an already-bound renderer never sees its React rebound.
|
|
345
|
+
const current = __mfReadSharedCache(cache, descriptor);
|
|
346
|
+
if (current !== undefined && __mfIsSameSharedModule(current, value)) return value;
|
|
283
347
|
cache[descriptor.canonical] = value;
|
|
284
348
|
const aliases = descriptor.aliases || [];
|
|
285
349
|
for (const alias of aliases) {
|
|
@@ -378,85 +442,181 @@ function getInstalledPackageJson(pkg, opts) {
|
|
|
378
442
|
installedPackageJsonCache.set(cacheKey, result);
|
|
379
443
|
return result;
|
|
380
444
|
}
|
|
445
|
+
function tryReadPackageJson(packageJsonPath, expectedName) {
|
|
446
|
+
if (!existsSync(packageJsonPath)) return void 0;
|
|
447
|
+
try {
|
|
448
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
449
|
+
if (expectedName !== void 0 && packageJson.name !== expectedName) return void 0;
|
|
450
|
+
return {
|
|
451
|
+
path: packageJsonPath,
|
|
452
|
+
dir: path$1.dirname(packageJsonPath),
|
|
453
|
+
packageJson
|
|
454
|
+
};
|
|
455
|
+
} catch {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
381
459
|
function resolveInstalledPackageJson(pkg, cwd, packageName, opts) {
|
|
382
|
-
const tryReadPackageJson = (packageJsonPath) => {
|
|
383
|
-
if (!existsSync(packageJsonPath)) return void 0;
|
|
384
|
-
try {
|
|
385
|
-
return {
|
|
386
|
-
path: packageJsonPath,
|
|
387
|
-
dir: path$1.dirname(packageJsonPath),
|
|
388
|
-
packageJson: JSON.parse(readFileSync(packageJsonPath, "utf-8"))
|
|
389
|
-
};
|
|
390
|
-
} catch {
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
460
|
const findPackageInPnpmStore = (startDir) => {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
461
|
+
for (const dir of ancestorDirs(startDir)) {
|
|
462
|
+
const pnpmStoreDir = path$1.join(dir, "node_modules", ".pnpm");
|
|
463
|
+
if (!existsSync(pnpmStoreDir)) continue;
|
|
464
|
+
try {
|
|
399
465
|
for (const entry of readdirSync(pnpmStoreDir, { withFileTypes: true })) {
|
|
400
466
|
if (!entry.isDirectory()) continue;
|
|
401
467
|
const candidate = tryReadPackageJson(path$1.join(pnpmStoreDir, entry.name, "node_modules", packageName, "package.json"));
|
|
402
468
|
if (candidate?.packageJson.name === packageName) return candidate;
|
|
403
469
|
}
|
|
404
470
|
} catch {}
|
|
405
|
-
const parentDir = path$1.dirname(currentDir);
|
|
406
|
-
if (parentDir === currentDir) break;
|
|
407
|
-
currentDir = parentDir;
|
|
408
471
|
}
|
|
409
472
|
};
|
|
410
473
|
let resolvedPath;
|
|
411
474
|
try {
|
|
412
|
-
const
|
|
475
|
+
const rootPackageJson = path$1.join(cwd, "package.json");
|
|
413
476
|
if (opts?.fromResolvedEntry) resolvedPath = opts.fromResolvedEntry;
|
|
414
477
|
else try {
|
|
415
|
-
resolvedPath =
|
|
478
|
+
resolvedPath = resolveModulePath(pkg, rootPackageJson);
|
|
416
479
|
} catch {
|
|
417
|
-
resolvedPath =
|
|
480
|
+
resolvedPath = resolveModulePath(packageName, rootPackageJson);
|
|
418
481
|
}
|
|
419
482
|
} catch {
|
|
420
483
|
resolvedPath = void 0;
|
|
421
484
|
}
|
|
422
485
|
if (resolvedPath !== void 0 && !path$1.isAbsolute(resolvedPath)) resolvedPath = void 0;
|
|
423
|
-
if (resolvedPath !== void 0)
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
486
|
+
if (resolvedPath !== void 0) {
|
|
487
|
+
const owner = findOwningPackageJson(path$1.dirname(resolvedPath), packageName);
|
|
488
|
+
if (owner) return owner;
|
|
489
|
+
}
|
|
490
|
+
for (const dir of ancestorDirs(cwd)) {
|
|
491
|
+
const directCandidate = tryReadPackageJson(path$1.join(dir, "node_modules", packageName, "package.json"), packageName);
|
|
492
|
+
if (directCandidate) return directCandidate;
|
|
493
|
+
}
|
|
494
|
+
return findPackageInDependents(packageName, cwd) ?? findPackageInPnpmStore(cwd);
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* A package installed only under a dependent is invisible to the walks above.
|
|
498
|
+
* Resolving it from each dependent in turn follows the same links that dependent
|
|
499
|
+
* does, so the copy found is the version it is installed against rather than
|
|
500
|
+
* whichever one the pnpm store happens to list first.
|
|
501
|
+
*/
|
|
502
|
+
function findPackageInDependents(packageName, cwd) {
|
|
503
|
+
const cacheKey = `${cwd}\0${packageName}`;
|
|
504
|
+
if (!dependentsLookupCache.has(cacheKey)) dependentsLookupCache.set(cacheKey, walkDependents(packageName, cwd));
|
|
505
|
+
return dependentsLookupCache.get(cacheKey);
|
|
506
|
+
}
|
|
507
|
+
function walkDependents(packageName, cwd) {
|
|
508
|
+
const root = tryReadPackageJson(path$1.join(cwd, "package.json"));
|
|
509
|
+
if (!root) return void 0;
|
|
510
|
+
const visited = /* @__PURE__ */ new Set();
|
|
511
|
+
const rootDependencyGroups = [getDependencyNames(root.packageJson), getDependencyNames(root.packageJson, ["devDependencies"])];
|
|
512
|
+
for (const rootDependencies of rootDependencyGroups) {
|
|
513
|
+
let level = rootDependencies.map((name) => ({
|
|
514
|
+
name,
|
|
515
|
+
fromDir: cwd
|
|
516
|
+
}));
|
|
517
|
+
while (level.length) {
|
|
518
|
+
const candidates = [];
|
|
519
|
+
const nextLevel = [];
|
|
520
|
+
for (const { name, fromDir } of level) {
|
|
521
|
+
if (name === packageName) continue;
|
|
522
|
+
const dependent = findPackageFrom(name, fromDir);
|
|
523
|
+
if (!dependent || visited.has(dependent.dir)) continue;
|
|
524
|
+
visited.add(dependent.dir);
|
|
525
|
+
const dependencies = getDependencyNames(dependent.packageJson);
|
|
526
|
+
if (dependencies.includes(packageName)) {
|
|
527
|
+
const copy = findPackageFrom(packageName, dependent.dir);
|
|
528
|
+
if (copy) candidates.push({
|
|
529
|
+
copy,
|
|
530
|
+
via: name
|
|
531
|
+
});
|
|
443
532
|
}
|
|
533
|
+
for (const dependency of dependencies) nextLevel.push({
|
|
534
|
+
name: dependency,
|
|
535
|
+
fromDir: dependent.dir
|
|
536
|
+
});
|
|
444
537
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
538
|
+
if (candidates.length) {
|
|
539
|
+
warnOnAmbiguousDependents(packageName, candidates);
|
|
540
|
+
return candidates[0].copy;
|
|
541
|
+
}
|
|
542
|
+
level = nextLevel;
|
|
448
543
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function warnOnAmbiguousDependents(packageName, candidates) {
|
|
547
|
+
const viaByVersion = /* @__PURE__ */ new Map();
|
|
548
|
+
for (const { copy, via } of candidates) if (!viaByVersion.has(copy.packageJson.version)) viaByVersion.set(copy.packageJson.version, via);
|
|
549
|
+
if (viaByVersion.size < 2) return;
|
|
550
|
+
const versions = [...viaByVersion].map(([version, via]) => `${version} (via ${via})`);
|
|
551
|
+
mfWarn(`Shared package "${packageName}" is not a dependency of the project, and its closest dependents install different versions: ${versions.join(", ")}. The fallback uses ${versions[0]}. Add "${packageName}" to the project's dependencies or set its shared "import" to choose the version.`);
|
|
552
|
+
}
|
|
553
|
+
/** The package Node's `node_modules` lookup finds from `fromDir`, read at its real path. */
|
|
554
|
+
function findPackageFrom(packageName, fromDir) {
|
|
555
|
+
const entry = findNodeModulesEntry(packageName, fromDir);
|
|
556
|
+
if (!entry) return void 0;
|
|
557
|
+
try {
|
|
558
|
+
return tryReadPackageJson(path$1.join(realpathSync(entry), "package.json"), packageName);
|
|
559
|
+
} catch {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Walks up from `startDir` to the package.json named `packageName`, preferring the
|
|
565
|
+
* one at `node_modules/<packageName>` so a nested `package.json` (for example a
|
|
566
|
+
* subpath's `type: module` marker) does not shadow the package root.
|
|
567
|
+
*/
|
|
568
|
+
function findOwningPackageJson(startDir, packageName) {
|
|
569
|
+
let matchingPackage;
|
|
570
|
+
for (const dir of ancestorDirs(startDir)) {
|
|
571
|
+
const candidate = tryReadPackageJson(path$1.join(dir, "package.json"), packageName);
|
|
572
|
+
if (!candidate) continue;
|
|
573
|
+
if (dir.endsWith(path$1.join("node_modules", packageName))) return candidate;
|
|
574
|
+
matchingPackage ??= candidate;
|
|
575
|
+
}
|
|
576
|
+
return matchingPackage;
|
|
577
|
+
}
|
|
578
|
+
function* ancestorDirs(startDir) {
|
|
579
|
+
let dir = startDir;
|
|
452
580
|
while (true) {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
currentDir = parentDir;
|
|
581
|
+
yield dir;
|
|
582
|
+
const parentDir = path$1.dirname(dir);
|
|
583
|
+
if (parentDir === dir) return;
|
|
584
|
+
dir = parentDir;
|
|
458
585
|
}
|
|
459
|
-
|
|
586
|
+
}
|
|
587
|
+
/** The first `node_modules/<packageName>` that Node's lookup reaches from `fromDir`. */
|
|
588
|
+
function findNodeModulesEntry(packageName, fromDir) {
|
|
589
|
+
for (const dir of ancestorDirs(fromDir)) {
|
|
590
|
+
const entry = path$1.join(dir, "node_modules", packageName);
|
|
591
|
+
if (existsSync(entry)) return entry;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* `require.resolve(specifier)` from the file `from`, limited to the `node_modules` lookup
|
|
596
|
+
* bundlers perform. Node also searches NODE_PATH, which pnpm's bin shims point at the
|
|
597
|
+
* store's hoisted `node_modules`, so it can find packages the bundler cannot.
|
|
598
|
+
*/
|
|
599
|
+
function resolveModulePath(specifier, from) {
|
|
600
|
+
const resolved = createRequire(pathToFileURL(from)).resolve(specifier);
|
|
601
|
+
if (!path$1.isAbsolute(resolved) || specifier.startsWith(".") || path$1.isAbsolute(specifier) || process.versions.pnp) return resolved;
|
|
602
|
+
if (findNodeModulesEntry(getPackageName(specifier), path$1.dirname(from))) return resolved;
|
|
603
|
+
const error = /* @__PURE__ */ new Error(`Cannot find module '${specifier}' from '${from}'`);
|
|
604
|
+
error.code = "MODULE_NOT_FOUND";
|
|
605
|
+
throw error;
|
|
606
|
+
}
|
|
607
|
+
function getDependencyNames(packageJson, fields = [
|
|
608
|
+
"dependencies",
|
|
609
|
+
"peerDependencies",
|
|
610
|
+
"optionalDependencies"
|
|
611
|
+
]) {
|
|
612
|
+
if (!packageJson) return [];
|
|
613
|
+
const names = /* @__PURE__ */ new Set();
|
|
614
|
+
for (const field of fields) {
|
|
615
|
+
const deps = packageJson[field];
|
|
616
|
+
if (!deps || typeof deps !== "object") continue;
|
|
617
|
+
for (const dep of Object.keys(deps)) names.add(dep);
|
|
618
|
+
}
|
|
619
|
+
return [...names];
|
|
460
620
|
}
|
|
461
621
|
function getInstalledPackageEntry(pkg, opts) {
|
|
462
622
|
const installed = getInstalledPackageJson(pkg, opts);
|
|
@@ -465,7 +625,7 @@ function getInstalledPackageEntry(pkg, opts) {
|
|
|
465
625
|
const packageName = opts?.packageName || getPackageName(pkg);
|
|
466
626
|
const packageJson = installed.packageJson;
|
|
467
627
|
if (pkg !== packageName && (opts?.resolveSubpathWithRequire !== false || packageJson.exports === void 0)) try {
|
|
468
|
-
return
|
|
628
|
+
return resolveModulePath(pkg, path$1.join(cwd, "package.json"));
|
|
469
629
|
} catch {}
|
|
470
630
|
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";
|
|
471
631
|
return path$1.join(installed.dir, explicitEntry);
|
|
@@ -479,6 +639,18 @@ function getIsRolldown(ctx) {
|
|
|
479
639
|
const viteMajor = Number(String(viteVersion ?? "").split(".")[0]);
|
|
480
640
|
return Number.isFinite(viteMajor) && viteMajor >= 8 || !!ctx?.meta?.rolldownVersion;
|
|
481
641
|
}
|
|
642
|
+
/**
|
|
643
|
+
* Rolldown 1.2.10 added `codeSplitting.groups[].debugName` and warns when a group's
|
|
644
|
+
* `name` is a function without one. Older versions reject it as an unknown option.
|
|
645
|
+
*/
|
|
646
|
+
function supportsCodeSplittingGroupDebugName(ctx) {
|
|
647
|
+
const rolldownVersion = ctx?.meta?.rolldownVersion;
|
|
648
|
+
if (typeof rolldownVersion !== "string") return false;
|
|
649
|
+
const [major = 0, minor = 0, patch = 0] = rolldownVersion.split(/[.+-]/, 3).map((part) => parseInt(part, 10) || 0);
|
|
650
|
+
if (major !== 1) return major > 1;
|
|
651
|
+
if (minor !== 2) return minor > 2;
|
|
652
|
+
return patch >= 10;
|
|
653
|
+
}
|
|
482
654
|
/** Walk up from Vite `config.root` (Nuxt may point at `.nuxt` cache dirs). */
|
|
483
655
|
function isNuxtProjectRoot(root) {
|
|
484
656
|
let dir = root;
|
|
@@ -513,4 +685,4 @@ function hasPackageDependency(dependencyName, cwd = packageDetectionCwd || proce
|
|
|
513
685
|
//#region src/utils/dtsConstants.ts
|
|
514
686
|
const DEFAULT_PUBLIC_TYPES_FOLDER = "@mf-types";
|
|
515
687
|
//#endregion
|
|
516
|
-
export {
|
|
688
|
+
export { isReactCoreShare as C, mfWarn as E, REACT_DOM_CLIENT_SHARE as S, mfError as T, resolveModulePath as _, getIsRolldown as a, supportsCodeSplittingGroupDebugName as b, getPackageNameFromNodeModulePath as c, isNuxtProjectRoot as d, isPackageExportAvailable as f, resolveImportPath as g, packageNameEncode as h, getInstalledPackageJson as i, getSharedCacheDescriptor as l, packageNameDecode as m, getDependencyNames as n, getPackageDetectionCwd as o, isPackageInstalled as p, getInstalledPackageEntry as r, getPackageName as s, DEFAULT_PUBLIC_TYPES_FOLDER as t, hasPackageDependency as u, setPackageDetectionCwd as v, createModuleFederationError as w, REACT_CLIENT_INTERNALS_KEY as x, sharedCacheHelperCode as y };
|
package/lib/index.d.ts
CHANGED
|
@@ -31,6 +31,12 @@ type ModuleFederationOptions = {
|
|
|
31
31
|
import: string;
|
|
32
32
|
}> | undefined;
|
|
33
33
|
filename?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Exact file name of the SSR remote entry emitted next to `filename`.
|
|
36
|
+
* Defaults to `<filename base>.ssr<ext>` so it never clobbers the browser
|
|
37
|
+
* entry when both builds share an output directory. `[hash]` is not supported.
|
|
38
|
+
*/
|
|
39
|
+
ssrFilename?: string;
|
|
34
40
|
library?: any;
|
|
35
41
|
name: string;
|
|
36
42
|
remotes?: Record<string, string | RemoteObjectConfig> | undefined;
|
|
@@ -57,10 +63,13 @@ type ModuleFederationOptions = {
|
|
|
57
63
|
name?: string;
|
|
58
64
|
version?: string;
|
|
59
65
|
shareScope?: string;
|
|
66
|
+
request?: moduleFederationPlugin.SharedConfig['request'];
|
|
67
|
+
shareKey?: moduleFederationPlugin.SharedConfig['shareKey'];
|
|
60
68
|
singleton?: boolean;
|
|
61
69
|
eager?: boolean;
|
|
62
70
|
requiredVersion?: moduleFederationPlugin.SharedConfig['requiredVersion'];
|
|
63
71
|
strictVersion?: boolean;
|
|
72
|
+
allowNodeModulesSuffixMatch?: boolean;
|
|
64
73
|
/** Suppress the missing local dependency warning for `import: false` shares. */
|
|
65
74
|
suppressMissingImportWarning?: boolean;
|
|
66
75
|
treeShaking?: TreeShakingConfig;
|
|
@@ -122,8 +131,11 @@ type ModuleFederationOptions = {
|
|
|
122
131
|
disableSnapshot?: boolean;
|
|
123
132
|
/**
|
|
124
133
|
* Additional packages to mark as external in the SSR remote entry build.
|
|
125
|
-
* Shared packages and MF runtime packages are
|
|
134
|
+
* Shared packages and MF runtime packages are external by default. Use this to
|
|
126
135
|
* add any other Node-only packages that should not be bundled into the SSR entry.
|
|
136
|
+
* To emit a self-contained SSR entry (loadable by hosts that cannot resolve the
|
|
137
|
+
* MF runtime from Node, such as the `@module-federation/sdk` reference loader),
|
|
138
|
+
* opt the MF runtime packages back in through Vite's `ssr.noExternal`.
|
|
127
139
|
*/
|
|
128
140
|
ssrExternals?: string[];
|
|
129
141
|
/**
|
|
@@ -230,6 +242,7 @@ interface DtsRemoteOptions {
|
|
|
230
242
|
extractRemoteTypes?: boolean;
|
|
231
243
|
abortOnError?: boolean;
|
|
232
244
|
deleteTsConfig?: boolean;
|
|
245
|
+
afterGenerate?: (options: moduleFederationPlugin.DtsGenerateTypesHookOptions) => Promise<void> | void;
|
|
233
246
|
}
|
|
234
247
|
interface DtsHostOptions {
|
|
235
248
|
typesFolder?: string;
|