forked from web-infra-dev/modern.js
-
Notifications
You must be signed in to change notification settings - Fork 0
test(integration): add rsc-mf fixture for module federation + RSC #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
320 commits
Select commit
Hold shift + click to select a range
3fa1479
test(rsc-mf): document host proxy action mapping intent
cursoragent cb8a21b
test(rsc-mf): expand exposure coverage for bundled action exports
cursoragent 77b3b26
test(rsc-mf): add bundled server-info expose coverage
cursoragent e5c6575
test(rsc-mf): map bundled action re-export ids to host proxies
cursoragent d680e23
refactor(rsc-mf): remove remote chunk text patching middleware
cursoragent 92f8e4e
test(rsc-mf): assert no browser runtime errors in dev mode
cursoragent a1d8490
test(rsc-mf): assert action posts stay on host endpoint
cursoragent 0f0ca8e
refactor(rsc-mf): drop remote client chunkLoadingGlobal override
cursoragent e75f56e
refactor(rsc-mf): consume bundled action expose via namespace import
cursoragent 336d821
test(rsc-mf): assert action posts avoid remote origin
cursoragent 6c19452
test(rsc-mf): assert host-resolvable x-rsc-action ids
cursoragent ed0f9f5
refactor(rsc-mf): use namespace imports in host server bundle coverage
cursoragent a40bae2
refactor(rsc-mf): route host proxy actions through bundled expose imp…
cursoragent 99989e1
test(rsc-mf): assert host proxy action manifest coverage
cursoragent cf1e7fb
test(rsc-mf): cover bundled nested and increment host actions
cursoragent 6871db7
refactor(rsc-mf): stabilize remote callback registration keying
cursoragent 051929d
refactor(rsc-mf): avoid client stringify in callback dependency
cursoragent 6cb5574
test(rsc-mf): assert posted action ids match host proxy set
cursoragent 76ec229
refactor(rsc-mf): centralize host proxy mapping and manifest forms
cursoragent 4368d53
test(rsc-mf): assert host proxy id list uniqueness and format
cursoragent 25af768
test(rsc-mf): surface direct and bundled proxy id groups
cursoragent 6256add
test(rsc-mf): validate proxy id group union membership
cursoragent 225df15
test(rsc-mf): assert proxy map entry count aligns with ids
cursoragent d806ec0
test(rsc-mf): assert proxy map entry count aligns with ids
cursoragent f02e2cf
test(rsc-mf): assert mapped proxy id coverage markers
cursoragent c220479
refactor(rsc-mf): model effective remote action map keys
cursoragent db078ac
test(rsc-mf): bind posted action ids to effective map key count
cursoragent 35e033c
test(rsc-mf): handle direct-bundled id collisions in request checks
cursoragent 12dd1e0
test(rsc-mf): expose exact proxy-map equality diagnostics
cursoragent 661c5c3
test(rsc-mf): expose proxy map collision count diagnostics
cursoragent ee24d53
test(rsc-mf): cover remote client default server action path
cursoragent 7483029
test(rsc-mf): assert request coverage across action families
cursoragent 9d3c307
test(rsc-mf): cover direct host nested and increment actions
cursoragent 0c0ca33
test(rsc-mf): enforce minimum action post volume per mode
cursoragent 963c240
test(rsc-mf): require action-family union coverage for posted ids
cursoragent 6f81467
test(rsc-mf): require action-family union coverage for posted ids
cursoragent 1256515
test(rsc-mf): assert repeated client callback request growth
cursoragent d321237
test(rsc-mf): align unique posted ids with effective action keys
cursoragent bf25039
test(rsc-mf): tighten per-family proxy id cardinality checks
cursoragent 93890ab
test(rsc-mf): tighten per-family proxy id cardinality checks
cursoragent 0dec94c
test(rsc-mf): assert action request URL-id parity
cursoragent 047f7d2
test(rsc-mf): assert family union spans all host proxy ids
cursoragent b4705d9
test(rsc-mf): enforce exact action post cardinality profile
cursoragent 542a4ad
test(rsc-mf): enforce exact action post cardinality profile
cursoragent be0ceaa
test(rsc-mf): assert uniform per-id action request frequency
cursoragent 549ba4e
refactor(rsc-mf): remove host proxy action glue and use bridge ids
cursoragent 301a7b4
refactor(rsc-mf): auto-register remote callback in federated client
cursoragent 72e8c86
test(rsc-mf): assert callback helper no longer needs expose
cursoragent 13edc5b
refactor(rsc-mf): initialize callback bridge via client side-effect m…
cursoragent 8621bd2
test(rsc-mf): assert callback expose chunk is never requested
cursoragent daaadd3
refactor(rsc-mf): centralize callback init in remote counter entry
cursoragent 18664e8
docs(rsc-mf): clarify bridge callback helper intent
cursoragent d6464ff
refactor(rsc-mf): move callback bootstrap to runtime module
cursoragent 7f870fa
refactor(rsc-mf): route exposed modules through runtime bootstrap wra…
cursoragent a86f3b5
refactor(rsc-mf): move callback registration helper into runtime name…
cursoragent 790f315
test(rsc-mf): assert callback wiring stays in runtime modules
cursoragent f53e085
test(rsc-mf): enforce runtime boundary across all component sources
cursoragent 6b3054d
refactor(rsc-mf): funnel all remote exposes through runtime boundary
cursoragent 9c2099a
refactor(rsc-mf): define remote exposes from single runtime map
cursoragent 90c4dac
refactor(rsc-mf): guard runtime expose paths in remote config
cursoragent 4da2b0a
test(rsc-mf): validate callback bootstrap wrapper set coverage
cursoragent f8aabd0
test(rsc-mf): assert remote manifest avoids source-path exposes
cursoragent 25443dc
refactor(rsc-mf): inline callback bootstrap in expose imports
cursoragent 2ef0c80
refactor(rsc-mf): bootstrap callback for all remote exposes
cursoragent 6953bab
refactor(rsc-mf): guard exposes to component modules
cursoragent 347d204
test(rsc-mf): lock lazy callback bootstrap import semantics
cursoragent 7dde578
test(rsc-mf): validate manifest expose set is userland subset
cursoragent e9f09d3
test(rsc-mf): assert config expose map matches expected userland keys
cursoragent 36966a9
test(rsc-mf): ensure host sources stay callback-wiring free
cursoragent f56389c
test(rsc-mf): lock host runtime plugins to transparent defaults
cursoragent b4da5b5
refactor(rsc-mf): memoize callback bootstrap initialization
cursoragent 88fdf16
refactor(rsc-mf): reset callback bootstrap promise after failures
cursoragent 088d643
test(rsc-mf): guard modern config callback wiring boundaries
cursoragent 66097a4
test(rsc-mf): assert modern config keeps transparent runtime boundaries
cursoragent 6a9e740
test(rsc-mf): enforce remote shared-scope and experiment config invar…
cursoragent 8baab1f
refactor(rsc-mf): validate expose keys and protect bootstrap module f…
cursoragent 8435ed6
test(rsc-mf): assert callback posting contract in runtime register so…
cursoragent b28577b
test(rsc-mf): lock runtime callback transport header semantics
cursoragent 82936fe
test(rsc-mf): assert callback bootstrap derives host origin dynamically
cursoragent 010fc9b
refactor(rsc-mf): normalize callback action URL and assert request Ac…
cursoragent 91e183e
test(rsc-mf): verify action requests preserve RSC accept header
cursoragent 2dbf236
test(rsc-mf): verify expose import files exist via source scan
cursoragent d18d90b
refactor(rsc-mf): require explicit TypeScript expose entry extensions
cursoragent fbd36bd
test(rsc-mf): assert runtime exposes wrapper directory stays empty
cursoragent b0e1593
test(rsc-mf): lock runtime callback helper file surface
cursoragent 114deee
test(rsc-mf): lock callback alias usage to runtime helpers
cursoragent f071c8d
test(rsc-mf): lock runtime callback initialization contract
cursoragent 1dba1cf
test(rsc-mf): prevent host callback runtime leakage
cursoragent 99b81e1
refactor(rsc-mf): guard expose imports against traversal paths
cursoragent f8e30d1
refactor(rsc-mf): validate callback bootstrap import boundaries
cursoragent 5762be3
refactor(rsc-mf): validate remote alias before bridge action prefixing
cursoragent 71afe3b
refactor(rsc-mf): enforce http(s) callback action URLs
cursoragent d72f82c
refactor(rsc-mf): reject callback URLs with embedded credentials
cursoragent aa01c52
refactor(rsc-mf): trim callback origin and block URL credentials
cursoragent 916209c
refactor(rsc-mf): normalize raw action ids before bridge prefix
cursoragent 97084d6
test(rsc-mf): reduce brittle runtime source assertions
cursoragent 102d1fd
test(rsc-mf): focus source guards on stable integration contracts
cursoragent 9cd4ad0
test(rsc-mf): add runtime callback contract behavior tests
cursoragent 6638c75
test(rsc-mf): cover action-id normalization and empty-origin skip
cursoragent 992d086
test(rsc-mf): cover alias trim dedupe in callback registration
cursoragent 423164b
test(rsc-mf): verify alias changes re-register callback handler
cursoragent 34dc442
test(rsc-mf): cover callback rebind on normalized URL changes
cursoragent 587ab25
test(rsc-mf): assert callback rebind when endpoint path changes
cursoragent a0168c4
test(rsc-mf): add init callback bootstrap behavior coverage
cursoragent 18cdc2e
test(rsc-mf): move mf config guardrails into behavior tests
cursoragent 2ff9d9e
test(rsc-mf): replace runtime source checks with behavior guards
cursoragent c429e03
test(rsc-mf): trim remaining source-content guardrail assertions
cursoragent 29137b8
test(rsc-mf): drop remaining filesystem source guard checks
cursoragent b7dbdc6
test(rsc-mf): expand host config behavior coverage
cursoragent 396e709
test(rsc-mf): add modern config behavior contract tests
cursoragent 23831f7
test(rsc-mf): verify host shared scope alignment
cursoragent c535de5
refactor(rsc-mf): validate callback URL parse before protocol checks
cursoragent a38a1d3
refactor(rsc-mf): remove redundant remote bridge import anchor
cursoragent 7e0c483
refactor(rsc-mf): rely on default remote alias in bootstrap
cursoragent d30b0e2
test(rsc-mf): assert no chunkLoadingGlobal modern config coupling
cursoragent eab45df
test(rsc-mf): assert modern plugin options and preEntry absence
cursoragent 7dc783c
refactor(rsc-mf): retry callback bootstrap on transient failures
cursoragent 8830523
refactor(rsc-mf): simplify callback keying and cover default alias
cursoragent 0e4dd7a
test(rsc-mf): cover host web chain and remote port precedence
cursoragent c6dc285
refactor(rsc-mf): fallback bootstrap retries without queueMicrotask
cursoragent cfbc77e
test(rsc-mf): assert no failed host or remote responses
cursoragent e9ca0b6
refactor(rsc-mf): normalize callback action pathname before registration
cursoragent 396a96d
test(rsc-mf): assert no failed browser requests in dev and build
cursoragent 4af5b4e
refactor(rsc-mf): fail fast on non-ok callback responses
cursoragent 9fd29b5
refactor(rsc-mf): retry callback fetch once before failing
cursoragent 269e5a4
test(rsc-mf): verify retry policy for callback 5xx and 4xx
cursoragent c734397
test(rsc-mf): assert callback retry request body reuse
cursoragent 0f92cc2
refactor(rsc-mf): extract callback expose wiring helper
cursoragent 3a8376e
refactor(rsc-mf): allow broader userland expose module paths
cursoragent 48c15eb
refactor(rsc-mf): support relative expose import paths
cursoragent cfb69fc
refactor(rsc-mf): accept cjs/mjs/cts/mts expose entries
cursoragent f6beeb9
refactor(rsc-mf): support object expose definitions with import arrays
cursoragent 5d39965
refactor(rsc-mf): normalize mixed expose definition shapes
cursoragent 73814a0
test(rsc-mf): lock mixed expose-definition guardrails
cursoragent 0d5ec92
refactor(rsc-mf): retry callback fetch on 429 responses
cursoragent ae03f8f
test(rsc-mf): allow multi-import expose definitions in config contract
cursoragent 4a92133
refactor(rsc-mf): dedupe repeated expose import entries
cursoragent 962d1e8
refactor(rsc-mf): retry callback fetch on timeout status codes
cursoragent 04bea87
test(rsc-mf): verify callback retry for 425 responses
cursoragent a289809
refactor(rsc-mf): trim expose import paths before validation
cursoragent a689f5b
test(rsc-mf): assert callback network failure after retries
cursoragent 8f9e303
test(rsc-mf): assert dedupe behavior in remote expose config
cursoragent ba39928
refactor(rsc-mf): normalize callback URLs with trailing slashes
cursoragent 442271f
test(rsc-mf): assert terminal 429 callback failure after retry
cursoragent 7ae305c
refactor(rsc-mf): enforce single-module object import arrays
cursoragent 4ec8948
test(rsc-mf): cover root callback URL slash dedupe
cursoragent 2c4a7f1
test(rsc-mf): cover slash+fragment callback URL dedupe
cursoragent 3b75a5c
test(rsc-mf): cover default-port callback URL normalization
cursoragent e2ab44d
refactor(rsc-mf): keep remote exposes as plain userland strings
cursoragent 21f7ed4
test(rsc-mf): relax expose-contract checks to behavior-level
cursoragent 51d9f59
test(rsc-mf): cover default https-port callback normalization
cursoragent de556c1
test(rsc-mf): assert callback rebind when endpoint port changes
cursoragent 44f2ead
refactor(rsc-mf): keep host remote public-path plugin always on
cursoragent 0b0942f
test(rsc-mf): assert browser expose-chunk coverage
cursoragent 28690f1
test(rsc-mf): cover host federated asset proxy middleware
cursoragent 8d4cb53
test(rsc-mf): validate forceRemotePublicPath runtime plugin behavior
cursoragent 1b8615c
test(rsc-mf): cover callback URL host-casing normalization
cursoragent 95bf06c
test(rsc-mf): cover remote entry URL normalization in runtime plugin
cursoragent 57ba0af
test(rsc-mf): cover additional federated asset proxy path markers
cursoragent b04a9b4
fix(rsc-mf): ignore malformed remote entry URLs in runtime plugin
cursoragent 22b8c20
fix(rsc-mf): add manifest fallback for stale expose chunk paths
cursoragent 9dcaef7
test(rsc-mf): cover shared-asset manifest fallback resolution
cursoragent 4087302
test(rsc-mf): cover css stale-path manifest fallback
cursoragent bc6434c
test(rsc-mf): assert no-match manifest fallback passthrough
cursoragent 800c14c
fix(rsc-mf): tolerate invalid remote manifest fallback payloads
cursoragent 9b62709
test(rsc-mf): cover manifest-fetch failure passthrough
cursoragent 8b96753
test(rsc-mf): extend manifest fallback query and async-asset coverage
cursoragent 3a11926
refactor(rsc-mf): skip manifest fallback for non-expose proxy paths
cursoragent 4321302
fix(rsc-mf): support alphanumeric fallback hash suffix matching
cursoragent 18a8193
test(rsc-mf): harden manifest fallback URL resolution
cursoragent 260278b
feat(rsc-mf): add remote expose-asset fallback middleware
cursoragent cc65c74
test(rsc-mf): expand remote manifest fallback contracts
cursoragent 42251e9
fix(rsc-mf): avoid host fallback refetching same expose URL
cursoragent cdf5a36
fix(rsc-mf): block fallback path traversal escapes
cursoragent 52e1eeb
test(rsc-mf): broaden remote fallback matching coverage
cursoragent fb1b47f
refactor(rsc-mf): share manifest fallback helpers
cursoragent 101d5cf
test(rsc-mf): add shared manifest fallback helper coverage
cursoragent 80084f9
fix(rsc-mf): mark host fallback fetches as internal
cursoragent 7fc15bf
fix(rsc-mf): skip host proxy on internal fallback requests
cursoragent 2d115bf
fix(rsc-mf): guard fallback helper against invalid origins
cursoragent a9551bc
test(rsc-mf): cover stale hashed expose fallback paths
cursoragent ff31a2f
fix(rsc-mf): reject encoded fallback path traversal
cursoragent 9dd6b4e
test(rsc-mf): cover stale-hashed css fallback paths
cursoragent 3407784
test(rsc-mf): cover malformed percent fallback paths
cursoragent 4dcb3f9
test: cover manifest query override precedence
cursoragent d71fde9
fix(rsc-mf): alias server-only in remote client bundle
cursoragent ee7456f
test(rsc-mf): guard host rsc streaming mode invariants
cursoragent b3ea214
fix(rsc-mf): sanitize proxied asset transport headers
cursoragent 42cffd9
refactor(rsc-mf): share safe proxy response helper
cursoragent e7aa758
test(rsc-mf): expand hop-by-hop header sanitization coverage
cursoragent bf39dff
fix(rsc-mf): strip proxy-connection hop headers
cursoragent 4220d7c
fix(rsc-mf): sanitize quoted connection hop headers
cursoragent b52cb63
fix(rsc-mf): normalize quoted connection tokens
cursoragent 91b8d88
test(rsc-mf): cover mixed-case connection token stripping
cursoragent 4f3cb6a
test(rsc-mf): assert proxied response status text
cursoragent 21b5649
fix(rsc-mf): guard no-body statuses in proxy responses
cursoragent 637bddd
test(rsc-mf): cover 205 and 304 proxy body stripping
cursoragent 2994076
fix(rsc-mf): normalize empty quoted connection tokens
cursoragent 18bbd03
fix(rsc-mf): typecheck and finalize federation asset middleware
cursoragent e1e43b0
test(rsc-mf): cover middleware context body response finalization
cursoragent 6db7873
fix(rsc-mf): prefer hashed manifest fallback assets
cursoragent eb3907e
test(rsc-mf): lock tsconfig rootDir shared-import contract
cursoragent d3a15f5
refactor(rsc-mf): localize server fallback utilities per fixture app
cursoragent f0c0530
refactor(rsc-mf): scope callback bootstrap to client/action exposes
cursoragent b52276d
refactor(rsc-mf): infer callback bootstrap from expose source directives
cursoragent 03b1c97
refactor(rsc-mf): make callback bootstrap injection source-driven
cursoragent 66f1360
refactor(rsc-mf): infer callback bootstrap from local import graph
cursoragent 29ec045
test(rsc-mf): lock callback bootstrap expose coverage
cursoragent 1259a7f
refactor(rsc-mf): infer callback bootstrap from dynamic imports
cursoragent aec0a14
fix(rsc-mf): ignore type-only imports in callback bootstrap inference
cursoragent f8adc5d
fix(rsc-mf): distinguish type-only and runtime specifier edges
cursoragent 2b24a63
test(rsc-mf): cover side-effect import callback inference boundaries
cursoragent 6d2e37d
test(rsc-mf): cover namespace and export-type-all inference edges
cursoragent 11d6e46
test(rsc-mf): cover inline export type-only and mixed bindings
cursoragent e40ab15
fix(rsc-mf): infer callback bootstrap through commonjs require edges
cursoragent 585a17e
refactor(rsc-mf): use TypeScript AST for callback edge detection
cursoragent d7b4139
docs(rsc-mf): document AST-based callback edge detection rationale
cursoragent edbbd3f
test(rsc-mf): cover import-equals and import-type callback inference
cursoragent 438da69
fix(rsc-mf): ignore type-only import-equals callback edges
cursoragent 7410cb8
feat(rsc-mf): auto-resolve remote public paths from federation state
cursoragent fc5e851
refactor(rsc-mf): generalize remote publicPath runtime resolution
cursoragent 1a291c7
test(rsc-mf): cover federation remotes-array and ssr-only path fallbacks
cursoragent 56679b4
refactor(rsc-mf): remove host fallback middleware layer
cursoragent 84938fb
refactor(rsc-mf): delete all fallback and proxy utilities
cursoragent 112bbec
chore(mf): vendor modern-js-v3 plugin into workspace
cursoragent 75e72d9
refactor(rsc-mf): remove callback pathname normalization helper
cursoragent 43b56b3
Merge remote-tracking branch 'origin/main' into cursor/module-federat…
ScriptedAlchemy fd6180e
chore: update pnpm-lock.yaml after merge with origin/main
ScriptedAlchemy b5c40da
feat(modernjs-v3): add plugin-first RSC MF bridge runtime
ScriptedAlchemy 45bd1f8
feat(modernjs-v3): finalize plugin-first MF+RSC bridge flow
ScriptedAlchemy 3f4bcb6
fix(ci): sync pnpm lockfile with @types/react specifiers
ScriptedAlchemy a64ce9e
refactor(rsc-mf): isolate MF runtime hooks from core
ScriptedAlchemy 494d849
fix(modernjs-v3): guard remote external URL rewrite
ScriptedAlchemy 23160ec
Merge pull request #2 from ScriptedAlchemy/cursor/module-federation-r…
ScriptedAlchemy de599db
fix(rsc-mf): harden callback routing and target config patching
cursoragent 27af5a7
fix(rsc-mf): harden action fallback and static headers
ScriptedAlchemy b5f6763
fix(rsc-mf): harden static path and bridge load dedupe
ScriptedAlchemy 66d692f
test(modernjs-v3): include config contract in rstest suite
cursoragent 69eb929
chore(ci): trigger workflow rerun
cursoragent 6180082
fix(ci): resolve lint regressions in rsc-mf changes
cursoragent c3edf41
test(builder): refresh snapshots after rsc-mf config updates
cursoragent cf44bf9
test(e2e): align inline-chunk runtime assertions
cursoragent 7642d35
test(e2e): update inline chunk html runtime expectations
cursoragent 8558ccb
fix(rsc-mf): update bridge runtime and test coverage
ScriptedAlchemy 3f4e4d5
fix: harden rsc bridge alias resolution and bundle path checks
cursoragent c196826
test: format fallback alias runtime guard assertion
cursoragent 22094ea
fix: harden mf rsc bundle loading and runtime hooks
ScriptedAlchemy 52489bf
fix: align callServer window access and avoid global strategy state
ScriptedAlchemy 27bb4e0
chore(rsc-mf): refresh federation canary pins and fixture contracts
ScriptedAlchemy 5683fbe
chore(ci): ignore rsc-mf canary fixture paths in dependency consisten…
ScriptedAlchemy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,310 @@ | ||
| # Module Federation + RSC Technical Specification (Current Branch) | ||
|
|
||
| This document describes how Module Federation + React Server Components (RSC) | ||
| works in this branch based on actual implementation. | ||
|
|
||
| Primary implementation paths: | ||
| - `packages/modernjs-v3/src/cli/index.ts` | ||
| - `packages/modernjs-v3/src/cli/configPlugin.ts` | ||
| - `packages/modernjs-v3/src/cli/ssrPlugin.ts` | ||
| - `packages/modernjs-v3/src/cli/mfRuntimePlugins/*` | ||
| - `packages/modernjs-v3/src/runtime/rsc-bridge-expose.ts` | ||
| - `packages/modernjs-v3/src/runtime/rsc-client-callback-bootstrap.js` | ||
| - `packages/runtime/render/src/client/callServer.ts` | ||
| - `packages/runtime/render/src/server/rsc/rsc.tsx` | ||
| - `packages/server/core/src/adapters/node/plugins/resource.ts` | ||
| - `packages/modernjs-v3/src/server/*` | ||
| - `tests/integration/rsc-mf/*` | ||
|
|
||
| ## 1) Runtime Components and Responsibilities | ||
|
|
||
| The system has four cooperating parts: | ||
|
|
||
| 1. Config/build patching | ||
| - Implemented by `moduleFederationConfigPlugin` and `moduleFederationSSRPlugin`. | ||
| - Converts user MF config into CSR/SSR target-specific configs and runtime plugin stacks. | ||
|
|
||
| 2. Host runtime bridge | ||
| - Implemented by `rsc-bridge-runtime-plugin`. | ||
| - Loads the remote bridge expose, merges manifest metadata into host runtime manifest, | ||
| and creates proxy action modules. | ||
|
|
||
| 3. Remote runtime bridge | ||
| - Implemented by `rsc-bridge-expose`. | ||
| - Exposes `{ getManifest, executeAction }` so host can discover and execute remote actions. | ||
|
|
||
| 4. Client/server action transport | ||
| - Client: `callServer.ts` plus callback bootstrap resolver. | ||
| - Server: `rsc.tsx` action endpoint (`x-rsc-action` based dispatch). | ||
|
|
||
| ## 2) Build-Time Specification | ||
|
|
||
| ### 2.1 Plugin entry wiring | ||
|
|
||
| `moduleFederationPlugin` in `packages/modernjs-v3/src/cli/index.ts`: | ||
| - Initializes shared mutable plugin options (`csrConfig`, `ssrConfig`, plugin refs). | ||
| - Registers browser MF plugin on web target. | ||
| - Registers server runtime plugin `@module-federation/modern-js-v3/server`. | ||
| - Chains: | ||
| - `moduleFederationConfigPlugin(...)` | ||
| - `moduleFederationSSRPlugin(...)` | ||
|
|
||
| ### 2.2 Config loading and cloning | ||
|
|
||
| `getMFConfig` in `configPlugin.ts`: | ||
| - Source precedence: | ||
| 1. `userConfig.config` if provided. | ||
| 2. else `module-federation.config.ts` from project root. | ||
| - Uses `jiti` with ESM resolve enabled. | ||
|
|
||
| `moduleFederationConfigPlugin`: | ||
| - Creates isolated CSR and SSR copies of MF config (`csrConfig`, `ssrConfig`). | ||
| - Applies target-specific patching per bundler chain target (`web` vs non-web). | ||
|
|
||
| ### 2.3 Required contracts and enforced invariants | ||
|
|
||
| In `patchMFConfig` and `assertRscMfConfig`: | ||
| - `mfConfig.name` is required, otherwise throws. | ||
| - If `experiments.rsc === true`, then: | ||
| - `experiments.asyncStartup` must be `true`. | ||
| - server runtime plugin list must include `@module-federation/node/runtimePlugin`. | ||
| - Default `remoteType` becomes `'script'` when unset. | ||
|
|
||
| ### 2.4 Runtime plugin injection rules | ||
|
|
||
| `patchMFConfig` injects: | ||
| - Always: | ||
| - `@module-federation/modern-js-v3/shared-strategy` | ||
| - SSR + dev only: | ||
| - `@module-federation/modern-js-v3/resolve-entry-ipv4` | ||
| - RSC enabled and remotes present: | ||
| - `rsc-bridge-runtime-plugin` (resolved local/esm/cjs path) | ||
| - Server target only: | ||
| - `@module-federation/node/runtimePlugin` | ||
| - `@module-federation/node/record-dynamic-remote-entry-hash-plugin` (dev only) | ||
| - `@module-federation/modern-js-v3/inject-node-fetch` | ||
|
|
||
| ### 2.5 RSC expose normalization | ||
|
|
||
| `setRscExposeConfig` in `configPlugin.ts`: | ||
| - For each user expose (except internal bridge expose): | ||
| - Prepends `RSC_CLIENT_CALLBACK_BOOTSTRAP_MODULE` to expose import list. | ||
| - Sets `layer = 'react-server-components'`. | ||
| - Ensures internal expose exists: | ||
| - `./__rspack_rsc_bridge__ -> rsc-bridge-expose` module, same RSC layer. | ||
|
|
||
| ### 2.6 Dev server and source defaults | ||
|
|
||
| `moduleFederationConfigPlugin` config output: | ||
| - Sets `REMOTE_IP_STRATEGY` define always. | ||
| - Sets `FEDERATION_IPV4` define in SSR dev mode. | ||
| - When exposes exist, adds wildcard CORS headers for dev server. | ||
| - Sets `source.enableAsyncEntry` to: | ||
| - explicit user value if provided | ||
| - else `!enableRsc` fallback | ||
|
|
||
| ## 3) Server-Side Loading and Static Asset Support | ||
|
|
||
| ### 3.1 Strategy-based bundle loading in server-core | ||
|
|
||
| `packages/server/core/src/adapters/node/plugins/resource.ts`: | ||
| - Introduces strategy registry: | ||
| - `registerBundleLoaderStrategy` | ||
| - `getBundleLoaderStrategies` | ||
| - `loadBundle(filepath)` algorithm: | ||
| 1. `require` / `compatibleRequire` | ||
| 2. if immediate non-promise export: return | ||
| 3. if promise export: await once | ||
| 4. if unresolved/error: iterate registered strategies | ||
| 5. if still unresolved: log and return `undefined` | ||
|
|
||
| ### 3.2 Async-startup loader strategy | ||
|
|
||
| `packages/modernjs-v3/src/server/asyncStartupLoader.ts`: | ||
| - Detects async-startup signature: | ||
| - `var __webpack_exports__ = __webpack_require__.x();` | ||
| - and `__webpack_require__.mfAsyncStartup` | ||
| - Rewrites call to: | ||
| - `__webpack_require__.x({}, [])` | ||
| - Executes patched bundle in VM context and returns exports. | ||
|
|
||
| ### 3.3 Server plugin registration | ||
|
|
||
| `packages/modernjs-v3/src/server/index.ts`: | ||
| - Registers `mfAsyncStartupLoaderStrategy` globally into server-core loader registry. | ||
| - In production: | ||
| - adds static middleware serving only `/bundles/*.js|.json` | ||
| - Optional: | ||
| - adds wildcard CORS middleware when `MODERN_MF_AUTO_CORS` is set. | ||
|
|
||
| ## 4) RSC Bridge Protocol | ||
|
|
||
| ### 4.1 Internal bridge expose | ||
|
|
||
| Remote exposes: | ||
| - Key: `./__rspack_rsc_bridge__` | ||
| - Interface: | ||
| - `getManifest(): ManifestLike` | ||
| - `executeAction(actionId: string, args: unknown[]): Promise<unknown>` | ||
|
|
||
| `ManifestLike` shape: | ||
| - `serverManifest?: Record<string, any>` | ||
| - `clientManifest?: Record<string, any>` | ||
| - `serverConsumerModuleMap?: Record<string, any>` | ||
|
|
||
| ### 4.2 Host merge behavior | ||
|
|
||
| In `rsc-bridge-runtime-plugin.ts`, `ensureRemoteAliasMerged(alias, args)`: | ||
| 1. Ensure single in-flight merge per alias via `aliasMergePromises`. | ||
| 2. Install proxy module ID: | ||
| - `__modernjs_mf_rsc_action_proxy__:<alias>` | ||
| 3. Load remote bridge: | ||
| - `${alias}/__rspack_rsc_bridge__` | ||
| 4. Read remote manifest and merge into host `__webpack_require__.rscM`. | ||
| 5. Track alias as merged (`mergedRemoteAliases`). | ||
|
|
||
| ### 4.3 ID namespacing and mapping | ||
|
|
||
| Module ID namespace: | ||
| - `remote-module:<alias>:<rawModuleId>` | ||
|
|
||
| Action ID namespace: | ||
| - `remote:<alias>:<rawActionId>` | ||
|
|
||
| Why these are different namespaces: | ||
| - `remote-module:*` is used for module identity inside `clientManifest` and | ||
| `serverConsumerModuleMap` (module graph identity). | ||
| - `remote:*` is used for server action references in `serverManifest` and | ||
| request header `x-rsc-action` (action invocation identity). | ||
| - Keeping them distinct avoids conflating module resolution IDs with action | ||
| dispatch IDs, even when both originate from the same remote alias. | ||
|
|
||
| Action remap map: | ||
| - global key: `__MODERN_RSC_MF_ACTION_ID_MAP__` | ||
| - semantics: | ||
| - `rawActionId -> remote:<alias>:rawActionId` when unique | ||
| - `rawActionId -> false` when collision across remotes is detected | ||
|
|
||
| Conflict policy: | ||
| - `assertNoConflict` throws if two remotes produce different payloads for same manifest key. | ||
|
|
||
| ## 5) Client Action Dispatch Specification | ||
|
|
||
| ### 5.1 Core call path | ||
|
|
||
| `packages/runtime/render/src/client/callServer.ts`: | ||
| - `requestCallServer(id, args)`: | ||
| - resolves action ID through global resolver key `__MODERN_RSC_ACTION_RESOLVER__` | ||
| - endpoint: | ||
| - `'/'` for `main`/`index`/missing entry | ||
| - else `/${window.__MODERN_JS_ENTRY_NAME}` | ||
| - request: | ||
| - `method: POST` | ||
| - header `Accept: text/x-component` | ||
| - header `x-rsc-action: <resolved-action-id>` | ||
| - body `encodeReply(args)` | ||
|
|
||
| Branch history note: | ||
| - This resolver indirection is new on this branch. | ||
| - On `main`, `callServer` sent the incoming action ID directly in | ||
| `x-rsc-action` with no global remap hook. | ||
|
|
||
| ### 5.2 Bootstrap resolver and callback install | ||
|
|
||
| `rsc-client-callback-bootstrap.js`: | ||
| - Calls `setResolveActionId(resolveActionId)` once. | ||
| - Repeatedly installs `setServerCallback` into discovered client.browser runtimes. | ||
| - Hooks webpack chunk loader (`__webpack_require__.e`) to re-install callbacks after late chunk loads. | ||
|
|
||
| Branch history note: | ||
| - `rsc-client-callback-bootstrap.js` and the chunk-loader hook are added on this | ||
| branch (not present on `main`). | ||
| - The hook is a runtime compatibility workaround to catch callbacks loaded after | ||
| initial bootstrap. A cleaner long-term option would be a first-class runtime | ||
| lifecycle event from federation/runtime instead of patching `__webpack_require__.e`. | ||
|
|
||
| `resolveActionId(id)` behavior: | ||
| 1. If already prefixed (`remote:`), return as-is. | ||
| 2. If remap entry is string, return mapped prefixed ID. | ||
| 3. If remap entry is `false`, return raw ID. | ||
| 4. Else: | ||
| - attempts fallback alias resolution when a single remote alias can be inferred, | ||
| - otherwise waits briefly on remap waiters map. | ||
|
|
||
| ## 6) Server Action Execution Specification | ||
|
|
||
| `packages/runtime/render/src/server/rsc/rsc.tsx`: | ||
| - Reads header `x-rsc-action`. | ||
| - Loads action via `loadServerAction(serverReference)`. | ||
| - Decodes args: | ||
| - `multipart/form-data` -> `decodeReply(formData)` | ||
| - else text -> `decodeReply(text)` | ||
| - Executes action (`await Promise.resolve(action.apply(null, args))`). | ||
| - Renders response stream via `renderToReadableStream`. | ||
|
|
||
| Error behavior: | ||
| - Missing action header: `404`. | ||
| - Decode failure: `400`. | ||
| - Execution failure: `500`. | ||
| - In development, `500` includes error message/stack in body. | ||
|
|
||
| ## 7) SSR Remote Entry URL Normalization | ||
|
|
||
| In `rsc-bridge-runtime-plugin.ts`: | ||
| - Snapshot patching normalizes: | ||
| - `ssrPublicPath` | ||
| - `remoteEntry.path` | ||
| - `ssrRemoteEntry` fallbacks from snapshot metadata | ||
| - If remote entry is broken (`undefined`, empty, malformed), plugin attempts to reconstruct from snapshot fields. | ||
| - Node-like runtime branch may prefix entry path with `bundles/` when `ssrRemoteEntry` is missing. | ||
|
|
||
| Recommendation: | ||
| - Preferred steady-state is to require a complete snapshot contract (non-undefined | ||
| `ssrRemoteEntry`/public path fields) from upstream runtime metadata. | ||
| - Current reconstruction logic exists for compatibility with incomplete snapshots | ||
| seen in practice; it should be reduced/removed once snapshot completeness is guaranteed. | ||
|
|
||
| ## 8) Fixture Specification (`tests/integration/rsc-mf`) | ||
|
|
||
| Host config (`tests/integration/rsc-mf/host`): | ||
| - `server.rsc = true` | ||
| - `source.enableAsyncEntry = false` | ||
| - `moduleFederationPlugin({ ssr: true })` | ||
| - remote manifest URL uses `RSC_MF_REMOTE_PORT` and points to `/static/mf-manifest.json` | ||
|
|
||
| Remote config (`tests/integration/rsc-mf/remote`): | ||
| - `server.rsc = true` | ||
| - `server.ssr = true` | ||
| - `source.enableAsyncEntry = false` | ||
| - `output.assetPrefix = http://127.0.0.1:${remotePort}` | ||
| - MF exposes include server/client components + actions. | ||
| - MF experiments include: | ||
| - `asyncStartup: true` | ||
| - `rsc: true` | ||
|
|
||
| Tested contracts: | ||
| - Remote server components render in host RSC route. | ||
| - Remote client components hydrate and function in host page. | ||
| - Remote actions execute via host endpoint and carry expected action headers. | ||
| - Expose list includes user exposes plus `./__rspack_rsc_bridge__`. | ||
|
|
||
| ## 9) Known Caveats (Current State) | ||
|
|
||
| 1. Fallback alias auto-prefixing | ||
| - In the bootstrap resolver, unresolved raw IDs may be auto-prefixed to a fallback alias when one remote is detectable. | ||
| - This can misroute host-local actions in mixed host+remote pages. | ||
|
|
||
| 2. Double `bundles/` risk | ||
| - SSR entry normalization can build `.../bundles/bundles/...` URLs for certain snapshot/publicPath combinations. | ||
|
|
||
| 3. Collision path with `false` remap values | ||
| - On raw action ID collisions across remotes, remap map stores `false`. | ||
| - Resolver then sends raw ID, while host manifest action keys are namespaced (`remote:<alias>:...`), causing unresolved lookup without explicit disambiguation. | ||
|
|
||
| ## 10) Practical Integration Rules | ||
|
|
||
| Use these rules to avoid known failure modes: | ||
| - Always set `experiments.asyncStartup = true` when using `experiments.rsc = true`. | ||
| - Keep unique action IDs across remotes when possible. | ||
| - Keep remote snapshot fields complete (`publicPath` and remote entry metadata) in SSR. | ||
| - For fixture-like setups, keep `source.enableAsyncEntry = false` for host and remote until async-entry semantics are explicitly validated for your target. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.