⚙️ Server vs Client Components in Next.js v15 — What’s the Difference?

If you’ve used plain React with create-react-app or Vite, you’re used to writing components that run entirely in the browser — these are called Client Components.

But with Next.js, things change dramatically. You now have two types of components:

  • 🖥️ Server Components (default in Next.js)

  • 🧠 Client Components (for interactive features)

Let’s break it down in simple words. 👇


🔧 What Are Server Components?

In Next.js, all components are Server Components by default.

This means:

  • They are rendered on the server, not the browser

  • They don’t have access to browser-only APIs (like window, document)

  • You can’t use React hooks like useState, useEffect inside them

  • They return pre-rendered HTML to the browser

Example:

export default function HomePage() {
  console.log('Rendering on server');
  return <h1>Hello from the server!</h1>;
}

When you open this page in your browser, you won’t see the log in your DevTools console.
Instead, the log shows up in your terminal, proving that the component ran on the server.


🤯 Why This Matters

  • Faster page loads: No JS needed to render static content

  • Better SEO: Search engines get fully rendered HTML

  • Smaller bundle sizes: Less JavaScript sent to the browser

✅ Server Components are great for:

  • Static pages

  • Displaying content from a CMS or database

  • Components that don’t need user interaction


🧠 What Are Client Components?

Sometimes you need components to:

  • Use state (useState, useEffect)

  • Respond to user actions (onClick)

  • Manage timers, animations, local storage, etc.

In those cases, you need a Client Component.

To define one, you just add a special directive at the top of your file:

'use client'; // 👈 This turns it into a Client Component

import { useState, useEffect } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  );
}

This code now runs in the browser, not the server.



🧪 Real-Life Example: Image Slideshow

Let’s say you have an image slideshow that swaps images every 5 seconds using useEffect and setInterval.

This logic only makes sense in the browser, not on the server.

So you turn it into a Client Component:

'use client';

import { useEffect, useState } from 'react';

export default function ImageSlideshow() {
  const [index, setIndex] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setIndex((prev) => (prev + 1) % 3);
    }, 5000);
    return () => clearInterval(timer);
  }, []);

  return <img src={`/images/image-${index}.jpg`} />;
}

✅ Now it works as expected — it only runs in the browser and swaps images interactively.


🔄 What Happens When You Mix Both?

You can mix Server and Client Components freely.

For example:

// app/page.js (Server Component)
import ImageSlideshow from '../components/image-slideshow';

export default function HomePage() {
  return (
    <main>
      <h1>Welcome</h1>
      <ImageSlideshow />
    </main>
  );
}

The HomePage component runs on the server, but the ImageSlideshow component runs on the client.

Next.js will automatically split the JavaScript bundle and handle rendering intelligently.


🧠 Quick Summary

FeatureServer ComponentClient Component
Runs on...ServerBrowser
Default in Next.js?✅ Yes❌ No, use 'use client'
Can use useState?❌ No✅ Yes
Can handle events?❌ No✅ Yes
Optimized for SEO?✅ Yes⚠️ Maybe
JavaScript needed?🚫 Minimal✅ Required

🔍 Pro Tips

  • Don’t make everything a Client Component. Only use it when needed.

  • Server Components are faster, smaller, and better for SEO.

  • Always remember to put 'use client'; at the top of the file if you need client-side behavior.

0
Subscribe to my newsletter

Read articles from Muhammad Sufiyan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Muhammad Sufiyan
Muhammad Sufiyan

As a former 3D Animator with more than 12 years of experience, I have always been fascinated by the intersection of technology and creativity. That's why I recently shifted my career towards MERN stack development and software engineering, where I have been serving since 2021. With my background in 3D animation, I bring a unique perspective to software development, combining creativity and technical expertise to build innovative and visually engaging applications. I have a passion for learning and staying up-to-date with the latest technologies and best practices, and I enjoy collaborating with cross-functional teams to solve complex problems and create seamless user experiences. In my current role as a MERN stack developer, I have been responsible for developing and implementing web applications using MongoDB, Express, React, and Node.js. I have also gained experience in Agile development methodologies, version control with Git, and cloud-based deployment using platforms like Heroku and AWS. I am committed to delivering high-quality work that meets the needs of both clients and end-users, and I am always seeking new challenges and opportunities to grow both personally and professionally.