Contents

React Server Components (RSC) are components that run only on the server: they can call the database and APIs directly, and only their output — not their code — is sent to the browser. Interactive parts are still written as client components. The main gain is less JavaScript in the browser and simpler data fetching; the cost is a new mental model and harder-to-debug caching.

Here is how RSC differ from familiar SSR, how to split server and client components and when switching is worth it.

How do Server Components differ from SSR?

With classic server-side rendering (SSR), all of a page's code runs on the server to produce HTML, and then the same code is downloaded and run again in the browser — hydration. With Server Components, some components' code never reaches the browser at all; the client receives only their output.

Criterion Classic SSR React Server Components
Where code runs On the server, then in the browser Server components — server only
JavaScript in the browser Code for every component on the page Client components only
Data fetching Page-level functions or client requests Directly in the component with async/await
Database and secrets access Only in special functions In any server component

On server rendering in general, see SEO for JavaScript websites and Nuxt vs Next.js.

How do you split server and client components?

In the App Router components are server components by default. A component becomes a client component when the file starts with the 'use client' directive — needed for state, event handlers and browser APIs. A good rule: server components fetch data and assemble the page; client components handle interactivity and sit as low in the tree as possible.

// app/products/[id]/page.tsx — a server component
export default async function ProductPage({ params }: { params: { id: string } }) {
  const product = await db.product.findUnique({ where: { id: params.id } })

  return (
    <article>
      <h1>{product.title}</h1>
      <p>{product.description}</p>
      <AddToCartButton productId={product.id} />
    </article>
  )
}

// components/AddToCartButton.tsx — a client component
'use client'
export function AddToCartButton({ productId }: { productId: string }) {
  const [pending, setPending] = useState(false)
  // ...
}

A smartphone and monitors with code on a developer's desk Photo: Unsplash

Which problems do Server Components solve?

Server Components solve three problems: too much JavaScript in the browser, request waterfalls for data and data-access logic leaking to the client.

  • less JavaScript — heavy libraries for text rendering, date formatting or code highlighting stay on the server;
  • simpler data fetching — a component gets its own data without an intermediate API for every page;
  • security — database queries and secret keys physically never reach the browser;
  • streaming — the page is shown in parts as data becomes ready.

Data changes use Server Actions — functions called from a client form but executed on the server. They are convenient but should be treated as a public API: check permissions and inputs.

What are the pitfalls of RSC?

The main difficulties are the new mental model, caching and the server-client boundary. Teams used to classic React often hit non-obvious errors in the first weeks.

  1. Serialisation boundary. A server component can pass only serialisable data to a client component — no functions or class instances.
  2. Caching. The framework caches requests and pages at several levels; you need to know when data refreshes.
  3. Libraries. Not every library works in server components — especially those using context and state.
  4. Debugging. Errors happen sometimes on the server, sometimes in the browser; good logging is essential.
  5. Server Action security. Every action is an open entry point that needs permission checks — see OWASP Top 10 explained.

Should you switch to Server Components?

Switching makes sense for new Next.js projects and for sites with lots of content and little interactivity: catalogues, media, documentation, marketing pages. Highly interactive apps such as editors and dashboards gain less — most of their code stays on the client anyway.

  • a new React project with public pages — start with the App Router;
  • an existing app — migrate gradually, starting with data pages;
  • admin panels and internal tools — no need to switch;
  • a team without experience — budget time for learning and conventions.

On choosing a framework, see Vue vs React: how to choose.

In short

  • Server components run only on the server, and their code never reaches the browser.
  • Client components marked 'use client' handle interactivity and belong low in the tree.
  • RSC reduce JavaScript, simplify data fetching and keep database access on the server.
  • Pitfalls: the serialisation boundary, caching, library compatibility and Server Action security.
  • Switching pays off for content sites and new projects, less so for interactive apps.

FAQ

  • Can Server Components be used without Next.js?

    Technically yes, but Server Components need support in the bundler and router. Next.js with the App Router is the most mature option; other frameworks are adding support, but it is less widespread.

  • Does an existing app need rewriting?

    No. Existing components can be marked as client components and moved to server components gradually, starting with data-heavy pages that have little interactivity.

  • Do Server Components affect SEO?

    Positively: content arrives as ready HTML and less JavaScript improves speed metrics. But ordinary server-side rendering can achieve the same SEO result.