Skip to content

fix: preserve Router context across SSR bundlers - #6

Open
dmchoi77 wants to merge 1 commit into
module-federation:mainfrom
dmchoi77:fix/router-context-ssr
Open

dmchoi77 wants to merge 1 commit into
module-federation:mainfrom
dmchoi77:fix/router-context-ssr

Conversation

@dmchoi77

Copy link
Copy Markdown
Contributor

Summary

Fix an issue where an Rsbuild SSR Host and a Vite SSR Remote could evaluate separate React/TanStack Router runtimes, preventing the Remote from reading the Host's RouterProvider context. React and TanStack Router runtimes are now aligned to the Host's singleton instances so SSR, hydration, and Remote navigation use the same context.

Problem

  • The reproduced combination is Rsbuild SSR Host + Vite SSR Remote. The Host renders each request through its RouterProvider, while the Remote consumes the Host Router context through Link or useNavigate.
  • The previous default shared contract covered only react and react-dom, so @tanstack/react-router and @tanstack/router-core could be evaluated separately in the Host and Remote SSR graphs.
  • In particular, Vite development SSR entries under /__mf_ssr__/ run through the Remote dev server's Vite 8 ModuleRunner and optimized dependency paths. If that path evaluates files different from the Host's share scope, the Host Provider and Remote hook reference different module-level context objects.
  • The Remote can then fail to read the Host Router during SSR; the reproduced failure included a protocolAllowlist-related null error. Remotes that render only static markup may not expose the problem because they do not consume Router context.
  • Production uses a separate Vite SSR loader path, but the previous shared defaults still had no contract guaranteeing one compatible Router runtime across bundlers.

Changes

  • packages/tanstack/src/shared.ts
    • Centralize the shared package list for react, react-dom, @tanstack/react-router, and @tanstack/router-core.
    • Use the same constants across the Vite adapter, Rsbuild adapter, and Node SSR loader instead of maintaining separate lists.
  • packages/tanstack/src/vite.ts
    • Detect Hosts from the remotes configuration and apply eager shared defaults for Hosts.
    • Preserve lazy behavior for Remote-only builds and keep explicit user shared entries authoritative.
    • This ensures the Host registers its Router runtime before a Remote can provide a different instance.
  • packages/tanstack/src/rsbuild.ts
    • Externalize React/Router shared modules from the Rsbuild SSR Host server bundle.
    • Preserve user-provided strings, arrays, import, scope, and shareKey settings.
    • This prevents a second Host Router runtime from being embedded in the server bundle without overriding existing Federation configuration.
  • packages/tanstack/src/node-entry-loader.ts
    • Register the Host's React/Router modules in the Module Federation share scope and Node module cache when the server starts.
    • Resolve transitive dependencies from the @tanstack/react-router or TanStack Start package roots when pnpm does not expose them from the app root.
    • Load Vite development SSR /__mf_ssr__/ entries through Vite 8 ModuleRunner with a host-aware transport.
    • Externalize optimized dependency IDs requested by Vite to the Host's actual file URLs so the Remote does not create a separate React/Router graph.
    • Keep production Vite SSR on the existing @module-federation/vite SSR loader and apply the custom transport only to development entries.
    • Use Vite's ModuleRunner protocol instead of rewriting transformed Remote source so Vite retains responsibility for re-exports, dynamic imports, and source maps.

Validation

  • pnpm test: all 61 tests passed
  • pnpm --filter @module-federation/tanstack typecheck: passed
  • pnpm --filter @module-federation/tanstack build: passed
  • node --test --test-concurrency=1 test/runtime.test.mjs test/release-contracts.test.mjs: 36/36 passed
  • pnpm exec prettier --check packages/tanstack/src/node-entry-loader.ts packages/tanstack/src/rsbuild.ts packages/tanstack/src/shared.ts packages/tanstack/src/vite.ts test/release-contracts.test.mjs test/runtime.test.mjs: changed-file formatting checks passed
  • Manual SSR reproduction: the Vite Router Remote rendered successfully in the Rsbuild SSR Host without the protocolAllowlist error

@dmchoi77
dmchoi77 force-pushed the fix/router-context-ssr branch from 844cfd1 to edada41 Compare October 10, 2026 14:15
@pkg-pr-new

pkg-pr-new Bot commented Oct 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/module-federation/tanstack/@module-federation/tanstack@6

commit: edada41

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant