SyntaxStudy
Sign Up
Next.js Understanding React Server Components
Next.js Beginner 1 min read

Understanding React Server Components

React Server Components (RSC) are a paradigm shift in how React applications are structured. Unlike traditional React components that run in the browser, Server Components execute exclusively on the server. Their output — a serialised component tree — is sent to the client and never includes the component code itself. This means zero JavaScript is sent to the browser for Server Components, resulting in dramatically smaller bundles. Server Components have unique capabilities unavailable to Client Components. They can directly await asynchronous operations like database queries or file system reads. They can access server-only modules and environment variables without exposing them to the client. They can render sensitive data (like partial API keys used in headers) without that information ever reaching the browser. The RSC protocol uses a special wire format — often called the RSC payload — to transmit the rendered server component tree to the client. This payload is separate from HTML: during initial load Next.js sends both HTML (for fast first paint) and the RSC payload (for React hydration). During client-side navigation only the RSC payload is sent, allowing React to update the page without a full HTML fetch.
Example
// Server Component — direct DB access, zero client JS
// app/users/page.tsx

import { prisma } from '@/lib/prisma';

// This import only exists on the server — never shipped to the browser
import 'server-only';

export default async function UsersPage() {
  // Direct database query — no API route needed
  const users = await prisma.user.findMany({
    select: { id: true, name: true, email: true, createdAt: true },
    orderBy: { createdAt: 'desc' },
    take: 20,
  });

  return (
    <div>
      <h1>Users ({users.length})</h1>
      <table className="w-full text-sm">
        <thead>
          <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Joined</th>
          </tr>
        </thead>
        <tbody>
          {users.map((user) => (
            <tr key={user.id}>
              <td>{user.name}</td>
              <td>{user.email}</td>
              <td>{user.createdAt.toLocaleDateString()}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

// To prevent accidental client-side imports of server-only modules:
// Install the 'server-only' package and import it at the top of any
// file that must not be bundled for the client.
// npm install server-only