The React team ended 2020 with a bang: Dan Abramov and Lauren Tan presented React Server Components, a new experimental feature that allows React components to run exclusively on the server. The demo and accompanying RFC have sparked intense discussion across the JavaScript community, and after spending the holiday break digging into the details, I have some thoughts.
The core idea is simple: some components don’t need to be interactive. They just fetch data and render HTML. Why ship all that code — and all those dependencies — to the browser if the client never needs to execute it?
How Server Components Work#
React Server Components introduce a new component type that executes only on the server. These components can directly access your database, file system, or internal APIs without exposing those capabilities or their dependencies to the client. The key innovation is that they integrate seamlessly with regular client-side React components in the same component tree.
The naming convention is straightforward: files ending in .server.js are Server Components, .client.js are Client Components, and plain .js files are shared. Server Components can render Client Components, but not vice versa (which makes sense — the server can produce markup that the client hydrates, but the client can’t execute server-only code).
The data fetching story is particularly compelling. Instead of the current pattern of useEffect → fetch → setState → re-render, or the more sophisticated solutions like React Query or SWR, Server Components can simply await data directly in the component body. No loading states, no waterfall fetches, no client-side caching complexity — the data is resolved on the server and streamed to the client as part of the rendered output.
The bundle size implications are significant. If a Server Component imports a heavy library — say, a Markdown parser or a date formatting library — that library never gets sent to the client. The demo showed an example where the notes app used a syntax highlighter and a date library, neither of which appeared in the client bundle. For applications that currently ship megabytes of JavaScript, this could be transformative.
The Good: Solving Real Problems#
Let me be clear about what I think React Server Components get right.
The bundle size problem is real. Modern React applications ship an absurd amount of JavaScript to the browser. Bundle splitting and lazy loading help, but they add complexity and don’t solve the fundamental issue that many components exist only to fetch and display data. Server Components elegantly eliminate this category of unnecessary client-side code.
Data fetching in React has always been awkward. The component lifecycle doesn’t naturally align with data fetching patterns, and the community has produced dozens of solutions (Redux, MobX, React Query, SWR, Apollo, Relay) that each add their own complexity. Server Components offer a model where data fetching is just… function calls. That’s refreshing.
The streaming architecture is smart. Server Components don’t return HTML — they return a serialized component tree that the client can merge with its existing state. This means the client can update parts of the UI from the server without losing client-side state like form inputs or scroll positions. It’s more sophisticated than traditional server-side rendering.
The Concerns: Complexity and Ecosystem Impact#
That said, I have reservations.
The mental model is getting complicated. React developers now need to think about three types of components (Server, Client, Shared), understand serialization boundaries, know which hooks work where, and reason about a component tree that spans two execution environments. React’s original appeal was its simplicity — a component is a function that takes props and returns UI. We’re moving further from that simplicity with every new feature.
The ecosystem implications are enormous. Every React library, every component framework, every tutorial will need to be reconsidered in the context of Server Components. Which components should be server-only? Which libraries are “server-safe”? How do you test a component tree that spans client and server? The migration path for existing applications is unclear.
It tightens the coupling between frontend and backend. One of the benefits of the current SPA model is a clean separation between your API layer and your UI. Server Components blur this boundary by allowing components to directly access backend resources. For teams with separate frontend and backend developers, or organizations with microservice architectures, this coupling could be problematic.
It requires a compatible server runtime. You need a Node.js (or compatible) server that can execute React Server Components and stream results to the client. This moves React further from the “just drop a script tag in your HTML” simplicity and toward a full-stack framework requirement.
Comparison with Existing Approaches#
It’s worth noting that server-rendered components aren’t a new idea. PHP, Ruby on Rails, and ASP.NET have been rendering HTML on the server for decades. More recently, frameworks like Next.js and Remix have brought server-side rendering back into the React ecosystem.
What makes React Server Components different is the granularity. Instead of rendering an entire page on the server and hydrating the whole thing on the client, you can mix server-rendered and client-rendered components at any level of your component tree. The server can render the data-heavy shell while the client handles the interactive widgets.
This is genuinely novel in the React ecosystem, and it could lead to applications that are both faster to load and more responsive to interact with — if the complexity can be managed.
My Take#
I’ve been building web applications long enough to have lived through every paradigm shift — from server-rendered pages to AJAX to SPAs and now back toward the server. The pendulum swings, and each swing carries lessons from the previous one.
React Server Components feel like a necessary evolution. The current model of shipping entire applications as client-side JavaScript and then fetching all data through API calls has reached its limits. The bundle sizes are unsustainable, the loading waterfalls are painful, and the complexity of client-side state management has gotten out of hand.
But I worry about the execution. React is already a complex ecosystem, and Server Components add another dimension of complexity. The RFC is still experimental, and the final API could change significantly. My advice: understand the concepts, follow the development, but don’t rewrite your application yet.
The most exciting thing about Server Components might not be the feature itself, but what it signals about the direction of web development. The industry is collectively recognizing that we went too far with client-side-everything, and we’re finding smarter ways to leverage the server without going back to full page reloads. That’s progress.
Part of the Developer Landscape series — tracking the shifts that shape how we build.
