Next.jsServer ComponentsClient ComponentsPerformance

Server Components vs Client Components in Next.js 15 — The Complete Guide

Learn when to use server and client components in Next.js 15, how they differ, how they impact performance, and how to combine them like a pro.

Pedro Tech
October 10, 2025
8 min read
Server Components vs Client Components in Next.js 15 — The Complete Guide

Server Components vs Client Components in Next.js 15 — The Complete Guide


Introduction


When I first heard about React Server Components, I had no idea why they mattered. They sounded fancy and cool, but I didn’t understand how they would actually change the way I build apps. Fast-forward to Next.js 15, and understanding the difference between server and client components is now essential if you want to write fast, scalable, modern applications.


In this article, we'll break down the difference, the trade-offs, and most importantly, how to use them together effectively.




What Are Server Components?


Server components are React components that run only on the server. They’re rendered before anything ever reaches the browser, and they don’t ship any JavaScript to the client. This means:


  • ✅ Zero JS bundle size for that component
  • ✅ Faster initial load and better SEO
  • ✅ Direct access to databases, APIs, and secrets
  • ✅ Automatic streaming support

If a component doesn’t need interactivity (like state or event listeners), it should probably be a server component.


Example:


1// app/page.tsx
2export default async function HomePage() {
3  const res = await fetch("https://jsonplaceholder.typicode.com/posts");
4  const posts = await res.json();
5
6  return (
7    <div>
8      <h1>Latest Posts</h1>
9      <ul>
10        {posts.map((post: any) => (
11          <li key={post.id}>{post.title}</li>
12        ))}
13      </ul>
14    </div>
15  );
16}

Notice the lack of "use client" — this is a pure server component. It never runs in the browser.




What Are Client Components?


Client components run in the browser. They’re hydrated with JavaScript and handle all the things server components can’t: state, effects, event listeners, animations, and user interactions.


They must start with the "use client" directive:


1"use client";
2
3import { useState } from "react";
4
5export default function Counter() {
6  const [count, setCount] = useState(0);
7  return <button onClick={() => setCount(count + 1)}>Clicked {count} times</button>;
8}

If you need useState, useEffect, or event handlers, you’re in client territory.




Key Differences


FeatureServer ComponentsClient Components
Runs onServer (Node.js/Edge)Browser
Supports state/effects❌ No✅ Yes
Access to backend/DB✅ Yes❌ No
Bundle size❌ None✅ Adds JS
SEO performance✅ Great⚠️ Depends
Interactivity❌ None✅ Yes



The Best of Both Worlds


The real magic happens when you combine them. You want most of your app to be server components and only sprinkle client components where interaction is necessary.


1// app/page.tsx (Server)
2import Counter from "./Counter";
3
4export default async function Page() {
5  const data = await fetch("https://api.example.com/data").then(res => res.json());
6
7  return (
8    <div>
9      <h1>{data.title}</h1>
10      <Counter />
11    </div>
12  );
13}
14
15// app/Counter.tsx (Client)
16"use client";
17import { useState } from "react";
18
19export default function Counter() {
20  const [count, setCount] = useState(0);
21  return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
22}

Here, the heavy lifting and data fetching happen on the server, while only the interactive button gets hydrated.




Common Mistakes to Avoid


  • Making everything a client component: This kills performance and makes your app heavier.
  • Using hooks in server components: Hooks like useState and useEffect don’t work on the server.
  • Fetching data on the client unnecessarily: You lose SSR and SEO benefits.



Best Practices


  • ✅ Use server components by default.
  • ✅ Keep client components small and focused.
  • ✅ Pass data from server to client via props.
  • ✅ Think about bundle size — server components are free, client ones cost.



Conclusion


Server and client components aren’t rivals — they’re partners. Server components keep your app fast, SEO-friendly, and secure. Client components bring interactivity and life. The secret to building truly modern Next.js 15 apps is knowing how to balance them.


Once you start thinking this way, your apps will not only feel faster but be faster — and your users (and Google) will love you for it.


Ready to Master Next.js?

You've learned the fundamentals from this article. Now take your skills to the next level with our comprehensive Next.js course.

Enroll in Course
Join thousands of developers already learning