Skip to main content
Engineering Blog
Engineering Blog2026-07-18

Next.js App Router: The Architectural Divide Between Server and Client Components

Quan Van|Technical Essay|4 min read

The introduction of the Next.js App Router (starting from version 13) marked a monumental paradigm shift in React development: the widespread adoption of React Server Components (RSC).

Historically, every single React component was bundled with JavaScript and shipped to the user's browser. Today, Next.js forcefully splits the component ecosystem into two distinct hemispheres, each with entirely different responsibilities and constraints.


1. Server Components (The New Default)

In the App Router, every component you create is a Server Component by default, unless explicitly stated otherwise.

  • The Execution Model: They run exclusively on the server. The final output sent to the browser is purely static HTML.
  • Zero JavaScript Bundle: Because they do not possess a lifecycle or internal state, the underlying code for these components (and any heavy dependencies they import) is never sent to the browser. Their client-side JS weight is strictly 0kb.
  • The Ultimate Advantage: You can declare these components as asynchronous functions (async) and communicate directly with databases or the local filesystem. This entirely eliminates the need to build intermediate REST or GraphQL APIs just to fetch data.
// Server-only: Fetch data securely and directly
export default async function UserProfile() {
  const user = await db.query("SELECT * FROM users WHERE id = 1"); 
  
  return (
    <div>
      <h1>Welcome back, {user.name}</h1>
    </div>
  );
}


2. Client Components ('use client')

These are the traditional React components you are already deeply familiar with. To instruct Next.js that a component belongs to the client layer, you must explicitly declare the "use client" directive at the very top of the file.

  • The Execution Model: This is where the "life" of the application resides. If your UI requires click events, keyboard inputs, swipe gestures, or dynamic state mutations, it must be a Client Component.
  • The Biggest Misconception: Many engineers assume the word "Client" means the component is only rendered in the browser. This is fundamentally false. In Next.js, Client Components are still pre-rendered on the Server (via SSR) to generate the initial HTML payload for SEO. Afterward, the JavaScript is sent down to the browser to "Hydrate" the static HTML and attach interactivity.
"use client"; // This directive is mandatory

import { useState } from 'react';

export default function LikeButton() {
  const [likes, setLikes] = useState(0);

  return (
    <button onClick={() => setLikes(likes + 1)}>
      {likes} Likes
    </button>
  );
}


3. Quick Comparison Matrix

The Golden Rule: Always default to Server Components. Only opt into Client Components when interactive necessity dictates it.

Capability / Metric Server Components Client Components ('use client')
Execution Environment Server Only Server (SSR) + Browser (Hydration)
JS Shipped to Browser None (0kb, blazing fast) Yes (Increases bundle size)
Security (API Keys, DB) Absolutely Secure High risk of data leaks if careless
Data Fetching Excellent (Native async/await) Fair (Requires React Query / useEffect)
Interactivity (onClick) Not Supported Fully Supported
State & Lifecycle Hooks Not Supported Supported (useState, useEffect)
Browser APIs (window) Inaccessible Accessible

4. Architectural Best Practice: The "Leaf" Pattern

When structuring a modern Next.js application, the optimal strategy is to push Client Components as far down the component tree as possible—to the "leaves."

Instead of declaring a massive, root-level HomePage as "use client" (which forces everything inside it to also become a client component), keep HomePage as a Server Component for lightning-fast data fetching. Extract interactive elements—like a LikeButton or a SearchBar—into small, isolated files marked with "use client", and inject them back into the HomePage.

By strictly adhering to this pattern, you preserve the massive performance benefits of Server Components while surgically injecting interactivity exactly where it is needed.

End of article

Want to link PomaiDB into your project?

Read the Engineering Manual