@module-federation/vite 1.20.9 → 1.21.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 -10
- package/lib/index.js +53 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -351,20 +351,29 @@ federation({
|
|
|
351
351
|
`provideExternalRuntime` injects a local runtime plugin that publishes `runtime-core` on `globalThis._FEDERATION_RUNTIME_CORE`. `externalRuntime` rewrites imports of `@module-federation/runtime-core` to read that global. Using `provideExternalRuntime` together with `exposes` throws — only pure consumers may provide the runtime.
|
|
352
352
|
The `externalRuntime` rewrite applies to the browser remote graph; SSR remote entries continue to resolve `@module-federation/runtime-core` from Node so they do not depend on the browser global.
|
|
353
353
|
|
|
354
|
-
## ⚠️ `codeSplitting`
|
|
354
|
+
## ⚠️ `codeSplitting` is managed by the plugin
|
|
355
355
|
|
|
356
|
-
Do not set
|
|
357
|
-
`build.rolldownOptions.output.codeSplitting` to `false`
|
|
356
|
+
Do not set `build.rollupOptions.output.codeSplitting` or
|
|
357
|
+
`build.rolldownOptions.output.codeSplitting` to `false` — it will be **ignored** (with a warning).
|
|
358
|
+
Module Federation requires chunk splitting so `loadShare` and `runtimeInitStatus` stay isolated for correct bootstrap order.
|
|
358
359
|
|
|
359
|
-
`codeSplitting.groups`
|
|
360
|
-
Module Federation needs `loadShare` and `runtimeInitStatus` isolated into separate chunks for correct bootstrap behavior.
|
|
360
|
+
### `codeSplitting.groups` (Vite 8+ / Rolldown)
|
|
361
361
|
|
|
362
|
-
|
|
362
|
+
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.
|
|
363
363
|
|
|
364
|
-
|
|
365
|
-
`
|
|
366
|
-
|
|
367
|
-
|
|
364
|
+
- No warning is emitted just for keeping your groups.
|
|
365
|
+
- If one of your existing groups sets a `priority` high enough to outrank the federation groups, it is **clamped** below them and the plugin warns once. This prevents those groups from capturing a `runtimeInit`/`loadShare` wrapper or the preload helper.
|
|
366
|
+
|
|
367
|
+
## ⚠️ `manualChunks` behavior depends on your Vite version
|
|
368
|
+
|
|
369
|
+
| Setting | Vite 5–7 (Rollup) | Vite 8+ (Rolldown) |
|
|
370
|
+
| --- | --- | --- |
|
|
371
|
+
| `manualChunks` (function) | **Composed as a fallback** — federation modules are claimed first, everything else falls through to your function | **Ignored** (warns) — move grouping to `codeSplitting.groups` |
|
|
372
|
+
| `manualChunks` (object) | **Ignored** (warns) — use the function form to compose | **Ignored** (warns) — move grouping to `codeSplitting.groups` |
|
|
373
|
+
|
|
374
|
+
On Vite 5–7, Rollup doesn't support `codeSplitting`, so the plugin isolates `runtimeInitStatus`, `loadShare`, and the preload helper via `manualChunks`. A user-provided **function** is called for any module the plugin doesn't claim; the **object** form isn't composed by the plugin and is ignored.
|
|
375
|
+
|
|
376
|
+
On Vite 8+, chunking is managed through `codeSplitting.groups` (see above), so `manualChunks` is removed — express your grouping as `codeSplitting.groups` instead, where user groups are preserved below the federation groups.
|
|
368
377
|
|
|
369
378
|
### So far so good 🎉
|
|
370
379
|
|
package/lib/index.js
CHANGED
|
@@ -9280,8 +9280,11 @@ function getRuntimeCapabilityConfigurationWarnings(options) {
|
|
|
9280
9280
|
//#endregion
|
|
9281
9281
|
//#region src/index.ts
|
|
9282
9282
|
const patchedManualChunks = /* @__PURE__ */ new WeakSet();
|
|
9283
|
+
const federationGroups = /* @__PURE__ */ new WeakSet();
|
|
9283
9284
|
const PRELOAD_HELPER_CHUNK = "vite-preload-helper";
|
|
9284
9285
|
const PRELOAD_HELPER_TEST = /\0?vite\/preload-helper/;
|
|
9286
|
+
const MF_GROUP_PRIORITY = 1e6;
|
|
9287
|
+
const USER_GROUP_MAX_PRIORITY = MF_GROUP_PRIORITY - 1;
|
|
9285
9288
|
function normalizeVinextRscPreloadHints(code) {
|
|
9286
9289
|
return code.replace(/(:HL\[[^\]\n]*?,)"stylesheet"/g, "$1\"style\"").replace(/(:HL\[[^\]\n]*?,)\\"stylesheet\\"/g, "$1\\\"style\\\"");
|
|
9287
9290
|
}
|
|
@@ -10025,33 +10028,33 @@ function federation(mfUserOptions) {
|
|
|
10025
10028
|
};
|
|
10026
10029
|
}
|
|
10027
10030
|
let warnedAboutCodeSplitting = false;
|
|
10028
|
-
let warnedAboutCodeSplittingGroups = false;
|
|
10029
10031
|
const ensureCodeSplitting = (output) => {
|
|
10030
|
-
if (output?.codeSplitting
|
|
10031
|
-
|
|
10032
|
-
|
|
10033
|
-
|
|
10034
|
-
|
|
10035
|
-
|
|
10032
|
+
if (output?.codeSplitting !== false) return;
|
|
10033
|
+
delete output.codeSplitting;
|
|
10034
|
+
if (warnedAboutCodeSplitting) return;
|
|
10035
|
+
warnedAboutCodeSplitting = true;
|
|
10036
|
+
mfWarn("Ignoring `output.codeSplitting = false` because module federation requires chunk splitting.");
|
|
10037
|
+
};
|
|
10038
|
+
const isFederationGroup = (group) => typeof group === "object" && group !== null && federationGroups.has(group);
|
|
10039
|
+
let warnedAboutGroupPriority = false;
|
|
10040
|
+
const clampUserGroup = (group) => {
|
|
10041
|
+
const candidate = group;
|
|
10042
|
+
if (typeof candidate?.priority !== "number") return group;
|
|
10043
|
+
if (candidate.priority <= USER_GROUP_MAX_PRIORITY) return group;
|
|
10044
|
+
if (!warnedAboutGroupPriority) {
|
|
10045
|
+
warnedAboutGroupPriority = true;
|
|
10046
|
+
mfWarn(`Clamping \`output.codeSplitting.groups\` priority to ${USER_GROUP_MAX_PRIORITY} — module federation groups must keep the highest priority so shared dependency init wrappers stay isolated in their own chunks.`);
|
|
10036
10047
|
}
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
10041
|
-
delete output.codeSplitting.groups;
|
|
10042
|
-
if (Object.keys(output.codeSplitting).length === 0) delete output.codeSplitting;
|
|
10043
|
-
if (warnedAboutCodeSplittingGroups) return;
|
|
10044
|
-
warnedAboutCodeSplittingGroups = true;
|
|
10045
|
-
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.");
|
|
10048
|
+
return {
|
|
10049
|
+
...candidate,
|
|
10050
|
+
priority: USER_GROUP_MAX_PRIORITY
|
|
10051
|
+
};
|
|
10046
10052
|
};
|
|
10047
10053
|
let warnedAboutManualChunks = false;
|
|
10054
|
+
let warnedAboutObjectManualChunks = false;
|
|
10048
10055
|
const applyManualChunks = (output, useCodeSplitting) => {
|
|
10049
10056
|
ensureCodeSplitting(output);
|
|
10050
10057
|
const isPatchedByPlugin = typeof output.manualChunks === "function" && patchedManualChunks.has(output.manualChunks);
|
|
10051
|
-
if (output.manualChunks && !isPatchedByPlugin && !warnedAboutManualChunks) {
|
|
10052
|
-
warnedAboutManualChunks = true;
|
|
10053
|
-
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.");
|
|
10054
|
-
}
|
|
10055
10058
|
const mfChunkName = function(id) {
|
|
10056
10059
|
if (id.includes(runtimeInitId) || id.includes("__mf_v__runtimeInit__mf_v__")) return "runtimeInit";
|
|
10057
10060
|
if (id.includes("__loadShare__")) {
|
|
@@ -10062,19 +10065,44 @@ function federation(mfUserOptions) {
|
|
|
10062
10065
|
};
|
|
10063
10066
|
patchedManualChunks.add(mfChunkName);
|
|
10064
10067
|
if (!useCodeSplitting) {
|
|
10065
|
-
|
|
10068
|
+
if (isPatchedByPlugin) return;
|
|
10069
|
+
const userManualChunks = output.manualChunks;
|
|
10070
|
+
if (userManualChunks && typeof userManualChunks !== "function" && !warnedAboutObjectManualChunks) {
|
|
10071
|
+
warnedAboutObjectManualChunks = true;
|
|
10072
|
+
mfWarn("Ignoring the object form of `output.manualChunks` because module federation cannot safely compose with it. Use the function form instead: federation modules are claimed first and your function runs for everything else.");
|
|
10073
|
+
}
|
|
10074
|
+
const mfManualChunks = function(id, ...rest) {
|
|
10066
10075
|
if (PRELOAD_HELPER_TEST.test(id)) return PRELOAD_HELPER_CHUNK;
|
|
10067
|
-
|
|
10076
|
+
const mfChunk = mfChunkName(id);
|
|
10077
|
+
if (mfChunk) return mfChunk;
|
|
10078
|
+
if (typeof userManualChunks === "function") return userManualChunks(id, ...rest) ?? void 0;
|
|
10068
10079
|
};
|
|
10069
10080
|
patchedManualChunks.add(mfManualChunks);
|
|
10070
10081
|
output.manualChunks = mfManualChunks;
|
|
10071
10082
|
return;
|
|
10072
10083
|
}
|
|
10073
|
-
|
|
10084
|
+
if (output.manualChunks && !isPatchedByPlugin && !warnedAboutManualChunks) {
|
|
10085
|
+
warnedAboutManualChunks = true;
|
|
10086
|
+
mfWarn("Ignoring `output.manualChunks` for the Rolldown build because module federation manages chunking with `output.codeSplitting.groups`. Move your grouping there — user groups are kept below the federation groups.");
|
|
10087
|
+
}
|
|
10088
|
+
const existingGroups = output.codeSplitting && typeof output.codeSplitting === "object" ? output.codeSplitting.groups : void 0;
|
|
10089
|
+
const userGroups = Array.isArray(existingGroups) ? existingGroups.filter((group) => !isFederationGroup(group)).map(clampUserGroup) : [];
|
|
10090
|
+
const mfPreloadGroup = {
|
|
10074
10091
|
name: PRELOAD_HELPER_CHUNK,
|
|
10075
10092
|
test: PRELOAD_HELPER_TEST,
|
|
10076
|
-
priority:
|
|
10077
|
-
}
|
|
10093
|
+
priority: 1000001
|
|
10094
|
+
};
|
|
10095
|
+
const mfNameGroup = {
|
|
10096
|
+
name: mfChunkName,
|
|
10097
|
+
priority: MF_GROUP_PRIORITY
|
|
10098
|
+
};
|
|
10099
|
+
federationGroups.add(mfPreloadGroup);
|
|
10100
|
+
federationGroups.add(mfNameGroup);
|
|
10101
|
+
const groups = [
|
|
10102
|
+
mfPreloadGroup,
|
|
10103
|
+
mfNameGroup,
|
|
10104
|
+
...userGroups
|
|
10105
|
+
];
|
|
10078
10106
|
output.codeSplitting = {
|
|
10079
10107
|
...output.codeSplitting || {},
|
|
10080
10108
|
groups
|