
今年初めにNext.js触れることになった時、調べてたやつ。
会社のプロダクトはPages Routerで作成しているものと、App Routerで作成しているものがあるので違いを知っておきたく。
App Routerとは
- Next.jsのバージョン13.4で安定版として登場したルーティングシステム
- React Server Components(RSC)を基盤としており、サーバーサイドでの処理を可能にすることで、従来のPages Routerよりもパフォーマンスの向上を図っている
- ディレクトリ構造ベースのルーティングシステム
Pages Routerからアップデートの想い
https://nextjs.org/blog/next-13-4#zero-setup-use-the-filesystem-as-an-api
フレームワークの利用が増えるにつれて、開発者がフレームワークを使って構築したいインターフェースの種類も増えてきた。
レイアウトの定義、UIの入れ子、ローディングとエラー状態の定義等、既存のルーターに後付けするのは難しかった。
フレームワークのあらゆる部分がルーターを中心に設計されなければならない。 ページ遷移、データのフェッチ、キャッシュ、データの変異と再検証、ストリーミング、コンテンツのスタイリングなどなど。
ルーターをストリーミングに対応させレイアウトのサポートを強化したいという要望を解決するため。
Pages Router とApp Routerの違い
| App Router | Pages Router | |
| ルーティング方式 | /app配下にファイル・ディレクトリを置く 1ディレクトリ=1ページ ルート:/app/page.js | /pages配下にルーティングの対象となるファイルやディレクトリを置く 1ファイル=1ページ ルート:/pages/index.js |
| 初期コンポーネント | サーバーコンポーネントとして設定 サーバー側でレンダリングし、クライアントに送信 ※getStaticProps,getServerSidePropsは不要となる ※ファイルの一行目に「use client」と記述することでクライアントコンポーネントとして機能させることもできる | クライアントコンポーネントとして設定 クライアント側でレンダリング |
| fetchしたデータ対応の変更 | データフェッチの際に自動でキャッシュする機能が備わっている →2回目以降のフェッチはキャッシュが利用できるためパフォーマンスの低下が起こりづらい ※自動キャッシュ機能が備わったことで親子間でのpropsによるデータの受け渡しが不要となった ・4つのキャッシュ | 同一のフェッチを繰り返す →パフォーマンスの低下 |
| メタデータの設定方法 | app/page.jsexport const metadata: Metadata = {もしくは export async function generateMetadata() { | /pages/index.js<Head> |
| リダイレクト | import { useRouter } from "next/navigation" | import { useRouter } from "next/router" |
| 共通コンポーネント | /app/layout.tsxのroot layoutが必ず必要。 | _app.js・・・全ページに必要な処理 _document.js・・・htmlタグやboduタグの定義を行う |
| その他 | ・特別な意味を持つファイルが追加 ・特別な意味を持つディレクトリが追加 layout.js,template.jsが登場 |
サーバーコンポーネントで処理する利点
App routerはデフォルトでサーバーコンポーネントとなっており、こちらを積極的に使用するべき
なぜか?
- データフェッチが高速になる
クライアントからデータを取得するよりもサーバー側から取得する方が処理が早い。(APIやデータセンターと物理的に近い位置にあるから) - サーバー側でレンダリングされる(SSR)されるのでJSバンドルサイズが削減される
クライアントサイドでのJSの実行やDOM操作が発生しないから初期表示やパフォーマンスの改善をすることができる (JSバンドルサイズ(クライアント側で処理するJS総量)が大きいと初期ロードに時間がかかるため、なるべく、サーバー側で処理をしてクライアント側での負荷を減らしたい。クライアントコンポーネントはJSバンドルに含まれてくる) →サーバーコンポーネントはRSC Payloadとして転送されるため、転送量が多くなる - クライアントのスペックにほぼ依存しなくなる
サーバー側で処理した結果をクライアントで表示するので、PCやSPの端末のスペックに依存しにくくなる - SEOの向上
・完全なHTMLの状態でクライアントに表示される(サーバー側で構築し完全な状態でクライアントに渡される→クローラに完全な状態で見せることができる)
・ページ表示速度が向上する
・動的メタデータ設定が可能 - セキュリティの強化
サーバー側で実行される=クライアント側で漏洩しにくくなる
サーバーコンポーネントでやるべきこと
- APIやDBからのデータ取得 → サーバーから直接呼ぶので、
- 秘密鍵(APIキーなど)を安全に保持できる
- サーバー → サーバー通信なので高速
- ブラウザに余計なJSを送らなくて済む(軽い)
- 例:
- 初期表示の天気データ取得
- DBからユーザー情報を引っ張って SSR
クライアントコンポーネントでやるべきこと
- ユーザーの操作に応じた処理 → ブラウザで実行されるので、
onClick,onChangeなどのイベントを処理できるuseState,useEffectが使える
- 例:
- 「検索ボタンをクリックして天気を更新」
- 「フォームに入力した都市を状態管理」
- 「グラフの表示を切り替える」
Pages RouterとApp Routerのディレクトリ構成
Pages Router
Pages Routerでは/pagesディレクトリは以下のファイル構造がURLの構造になる
- 1ファイル=1ページ
- ファイル名がURLになる
- pasesフォルダ内使用
pages/
├── _app.tsx # グローバルレイアウト (Client Component)
├── index.tsx # ルート: / (Client Component)
├── about.tsx # ルート: /about (Client Component)
├── products/
│ ├── index.tsx # ルート: /products (Client Component)
│ └── [id].tsx # ルート: /products/[id] (Client Component)
└── api/
└── products.tsx # API route: /api/products
components/
├── Header.tsx # 共通ヘッダー (Client Component)
├── Footer.tsx # 共通フッター (Client Component)
├── ProductList.tsx # 製品リスト (Client Component)
└── ProductFilter.tsx # 製品フィルター (Client Component)App Router
ディレクトリ切ってその中にpages.tsxを作成する
app
└── (Auth) # ルートグループ。URLには影響しないが、関連するページをグループ化する
├── layout.tsx # 共通化したいレイアウトを定義する
└── signin
└── page.tsx # /signinにアクセスした際に表示する内容を定義するappフォルダ内のファイルの意味
app/
├── page.js --> 一番最初に読み込まれるファイル
├── route.js --> APIの定義(page.jsと共存不可)
├── layout.js --> 共通の見た目
├── loading.js --> 読み込み中の画面
├── error.js --> エラー時の画面
├── global-error.js --> グローバルエラー画面
├── templete.js --> 共通の見た目
├── default.js --> デフォルトの画面
└── not-found.js --> notFound関数がスローされたときの画面参考:
https://zenn.dev/blueish/articles/4b2ae3781ade57
https://rakuraku-engineer.com/posts/nextjs-app/
c.sakyou