React 18 introduces streaming SSR with Suspense.
Server:
1import { renderToPipeableStream } from "react-dom/server";23app.get("/", (req, res) => {4 const { pipe, abort } = renderToPipeableStream(5 <App url={req.url} />,6 {7 bootstrapScripts: ["/client.js"],8 onShellReady() {9 // Shell ready — start streaming10 res.statusCode = 200;11 res.setHeader("Content-type", "text/html");12 pipe(res);13 },14 onShellError(error) {15 res.statusCode = 500;16 res.send("<h1>Something went wrong</h1>");17 },18 onError(error) {19 console.error(error);20 },21 }22 );23 setTimeout(abort, 10000); // Timeout24});
Client hydration:
1import { hydrateRoot } from "react-dom/client";23hydrateRoot(document, <App />);
With Next.js App Router:
1// Server Component (default)2async function Page() {3 const data = await fetchData();4 return <Content data={data} />;5}67// Streaming with Suspense8function Page() {9 return (10 <div>11 <Header />12 <Suspense fallback={<Skeleton />}>13 <SlowComponent />14 </Suspense>15 <Footer />16 </div>17 );18}
Benefits: