For years, frontend developers have been stuck in an annoying trade-off:
- SSG (Static Site Generation): Fast, but data gets stale
- SSR (Server-Side Rendering): Fresh data, but slower
It always felt like:
“Pick speed OR freshness… you can’t have both.”
But what if you didn’t have to choose?
That’s where Partial Prerendering (PPR) comes in.
Table of Contents
- The Problem: Blank Screen vs Spinner Hell
- The Idea: The Swiss Cheese Model
- Real-World Scenario: Buying Concert Tickets
- How PPR Actually Works
- Code Example (Next.js + Suspense)
- Why PPR is a Game Changer
- Mental Model
- Final Thoughts
The Problem: Blank Screen vs Spinner Hell
Let’s say you're building something like an e-commerce site.
A user clicks on a product page.
Now depending on your rendering strategy…
❌ SSR (The Waiting Game)
The server waits to fetch:
- User name
- Personalized price
- Cart count
Then sends the page
Result:
- White screen for 1–2 seconds
- User thinks: “Is this site slow?”
❌ CSR (Spinner Chaos)
The page loads instantly…
But:
- Price loads later
- Cart loads later
- Recommendations load later
Everything appears in pieces
Result:
- Layout shifts
- Janky experience
- Feels unpolished
So you’re stuck between:
- Blank screen (SSR)
- Spinner hell (CSR)
The Idea: The Swiss Cheese Model
Partial Prerendering solves this beautifully.
Think of your page like:
Swiss Cheese🧀
- The solid part (cheese) = Static content
- The holes = Dynamic content
What Happens?
At build time:
- Static parts are pre-rendered
- Dynamic parts are left as “holes”
At runtime:
- Static loads instantly
- Dynamic content streams in later
Best of both worlds.
Real-World Scenario: Buying Concert Tickets
Imagine you're on a ticket booking site during a huge sale.
50,000 people are trying to buy tickets at the same time.
What Loads Instantly (Static Shell)
- Artist name
- Event details
- Venue map
- Page layout
This is pre-rendered and served from CDN
What Loads Dynamically (The “Holes”)
- Remaining ticket count
- Your personalized price
- “Buy Now” button state
What You Experience
- Page appears instantly
- You can already read and interact
- Dynamic data fills in smoothly
Even if the database takes 1 second…
The page feels like it loaded in 0.1 seconds
How PPR Actually Works
Under the hood:
- Static HTML is served immediately
- Dynamic components are streamed in later
- React fills in the gaps without reloading the page
This is powered by:
- React Suspense
- Streaming rendering
Code Example (Next.js + Suspense)
Here’s a simple example:
export default function ProductPage() {
return (
<main>
{/* Static content (instant) */}
<ProductNavigation />
<ProductDetails />
{/* Dynamic part (hole) */}
<Suspense fallback={<PriceSkeleton />}>
<DynamicUserPrice />
</Suspense>
{/* Another dynamic part */}
<Suspense fallback={<RecommendationSkeleton />}>
<RecommendedProducts />
</Suspense>
</main>
);
}
`
What’s Happening Here?
- Static components load immediately
- Suspense creates “holes”
- Fallback UI (skeletons) prevents layout shift
- Data streams in and fills the gaps
Smooth, fast, and user-friendly
Why PPR is a Game Changer
Instant First Paint
Users see something immediately
→ Feels fast
Better SEO
Search engines see:
- Titles
- Content
- Structure
No waiting for JavaScript
No Layout Shift
Skeletons reserve space
No jumping UI
Better Perceived Performance
Even if backend is slow:
UI feels instant
Mental Model
If you remember just this:
- SSG = Everything ready early
- SSR = Everything waits
- PPR = Load what you can now, stream the rest
PPR = “Render now, stream later”
Final Thoughts
Partial Prerendering is a big shift in how we think about rendering.
It’s not:
- Static vs Dynamic
It’s:
Static + Dynamic together
The future of the web isn’t about loading pages.
It’s about making them feel instant.
What Do You Think?
Are you planning to try PPR in your next project?
Or still sticking with SSR/CSR?
Let’s discuss in comment...
This article was originally published by DEV Community and written by Abdullah al Mubin.
Read original article on DEV Community