Two Years with Server Components: Honest Thoughts
An honest retrospective on using React Server Components in production for two years
January 2024, "What Is This?"
I first started using Server Components seriously in a Next.js 14 project. My initial reaction was, honestly, confusion. Slap async on a component, call fetch directly, but you can't use useState. My existing React mental model kept clashing with this new paradigm.
Two years later, I can't even remember how I used to develop without Server Components.
The Best Part: API Files Disappeared
Before, fetching data on the frontend meant creating API endpoints, writing fetch calls, managing loading states, handling errors. The whole routine. With Server Components, you call the DB or external API directly inside the component.
Take my blog post listing page, for example. Before, I'd create a /api/posts endpoint and call it from the client with useEffect. Now I just call getPosts() directly in page.tsx and that's it. No API file, no loading state management, and the code is literally cut in half. Seriously.
Still Confusing After Two Years
"Is this component server or client?" This decision still trips me up after two years. The rule is simple: no interaction means server, interaction means client. But in practice, you need to predict "will interaction be added here later?" -- and that prediction is often wrong.
You build something as a server component, then someone says "can you add a like button here?" and now you either convert the whole component to client or split the button out separately. The hard part of Server Components isn't the technology -- it's the design. You need a sense for where to draw the boundary. (That sense is still a work in progress for me.)
Performance Is Noticeably Better
The reduction in client-side JS is measurable. In projects where I switched to server components, the initial JS bundle dropped by roughly 30%. On my blog, TTFB improved by about 200ms. Makes sense -- the server is sending complete HTML. Obvious result, but still satisfying to see.
Debugging Is Still Frustrating After Two Years
When a server component errors, you check server logs, not the browser console. During development, just watch the terminal alongside the browser -- fine. In production, you need a logging service. Serialization errors at the server-client boundary are particularly painful. Pass a Date object and it becomes a string. Map and Set don't transfer at all. The fact that these errors blow up at runtime instead of build time is genuinely annoying.
Onboarding New Team Members
New team members take about 2-3 weeks to get comfortable with Server Components. Existing React experience can actually be a hindrance. They start with "wait, components don't run in the browser?" and work up to "so when do I use useEffect?" Once they get it, it's actually a simpler model. But breaking apart the old mental model and rebuilding it isn't easy.
The Direction Is Right
I'm convinced Server Components are the right direction for web development. The principle of not sending things to the client that can be handled on the server makes sense for both performance and security. But it's not necessary for every project. Interactive dashboards, for instance, will be mostly client components anyway, so the benefits are limited there.
For content-heavy sites like mine, it's a perfect fit. For a real-time collaboration tool, the cost of managing the boundary might outweigh the benefits. Use the tool in the right context. That's an obvious statement, but it's surprisingly easy to forget.