Ever heard someone say “React Server Components are just a better version of server-side rendering”?
Yeah, me too.
And while they sound similar, they’re actually very different under the hood.
Let’s break it down.
TL;DR
- Use RSC to reduce JS and enable streaming
- Use
"use client"
only where needed - Be prepared for a learning curve, and some ecosystem frictions.
Quick Recap: What’s SSR Again?
Server-side rendering (SSR) is when React pre-renders components on your server, sends fully formed HTML to the browser, and then hydrates it with JavaScript to make it interactive.
That’s good. But also… expensive.
The catch is: Every single component—even simple ones like <Button />
—gets shipped with JavaScript. That means slower loads, larger bundles, and more hydration.
React Server Components: A Restaurant Metaphor 🍽️
Imagine you’re at a restaurant.
-
Server Components are like chefs preparing your meal in the kitchen. They handle all the heavy lifting—data fetching, UI rendering—behind the scenes. Your browser just receives the beautifully plated result.
-
Client Components? They’re more like handing you ingredients and a mini kitchen at your table. Flexible, sure, but heavier and slower.
With RSC, you can choose exactly what gets done server-side and what’s handled client-side.
Server vs. Client Components: Side-by-Side
Here’s the server side:
// Server Component
export default async function PostPage() {
const post = await fetchPost();
return <div>{post.title}</div>;
}
This runs entirely on your server—zero JS shipped to the client.
Now, the client side:
'use client';
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
This runs in the browser. It’s interactive, but it ships JS and needs hydration.
With RSC, you can mix both: Server where you can, Client where you must.
Streaming: The Real Superpower
Let’s say part of your page is slow — maybe a DB call.
Traditionally, the full page waits.
With RSC + React 18 + Suspense, React streams the fast parts first. The slow ones come later:
<Suspense fallback={<Loading />}>
<SlowComponent />
</Suspense>
The browser sees <Header />
, <Sidebar />
, etc. immediately. <SlowComponent />
arrives when ready — no reload.
Behind the Scenes: How Browsers Handle This 🛠️
Modern browsers can parse incoming HTML as it’s streamed.
React leverages its Flight protocol to send serialized component chunks. The browser hydrates selectively—only the interactive parts.
It’s like React saying: “Here’s the structure—I’ll hand over bricks as soon as they’re ready.”
But Wait… What’s the Catch? 🤔
RSCs are awesome, but they’re not friction-free:
1. Not Everything Works in Server Components
No useState
, useEffect
, or browser globals (window
, document
) since server components never touch the browser.
// ❌ Error!
export default function MyServerComponent() {
const [state, setState] = useState(0);
}
Need interactivity? Move that part to a "use client"
component.
2. The Ecosystem is Still Catching Up
Many libraries (like chart.js
) assume a browser environment. They’ll have to run in client components for now.
Even devtools and test frameworks may not fully support the RSC model yet.
3. Mental Shift Required
You’ll constantly ask:
- Should this be client or server?
- Am I overdoing it with
"use client"
? - Where should data fetching live?
It takes time to get used to the new paradigm.
4. Debugging Feels Different
No React DevTools visibility for RSCs. Errors show up in your terminal, not your browser.
A bit strange at first.
5. Deployment: Servers Required 🚀
No static export anymore. Platforms like Vercel? handled this automatically but not with something like GitHub Pages
Caching and latency become new priorities to reduce server load
Use RSC—But Keep Your Eyes Open 👀
React Server Components are a big step forward.
They shine when:
- You’re mindful about splitting heavy data fetching from interactive UI.
- You’re comfortable with server-based hosting solutions.
- Your app can avoid browser-only dependencies.
In conclusion here is the comparison: SSR vs. RSC:
Feature | SSR | RSC |
---|---|---|
Output | Full HTML + Full Hydration | Partial HTML + Selective Hydration |
Data Fetching | Route-level (getServerSideProps ) | Component-level (async/await , fetch ) |
JS in Browser | All JS | Only necessary JS |
Streaming | Limited | Built-in (Suspense ) |
Hydration Cost | High | Minimal |
React Server Components aren’t just improved SSR—they’re a whole new way to think about what runs where and why it needs to run there.
Not perfect, but it’s an exciting way to improve your app experience and you can adjust your approach as you go. ✅