React Server Components (RSC) are one of the most significant changes to React in years. They are also one of the most misunderstood. This guide explains what they actually are, what problems they solve, and when to choose them over other rendering approaches.
What RSC Actually Is
A Server Component is a React component that runs exclusively on the server. It is never sent to the client as JavaScript. The server renders it to HTML (or a serialized RSC payload), sends the result to the browser, and the browser displays it without needing the component code.
The critical implication: a Server Component contributes zero bytes to your JavaScript bundle. If you have a component that renders a data table, that component's logic (fetching, sorting, formatting) stays on the server. The user's browser never downloads it.
This is different from Server-Side Rendering (SSR). With traditional SSR, the component runs on the server to generate HTML, but the same JavaScript is also sent to the browser for hydration. With RSC, there is no hydration for the server component itself. It just renders and is done.
Why It Matters
Zero bundle cost. The most concrete benefit. A library used only in a Server Component does not appear in the client bundle. A component with complex formatting logic contributes nothing to the JavaScript the user downloads and parses.
Direct data access. Server Components can access databases, file systems, and internal services directly. No API route needed. You write a database query in the component body, and it executes on the server with no client involvement.
// This component queries MongoDB directly. None of this code reaches the browser.
async function UserProfile({ userId }: { userId: string }) {
const db = await getDatabase();
const user = await db.collection("users").findOne({ _id: new ObjectId(userId) });
if (!user) return <div>User not found</div>;
return <div>{user.name}</div>;
}
No waterfall for initial data. Client-side data fetching with useEffect causes a waterfall: render empty shell, ship JavaScript to browser, browser executes component, component fires fetch, data arrives, rerender. Server Components eliminate this for initial page data. The data is fetched during the server render, and the populated HTML arrives in the first response.