Capítulo 42 de 57
TanStack Router supports both non-streaming SSR (render everything, send one complete HTML response) and streaming SSR (send critical first paint immediately, stream the rest as it resolves), using a shared createRouter factory, RouterClient/RouterServer components, and automatic loader dehydration/hydration.
defaultRenderHandler (automatic) or renderRouterToString + RouterServer (manual Wrap control).defaultStreamHandler or renderRouterToStream + RouterServer.createRouter shared factory: must be defined in a shared file (e.g. src/router.tsx) and called identically by both server and client entry files, ensuring consistent router configuration.createMemoryHistory instead of createBrowserHistory (which needs window), handled for you by RouterServer.createRequestHandler: takes a standard web API Request and a createRouter function, returns a handler that produces a Response; used identically for both streaming and non-streaming.RouterClient: client entry component (e.g. with hydrateRoot) that renders the app and implements the router's Wrap option automatically.JSON.stringify/parse for undefined, Date, Error, and FormData; more complex types (Map, Set, BigInt) require a custom serializer.src/pages/, getServerSideProps, Remix-style loader/action exports, or react-router-dom/next/ imports. Use src/routes/ + createFileRoute, and for TanStack Start, createServerFn.// src/router.tsx
import { createRouter as createTanstackRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
export function createRouter() {
return createTanstackRouter({ routeTree })
}
declare module '@tanstack/react-router' {
interface Register {
router: ReturnType<typeof createRouter>
}
}
// src/entry-server.tsx (streaming)
import { createRequestHandler, defaultStreamHandler } from '@tanstack/react-router/ssr/server'
import { createRouter } from './router'
export async function render({ request }: { request: Request }) {
const handler = createRequestHandler({ request, createRouter })
return await handler(defaultStreamHandler)
}
defaultStreamHandler.// src/entry-client.tsx
import { hydrateRoot } from 'react-dom/client'
import { RouterClient } from '@tanstack/react-router/ssr/client'
import { createRouter } from './router'
const router = createRouter()
hydrateRoot(document, <RouterClient router={router} />)
defaultRenderHandler/defaultStreamHandler for the simplest setup; drop to renderRouterToString/renderRouterToStream + RouterServer only when you need custom Wrap providers.Await, see Ch 37) to actually stream from server to client; without it, deferred data resolves client-side only.dehydrate/hydrate/Wrap router options integrate directly with this chapter's SSR pipeline.<HeadContent /> and <Scripts /> render as part of the same server-rendered markup.