feat(ssr): support mf-manifest.json as remote entry URL#798
Merged
gioboa merged 28 commits intoJun 16, 2026
Conversation
Enable manifest-first SSR entry resolution, ENV_TARGET node for Environment API server builds, and synchronous remote/shared exports on first server render so hosts can use mf-manifest.json interchangeably with remoteEntry.js. Co-authored-by: Cursor <[email protected]>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Contributor
Author
|
I can also adjust the vite examples PR (gioboa/module-federation-vite-examples#6) to use the manifest instead of the remoteEntry.js as a demo. |
commit: |
mf-manifest.json as remote entry URLCo-authored-by: Cursor <[email protected]>
Vite 5/6 may invoke config() without a bound `this`, so read SSR target only from config.build.ssr there. Environment API ssr/server targets stay in configEnvironment, with the unit test updated accordingly. Co-authored-by: Cursor <[email protected]>
Use lazy client initPromise in browser builds while SSR bundles await the local fallback, so singleton shared libs initialize once in preview and named workspace exports stay defined on the server. Co-authored-by: Cursor <[email protected]>
Use existing __mfRemotePending.then chains instead of await in generated remote modules so unified/client wrappers stay synchronous for Nuxt and other frameworks. Workspace singleton shares keep initPromise.then lazy fallbacks in build output without import.meta.env.SSR await branches. Co-authored-by: Cursor <[email protected]>
configEnvironment was mutating a shared define object, so the ssr env's node target leaked into the client graph and pulled Node builtins into the browser. Copy define per environment so client stays web and ssr stays node. Co-authored-by: Cursor <[email protected]>
Revert virtualRemoteEntry, virtualShared_preBuild, and their tests to main. Remove the merged react-redux optimizeDeps test from index.test.ts so the branch diff stays focused on manifest-as-entry SSR support. Co-authored-by: Cursor <[email protected]>
configEnvironment now returns early for client environments so ENV_TARGET stays web in the browser graph. SSR entry resolution is cached per remote entry URL so mixed remoteEntry.js and mf-manifest.json hosts resolve correctly. Co-authored-by: Cursor <[email protected]>
Use sync local share imports during SSR builds while keeping lazy initPromise on the client so workspace singletons initialize once in preview without breaking named exports on the server. Co-authored-by: Cursor <[email protected]>
…nner Fall through to the HTTP temp-file loader when ModuleRunner is unavailable or returns an invalid module, and probe /__mf_ssr__/ and /__mf_server__ when a pre-resolved .ssr.js URL from the manifest is unreachable. Co-authored-by: Cursor <[email protected]>
gioboa
reviewed
Jun 12, 2026
gioboa
reviewed
Jun 13, 2026
gioboa
left a comment
Collaborator
There was a problem hiding this comment.
I did a check with LLM and there are few things to fix.
Findings:
- src/index.ts:627 removes LOAD_SHARE_TAG / PREBUILD_TAG from parse-end exclusion. That reverts the recent “reduce latency” behavior and
makes generated shared modules gate parsePromise again. Risk: large builds wait/timeout on MF-generated virtual modules unrelated to app
parse completion. - src/utils/ssrEntryLoader.ts:550 now falls through from /mf_ssr/ ModuleRunner failure/unavailable into fetchEsmToTempFile. For dev SSR
this path is known broken: served SSR entry imports virtual:mf-exposes-ssr:*, and temp-file import can’t resolve Vite virtual ids. This
silently masks runner failures and does wasted/brittle fetch/import work. - src/index.ts:1105 configEnvironment overwrites existing env-level define.ENV_TARGET. Root config() deliberately preserves user-defined
ENV_TARGET; this hook should likely do same or warn.
gioboa
requested changes
Jun 13, 2026
gioboa
reviewed
Jun 13, 2026
gioboa
reviewed
Jun 13, 2026
Resolved conflict in virtualShared_preBuild.test.ts by preserving the
SSR-specific assertions (if (import.meta.env.SSR) guard and await import)
from the PR while incorporating the initPromise.then assertion from
upstream. Dropped upstream's not.toContain('await ') assertion which is
incompatible with the SSR branch that intentionally uses await.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
gioboa
reviewed
Jun 15, 2026
…onous local fallback
gioboa
reviewed
Jun 15, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.


Summary
SSR hosts can use
entry: "…/mf-manifest.json"interchangeably withremoteEntry.js. On the server,ssrEntryLoaderreadsmetaData.ssrRemoteEntryfrom the manifest and loads the Node SSR entry. This unlocks Module Federation Chrome DevTools manifest-based discovery.Scope (intentionally narrow):
ssrEntryLoader— manifest-first SSR resolution for.jsonentries; HEAD-checkssrRemoteEntry; fallback to__mf_server__/ URL convention; existingremoteEntry.jspath unchangedindex.ts—configEnvironmentsetsENV_TARGET: "node"on server/ssr Vite environments only (client stays"web")Out of scope: no changes to virtual remote wrappers, shared prebuild codegen, or client-side manifest handling (handled by
@module-federation/enhancedruntime).Usage
Remote (
manifest: truerequired):Host (either entry style):
Test plan
pnpm test(ssrEntryLoader manifest-as-entry + ENV_TARGET configEnvironment tests)pnpm playwright test --project=multi-example(10/10)