Skip to content

fix: stabilize TanStack SSR remote revalidation - #5

Merged
Nsttt merged 1 commit into
module-federation:mainfrom
dmchoi77:fix/ssr-remote-revalidation
Oct 10, 2026
Merged

Nsttt merged 1 commit into
module-federation:mainfrom
dmchoi77:fix/ssr-remote-revalidation

Conversation

@dmchoi77

@dmchoi77 dmchoi77 commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Summary

TanStack Start SSR hosts cache remote server entries and Module Federation containers for the lifetime of the Node process by default. This change adds TTL-based revalidation so a running host can load a redeployed remote, while preventing duplicate fetch/evaluation during an expiration window.

Rsbuild hosts now handle both Rsbuild CommonJS remotes and Vite ESM remotes through the same Node entry-loader path, while Vite hosts preserve ssrEntryLoader options for the upstream Vite adapter.

Changes

  • TTL revalidation and timestamp semantics
    • When maxAgeMs is configured, the loader records the time of a successful remote load and measures the TTL from that entry load.
    • Loading another exposed module does not refresh lastLoadedAt, so repeated expose requests cannot postpone remote-entry revalidation indefinitely.
    • Once the TTL expires, registerRemotes(..., { force: true }) invalidates the runtime container/module cache before the next remote entry load.
  • Concurrency control
    • When an already-loaded remote expires and multiple SSR requests arrive together, they share an origin/remote-scoped pending barrier.
    • Only the first request performs revalidation; the other requests wait for the new remote load to complete.
    • Both success and failure clear the pending state. Failures do not update the timestamp, allowing later requests to retry.
  • Vite/Rsbuild server-entry handling
    • Rsbuild CommonJS remotes fetch and re-evaluate the new remoteEntry.ssr.cjs as a Node CommonJS module.
    • Vite ESM remotes use revalidate() and the cache owned by @module-federation/vite/ssrEntryLoader.
    • strategy, fetchTimeoutMs, and fetchMaxBytes are forwarded to the Vite SSR loader. fetchTimeoutMs: 0 disables timeouts for CommonJS requests and Vite fallback requests.
    • The Rsbuild runtime-plugin boundary now uses an explicit NodeEntryLoaderOptions type instead of accepting arbitrary option keys.
  • Documentation and regression coverage
    • Added tests for the lastLoadedAt regression, concurrent TTL revalidation single-flight, and disabled timeouts.
    • Added release-contract coverage proving that Vite and Rsbuild preserve and forward all SSR entry-loader options.
    • Documented that Vite's native loader needs a manifest version for automatic change detection, and that shared singleton replacement and remote module-scope side effects are not handled automatically.
    • Added a patch changeset for @module-federation/tanstack.

Runtime Behavior and Limitations

  • Without maxAgeMs, remotes remain cached until the host process exits, as before.
  • Revalidation is not background polling; it runs on the next loadRemote() request after the TTL expires.
  • Revalidation makes subsequent requests use the new remote entry and exposed modules, but it does not hot-swap in-flight requests or existing module references.
  • Vite's native maxAgeMs is version-aware when the remote is resolved from mf-manifest.json. Direct or convention-based server-entry URLs may require an explicit revalidate() call.
  • Changes to process-level shared singleton versions or implementations, such as React, require a host restart.
  • Rsbuild/CommonJS remote entries are evaluated again, so module-scope effects such as timers, process listeners, or connections are not automatically disposed. TTL revalidation should only be enabled for remotes whose evaluation is safe to repeat.

Validation

  • pnpm test: 65 tests passed, including the full build and Vite/Rsbuild client/SSR interoperability checks
  • pnpm typecheck: 8 packages passed
  • node --test --test-concurrency=1 test/release-contracts.test.mjs: 26 tests passed, including the latest option-forwarding contracts
  • pnpm exec prettier --check packages/tanstack/README.md TODO.md test/release-contracts.test.mjs: passed

@pkg-pr-new

pkg-pr-new Bot commented Oct 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 3b7f555

@Nsttt
Nsttt merged commit 20e7379 into module-federation:main Oct 10, 2026
6 checks passed
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.

2 participants