React Server Components
โฑ๏ธ ~4-minute bite ยท solve the sandbox to master
5-Year-Old Metaphor
โ The physical, real-world picture. No jargon.๐ณ RSCs = restaurant with kitchen and dining room. Kitchen (server) prepares food (renders, fetches data). Dining room (client) only receives finished dishes. Cheaper to keep prep in the kitchen.
Before RSC
Client fetches data via API routes. Loading states, race conditions, N+1 waterfalls, secrets passed through client bundles, over-fetching. The entire data layer lives on the client.
With RSC
Server Components fetch data directly, next to the JSX that renders it. No API layer, no loading state, no secrets in client bundles. Zero JS shipped for the server components themselves.
SSR vs RSC โ they're different
SSR (Server-Side Rendering): renders ANY React component on the server to produce HTML. The component's JS bundle is still sent to the client for hydration.
RSC (React Server Components): a specific component type that only runs on the server. Its JavaScript is never sent to the client. No hydration needed โ just HTML or RSC payload.
Next.js App Router uses both: SSR for the initial HTML pass, RSC payload for subsequent navigation.
Interactive Sandbox
โ Move something, see it react instantly.RSC Concept
Runs only on the server. Has access to databases, file system, environment variables. The component's JavaScript is never sent to the client โ zero bundle cost.
Can do
โAccess database directly (no API layer needed)
โRead environment variables and secrets
โRead the file system
โUse async/await in the component body
โImport heavy server-only libraries (no bundle cost)
Cannot do
โUse useState, useReducer, useEffect
โUse browser APIs (window, document, localStorage)
โUse event handlers (onClick, onChange)
โUse React context (as a provider or consumer)
Challenge
Explore all 5 RSC patterns. Toggle the code view to see how each is implemented.
Why Should I Care?
โ The exact interview question + the bug it kills.Interview questions
Q: What is the difference between a Server Component and SSR?
SSR renders any React component on the server to produce HTML, but the component's JavaScript is still sent to the client for hydration. RSC is a component that only runs on the server โ its code never reaches the client bundle. RSC = zero bundle contribution. SSR = HTML first, then JS hydration.
Q: Why can't Client Components import Server Components?
Server Components may access server-only resources (database, file system, secrets). If a Client Component could import them, those resources would need to run in the browser โ which is impossible and insecure. The boundary is one-way by design. The workaround: pass Server Component output as children props through the boundary.
Q: How do RSCs eliminate client-side data fetching?
| 1 | // Before RSC: client-side data fetching |
| 2 | function UserCard({ id }) { |
| 3 | const [user, setUser] = useState(null); |
| 4 | const [loading, setLoading] = useState(true); |
| 5 | useEffect(() => { |
| 6 | fetch(`/api/users/${id}`) |
| 7 | .then(r => r.json()) |
| 8 | .then(data => { setUser(data); setLoading(false); }); |
| 9 | }, [id]); |
| 10 | if (loading) return <Skeleton />; |
| 11 | return <div>{user.name}</div>; |
| 12 | } |
| 13 | ย |
| 14 | // With RSC: zero boilerplate, zero bundle |
| 15 | async function UserCard({ id }) { |
| 16 | const user = await db.user.findUnique({ where: { id } }); |
| 17 | return <div>{user.name}</div>; |
| 18 | } |
The Deep Dive
โ Spec refs, engine internals, the minutiae.RSC in frameworks beyond Next.js
Waku is a minimal RSC framework built by the React team. Remix is exploring RSC support. RSC is a React feature, not a Next.js feature โ but Next.js App Router is the most mature implementation available today. The RSC protocol is part of the React package and can be used by any bundler that implements the RSC transform.
Server Actions โ mutations from Client to Server
| 1 | // Server Action โ runs on server, called from client |
| 2 | 'use server'; |
| 3 | async function createTodo(formData: FormData) { |
| 4 | const title = formData.get('title') as string; |
| 5 | await db.todo.create({ data: { title } }); |
| 6 | revalidatePath('/todos'); // refresh RSC data |
| 7 | } |
| 8 | ย |
| 9 | // Client Component uses Server Action in a form |
| 10 | 'use client'; |
| 11 | export function AddTodoForm() { |
| 12 | return ( |
| 13 | <form action={createTodo}> |
| 14 | <input name="title" /> |
| 15 | <button type="submit">Add</button> |
| 16 | </form> |
| 17 | ); |
| 18 | // No fetch(), no API route, no event handler needed |
| 19 | } |
Bundle size impact
Every package imported by a Server Component stays on the server. A Server Component that imports a 500KB markdown parser adds 0 bytes to the client bundle. Before RSC, you'd use dynamic imports or move the parsing to an API route. With RSC, co-locate the heavy import with the component โ the bundler handles the rest automatically.
Interview Questions
โ Real questions from real interviews โ with answers.SSR sends HTML + JS bundle for hydration; RSC sends HTML but zero JS โ the component never runs on the client.
Server Components access server-only resources that cannot run in a browser; allowing the import would expose secrets and crash at runtime.
Only serializable values can cross the boundary as props: primitives, plain objects, arrays, and JSX (as children).
Each async Server Component fetches its own data in parallel; Promise.all at the page level removes sequential dependency.
RSC sends a JSON-like UI description (not HTML); it enables partial page updates while Client Components retain their state.
Server Actions are async functions marked 'use server' โ called from Client Components via forms or event handlers, no API route needed.
Memory Game
โ Quick quiz โ lock the concept in long-term memory.What is the performance benefit of Suspense boundaries for RSC pages with slow data dependencies?