Next.js13.4から正式実装になったApp Routerを使うためのメモ。
第三回はルーティングの基礎、の基礎の基礎。
詳細は以下の公式で。
基本的には公式ページを読んでもらえればわかること。
App Router
Appルーターの一番最初に出てくる基本的なことが、「React Server Components」。
サーバー上ですでにレンダリングしてあるものをユーザーに渡すことでページが表示される。
Next.jsでは、ビルドした時(静的レンダリング)、リクエストがあった時(ダイナミックレンダリング)、リクエストがあった時に分割して(ストリーミング)の三つが用意されており、デフォルトでは静的レンダリングになっている。
基本的には、コンポーネントで明示しない限り、APP Router内のコンポーネントは全てサーバーコンポーネントになる。
というのが、まず前提条件。
appディレクトリの基礎
Next.jsをApp Router仕様でインストールすると、最初に以下のようなファイル構成になる。
└─ src └─ app ├─ favicon.ico ├─ globals.css ├─ layout.tsx └─ page.tsx
appディレクトリ内にある物が、ルーティングの対象になる。
appディレクトリ直下のpage.tsxが、トップページになる。pagesディレクトリの時はindex.tsx
だったが、appディレクトリではpage.tsx
になるのが大きな違い。
pagesディレクトリとの併用もできるが、ルーティング的にはappディレクトリが優先される。
フォルダはルート
例えば、以下のように、app配下にaboutフォルダを作り、その中にpage.tsxを作ると、○○.com/about
がURLパスになる。
└─ app ├─ about │ └─ page.tsx └─ page.tsx
ネストを複数作ることも可能。aboutの下にtestを作ってpage.tsxを作れば、○○.com/about/test
になる。
ファイル名には意味がある
page.tsxという名称に意味があり、このファイル名にすることで、すぐ上のフォルダ名でパスが作られる。
それと同じように、Next.jsですでに予約されているファイル名がある。
詳細は以下の公式を確認。
エラー系やAPIエンドポイントなども用意されているので結構便利。
ページのデザインに直接かかわってくるのはlayout
。
pageルーターの_app.tsx
みたいなものだが、いろいろ便利になっている。
例えば以下のような構成の場合。
└─ app ├─ page.tsx ├─ layout.tsx └─ about └─ page.tsx
layout.tsx
で作ったレイアウトは同階層のpage.tsx
にも、aboutのpage.tsx
にも反映される。
親フォルダ内にある「ファイル名に意味のあるもの」は、子のフォルダに引き継がれ、子は親にネストされるのが特徴。
全ページ共通のヘッダーなどは、一番上の階層でlayout.tsx
内に含めると、子に全て反映されるということになる。
ちなみにappディレクトリ内のlayout.tsx
は必須。
ルート内でのデザイン共通化がとても楽になるが、ルート内でも個別にデザインを切り替えたい時は注意が必要。ルートの決め方でファイル構成は大きく変化することになる。
最初からデザインを細かく決めて作り出したプロジェクトの場合は良いが、その後にいろいろ変化させようとすると結構大変。
とりあえず動くものをさっと作ろうとする場合、デザインを一括にして手間暇少なく作れるので、それは楽。
astroとかに少し似ているけど、astroや他のフレームワークみたいにslot
が使えないので、汎用性は高くない。コンポーネントとしてReactの記述がされているコードのchildren
は1つだけというのが、Reactの宿命でもある、ということなのか。
astroのslot
のような機能があれば、layout.tsx
はかなり使いやすくなるのだけど、現状では複雑なコンポーネント分けなどができないので、いろんなレイアウトにしたい場合はlayout.tsxはちょっと使いにくい。ブログみたいにルートの全てが同じレイアウトなサイトには便利そうな機能。
作るときに、共通の部分とそうでない部分をきっちり分けておけばlayout.tsx
はかなり便利だと思うけど、作ってるとそうはいかなくなることが多い、という印象ではある。
コロケーション
コロケーションという概念を近年見るようになったが、非常に大雑把にいってしまうのならば、関連するのものはできるだけ近くに置く、という意味。
appディレクトリ内にフォルダを作って、その中にappディレクトリのpage.tsxやlayout.tsxで使うコンポーネントなどを保存しておくということができる。
└─ app ├─ components │ └─ button.tsx │ ├─ page.tsx └─ layout.tsx
例えばボタンのコンポーネントをapp配下のcomponents
フォルダに保存することができる。
フォルダの中にpage.tsx
がないとルーティング対象にならないので、上のbutton.tsx
はページとしては作成されない。
フォルダを明示的にルーティングの対象から外すという指定もできる。プライベートフォルダーという機能。フォルダ名の前に_
を入れるだけ。
└─ app ├─ _components │ └─ button.tsx │ ├─ page.tsx └─ layout.tsx
_components
配下は子のフォルダも含めて全てルーティングから除外される。
公式にも書いてあるが、appディレクトリ内の指定のファイル名のもの以外は、デフォルトでルーティングから除外されるので、プライベートフォルダを使う必要は実はない。
ないが、公式いわく、将来のNext.jsのファイル名規則との名前競合を回避できるなどの利点もある、などいくつか具体的な使う理由が上がっている。
フォルダが増えてくると、_
があるだけで、ルーティング対象ではないとわかるので、ついていたほうが管理はしやすい。
まとめ
Next.jsのAppルーターでは、既存のルーティングから結構変わっている。
以前は、ルーティング対象のフォルダabout
の中にindex.tsx
を作れば、それは.com/about
でアクセスできた。また、pages配下でabout.tsx
を作れば、それも.com/about
だった。
Appルーターで.com/about
ページを作るには、appフォルダ配下にabout
フォルダを作り、その中にpage.tsx
を作る、という形になった。
それ自体は難しくないし、対応するのも簡単だけど、プロジェクトのフォルダ構成自体は大きく変化することになる。
これで作る利点はルーティング対象が全部urlになるフォルダ名称で分けられているので、管理がしやすいこと。各ページ個別の部品は全て近くのフォルダ内に収めて管理できる。要はそのフォルダ内で完結できる。ただ、共通部品を使うとそうはならないのだけど。
欠点としては、VSCodeで複数のpage.tsxを開いていると、どれがどれだかわからなくなるところ。以前はファイル名が個別の意味も持っていたので、判別が楽だった。使っていないタブは閉じるというのが、間違いも少なくなるし、基本的なことではあるので、それを意識するしかなさそう。
また、layout.tsxには入れたくないけど、他の場所で使っているコンポーネントを使いたい、という時には結局管理が煩雑になる。個人で作る分には気にならないけど、複数人で作るのならば、きちんとしたルール付けが必要そう。というのは多分pageルーターでも変わらないと思うけど。