Introduction to the Next.js App Router: A Beginner's Guide

Published On
Posted

Learn about the Next.js App Router, its key features, and how to set it up with in this comprehensive beginner's guide.


Next.js logo

Next.js App File Structure

Introduction to the Next.js App Router: A Beginner's Guide

The Next.js App Router is a powerful tool introduced in Next.js 13 that brings a host of new features to streamline and enhance web application development. This guide will walk you through the essential aspects of the App Router, demonstrating how it can be used to create dynamic and efficient applications. We'll explore its key features, how to set it up, and provide practical examples with detailed explanations.

What is the Next.js App Router and Why is it Important?

The Next.js **App Router is designed to enhance the flexibility and performance of your Next.js applications. It leverages modern web technologies such as **React Server Components, Streaming with Suspense, and Server Actions, making it easier to build scalable and efficient web applications. By separating server and client components, the App Router simplifies data fetching and rendering processes, resulting in better performance and developer experience.

Key Features of the Next.js App Router

1. Nested Layouts

The App Router supports nested layouts, allowing you to create complex UIs with reusable components. This feature makes it easier to manage and structure different parts of your application independently.

2. Server and Client Components

The router differentiates between server components and client components. Server components handle data fetching and rendering on the server, while client components manage interactivity on the client side. This separation helps in optimizing performance and maintaining a clean codebase.

3. Streaming

Streaming allows parts of a page to be rendered as they gradually become available, improving the loading experience for users. This feature ensures that users can interact with parts of the application even if some data is still being fetched from the network.

4. Server Actions

Server Actions are asynchronous functions that handle server-side logic, such as data mutations and form submissions. They provide a modular and clean way to manage server-side operations, reducing the complexity of handling client-server interactions.

5. Improved Data Fetching

Data fetching is simplified by allowing requests to be made directly within server components. This reduces complexity and avoids issues like hydration mismatches that were common with previous versions.

Setting Up a Basic Next.js App Router

Let's see how you can set up a minimal Next.js application utilising the App Router.

1. Install Next.js

To start using the Next.js App Router, first install Next.js:

bash
npx create-next-app@latest my-app cd my-app npm run dev

These commands set up a new Next.js project and start the development server.

2. Create the App Directory

The app directory is where you organize your routes and components. Create it at the root of your project:

structure
my-app/ ├── app/ ├── pages/ ├── public/ ├── styles/ └── ...

3. Define Layouts

Layouts are used to define the structure and the shell of your application. To create layouts, you must define a file called layout.tsx, e.g. app/layout.tsx for the root layout:

tsx
// app/layout.tsx import { ReactNode } from 'react'; export default function RootLayout({ children }: { children: ReactNode }) { return ( <html> <head> <title>Hello World!</title> </head> <body>{children}</body> </html> ); }

This layout component serves as the root wrapper for all your pages. The { children } prop represents the nested content within the layout, which will be rendered inside the <body> tag.

4. Create Pages

You can define pages in Next.js using the new file-based routing in the app directory. For example, to create a homepage, create a page.tsx at the root of your app:

tsx
// app/page.tsx export default function HomePage() { return <h1>Welcome to Next.js App Router!</h1>; }

This is a simple page component that will be rendered when you visit the root URL ("/") of your application. It simply outputs a heading element with a welcome message.

Practical Examples of Using the Next.js App Router

1. Nested Routes

Let's now examine different examples of nested pages inside your application.

tsx
// app/dashboard/page.tsx export default async function Dashboard() { const user = await auth(); if(!user) redirect("/signin"); return <h2>Welcome to the dashboard page.</h2>; } // app/teams/[teamId]/page.tsx export default async function Team({ props }) { const { teamId } = props.params; const team = await getTeam(teamId); return ( <div> <h2>Team details: </h2> <div>Name: {team.name}</div> <div>Members: {team.members.count}</div> </div>); } // app/profile/account/page.tsx export default async function Account() { const account = await getMyAccount(); return ( <div> <h2>Account: </h2> <div>Name: {account.name}</div> <div>Email: {account.email}</div> </div>); }

These components demonstrate how you can create nested routes inside different sections / folders of your application.

2. Data Fetching

Next.js extends the native fetch Web API to allow you to configure the caching and revalidating behavior for each fetch request on the server. React extends fetch to automatically memoize fetch requests while rendering a React component tree.

You can use fetch with async / await in Server Components, in Route Handlers, and in Server Actions.

tsx
// app/page.tsx export async function getDogFacts() { const res = await fetch('https://dog-facts-api.herokuapp.com/api/v1/resources/dogs/all'); return res.json(); } export default async function HomePage() { const facts = await getDogFacts(); return ( <div> <h1>Dog Facts</h1> <ul> {facts.map((fact, index) => ( <li key={index}>{fact.fact}</li> ))} </ul> </div> ); }

This example demonstrates how to fetch data from an API within a server component. The getDogFacts function fetches data from a public API, and the HomePage component displays this data in a list.

3. Server Actions

Server Actions are asynchronous functions that are executed on the server. They can be used in Server and Client Components to handle form submissions and data mutations in Next.js applications. To define a server action, you must use the special directive "use server" at the top of a module and export your action as an async function. Then, inside your components, you can simply invoke it in your event handlers.

tsx
// app/actions/update.ts 'use server'; export async function update(data) { // Perform server-side logic here console.log('Server action executed', data); } // app/page.tsx import { update } from './actions/update'; export default function HomePage() { const handleSubmit = async (e) => { e.preventDefault(); await update({ key: 'value' }); }; return ( <form onSubmit={handleSubmit}> <button type="submit">Submit</button> </form> ); }

This example shows how to use server actions to handle a form submission. The update function logs the submitted data on the server, and the form in the HomePage component triggers this action when submitted.

Benefits of Using the Next.js App Router

The Next.js App Router brings several notable benefits to web application development, enhancing both the developer experience and the end-user performance. Here are some of the key advantages:

  • Improved Performance:

    • Server-Side Rendering (SSR): By rendering pages on the server, the App Router reduces the time it takes for a user to see the initial content, improving perceived performance and SEO.
    • Streaming: This feature allows parts of a page to be rendered and displayed as they become available, leading to faster interaction times even if some data is still loading.
  • Enhanced Simplicity:

    • Unified Data Fetching: The App Router simplifies data fetching by allowing requests directly within server components, avoiding the complexity and potential issues of client-side fetching.
    • Server Actions: These provide a clean, modular approach to handling server-side logic, making it easier to manage data mutations and form submissions.
  • Flexibility and Modularity:

    • Nested Layouts: The ability to define nested layouts helps in organizing complex UIs and allows for reusable components, improving code maintainability and scalability.
    • Client and Server Components: Separating components into server-side for data fetching and client-side for interactivity enhances the clarity and performance of applications.

These are just some of the benefits that make the Next.js App Router a powerful tool for developers looking to build high-performance, scalable, and maintainable web applications. If you're further interested in the Next.js App Router and its features, you can checkout the official docs for more in-depth explanations.

Conclusion

The Next.js App Router is a significant advancement in web development, offering rich benefits such as enhanced performance, simplicity, and flexibility. By leveraging its features, you can build efficient and scalable applications with ease. Whether you're a novice or an experienced developer, understanding and using the App Router will undoubtedly improve your Next.js projects.