Skip to main content

Server vs Client Components

As you've probably already read in the Next.js Routing Fundamentals, the App Directory introduces a new model for building applications using React's latest features such as Server Components. All components in the App Directory are Server Components by default. Server Components are rendered on the server rather than on the client (the client is the browser in this context).

Server Components

Server Components are rendered in two main scenarios:

  • Build Time: During the application build process, Server Components for static routes are pre-rendered and cached. This means the HTML is generated once and can be reused for all users of the application, making the initial page load really fast.
  • Request Time: For dynamic routes or when using dynamic data fetching, Server Components are rendered "on-demand" when a request reaches the server. This happens before any client-side JavaScript loads or executes. The server processes the request, renders the components, and sends the generated HTML to the client.
info

While dynamic routes are often rendered at request time, they can also be pre-rendered at build time using Next.js's generateStaticParams. This function allows you to specify which dynamic routes should be generated during build, improving performance by avoiding runtime rendering.

Rendering process

  1. React renders the Server Components on the server into a special format called the React Server Component Payload (RSC).
  2. This payload contains the rendered HTML and any references to Client Components.
  3. The server sends this payload to the client.
  4. The client receives the pre-rendered HTML (allowing for immediate display).
  5. The client then "hydrates" only the Client Components, adding interactivity where needed.

The key advantage is that Server Components don't need to be shipped to the client as JavaScript code, and they can be rendered independently of any client-side processing. This results in smaller JavaScript bundles and faster page loads, as the browser doesn't need to do the work of rendering these components.

Main reasons to use Server Components

  • Data fetching from database.
  • Keep sensitive data on server.
  • To reduce client-side JavaScript.
  • SEO Optimization.
  • Static content rendering.

Client Components

Client Components are components that are rendered and hydrated on the client (browser). To create a Client Component, you simply need to add the 'use client' directive at the top of your file. The 'use client' directive must be written at the very top of the file (before imports) and tells React that this component and all its children should be treated as Client Components. This means they will be:

  • Rendered on the client side
  • Hydrated with interactivity
  • Able to use browser APIs and React hooks
  • Included in the client-side JavaScript bundle

Note that once you mark a component as a Client Component, all its child components are automatically treated as Client Components as well, even if they don't have the 'use client' directive. Therefore, it's important to be careful about where you place the directive to minimize the amount of client-side JavaScript.

Make sure to check out the documentation's section "Composition Patterns" to see a comprehensive summary when to choose which one.

Main reasons to use Client Components

  • User interactivity (button clicks, hover effects etc.).
  • To use browser APIs.
  • State management.
  • Client-side validation.
  • Event listeners.
  • Dynamic user interfaces.

Hydration

Make sure to read "Hydration" documentation in the further reading section but think of it like this: The server sends a "dry" HTML structure (like a dehydrated meal), and hydration adds the "water" (JavaScript interactivity) back in, making it fully functional. This is one reason why Server Components are more performant - they skip the hydration step entirely.

Therefore it is strongly recommended to not have unnecessary Client Components in your app.

Further reading