Skip to content

feat(runtime): add package selectors for runtime capabilities - #5095

Open
ScriptedAlchemy wants to merge 18 commits into
rfc5036/02-compiler-coordinationfrom
rfc5036/03-runtime-selectors
Open

ScriptedAlchemy wants to merge 18 commits into
rfc5036/02-compiler-coordinationfrom
rfc5036/03-runtime-selectors

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 18, 2026 •

Copy link
Copy Markdown
Member

Part of RFC #5036. An alternate proposal is open at #5128 with its own stack. This PR stays open until the decision on #5036 is made.
Stack: 3 of 7. Base: #5094 (rfc5036/02-compiler-coordination). Next: #5096.
Landing order: #5093 → #5094 → #5095 → #5096 → #5097 → #5098 → #5107.

What changes

A build that sets no module-federation:* condition gets the same runtime exports and define behavior as today. A build that sets a module-federation:no-* condition gets a disabled file, so the disabled code never enters the module graph. DefinePlugin can only delete it after parsing. A module-federation:target-* condition picks the SDK target. The compiler does not pass these conditions yet.

The runtime packages add private selector files and keep their public exports. Runtime-core selects remote, shared, snapshot, preload, and helper modules. The bundler runtime selects container entry, remotes, and shared adapters. The SDK selects web, Node, worker, and universal targets. Each legacy, enabled, and disabled file is built for ESM and CommonJS. The enabled files are published for the upcoming positive conditions, and nothing selects them yet.

The worker loader uses importScripts and import(). It stores an imported ESM remote under the remote's global name, as the Node loader does. Without that, getRemoteEntry failed with RUNTIME-001.

Disabled snapshot, shared, and remote handlers keep every member the runtime and bridge-react call, such as loadRemoteSnapshotInfo, manifestCache, idToRemoteMap, the resolveShare hook, and the full remote hook set. The enabled and disabled remote handlers build their hooks from one function. ModuleFederation keeps the enabled class types for its handler fields. This work moved here from #5107 so this PR works on its own.

Runtime JavaScript keeps its #mf/* imports so the consumer's conditions choose the file. Published declarations contain no #mf/* imports and point at the default files, so consumers on moduleResolution: node10 still get real types.

Verification

  • The branch history was rewritten on 2026-09-26 to remove attribution trailers from commit messages only. Every tree and patch is identical to the verified head; 9fb0f2fc7 is the rewritten tip.

  • worker-remote-entry.spec.ts loads an ESM remote entry through the worker loader.

  • Tests cover Node resolution, runtime behavior, and Webpack and Rspack graphs.

  • CI at 9fb0f2fc7 passed 20 checks, cancelled 4, and skipped 13.

  • The 4 cancelled checks are checkout-install and node20-compat in Build Affected Packages, lint-deps in Lint Dependencies, and publish-preview in pkg.pr.new Preview. Those three workflows each ran twice on this commit. They set cancel-in-progress: true per PR, so the second run cancelled the first about a second after it started. The second run of each workflow passed on the same commit. The cancelled runs were not rerun.

  • 12 skipped checks are the jobs of the cancelled Build Affected Packages run, which wait on checkout-install. e2e-treeshake was skipped in the second run because tools/scripts/ci-is-affected.mjs did not select it.

  • No compiler in this stack passes the conditions, so only the package tests exercise the selected files.

Deviations from the RFC

None noted.

Overlaps with open PRs

File overlaps with 10 other open PRs

@changeset-bot

changeset-bot Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9fb0f2f

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/runtime-core Minor
@module-federation/webpack-bundler-runtime Minor
@module-federation/sdk Minor
@module-federation/nextjs-mf Patch
@module-federation/runtime Minor
@module-federation/bridge-react Minor
@module-federation/enhanced Minor
@module-federation/esbuild Patch
@module-federation/runtime-tools Minor
@module-federation/devtools Minor
@module-federation/cli Minor
@module-federation/dts-plugin Minor
@module-federation/managers Minor
@module-federation/manifest Minor
@module-federation/metro Minor
@module-federation/modern-js-v3 Minor
@module-federation/modern-js Minor
@module-federation/node Patch
@module-federation/observability-plugin Patch
@module-federation/retry-plugin Minor
@module-federation/rsbuild-plugin Minor
@module-federation/rspack Minor
@module-federation/rspress-plugin Minor
@module-federation/rstest Minor
@module-federation/storybook-addon Patch
@module-federation/utilities Patch
@module-federation/bridge-react-webpack-plugin Minor
@module-federation/bridge-vue3 Minor
@module-federation/playground Patch
website-new Patch
shared-tree-shaking-no-server-host Patch
shared-tree-shaking-no-server-provider Patch
@module-federation/inject-external-runtime-core-plugin Minor
@module-federation/metro-plugin-rnc-cli Minor
@module-federation/metro-plugin-rnef Minor
@module-federation/metro-plugin-rock 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
remote5 Patch
remote6 Patch
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

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@pkg-pr-new

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

Copy link
Copy Markdown

Open in StackBlitz

@module-federation/devtools

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

@module-federation/cli

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

create-module-federation

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

@module-federation/dts-plugin

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

@module-federation/enhanced

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

@module-federation/error-codes

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

@module-federation/esbuild

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

@module-federation/managers

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

@module-federation/manifest

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

@module-federation/metro

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

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

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

@module-federation/metro-plugin-rnef

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

@module-federation/metro-plugin-rock

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

@module-federation/modern-js

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

@module-federation/modern-js-v3

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

@module-federation/native-federation-tests

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

@module-federation/native-federation-typescript

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

@module-federation/nextjs-mf

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

@module-federation/node

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

@module-federation/observability-plugin

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

@module-federation/playground

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

@module-federation/retry-plugin

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

@module-federation/rsbuild-plugin

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

@module-federation/rspack

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

@module-federation/rspress-plugin

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

@module-federation/rstest

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

@module-federation/runtime

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

@module-federation/runtime-core

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

@module-federation/runtime-tools

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

@module-federation/sdk

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

@module-federation/storybook-addon

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

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

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

@module-federation/treeshake-frontend

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

@module-federation/treeshake-server

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

@module-federation/typescript

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

@module-federation/utilities

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

@module-federation/webpack-bundler-runtime

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

@module-federation/bridge-react

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

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

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

@module-federation/bridge-shared

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

@module-federation/bridge-vue3

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

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

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

commit: 9fb0f2f

@ScriptedAlchemy
ScriptedAlchemy force-pushed the rfc5036/02-compiler-coordination branch from 8939c8c to 8cb38c9 Compare September 18, 2026 15:36
@ScriptedAlchemy
ScriptedAlchemy force-pushed the rfc5036/03-runtime-selectors branch from dbe2d5a to 2d4f5e6 Compare September 18, 2026 15:40
@ScriptedAlchemy ScriptedAlchemy changed the title feat(runtime): select capabilities through package conditions feat(runtime): publish capability selector leaves Sep 18, 2026
@ScriptedAlchemy
ScriptedAlchemy force-pushed the rfc5036/02-compiler-coordination branch from 8cb38c9 to 5588bd3 Compare September 18, 2026 16:08
Publish selector leaves in both module formats.

Keep define behavior by default.

Namespaced conditions remove disabled capabilities and Node loaders from compiler graphs.
@ScriptedAlchemy
ScriptedAlchemy force-pushed the rfc5036/03-runtime-selectors branch from 2d4f5e6 to 1b84bc8 Compare September 18, 2026 16:09
Treat Node package-import specifiers as package-local aliases instead of npm dependencies.
The selector checks only need the program result. Production minification
did not finish before the test runner reached its limit, so the assertion
never ran.
These tests start Webpack and Rspack compiles. On CI the first compile
takes longer than Jest's 5 second default while other package suites run,
so the job stopped them before they asserted.
@ScriptedAlchemy ScriptedAlchemy changed the title feat(runtime): publish capability selector leaves feat(runtime): add package selectors for runtime capabilities Sep 24, 2026
Declarations resolved `#mf/*` as external, so published .d.ts files kept
the private specifiers. Consumers on `moduleResolution: node10` got TS2307,
or `any` types with skipLibCheck. Declarations now inline the legacy leaf
through tsconfig paths. Runtime JS keeps its `#mf/*` imports.
The worker leaf called `import(url)` without bundler ignore comments, so
webpack and Rspack reported a critical dependency and built a context
module for the remote URL.
Move the handler contract from the handler-contracts branch down to the
selector branch. With remotes, shared, or snapshots disabled, the handlers
now keep the hooks and methods the runtime and bridge-react call, so this
branch works without the later one.
runtime-core reads a loaded remote entry from its global name. The worker
loader returned the imported module without storing it there, so ESM
remotes failed with RUNTIME-001.
CI sets FORCE_COLOR, so console.log in the child Node process colored
numbers and booleans and the string assertions failed. The shared helper
now drops FORCE_COLOR and sets NO_COLOR, and the SDK spec uses it.
The remote hooks moved to remote/hooks.ts, which imports the type itself.

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