Skip to content

feat: strengthen SSR federation (dev parity, shared strategy, resilience)#4

Merged
Nsttt merged 1 commit into
mainfrom
feat/ssr-federation-hardening
Jul 9, 2026
Merged

feat: strengthen SSR federation (dev parity, shared strategy, resilience)#4
Nsttt merged 1 commit into
mainfrom
feat/ssr-federation-hardening

Conversation

@Nsttt

@Nsttt Nsttt commented Jul 3, 2026

Copy link
Copy Markdown
Member

Summary

Strengthens the module's SSR federation so remote components are truly server-rendered wherever the toolchain allows it, and degrade predictably where it doesn't.

Changes

  • ssr module option (default true) replaces the hard !nuxt.options.dev gate. Server federation is now controlled by the option and the app's ssr setting, not by dev vs prod.
    • Dev mode checks the installed Vite version: the @module-federation/vite ssrEntryLoader dev path (ModuleRunner over /__mf_runner__) requires Vite 8+, and on Vite 7 it deadlocks the SSR render (verified empirically). On Vite 7 (current Nuxt) dev falls back to client-only remotes with an info log; when Nuxt ships Vite 8 next minor, dev upgrades to real MF SSR automatically.
  • shared-strategy runtime plugin (new @module-federation/nuxt/shared-strategy export) forcing loaded-first on all shared deps, injected into both the client and server federation configs, so an already-loaded shared module (e.g. the host's Vue instance) is reused across remotes instead of re-negotiated.
  • Unified config assembly: one config source patched per target via patchMFConfig(config, isServer) with runtime-plugin injection/dedupe. Configs stay lazy inside the Vite plugin factories because exposed components are collected by Nuxt hooks after module setup.
  • Shared-version mismatch warnings at build time: the Vite server side aliases shared packages to the host's installed copies with no share-scope negotiation, so divergence between host and remote versions is now surfaced instead of silent.
  • Graceful SSR failure fallback: if a remote can't be loaded during SSR, the server logs a warning and renders nothing for that component instead of failing the whole response; the client renders it after hydration.
  • Fix: missing CORS headers on the root-level remoteEntry.js copy that the rebased manifest points browsers at (pre-existing bug on main; client-side federation failed with RUNTIME-015 in the browser while all curl-level checks passed).

Verification

Playwright (Chromium) against the example apps:

  • Prod (6/6): remote Widget/Counter markup present in the raw SSR HTML, both components visible after hydration, no hydration mismatch warnings, no console errors, buttons interactive.
  • Dev on Vite 7 (4/4): SSR responds in ~400 ms (no hang), remote components correctly deferred and mounted client-side, no console errors.

Plus tsc --noEmit, package build, and full builds of both example apps.

Caveat

The dev-mode true-MF-SSR path is implemented but can't be exercised until Nuxt ships Vite 8 — it should be re-verified in dev when that lands.

…nce)

- Gate server federation on a new `ssr` module option (default true)
  and the app's ssr setting, instead of hard-disabling it in dev.
  Dev-mode MF SSR activates automatically on Vite 8+ (Nuxt's next
  minor); on Vite 7 it falls back to client-only remotes with an
  informative log, since the ssrEntryLoader ModuleRunner path
  requires Vite 8 and hangs on older versions.
- Inject a shared-strategy runtime plugin (loaded-first) into both
  the client and server federation configs so an already-loaded
  shared module (e.g. the host's Vue) is reused across remotes.
- Restructure config assembly into a patchMFConfig step with
  per-target runtime-plugin injection and dedupe.
- Warn at build time when a remote manifest's shared dependency
  versions diverge from the host's installed versions, since the
  Vite server side has no share-scope version negotiation.
- Degrade gracefully when a remote fails to load during SSR:
  render nothing on the server and let the client render it after
  hydration instead of failing the whole server render.
- Fix missing CORS headers on the root-level remoteEntry.js copy
  that the rebased manifest points browsers at (pre-existing bug
  surfaced by browser-level verification).
@Nsttt Nsttt self-assigned this Jul 3, 2026
@Nsttt Nsttt merged commit eeab046 into main Jul 9, 2026
@Nsttt Nsttt deleted the feat/ssr-federation-hardening branch July 9, 2026 09:42
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