Ship less JavaScript: Server vs Client Components
Quick answer: In the App Router, components are Server Components by default—great for data, secrets, and slim bundles. Add 'use client' only where you need hooks, events, or browser APIs. This page ties that split to Scrimba’s interactive lessons.
Who this is for
React devs who paste 'use client' everywhere “just in case” and wonder why bundles balloon.
1. Server Components (Default)
Server Components are rendered on the server. The HTML is sent to the browser. No JavaScript is sent for that component logic.
Benefits:
- Data Fetching: Access your database directly.
- Security: Keep sensitive data (API keys) on the server.
- Performance: Smaller JavaScript bundles.
// app/page.tsx
async function Page() {
const data = await db.post.findMany(); // Direct DB access!
return <ul>{data.map(p => <li key={p.id}>{p.title}</li>)}</ul>;
}
Learn it on Scrimba: -> Interactive Lesson: Server Components
2. Client Components
Client Components are rendered on the client (browser). They are the "React" you are used to.
When to use them:
- Interactive elements (
onClick,onChange). - Using Hooks (
useState,useEffect). - Using browser APIs (
window,localStorage).
How to use them:
Add 'use client' at the very top of your file.
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
Learn it on Scrimba: -> Interactive Lesson: Client Components
3. Mixing Server and Client Components
You can pass a Server Component as a child to a Client Component. But you cannot import a Server Component into a Client Component.
Next.js handles this boundary automatically.
4. Static vs Dynamic Rendering
By default, Next.js statically renders routes at build time. Use dynamic = 'force-dynamic' or revalidate = 0 to opt into dynamic rendering (computed on each request). This affects caching and when your page is revalidated.
5. Partial Prerendering (PPR)
Next.js 15 introduces Partial Prerendering — a single page can have a static shell with dynamic holes. The shell is prerendered instantly; dynamic parts stream in. Enable with experimental: { ppr: true } in next.config.js. This gives you the best of both worlds: fast initial load and fresh data where needed.
Next step (free on Scrimba): Practice Server + Client Components →
Read this when…
Interviews or PRs keep asking why a component is client-only—and you want a crisp answer backed by reps.
Related Scrimba Courses
Feel the Server/Client split in-browser
Scrimba’s App Router course lets you toggle boundaries and see bundle impact immediately.