Next.js 13: complete guide to Server Components and the App Directory

Next.js 13: complete guide to Server Components and the App Directory

Unlock the full potential of Next.js 13 with our most complete and definitive tutorial on using server components and the app directory.

What does Next.js 13 bring to the table?

Next.js 13 is a major release of the most popular React framework: in fact, it ships with a new routing system, also called App Router. In many ways, this new routing system is a complete rewrite of the previous one, and fundamentally changes the way we will write Next.js applications.

The new app directory brings many improvements to the existing pages directory, and it's the new default way to write Next.js apps, after a period of experimental releases.

Server Components (RSC)

The biggest change in the new App Router is the introduction of Server Components, a new type of React components that run on the server and return compiled JSX that is sent to the client. Server Components are useful for rendering the skeleton of a page, fetching data from the server in parallel, and passing it to the "client components".

Server Components are the default component type in the new app directory.

Layouts

Powered by Server Components, layouts are foundational components that wrap pages. Next.js Layouts are not only useful for displaying a common UI across pages, but also to reuse logic and data fetching across pages.

Layouts also solve the waterfall problem, which is a common issue with the current Next.js routing system. In fact, with the new App Router, we can fetch data in parallel, and pass it to the page component: this is a substantial performance improvement over the current routing system.

Server Actions

Still in alpha, Server Actions are a new way to execute functions on the server, instead of wiring them through an API handler. Server actions are useful for executing server-side logic, such as sending emails, or updating a database. Server actions are useful for submitting forms, execute server-side logic, and redirect the user to a new page.

Additionally, server actions offer us the ability to revalidate data fetched from Server Components, eliminating the need for complex client-side state management as a result of data mutation (such as updating a Redux store).

We introduce Server Actions in this tutorial, but we cover them in detail in a separate article, linked at the end of this tutorial.

Enhanced Router

Using conventional filenames, we can add various types of components in the app directory. This is a big improvement over the current routing system, which requires us to use a specific directory structure to define pages, API handlers, and so on.

What does this mean? From now on, we can create various types of components in the app directory using a specific filename convention specific to Next.js:

  • pages are defined as page.tsx
  • layouts are defined as layout.tsx
  • templates are defined as template.tsx
  • errors are defined as error.tsx
  • loading states are defined as loading.tsx
  • not found pages are defined as not-found.tsx

What are Server Components?

Server Components are a new type of React components that run on the server and return compiled JSX that is sent to the client. Next.js, with its new app directory released in Next.js 13, fully embraced Server Components by making them the default type components.

This is a big shift from traditional React components that run both on the server and on the client. In fact, as we have specified, React Server components do not execute on the client.

As such, there are some constraints to using Server Components that we need to keep in mind:

  • Server components cannot use browser-only APIs
  • Server components cannot use React hooks
  • Server components cannot use Context

So, what are they for?

React Server Components are useful for rendering the skeleton of a page, while leaving the interactive bits to the so-called "client components".

Despite their name, "client components" (which, IMHO, is unfortunate) are also server-rendered, and they run on both the server and the client.

React Server Components can be useful because they allows us to:

  • render pages faster
  • reduce the amount of JavaScript that needs to be sent to the client
  • improve the routing performance of server-rendered pages

In short, we use Server Components to fetch data from the server and render the skeleton of a page: then, we can pass the data to the "client components".

Server Components vs Client Components

As we have seen, Server Components are useful for rendering the skeleton of a page, while Client Components are the components as we know them today.

This comparison in the Next.js docs is a good way to understand the difference between the two.

Defining Server Components

Server components do not need a notation to be defined as such: server components are the default components when rendered in the app directory.

We cannot use React hooks, Context, or browser-only APIs in Server Components. However, we can use Server Components only APIs, such as headers, cookies, etc.

Server components can import client components.

There is no need to specify a notation to define a Server Component: in fact, Server Components are the default component type in the new app directory.

Assuming the component ServerComponent is not a child of a Client Component, it will be rendered on the server and sent to the client as compiled JSX:

Defining Client components

On the contrary, in the Next.js app directory, we need to specifically define client components.

We can do this by specifying the use client pragma at the top of the file:

When we use client components, we can use React hooks, Context, and browser-only APIs. However, we cannot use some Server Components only APIs, such as headers, cookies, etc.

NB: Client components cannot import server components, but you can pass a Server Component as a child or prop of a Client Component.

App directory

The new "app" directory released in Next.js 13 is an experimental a new way to build Next.js apps. It coexists with the pages directory, and we can use it to incrementally migrate an existing project to the new directory structure.

This new directory structure is not just a new way to write apps, it's a whole new routing system underneath, much more powerful than the current one.

Next.js 13 Folder Structure

What does the new Next.js 13 file structure look like? Let's take a look at the example app we'll be using in this tutorial.

Below is an example of a Next.js 13 app with the new app directory:

As you can see, the name of the file reflects the type of component it is. For example, layout.tsx is a layout component, while page.tsx is a page component, and so on.

Don't worry, we will go through all the different types of components in the next sections.

Co-locating files in Next.js Routing Structure

One important side effect of the new app directory is that it allows us to colocate our files. Since filenames are conventional, we can define any file in the app directory without these becoming pages components. Unlike the older pages router, we can define any type of component in the app directory without it becoming a page.

For example, we could place our components for a specific page right in the folder where it's defined:

Side-note: why is (site) in parentheses? By using parentheses, we make the directory site "pathless", which means we can create new layouts, loading files, and pages in the site directory, without adding a new path segment to the routing.

All pages under (site) will be accessed from the root path /: for example, the page app/(site)/page.tsx will be accessible at /.

Next.js 13 folder structure best practices

When it comes to the new app directory, there are some 

# Details

Published on January 31, 2024 6 min read

Web dev