Skip to content

feat(enhanced): compose the runtime bootstrap behind experiments.composedRuntime - #5140

Open
ScriptedAlchemy wants to merge 24 commits into
rfc5128/04-managers-compositionfrom
rfc5128/05-enhanced-composed
Open

ScriptedAlchemy wants to merge 24 commits into
rfc5128/04-managers-compositionfrom
rfc5128/05-enhanced-composed

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

Part of RFC #5128 (alternate proposal to #5036).
Stack: 5 of 7. Base: #5134 (rfc5128/04-managers-composition). Next: #5141.
Landing order: #5135 → #5137 → #5139 → #5134 → #5140 → #5141 → #5142.
Companions on main: #5143 (disabled remote loadEntry), #5144 (enhanced duplicate serializer keys). #5126 (@rspack/core 2) is on main. PR 6 and 7 include it.

What changes

ModuleFederationPlugin in @module-federation/enhanced gets experiments.composedRuntime. With the flag on, enhanced generates a federation bootstrap that imports only the runtime-core capabilities and bundler-runtime adapters the build uses, so the excluded parts are not in the module graph. Builds without the flag are unchanged.

Every federation plugin registers a participant on a compiler slot that all installed copies of enhanced share. ModuleFederationPlugin registers one participant for its options, and a standalone ContainerPlugin, ContainerReferencePlugin, ConsumeSharedPlugin, or ProvideSharedPlugin registers what it needs. The plan is sealed in afterResolvers. An older runtime, an externalized runtime, or a user alias on a runtime package selects today's bootstrap and defines, with a warning that names the reason. A finishModules graph check reports federation modules whose adapter is missing.

Two installed copies of enhanced could not share one webpack, because both registered serializers under the same enhanced/lib/... key. This PR carries the fix from #5144 so the two-copies test loads a real second copy.

Verification

  • configCases/composed-runtime/* has 7 cases (default, remotes-only, exposes-only, shared-only, all-off, after-plugins, standalone-share-plugin). Each runs the bundle, loads a remote module or a shared singleton, and asserts the planned parts are bundled and the excluded runtime-core modules are not. All 7 fail on the parent branch. All-off fails with expected false to be true, and the other 6 fail with expected [ 'compose', false ] to deeply equal [ 'compose', true ].
  • compiler-unit/container/FederationCompositionPlugin.test.ts covers the fallbacks and errors. An older runtime family, a function external on runtime-core, and a user alias each select legacy with a warning. A plan that never ran warns. An external runtime package and a remote module without its adapter are build errors. Legacy output with the flag on is byte-identical to the flag off. Composed builds keep ENV_TARGET and drop the capability and build-id defines. Two copies of enhanced plan once. A participant registered after sealing is refused. The shared tree-shaking compiler builds.
  • Mutation checks. Removing a standalone registration turns the graph check into a build error, and a per-copy slot fails the two-copies test.
  • The proof harness (webpack, Node and browser) passes 17/17 with --composed. Flag-off output is byte-identical to the parent branch.
  • pnpm --filter @module-federation/enhanced run test passes locally with 479 + 6 tests (unit, config cases, and the serial tree-shaking run). CI has no enhanced unit-test job, so this local run is the only run of that suite.
  • Independent verification passed at c2aea32c3. The full gates review ran at 884586498 and found watch, multicompiler, and filesystem-cache profile flips correct. Its audit found that the graph check used ExternalModule.request instead of userRequest, and that 10 stray node_modules files were committed. The verifier reproduced both fixes as fixed, and checked the fix(enhanced): key cache serializers by install directory #5144 port with its test workaround removed. The patch is unchanged through 232dbe30e and the live head f2eb03cee.
  • CI passes at f2eb03cee with 18 checks. e2e-treeshake was skipped because the affected-suite selector did not pick it.
  • Rspack builds are not composed in this PR. feat(rspack): redirect the native bundler runtime to a composed entry #5141 adds them.

Deviations from the RFC

  • Mode selection and rendering run in beforeCompile, once per compiler, not in afterResolvers. selectMode is async because function externals can be, and afterResolvers is synchronous. beforeCompile still runs before make, where ContainerPlugin reads the entry path. The RFC now describes this timing.

Overlaps with open PRs

This PR carries the #5144 serializer-key fix (the same makeSerializable helper and call sites). It carries no code from other open PRs. The PRs below change files this PR also changes. This PR does not include their changes.

@changeset-bot

changeset-bot Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f2eb03c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 48 packages
Name Type
@module-federation/enhanced Minor
@module-federation/sdk Minor
@module-federation/modern-js-v3 Minor
@module-federation/modern-js Minor
@module-federation/nextjs-mf Patch
@module-federation/node Patch
@module-federation/rsbuild-plugin Minor
@module-federation/rspress-plugin Minor
@module-federation/rstest Minor
@module-federation/storybook-addon Patch
shared-tree-shaking-no-server-host Patch
shared-tree-shaking-no-server-provider Patch
@module-federation/devtools Minor
@module-federation/cli Minor
@module-federation/dts-plugin Minor
@module-federation/esbuild Patch
@module-federation/managers Minor
@module-federation/manifest Minor
@module-federation/metro Minor
@module-federation/observability-plugin Patch
@module-federation/retry-plugin Minor
@module-federation/rspack Minor
@module-federation/runtime-core Minor
@module-federation/runtime Minor
@module-federation/utilities Patch
@module-federation/webpack-bundler-runtime Minor
@module-federation/bridge-react-webpack-plugin Minor
@module-federation/bridge-react Minor
@module-federation/bridge-vue3 Minor
shared-tree-shaking-with-server-host Patch
shared-tree-shaking-with-server-provider Patch
node-dynamic-remote-new-version Patch
node-dynamic-remote Patch
@module-federation/playground Patch
remote5 Patch
remote6 Patch
website-new Patch
@module-federation/metro-plugin-rnc-cli Minor
@module-federation/metro-plugin-rnef Minor
@module-federation/metro-plugin-rock Minor
@module-federation/runtime-tools Minor
@module-federation/inject-external-runtime-core-plugin Minor
create-module-federation Minor
@module-federation/error-codes Minor
@module-federation/third-party-dts-extractor Minor
@module-federation/treeshake-frontend Minor
@module-federation/treeshake-server Minor
@module-federation/bridge-shared Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@module-federation/devtools

pnpm add https://pkg.pr.new/@module-federation/devtools@f2eb03c

@module-federation/cli

pnpm add https://pkg.pr.new/@module-federation/cli@f2eb03c

create-module-federation

pnpm add https://pkg.pr.new/create-module-federation@f2eb03c

@module-federation/dts-plugin

pnpm add https://pkg.pr.new/@module-federation/dts-plugin@f2eb03c

@module-federation/enhanced

pnpm add https://pkg.pr.new/@module-federation/enhanced@f2eb03c

@module-federation/error-codes

pnpm add https://pkg.pr.new/@module-federation/error-codes@f2eb03c

@module-federation/esbuild

pnpm add https://pkg.pr.new/@module-federation/esbuild@f2eb03c

@module-federation/managers

pnpm add https://pkg.pr.new/@module-federation/managers@f2eb03c

@module-federation/manifest

pnpm add https://pkg.pr.new/@module-federation/manifest@f2eb03c

@module-federation/metro

pnpm add https://pkg.pr.new/@module-federation/metro@f2eb03c

@module-federation/metro-plugin-rnc-cli

pnpm add https://pkg.pr.new/@module-federation/metro-plugin-rnc-cli@f2eb03c

@module-federation/metro-plugin-rnef

pnpm add https://pkg.pr.new/@module-federation/metro-plugin-rnef@f2eb03c

@module-federation/metro-plugin-rock

pnpm add https://pkg.pr.new/@module-federation/metro-plugin-rock@f2eb03c

@module-federation/modern-js

pnpm add https://pkg.pr.new/@module-federation/modern-js@f2eb03c

@module-federation/modern-js-v3

pnpm add https://pkg.pr.new/@module-federation/modern-js-v3@f2eb03c

@module-federation/native-federation-tests

pnpm add https://pkg.pr.new/@module-federation/native-federation-tests@f2eb03c

@module-federation/native-federation-typescript

pnpm add https://pkg.pr.new/@module-federation/native-federation-typescript@f2eb03c

@module-federation/nextjs-mf

pnpm add https://pkg.pr.new/@module-federation/nextjs-mf@f2eb03c

@module-federation/node

pnpm add https://pkg.pr.new/@module-federation/node@f2eb03c

@module-federation/observability-plugin

pnpm add https://pkg.pr.new/@module-federation/observability-plugin@f2eb03c

@module-federation/playground

pnpm add https://pkg.pr.new/@module-federation/playground@f2eb03c

@module-federation/retry-plugin

pnpm add https://pkg.pr.new/@module-federation/retry-plugin@f2eb03c

@module-federation/rsbuild-plugin

pnpm add https://pkg.pr.new/@module-federation/rsbuild-plugin@f2eb03c

@module-federation/rspack

pnpm add https://pkg.pr.new/@module-federation/rspack@f2eb03c

@module-federation/rspress-plugin

pnpm add https://pkg.pr.new/@module-federation/rspress-plugin@f2eb03c

@module-federation/rstest

pnpm add https://pkg.pr.new/@module-federation/rstest@f2eb03c

@module-federation/runtime

pnpm add https://pkg.pr.new/@module-federation/runtime@f2eb03c

@module-federation/runtime-core

pnpm add https://pkg.pr.new/@module-federation/runtime-core@f2eb03c

@module-federation/runtime-tools

pnpm add https://pkg.pr.new/@module-federation/runtime-tools@f2eb03c

@module-federation/sdk

pnpm add https://pkg.pr.new/@module-federation/sdk@f2eb03c

@module-federation/storybook-addon

pnpm add https://pkg.pr.new/@module-federation/storybook-addon@f2eb03c

@module-federation/third-party-dts-extractor

pnpm add https://pkg.pr.new/@module-federation/third-party-dts-extractor@f2eb03c

@module-federation/treeshake-frontend

pnpm add https://pkg.pr.new/@module-federation/treeshake-frontend@f2eb03c

@module-federation/treeshake-server

pnpm add https://pkg.pr.new/@module-federation/treeshake-server@f2eb03c

@module-federation/typescript

pnpm add https://pkg.pr.new/@module-federation/typescript@f2eb03c

@module-federation/utilities

pnpm add https://pkg.pr.new/@module-federation/utilities@f2eb03c

@module-federation/webpack-bundler-runtime

pnpm add https://pkg.pr.new/@module-federation/webpack-bundler-runtime@f2eb03c

@module-federation/bridge-react

pnpm add https://pkg.pr.new/@module-federation/bridge-react@f2eb03c

@module-federation/bridge-react-webpack-plugin

pnpm add https://pkg.pr.new/@module-federation/bridge-react-webpack-plugin@f2eb03c

@module-federation/bridge-shared

pnpm add https://pkg.pr.new/@module-federation/bridge-shared@f2eb03c

@module-federation/bridge-vue3

pnpm add https://pkg.pr.new/@module-federation/bridge-vue3@f2eb03c

@module-federation/inject-external-runtime-core-plugin

pnpm add https://pkg.pr.new/@module-federation/inject-external-runtime-core-plugin@f2eb03c

commit: f2eb03c

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a3c075c1d1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +163 to +166
const composition = renderComposition(
plan,
resolveImports(plan, family),
this._buildId(compiler),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fall back when composed imports cannot resolve

When a custom implementation declares the required export keys but exposes them only under conditions such as require, selectMode accepts the runtime family, but resolveImports uses only import/module/default conditions and throws here. This makes beforeCompile reject and the build fail, even though the legacy bootstrap can resolve that implementation and the new option promises to fall back when composition is unavailable. Catch composition import/render failures and return a legacy outcome with a warning instead.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-25T14:16:22.950802Z a3c075c PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

The planner already skips SharedContainerPlugin compilers, so a participant registered there is never read. Drop the stale fourth getTemplate argument from the runtime-guard unit test.
…enhanced's own runtime aliases

A user alias on @module-federation/runtime$ now selects the legacy bootstrap. The graph check realpaths only runtime package roots and tolerates roots outside the real disk.
0a88a0b committed node_modules that the tree-shaking config case writes at test time. Ignore that path so they stay out.
…ph check

ExternalModule.request is the external target, such as a global name, so an externalized runtime package passed the check. Use userRequest.
…from the planner

FederationRuntimePlugin.apply returns for SharedContainerPlugin compilers before it creates the planner.
Two installed copies of enhanced in one process both registered their
classes under the same 'enhanced/lib/...' key, and webpack's global
serializer registry throws on the second registration.

(cherry picked from commit 8b63693)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant