For over a decade, every React component was a Client Component: it executed in the browser, was bundled into client JavaScript, and could hold local state and event handlers.
React Server Components (RSC) represent the most significant architectural evolution in React history.
In RSC architecture:
Components execute EXCLUSIVELY ON THE SERVER during the build or request time. Their code NEVER downloads to the user's browser, resulting in ZERO client bundle size!
Output
1Client Component (.jsx / 'use client'):
2- Downloaded to browser in JS bundle
3- Executed on client
4- Can use useState, useEffect, onClick
5- Bundle Size: Adds to client JS download!
6
7React Server Component (.jsx - Default in Next.js App Router):
8- Executed ONLY on server
9- NEVER downloaded to browser
10- Can access database, files, and secrets directly!
11- Bundle Size: 0 KB added to client JS!
2. Direct Database & Backend Access
Because Server Components run strictly on the backend, they can query databases, read file systems, and use private API keys directly inside the component function without creating an intermediary REST API endpoint:
JSX
1// A React Server Component (Runs ONLY on server!)
2import db from'@/lib/database';
3
4exportdefaultasyncfunctionStudentRoster(){
5// Query database directly! No fetch(), no useEffect(), no loading spinner!
6const students =await db.query('SELECT * FROM students ORDER BY enrolled_at DESC');
7
8return(
9<divclassName="roster-view">
10<h2>Enrolled Students({students.length})</h2>
11<ul>
12{students.map((s)=>(
13<likey={s.id}>{s.name} — {s.course}</li>
14))}
15</ul>
16</div>
17);
18}
3. The 'use client' Directive
In RSC architecture (as implemented in Next.js App Router), all components are Server Components by default.
If a component needs interactivity:
React state (useState, useReducer)
Lifecycle effects (useEffect)
Browser APIs (window, localStorage, geolocation)
Event listeners (onClick, onChange)
You declare the 'use client' directive at the very top of the file:
JSX
1'use client';// Marks this file and its imports as a Client Component boundary!