Next.js 13.4から「App Router」というルーティング機能が安定版(Stable)となりました。
ルーティングとは、Webサイト内で特定のURLにアクセスした際に表示するページを決定する仕組みのことです。
例: /aboutにアクセスしたら、Aboutページを返す など
この記事では「App Router」の特徴や、以前までのルーティング機能「Pages Router」との違いについて解説したいと思います。
※2024/05時点のNext.js最新バージョンは14.2です。
Next.jsはReactのフレームワークとして、様々な機能が実装されています。
その中の1つに「ルーティング」があり、ファイルシステム(ディレクトリ構成)に沿ったページを生成してくれます。
pages
├── about
│ └── index.js // https://example.com/about
├── help
│ ├── help01.js // https://example.com/help/help01
│ └── help02.js // https://example.com/help/help02
├── blog
│ └── [slug].js // https://example.com/blog/[slug] (動的に可変)
└── contact
└── index.js // https://example.com/contact
これはとても便利な機能で、ディレクトリ内にファイルを配置するとディレクトリ名がURLパスとなり直感的にサイトを構築できるのが特徴です。
これはNext.jsに限ったことではなく他のフレームワーク(GatsbyやVueベースであるNuxtなど)でも採用されています。
しかし冒頭で述べた通りNext.js 13.4からは「App Router」という機能が実装され今までの「Pages Router」から進化しています。
まずはApp Routerが実装された理由を見てみます。
we received feedback from the community and identified areas
where we started to reach the limits of the Pages Router.
[翻訳]
コミュニティからのフィードバックを受け、Pages Routerの限界に達し始めた部分を特定しました。
Most notably, the Next.js Pages Router was not designed for streaming,
a cornerstone primitive in modern React
[翻訳]
最も注目すべき点は、Pages Routerが、
現代のReactの基本的な構造であるストリーミング用に設計されていないことです
Server Components, Suspense, and more,
which have been designed for streaming architectures.
[翻訳]
Server ComponentsやSuspenseなど、ストリーミングアーキテクチャ用に設計されたものです。
出典:Next.js App Router Update (2023/06/22)
これだけだと理解することは難しいのですが、Pages Routerではページの一部ではなく全体を返却するシステムだったため、Reactの基本構造とは離れた設計になっていたとのことです。
そのため後述する箇所の変更・アップグレードがなされたということみたいです。
変更点を挙げる前に、まず共通の仕様を説明します。
App RouterとPages Routerの両方ともファイルベースのルーティングを採用しています。
例に挙げた通り、ディレクトリ構成でルーティングが生成されることはどちらも変わりません。
またApp RouterとPages Routerは同時に使用できるため、Next.jsをアップグレードする際は、1つずつ順番にルーティングの対応を行うことが可能です。
// 下記のような構成でも併用可能です
// App Router
app
└── about // https://example.com/about
├── layout.js
└── page.js
// Pages Router
pages
├── help
│ ├── help01.js // https://example.com/help/help01
│ └── help02.js // https://example.com/help/help02
├── blog
│ └── [slug].js // https://example.com/blog/[slug] (URLの一部が動的に変化)
└── contact
└── index.js // https://example.com/contact
App Router側にあるファイルのlayout.jsやpage.jsについては後述します。
では本題の変更点を説明します。
App Routerでは下記の項目が変わりました。
全てではないですが、大きく変更となっている点を列挙しました。
個人的に大きく変わったと感じた点を下記で詳しく確認していきたいと思います。
Pages Routerではファイル名までURLパスとして認識されていましたが、 App Routerではディレクトリ名のみがURLパスとなります
// App Router
app
├── help // https://example.com/help
│ ├── layout.js
│ └── page.js
└── blog
└── [slug] // https://example.com/blog/[slug] (動的に可変)
├── layout.js
└── page.js
// Pages Router
pages
├── help
│ ├── help01.js // https://example.com/help/help01
│ └── help02.js // https://example.com/help/help02
└── blog
└── [slug].js // https://example.com/blog/[slug] (動的に可変)
ディレクトリ配下にあるlayout.jsやpage.jsはApp Routerで新しく実装された仕様です。
ディレクトリ配下には最低限page.jsが存在しなければいけません。
他にも下記のようなファイルタイプがあります。
ファイルタイプ | 説明 |
---|---|
layout | セグメントと下層ディレクトリの共有UI |
page | ルートのユニークなUIを作成し、ルートを公開可能にする |
loading | セグメントと下層ディレクトリのローディングUI |
not-found | セグメントと下層ディレクトリのnot found UI |
error | セグメントと下層ディレクトリのエラーUI |
global-error | グローバルエラーUI |
route | サーバーサイドAPIエンドポイント |
template | 特殊化された再レンダリングレイアウトUI |
default | 並行ルートのためのフォールバックUI |
[slug]ディレクトリは動的ルーティングになります。
page.jsからは下記のようにslugを取得できます。
// https://example.com/about にアクセスした場合
export const Page = ({ params }: { params: { slug: string } }) => {
return <>slug: {params.slug}</>; // slug: about が表示される
}
App Routerでは、RSC(React Server Components)という新しいコンポーネント設計が導入されました。
サーバーコンポーネントとは、サーバー側でレンダリングされるコンポーネントで、クライアント側ではなくサーバー側で実行されます。
コンポーネント単位で、サーバー側で生成するかクライアント側で生成するかを選ぶことができます。
サーバーコンポーネントに関するメリットの1つとしては、コンポーネントごとの責務が明確になることが挙げられます。
今までのPages Routerではサーバーサイドの処理を記述する際、getServerSidePropsという関数を利用する必要があり、データのやり取りの冗長化やクライアントサイド処理との混在が起きていました。
それを分割することでコンポーネントごとの責務が明確となります。
他にもメリットは多くあります。
デメリットとしては今までと大きくコンポーネントの分け方が変わるため、コンポーネント設計を再考する必要があるということが挙げられます。
クライアントサイドで実行する処理(例:useState、useEffectなど)を使用するには、コンポーネントの最上部に'use client'と記述する必要があります。
この記述を加えると、そのコンポーネントはクライアント側で実行されるようになり、サーバー側の処理は利用できなくなります。
上記で挙げた内容以外にも細かく変更されていますが、App RouterとPages Routerの違いを理解する上で重要な部分を抜粋しました。
個人的な感覚としては、App Routerが主軸になっていくので今後の開発ではApp Routerをメインに利用していきたいと思います。
ただ個人ブログや更新が少ないサイトなど、Static Exportを利用しているサイトはPages Routerで事が足りる認識であるためサイトの目的や開発規模によって使い分けても良いかもしれません。
Next.js 14からはServer Actionsが安定版(Stable)となっており、Next.jsの進化が著しいです。
徐々に参考記事なども集まってきているので便利な機能は理解して、効率よく開発を行いたいです!
最後までご覧いただきありがとうございました!