Server vs Client Components
The fundamental divide in the App Router: where does your code actually run?
What are Server and Client Components?
In the Next.js App Router, React components can run in two completely different environments: on the server, or in the user's web browser (the client).
By default, every component you write is a Server Component. It renders into static HTML on the server. The actual JavaScript code that powers it is never sent to the browser, resulting in a zero-kilobyte bundle size for that piece of UI.
Client Components, on the other hand, are the traditional React components you are used to. They are bundled, sent over the network, and executed in the browser to enable interactivity, state, and event listeners.
Why split them up?
Before React Server Components, you had to make a painful choice. You either sent all your component code to the client (bloating the bundle size and slowing down the initial load), or you used complex fetching patterns to render HTML early.
This architecture lets you have the best of both worlds. You can write heavy, data-fetching UI on the server, and only ship JavaScript to the client for the specific buttons, forms, and animations that actually need it.
How do you use them?
You don't have to do anything to create a Server Component; it is the default behavior. Just write a normal React function.
To create a Client Component, you must add the "use client" directive at the absolute top of the file, before any imports.
This directive acts as a network boundary. When Next.js sees "use client", it bundles that file and every file it imports into the client-side JavaScript payload.
The Network Boundary
Toggle the environment to see how code execution moves across the network boundary, and watch the impact on the client-side JavaScript bundle.
Interactive Lab
Add the directive to move the component across the network boundary.
Server
Zero KB JavaScript shipped. Direct access to databases.
Client (Browser)
Hydrated for interactivity and event listeners.
// No directive = Server Component import { useState } from "react";
export default function Btn() { // Executes on Server
return <button>Click me</button>;
}
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- All components in the App Router are Server Components by default.
- Use the
"use client"directive only at the leaves of your component tree. - Server Components cannot use hooks like
useStateor attach event listeners. - Importing a Server Component into a Client Component turns it into a Client Component.
Done with this concept?
Mark it complete to track your progress. No login needed.