
- Next.js - Home
- Next.js - Overview
- Next.js - Project Setup
- Next.js - Folder Structure
- Next.js - App Router
- Next.js - Page Router
- Next.js Features
- Next.js - Pages
- Next.js - Data Fetching
- Next.js - ISR
- Next.js - Static File Serving
- Next.js - Pre-Rendering
- Next.js - Partial Pre Rendering
- Next.js - Server Side Rendering
- Next.js - Client Side Rendering
- Next.js Routing
- Next.js - Routing
- Next.js - Nested Routing
- Next.js - Dynamic Routing
- Next.js - Parallel Routing
- Next.js - Imperative Routing
- Next.js - Shallow Routing
- Next.js - Intercepting Routes
- Next.js - Redirecting Routes
- Next.js - Navigation and Linking
- Next.js Configuration
- Next.js - TypeScript
- Next.js - Environment Variables
- Next.js - File Conventions
- Next.js - ESLint
- Next.js API & Backend
- Next.js - API Routes
- Next.js - Dynamic API Routes
- Next.js - Route Handlers
- Next.js - API MiddleWares
- Next.js - Response Helpers
- Next.js API Reference
- Next.js - CLI Commands
- Next.js - Functions
- Next.js - Directives
- Next.js - Components
- Next.js - Image Component
- Next.js - Font Component
- Next.js - Head Component
- Next.js - Form Component
- Next.js - Link Component
- Next.js - Script Component
- Next.js Styling & SEO
- Next.js - CSS Support
- Next.js - Global CSS Support
- Next.js - Meta Data
- Next.js Advanced Topics
- Next.js - Error Handling
- Next.js - Server Actions
- Next.js - Fast Refresh
- Next.js - Internationalization
- Next.js - Authentication
- Next.js - Session Management
- Next.js - Authorization
- Next.js - Caching
- Next.js - Data Caching
- Next.js - Router Caching
- Next.js - Full Route Caching
- Next.js - Request Memoization
- Next.js Performance Optimization
- Next.js - Optimizations
- Next.js - Image Optimization
- Next.js - Lazy Loading
- Next.js - Font Optimization
- Next.js - Video Optimization
- Next.js - Script Optimization
- Next.js - Memory Optimization
- Next.js - Using OpenTelemetry
- Next.js - Package Bundling Optimization
- Next.js Testing
- Next.js - Testing
- Next.js - Testing with Jest
- Next.js - Testing with Cypress
- Next.js - Testing with Vitest
- Next.js - Testing with Playwright
- Next.js Debugging & Deployment
- Next.js - Debugging
- Next.js - Deployment
- Next.js Useful Resources
- Next.js - Interview Questions
- Next.js - Quick Guide
- Next.js - Useful Resources
- Next.js - Discussion
Next.js - Partial Pre-Rendering
Partial Pre-rendering (PPR) is a rendering pattern in Next.js that combines static and dynamic content in a single page. The static contents along with static fallback for dynamic contents will be pre-rendered at the build time. The dynamic contents will be rendered as per request from user. This method ensures a faster initial page loads as the static content is pre-rendered, and results in better SEO and user experience.
Note: Partial Prerendering is an experimental feature only available on canary browser and is subject to change. It is not ready for production use.
How Partial Pre-Rendering Works?
Partial Pre-rendering works by combining static content with dynamic content. Here's how it works:
Initial Static Content
- At build time, Next.js generates a static shell of the page
- This includes all the static content that doesn't need real-time data
- When a user visits the page, they see the static shell immediately without any loading.
Dynamic Content Streaming
- Dynamic parts of the page are loaded on client-side.
- These parts are wrapped in React Suspense boundaries, and while loading, they will show fallback content.
- Once the dynamic content is loaded, it will replace the fallback content.
Example of Partial Pre-Rendering
In the following example, we have a page that displays static content and dynamic content. The static content is pre-rendered at build time, and the dynamic content is loaded on the client-side. The dynamic content is . In short,
- The 'StaticContent' component is pre-rendered and served immediately
- The 'DynamicProducts' component fetches products from an API
- The 'Page' component wraps the dynamic component in a React Suspense component that shows a loading state while the content is being fetched.
// app/page.tsx import { Suspense } from 'react' // Static, pre-rendered content function StaticContent() { return ( <div> <h1>Welcome to Our Store</h1> <p>Browse our latest collection of products</p> </div> ) } // Dynamic, streaming content async function DynamicProducts() { // Simulate fetching products from an API const products = await fetch('https://jsonplaceholder.typicode.com/users', { // This cache option enables PPR cache: 'no-store' }).then(res => res.json()) return ( <div> {products.map(product => ( <div key={product.id}> <h2>{product.name}</h2> <p>{product.price}</p> </div> ))} </div> ) } export default function Page() { return ( <main className="p-8"> {/* Static content is pre-rendered */} <StaticContent /> {/* Dynamic content is loaded client-side with loading state */} <Suspense fallback={<div>Loading products...</div>}> <DynamicProducts /> </Suspense> </main> ) }
Output
In the output below, a loading component is visible before the dynamic content is being fetched. Once the content is loaded, it is replacing the loading component.
