Next.js introduces a distinction between Server Components and Client Components to optimize performance and developer experience. By default, layouts and pages are Server Components, which lets you fetch data and render parts of your UI on the server, optionally cache the result, and stream it to the client. When you need interactivity or browser APIs, you can use Client Components to layer in functionality.
1. What is client component
A Client Component is a React component that runs in the browser (after hydration) and can contain browser-only logic (event handlers, state, effects):
- Mark it by placing
'use client'at the top of the file. - It appears in the client bundle, so it includes to JavaScript load.
- Whenever you need interactivity (hooks, event handlers, local state, refs).
- Can consume props from a parent server component (or can fetch its own data client-side).
Example:
'use client';
import { useState } from 'react';
export default function FilterControls({ onFilter }) {
const [search, setSearch] = useState('');
return (
<div>
<input
value={search}
onChange={e => setSearch(e.target.value)}
placeholder="Search..."
/>
<button onClick={() => onFilter(search)}>Apply Filter</button>
</div>
);
}
2. What is server component
A Server Component is a React component that runs only on the server:
- Can NOT include browser-only APIs (like
window,document, event listeners). - It is excluded from the client JavaScript bundle, thereby reducing bundle size.
- Can fetch data directly in server without needing an API route as client.
- Server rendering: the server composes HTML, streams if necessary, and the client – when required – hydrates only interactive parts.
Example:
import { getServerData } from '@/lib/data';
export default async function DashboardPage() {
const data = await fetch(`https://api.example.com/user-activity`)
return (
<main>
<h1>Dashboard</h1>
<p>User count: {data.userCount}</p>
<RecentActivityList items={data.recent} />
</main>
);
}
3. How they differ
| Client component | Server component | |
| Run on | Browser (client JavaScript) | Server (NodeJS) |
| Bundled for | Included in client bundle | No client bundle (only server) so reduce client bundle size |
| Browser APIs (window/document) | Available | Not available |
| Interactivity (hooks, state) | Full React hooks and event handlers | No support React state/hooks |
| Data fetching | Fetch directly (sync/async) on server | Fetch client-side and update to UI via state/hooks |
| SEO | No support | Support |
| Security | Fully visible and auditable by the end-user | Avoid exposing sensitive logic or secrets |
| Use case | – Need interactivity (forms, input, animations, drag-drop,…) – Rely on browser APIs (e.g. localStorage, window, event handlers)– Need client-side state that persists across interactions | – Static content or changes only on server side (e.g. blog article, marketing page, dashboard layout) – Need SEO benefits – Fetch data server-side and render UI with minimal client JS – Compose heavy UI trees and want processing it to the server |