Repository navigation
feat(enhanced): align Webpack and Rspack layer support - #5039
ScriptedAlchemy wants to merge 39 commits into
Conversation
Rspack's layer-aware Module Federation stack (web-infra-dev/rspack#12977, #14912, #14913) changes what the public v2 wrapper receives: - ContainerManager.containerPluginExposesOptions rebuilt exposes from import/name only and dropped exposes.*.layer, so a layered expose was silently built unlayered. Preserve layer, including the empty string. - The manifest reader extracted the shared package/version from a fixed space-delimited position, which the structural identifiers (provide shared module [<key>]@<version> = ...) move; it also cast the container-entry bracket payload to an expose-pair array, which the layered [exposes, layers] tuple breaks with a TypeError. Decode the structural key by its length-prefixed components and validate both container payload generations (and array share-scope prefixes), keeping the legacy formats working. Shared records are still aggregated by package name only; representing concrete provider variants is coordinated separately with the native manifest producer.
🦋 Changeset detectedLatest commit: 531536c The changes in this PR will be included in the next version bump. This PR includes changesets to release 48 packages
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 |
@module-federation/devtools
@module-federation/cli
create-module-federation
@module-federation/dts-plugin
@module-federation/enhanced
@module-federation/error-codes
@module-federation/esbuild
@module-federation/managers
@module-federation/manifest
@module-federation/metro
@module-federation/metro-plugin-rnc-cli
@module-federation/metro-plugin-rnef
@module-federation/metro-plugin-rock
@module-federation/modern-js
@module-federation/modern-js-v3
@module-federation/native-federation-tests
@module-federation/native-federation-typescript
@module-federation/nextjs-mf
@module-federation/node
@module-federation/observability-plugin
@module-federation/playground
@module-federation/retry-plugin
@module-federation/rsbuild-plugin
@module-federation/rspack
@module-federation/rspress-plugin
@module-federation/rstest
@module-federation/runtime
@module-federation/runtime-core
@module-federation/runtime-tools
@module-federation/sdk
@module-federation/storybook-addon
@module-federation/third-party-dts-extractor
@module-federation/treeshake-frontend
@module-federation/treeshake-server
@module-federation/typescript
@module-federation/utilities
@module-federation/webpack-bundler-runtime
@module-federation/bridge-react
@module-federation/bridge-react-webpack-plugin
@module-federation/bridge-shared
@module-federation/bridge-vue3
@module-federation/inject-external-runtime-core-plugin
commit: |
Bundle Size Report10 package(s) changed, 33 unchanged. Package dist + ESM entry
Bundle targets
Consumer scenarios
Total dist (raw): 23.35 MB (+35.6 kB (+0.1%)) Bundle sizes are generated with rslib (Rspack). Package-root metrics preserve the historical report. Tracked subpath exports such as |
…ayers Rspack's layer-aware stack now emits the same identifier layouts as webpack's enhanced plugin: shared modules insert a ' (layer)' segment after the '(scope)' segment and keep 'name@version' at its legacy token position; container entries keep the '[[key, options]]' payload with a 'layer' inside the expose options when present. Drop the structural-key and tuple decoding that the earlier draft anticipated and parse the layer segment instead (for webpack provide identifiers too). Add a compatibility suite that runs the last published reader (@module-federation/manifest@2.8.2, aliased as a dev dependency) and the current source against the same Rspack-shaped identifiers: unlayered shares and containers (with or without a layered expose) read identically, layered shares are skipped by the old reader without failing, and the superseded structural/tuple shapes are documented as breaking it.
Resolve pnpm-lock.yaml by taking main's lockfile and regenerating it with pnpm install --lockfile-only for this branch's package.json additions.
|
A pkg.pr.new preview now exists for the current top of the Rspack stack, |
|
Two docs gaps against the checklist, from a read of the diff. |
…ack-layered-shared-metadata # Conflicts: # packages/runtime-core/src/remote/index.ts # pnpm-lock.yaml
Description
Let enhanced Webpack expose modules in a named layer, and preserve expose and shared layers in Webpack and Rspack manifests. A remote can build separate variants of the same source:
Module rules retain precedence. Omitting
layerpreserves existing behavior; an empty expose-layer string is rejected.Layer-specific relative shared requests now match by issuer layer and resolve their fallback from the importing module's directory. Manifest entries retain public expose aliases, shared requirements, and assets when chunks merge, exposes have multiple imports, or asset analysis is disabled. Unlayered shared IDs stay unchanged; no public
identityIdfield is added.At runtime, providers with the same scope, key, and version stay separate by layer. Lookup prefers the requested layer and uses an unlayered provider only when that layer is absent. Registration, singleton/version selection, remote cleanup, and snapshot asset matching follow that identity. Unlayered share-scope entries retain their existing format for older runtimes.
Review order
The generic Webpack graph collector and rollback option belong to the base PR, Collect Webpack stats from the compilation graph. Native Rspack still collects its data in Rust.
Verification
RFC follow-up, October 21
The host snapshot describes the local shared fallback from that build. Runtime negotiation can select a different provider. Initialization saves the configured local getter as
treeShaking.getand wrapsgetto load the full fallback entry. A snapshot for a different version or scope cannot install its secondary getter or tree-shaking status. This does not promise preservation of a pre-existingtreeShaking.getbefore initialization. Omitted version/scope metadata retains legacy matching behavior.The follow-up adds 15 regressions across commits 71e1cb6 and ad0b69f. They cover unlayered identity matching, legacy metadata, real v2-provider/v1-fallback selection, and execution of secondary, local, and full fallback factories. The new getter cases use the production fallback wrapper and stub entry loading. Removing version matching or admitting a mismatched scope makes the respective regression fail.
All 118 bundler-runtime tests pass after dependency/package builds. Package lint, repository-wide formatting, and normal commit hooks pass. The snapshot follow-ups change tests and documentation only.
The hosted run at ad0b69f passed the runtime, manifest, Node, SSR, router, and Metro E2E jobs. Its three failures were Playwright 1.57.0 rejecting Ubuntu 26.04 before browser tests started. Commit 531536c pins those Rstest, treeshake, and devtools jobs to Ubuntu 24.04. Actionlint, changed-workflow formatting, and normal commit hooks pass; the hosted rerun is pending. Linux browser jobs were not rerun locally on macOS. The results below describe earlier implementation checks.
Latest local checks passed: runtime-core (141), SDK (70; one existing skip), bundler runtime (103), 18 Webpack layer/scalar-scope config cases, and 20 manifest-reader compatibility tests. The affected dependency builds and normal commit hooks passed.
Actual Federation 0.24.1 and 2.9.1 constructors pass 26 no-layer compatibility assertions in both host directions, including async factories, singleton/version selection, and mixed layered-provider/local-fallback behavior. The final Rspack adapter passes four same-scope/key/version layer cases across both registration orders and sync/async loading. The earlier ee3f65a runtime head passed hosted formatting, package builds, publishing checks, affected tests, and Node.js 20 verification. Final-head validation is tracked below.
Layered scope metadata transfers by reference; JSON or copying a scope does not preserve it. Unrelated full app/Metro/release suites were not run.
Related Issue
Layer-aware federation RFC.
Same-version shared modules across scopes is a separate follow-up. Provider metadata is not part of this stack; it has its own RFC and independent draft.
Types of changes
Checklist
The compiler compatibility fixture pins Rspack 1.3.9/Federation 0.13.1 as the older host and the published final Rspack d538c9c preview (2.2.7) with the current workspace runtime as the remote. All four old-host cases pass locally across default/custom scopes and remote-entry/manifest loading. The complete manifest suite passes 55/55 tests. The final published c4521e5 Federation suite (2.9.2) passes four actual native same-scope/key/version layer cases, both provider orders and eager/lazy loading, plus four sync/async adapter cases, 26 assertions with actual Federation 0.24.1/2.9.1, and two classic share-entry checks. Both Linux x64 and Mac ARM64 compiler preview workflows succeeded. The preceding c4521e5 stack passed hosted formatting, package builds, publishing checks, affected package tests, and Node.js 20 verification. The two shared preview checksums were refreshed after the Mac publication; an empty-store frozen installation verifies the compiler, wrapper, and Linux binary.
Two sync/async regressions cover compiler-provided share entries without enhanced
shareConfig. The seven formerly failing legacy config cases and two provider cases pass locally after the one-line compatibility fix.The #5080 follow-up is propagated here: EN/ZH manifest guides document
useLegacyStats, and rollback retains pre-PR unnamed-chunk asset output while the graph path explicitly includes unnamed groups. The new real Webpack regression fails before the fix and passes afterward in both JSON artifacts. The complete manifest suite now passes 56/56, including all four compiled Rspack 1.3.9/Federation 0.13.1 host cases and the native layer case. The initial restricted Mac run timed out in the unchanged old-host cases; the targeted and complete suite pass outside that sandbox. Manifest build, package lint, changed-file formatting and normal hooks pass; full local root formatting is blocked by an unrelated missing app dependency. At that earlier head, hosted formatting, builds, publishing checks and affected tests passed. Node.js 20 and broad E2E passed on those three heads. The latest installed 06aa6be preview also passes native layer, adapter and older-runtime matrices against final compiler d538c9c.