本記事は Reactウィーク 3日目の記事です。
📍 2日目 ▶▶ 本記事 ▶▶ 4日目 📱
- はじめに
- Pages Router: シンプルなファイルベースのルーティング
- App Router: 次世代の柔軟なルーティング
- どちらを選ぶべきか?
- Pages Router 利用者が App Router を使い始めて苦戦したポイント
- まとめ
はじめに
こんにちは。先日配信されたPerfumeの最新アルバムがかっこよくて、最近なかなか寝付けなくなっているNRIネットコムの小畑です。
App Routerを触り始めてからちょうど1年が経過したので、この記事ではPages Router
と App Router
の違いと、それぞれの利点と適用例を私の所感を交えながら紹介したいと思います。
Next.js は、React ベースのフレームワークとして、サーバーサイドレンダリング(SSR)や静的サイト生成(SSG)などの機能を提供しています。バージョン 13 では新しいルーティングシステムである App Router
が導入され、従来の Pages Router
と比べてより柔軟な機能を備えるようになりました。
Pages Router: シンプルなファイルベースのルーティング
Pages Router
は、Next.js が誕生した当初から提供されているルーティングシステムで、pages
ディレクトリを使用してルートを定義します。ファイル名がそのまま URL パスに対応し、直感的な構造で利用できる特徴があります。
主な特徴
- データ取得の簡便性:
getStaticProps
やgetServerSideProps
を使用して、ページ単位でデータを取得できます。- 静的サイト生成(SSG)やサーバーサイドレンダリング(SSR)を簡単に設定可能です。
- ルートごとのコード分割:
- 各ページは独立した JavaScript バンドルとしてロードされるため、初期ロードが速くなります。
- ファイルシステムベースのルーティング:
pages
ディレクトリ内のファイルが自動的にルートとして設定されます。- 例:
pages/about.js
は/about
に対応します。
利点
- シンプルで直感的:
- ルート設定がファイルシステムベースで行われるため、ディレクトリ構造を見ればサイトの全体像が把握しやすいです。
- 学習コストが低い:
- App Routerと比較して、学習コストが低く、React の基本知識と Next.js 固有のルールを少し学べば、すぐに使い始められます。
欠点
- レイアウトの管理が複雑:
- 複数のページにまたがる共通レイアウトの管理が煩雑になることがあります。
- 大規模アプリケーションでのスケーラビリティの問題:
- 大規模アプリの開発等でページ数が増えると、
pages
ディレクトリの管理が難しくなることがあります。
- 大規模アプリの開発等でページ数が増えると、
Pages Router を使うべき場面の具体例
- シンプルな企業サイトやランディングページ:
- 企業のコーポレートサイトやプロダクトのランディングページなど、ページ数が少なく、静的なコンテンツが主な場合に最適です。シンプルなファイル構成で開発がしやすく、SSG を利用することで高速なページ読み込みを実現できます。
- 個人ブログや小規模なブログサイト:
- getStaticProps を使用して、ビルド時に記事データを取得することで、静的に生成された高速なブログサイトを構築できます。ルーティングも直感的で、記事のページ数が増えても管理が容易です。
- API ベースのヘッドレス CMS サイト:
- Contentful や Strapi などのヘッドレス CMS からデータを取得し、静的に生成するようなサイトでは、
Pages Router
を利用することで簡単に SSG と SSR を切り替えながら開発できます。
- Contentful や Strapi などのヘッドレス CMS からデータを取得し、静的に生成するようなサイトでは、
App Router: 次世代の柔軟なルーティング
Next.js 13 で導入された App Router
は、app
ディレクトリを使用してルーティングを行います。この新しいルーティングシステムは、従来の Pages Router
よりもモジュール化されており、React Server Components などの最新の機能をサポートしています。
主な特徴
- React Server Components のサポート:
- サーバーコンポーネントとクライアントコンポーネントを使い分けることで、パフォーマンスを最適化できます。
- 柔軟なレイアウト管理:
layout.js
ファイルを使用して、ネストされたルートごとにレイアウトを定義できます。- 共通レイアウトやネストされたレイアウトを簡単に構成可能です。
- 新しいデータ取得の方法:
getStaticProps
やgetServerSideProps
の代わりに、use
フックや React の標準 API を使用してデータを取得します。- コンポーネント単位でデータフェッチのタイミングを柔軟に制御可能です。
- ディレクトリベースのルーティング:
app
ディレクトリを使用してルーティングを行います。- 例:
app/about/page.js
は/about
に対応しています。
利点
- 高い柔軟性とモジュール化:
- レイアウトやデータ取得の管理がしやすく、再利用性が高いです。
- パフォーマンスの向上:
- サーバーコンポーネントを使用することで、初期ロードの時間を短縮し、ユーザーにとっての体感速度が向上します。
- 階層化されたルーティング:
- ネストされたルートとレイアウトの管理が簡単で、複雑なアプリケーション構造に対応しやすいです。
欠点
- 学習コストが高い:
- サーバーコンポーネントや新しいデータ取得の仕組みを理解する必要があり、従来の
Pages Router
よりも学習コストが高いです。
- サーバーコンポーネントや新しいデータ取得の仕組みを理解する必要があり、従来の
- 互換性のないライブラリがある:
- 一部のライブラリやツールは、従来のPages Routerに依存している可能性があり、App Routerとの互換性が保証されていない場合があります。
App Router を使うべき場面の具体例
- 大規模な Web アプリケーション:
- ダッシュボードや管理画面、EC サイトなど、複雑な画面構成と大量のデータを扱うアプリケーションに最適です。サーバーコンポーネントを活用し、データフェッチをサーバー側で処理することで、クライアントの負荷を軽減し、パフォーマンスを向上させられます。
- 動的なデータが多いアプリケーション:
- ユーザーごとに異なるデータを表示するようなアプリケーション(例えば、ユーザーごとの設定ページやダッシュボードなど)では、サーバーサイドでのデータ取得が柔軟に行える
App Router
が適しています。サーバーコンポーネントとクライアントコンポーネントを組み合わせることで、データ取得と表示を最適化できます。
- ユーザーごとに異なるデータを表示するようなアプリケーション(例えば、ユーザーごとの設定ページやダッシュボードなど)では、サーバーサイドでのデータ取得が柔軟に行える
- 多階層のレイアウトが必要なアプリケーション:
- 複数のレイアウトがネストされているアプリケーション、例えばマルチテナント型のアプリケーションや、管理画面とユーザー向け画面で異なるレイアウトを持つ場合、
App Router
の柔軟なレイアウト管理機能を活用することで、開発が容易になります。
- 複数のレイアウトがネストされているアプリケーション、例えばマルチテナント型のアプリケーションや、管理画面とユーザー向け画面で異なるレイアウトを持つ場合、
- SSR と CSR の柔軟な切り替えが必要なアプリケーション:
- 一部のコンポーネントは SSR でレンダリングし、他の部分はクライアントサイドでインタラクティブに動作させたい場合に、
App Router
はサーバーコンポーネントとクライアントコンポーネントの混在ができるため、要件に応じて柔軟に切り替えが可能です。
- 一部のコンポーネントは SSR でレンダリングし、他の部分はクライアントサイドでインタラクティブに動作させたい場合に、
どちらを選ぶべきか?
Pages Router と App Router のどちらを選択するかは、プロジェクトの要件や開発チームのスキルセットに依存します。小規模な場合は「Pages Router」、大規模な場合は「App Router」が適しているのではと感覚的には感じています。
- 小規模でシンプルなアプリケーション:
- 学習コストを抑えたい、あるいは素早くプロトタイプを作成したい場合は、
Pages Router
が適していると考えています。
- 学習コストを抑えたい、あるいは素早くプロトタイプを作成したい場合は、
- 大規模で複雑なアプリケーション:
- 高い柔軟性やパフォーマンス、将来的な拡張性を重視する場合は、
App Router
が適していると考えています。
- 高い柔軟性やパフォーマンス、将来的な拡張性を重視する場合は、
Pages Router 利用者が App Router を使い始めて苦戦したポイント
これまで Pages Router を使用していたところから App Router を利用し始めた際、いくつか考え方の異なる点で戸惑いました。
- サーバーコンポーネントとクライアントコンポーネントの違い:
App Router
では、サーバーコンポーネントとクライアントコンポーネントを使い分ける必要があります。
これにより、クライアント側でしか使用できないフック(例:useState
やuseEffect
)が使えなくなるため、どのコンポーネントをどこで使用するかを十分に理解したうえで設計する必要があります。
この違いを理解し、使い分けることがあったため、苦戦しました。
- レイアウトの階層管理の複雑さ:
App Router
では、layout.js
を用いてレイアウトを管理しますが、これによりルートごとのレイアウトの階層構造を理解し、管理する必要があります。
ネストされたレイアウトが多くなると、どのページがどのレイアウトを使用しているのかを把握するのが難しくなりがちです。特にPages Router
のシンプルな構造に慣れていると、最初は煩雑に感じました。
しかし、慣れてくるとレイアウトのネストができるため、特定のページやページのグループごとに異なるレイアウトを適用することが容易で便利と感じるようになってきました。
- データフェッチの方法の変化:
getStaticProps
やgetServerSideProps
の代わりに、React のuse
フックや標準 API を使ったデータフェッチに慣れる必要があります。
特に、サーバーコンポーネントでのデータフェッチとクライアントコンポーネントでのデータフェッチの使い分けが難しく、どのタイミングでデータが取得されるかを理解するのに苦労しました。
- App Router 固有のファイル構成の理解:
App Router
では、page.js
、layout.js
、loading.js
、error.js
など、特定の役割を持つファイルを使い分ける必要があります。
これにより、各ファイルの役割を理解し、正しい場所に配置する必要があります。このファイル構成に慣れていなかったため、初めての設定時にどこに何を置くべきか迷いました。
慣れてくると、エラーハンドリング時のページ遷移などが容易となり、開発のしやすさに繋がっています。
まとめ
Next.js 13 で導入された App Router
は、従来の Pages Router
に比べて多くのメリットがありますが、使いこなすには学習コストが必要と感じています。Next.js の公式では App Router の使用が推奨されていますが、各プロジェクトの要件に応じて、どちらのルーティングシステムを採用するかを慎重に検討することが重要と考えています。