hardFrontend EngineerTechnology
Explain React Server Components (RSC) — how do they differ from Client Components, and what are the performance implications?
Posted 18/04/2026
by Mehedy Hasan Ador
Question Details
At a Next.js-focused interview, the candidate was asked:
> "Can you explain the difference between Server Components and Client Components in Next.js? When would you use each, and what happens to the bundle size?"
> "Can you explain the difference between Server Components and Client Components in Next.js? When would you use each, and what happens to the bundle size?"
Suggested Solution
Server Components (Default in Next.js App Router)
// This is a Server Component by default (no "use client")
async function ProductPage({ id }) {
// Runs ONLY on the server
const product = await db.product.findUnique({ where: { id } });
return (
<div>
<h1>{product.name}</h1>
<p>{product.description}</p>
<AddToCartButton productId={id} /> {/* Client Component */}
</div>
);
}
// This component's JS is NEVER sent to the browser
Client Components
"use client";
import { useState } from "react";
function AddToCartButton({ productId }) {
const [loading, setLoading] = useState(false);
// Needs interactivity → must be a Client Component
return (
<button onClick={() => addToCart(productId)} disabled={loading}>
Add to Cart
</button>
);
}
Key Differences
The Mental Model
Server Components (can import Server or Client)
└── Server Component
└── Client Component (boundary — "use client")
└── Client Component (everything below is client)
└── ❌ Cannot import Server Component
Rule: Server Components can render Client Components, but NOT vice versa. If a Client Component needs server data, pass it as props.Performance Impact
Before RSC (Pages Router):
Bundle: React + ReactDOM + all page components + libraries
Typical: 80-150KB gzipped
With RSC (App Router):
Bundle: React runtime + only Client Components
Server Component JS is zero (just HTML streamed)
Typical: 30-60KB gzipped for same functionality
Best Practices
1. Default to Server Components — only add "use client" when needed2. Push client boundaries down — keep interactive parts small
3. Pass server data as props — don't fetch in client if possible
4. Use for heavy dependencies — markdown parsers, date libraries stay on server
// ✅ Good: markdown parsing stays on server (0KB client cost)
async function Article({ content }) {
const html = await parseMarkdown(content); // 200KB lib, stays on server
return <div dangerouslySetInnerHTML={{ __html: html }} />;
}