Understanding React Server Components
React Server Components (RSC) change how you think about where React code runs. If you have spent years treating React as something that always ends up in the browser, this feels like a reset. Some components stay on the server forever, and that opens up a different set of tradeoffs.
What Are React Server Components?
Server Components run only on the server. They render to a format React can stream to the client, but the component code itself never ships to the browser. That means no client bundle cost for those components.
// This is a Server Component by default in Next.js 13+
async function BlogPost({ id }) {
// Direct database access
const post = await db.posts.findById(id);
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
);
}Why People Care
1. Less JavaScript on the Client
Server Components do not add to your client bundle, which usually means:
- Faster initial loads
- Better performance on slower devices
- Less bandwidth used
2. Direct Access to Backend Data
You can talk to your database, file system, or internal APIs without setting up a separate client fetch layer.
async function UserProfile({ userId }) {
const user = await db.users.findById(userId);
const posts = await db.posts.where({ authorId: userId }).fetch();
return (
<div>
<h2>{user.name}</h2>
<PostList posts={posts} />
</div>
);
}3. Automatic Code Splitting
Every Server Component is already split from the client bundle. You do not have to think about it as much.
Server vs Client Components
Scroll horizontally to view all columns
| Feature | Server Components | Client Components |
|---|---|---|
| Runs on | Server only | Server + Client |
| Can use hooks | No | Yes |
| Can access backend | Yes | No |
| Adds to bundle | No | Yes |
| Can be async | Yes | No |
Common Patterns
Data Fetching
// Server Component - fetches data directly
async function ProductList() {
const products = await fetchProducts();
return (
<div>
{products.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}Composition
// Mix Server and Client Components
import ClientCounter from "./ClientCounter"; // 'use client'
async function Dashboard() {
const stats = await getStats();
return (
<div>
<h1>Dashboard</h1>
<StaticContent data={stats} />
<ClientCounter initialValue={stats.count} />
</div>
);
}Challenges and Things to Watch
Props Serialization
Props passed from Server to Client Components must be serializable.
// Will not work - functions are not serializable
<ClientComponent onClick={handleClick} />
// Works - pass data, handle events in client
<ClientComponent data={data} />Context Limitations
Server Components cannot read React Context. If you need context, you either pass data down or move that part into a Client Component.
Migration Strategy
If you are moving an existing app over, this is a safe order:
- Start with layouts and static pages
- Move data fetching into Server Components
- Keep interactive pieces as Client Components
- Optimize based on real performance data
The Bigger Shift
RSC is not just another API. It changes the architecture. You get clearer boundaries between server and client code, simpler data paths, and a better default performance story. It does take a mental shift, but it also cleans up a lot of old patterns.
Conclusion
React Server Components are a major shift in the React ecosystem. If you are building with Next.js today, you can start with small pieces and grow from there. The value shows up when you keep the client bundle lean and let the server do the heavy lifting.
Related Posts
The Art of Minimal Design
Exploring the principles of minimal design, how to achieve clean interfaces, and the balance between functionality and aesthetics in modern web applications.
Building Type-Safe APIs with TypeScript
Leveraging TypeScript's type system to create robust, maintainable APIs with end-to-end type safety.
Inside the Cloudflare Outage (Nov 18, 2025)
A clear breakdown of what went wrong on November 18, 2025 and the distributed systems lessons that followed.