Partial Prerendering (PPR)

Hybrid technique combining static shells prerendered at build time with dynamic content streamed via Suspense. Best for Hybrid apps, Optimal performance scenarios, and Modern pages that mix static UI with dynamic data.

Build Time

React.renderToStaticMarkup()
Generate static shell
Store static shell

Runtime

🌐
Request
Response
πŸ–₯️
Server sends static shell
Server fetches dynamic data
Server streams dynamic content

Client

Client sends request
Client receives static shell
Client receives dynamic content
React.hydrate()
✨Page interactive
Benefits x Trade-offs

Benefits

  • β€’Instant Static Shell: Fast initial page load
  • β€’Progressive Enhancement: Dynamic content streams in
  • β€’Optimal UX: Users see content immediately
  • β€’Flexible Architecture: Mix static and dynamic content

Trade-offs

  • β€’Suspense complexity: Requires proper Suspense wrappers
  • β€’Browser buffering delays: May delay dynamic content
  • β€’Status codes can't change: Set before streaming starts
  • β€’Experimental: Still evolving API and best practices
How to implement?

PPR combines static shell with dynamic content streaming. Requires React 19 and RSC. Introduced in Next.js 14.1 (experimental), stable in 15+.

// next.config.js
export default {
  experimental: {
    ppr: true, // or cacheComponents: true
  },
};

import { Suspense } from "react";

export default function Page() {
  return (
    <div>
      <StaticHeader />
      <Suspense fallback={<Skeleton />}>
        <DynamicContent />
      </Suspense>
    </div>
  );
}
  • β€’Enable PPR via experimental ppr setting in next.config.js
  • β€’Requires React 19 and React Server Components
  • β€’Wrap dynamic components in <Suspense fallback={<Skeleton />}>
  • β€’Use 'use cache' directive for cacheable dynamic content
  • β€’Static parts are prerendered at build time