Technical
React Server Components: Where They Earned Their Keep
React Server Components promised to fix the waterfall problem and shrink bundle sizes. A year into using them in production I have a clearer sense of where they earn their keep and where they add complexity without payoff. Here is the honest breakdown.
Where They Won
Server Components are great at:
- Content pages: blog posts, docs, marketing pages
- Data-heavy dashboards with minimal interactivity
- SEO-critical pages where server-rendering is mandatory
- Pages with large dependencies that would otherwise bloat the client bundle
My blog ships almost zero client-side JavaScript for content pages. That is a measurable win.
// Server Component: runs on the server, zero JS to client
import { getPost } from '@/lib/posts'
export default async function PostPage({ params }) {
const post = await getPost(params.slug)
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</article>
)
}Where They Struggled
Server Components are awkward for:
- Highly interactive UIs where state lives on the client
- Forms with complex validation that needs both sides
- Real-time features where the server is not the source of truth
- Mental model cost for teams new to the split
The use client directive is powerful but it is also where bugs live.
The Boundary Pattern
My mental model: Server Components own data fetching. Client Components own interactivity. The boundary is usually at the form or the interactive widget. Everything above is server. Everything inside the widget is client.
What I Got Wrong
I tried to make everything a Server Component early on. The result was awkward prop drilling and odd re-renders at client boundaries. Now I default to Server Components but mark whole sections client-side when they share interactive state.
The Bundle Size Reality
My content pages went from 180KB of client JS to 12KB. That is a real user experience improvement. First load feels faster because it is faster. Server Components delivered on the bundle promise.
The Verdict
Server Components are worth adopting for content-heavy apps. They are not worth forcing onto highly interactive apps. Choose the tool to match the shape of the app, not the other way around.
What Tripped Up My Team
Developers coming from classic React got confused by the serialization boundary. You cannot pass a function from a Server Component to a Client Component. You cannot pass a class instance. The boundary forces discipline on shape. That discipline is good but the learning curve is real. Budget time for it when onboarding new developers.
The DX Wins
Direct data fetching inside components removed a whole category of boilerplate from my codebase. No more getServerSideProps. No more useEffect for initial data. Just an async component that fetches what it needs and renders the result. That ergonomic win compounded across every page.
For the current guidance, see the React Server Components documentation.
RELATED READING
The Consulting Shift I Am Making In Year Two
After a year of writing and building, my consulting practice is changing shape. Shorter engagements. Sharper outcomes.
ReadThe Frontend Shift: Shipping Less JavaScript In Year Two
A year ago I reached for Next.js for everything. This year I often reach for nothing.
ReadThe Serverless Lesson I Would Write On A Sticky Note
After a year of shipping serverless projects, one rule explains most of the wins and all of the losses.
Read