The naming has caused years of confusion. Server-side rendering renders a component to HTML on the server and then sends the component's JavaScript to the browser so it can hydrate and become interactive. A server component does the first part and never does the second. Its code stays on the server permanently. The browser receives the rendered result and nothing else.
Once that distinction lands, most of the rest follows.
What changed in 2026
- Framework support matured beyond one implementation. Server components moved from being effectively a single framework's feature to something multiple frameworks and build tools supported.
- The mental model settled. Community understanding converged on thinking in terms of where code executes rather than in terms of rendering strategies, which made the boundary rules feel less arbitrary.
- Tooling caught up on errors. Build-time and runtime errors for boundary violations became far more legible than the confusing failures of earlier versions.
- The counter-argument sharpened. For genuinely interactive applications, a clearer consensus emerged that server components add complexity without commensurate benefit.
What runs where
| Capability |
Server component |
Client component |
| Ships JavaScript to browser |
No |
Yes |
| Direct database or filesystem access |
Yes |
No |
| Uses state and effects |
No |
Yes |
| Handles user events |
No |
Yes |
| Uses browser APIs |
No |
Yes |
| Can be async and await data |
Yes |
Not directly |
| Can render the other kind |
Yes, renders client components |
Only via children passed from server |
| Access to secrets and environment |
Yes |
Never put secrets here |
The asymmetry in the second-to-last row is the rule people trip over. A server component can render a client component directly. A client component cannot import and render a server component — it can only render one that was passed to it as a child from further up the server tree. This is because the client bundle is assembled at build time and cannot pull server code into itself.
Where the payoff actually is
Content-heavy pages. A documentation site, a marketing page, a product listing, a blog — pages where most of the tree is presentation over fetched data. All the data-fetching logic, the date formatting library, the markdown renderer, the syntax highlighter: none of it reaches the browser. On a page like that the bundle reduction is substantial and directly improves load performance.
Where the payoff is thin is a dashboard or an editor, where nearly every component needs state, handles events, or responds to user input. Those are client components regardless, and adding a server layer above them buys a small amount of data-fetching convenience for a meaningful amount of architectural complexity.
The honest evaluation is to look at your component tree and ask what fraction genuinely needs interactivity. If it is most of it, the model is not for you.
Note also that the serialization boundary is a real constraint on API design. Anything passed from a server component to a client component must serialize, so functions, class instances, and dates need care. Passing a callback down across the boundary does not work, and restructuring around that is where most migration effort goes.
Common mistakes
- Marking everything as a client component to avoid errors. This works and defeats the purpose entirely.
- Confusing server components with server-side rendering. They coexist and solve different problems.
- Passing non-serializable props across the boundary. Functions cannot make the trip.
- Putting secrets in a component that later gets marked client. Verify the boundary before assuming code stays server-side.
- Adopting it for a highly interactive app. Complexity without payoff.
FAQ
Do server components replace server-side rendering?
No. They are complementary — server components determine what code ships, rendering strategy determines when HTML is generated. Most setups use both.
Can I use them without a framework?
Technically the primitives exist, and practically a framework handles the bundling, routing, and streaming coordination. Doing it manually is not a good use of time.
Do they work with existing component libraries?
Interactive libraries need the client directive, which most now include. Purely presentational components work either way.
Is this the future of React?
It is one supported model rather than a mandate. Client-only React applications remain fully supported and appropriate for many products.
Where to go next
For deployment considerations, read edge runtime vs Node runtime. For the type system underneath, TypeScript native compiler.