t0mmy

2020年12月30日に参加

学習履歴詳細

実践Next JS 3章 App Router の規約 読了

やったこと

  • 実践Next JS 3章 App Router の規約 読了

学んだこと

App Router では、予約済みの特殊なファイル(以下構成ファイル)が存在する。

構成ファイルの一覧は、以下を参照。

構成ファイル名は事前に決まっている。
つまり、構成ファイルとして決めれられている名前でファイルを作成すると、Next JS が自動で読み込んで、適用してくれる。

構成ファイルは、 Segment 別に定義できる。

構成ファイルを使用することで、Next JS の機能を活かした効率的な開発を実現できる。

Segment 構成ファイルの役割

構成ファイル名 役割 備考
loading ローディング UI を提供
not-found 404 UI を提供する next/navigationnotFound() 関数を呼び出すのが通例
error 何らかの例外を捕捉した場合の UI を提供する use client でのみ機能する
route web api を提供する
default Parallel Routes 用ファイル
global-error error 構成ファイルで捕捉できなかった例外用の UI を提供する use client でのみ機能する

Segment 構成フォルダ

予約済みの特殊なフォルダ(以下構成フォルダ)も存在する。
構成フォルダにて、Segment 構成をコントロールできる。

Dynamic Route Segment

パスに含まれるパラメータを参照できる。
パラメータ変数は、[slug] のように [] で埋め込む。

基本

[slug] という命名規約でフォルダを作成する。

Route(ディレクトリ構成) URL リクエストの例 params
app/blog/[slug]/page.tsx /blog/a {slug:'a'}
app/blog/[slug]/page.tsx /blog/b {slug:'b'}

Catch-all Segment

[...slug] という命名規約でフォルダを作成する。

[] から page.tsx までの間に存在する全パラメータを、配列として参照できる。

Route(ディレクトリ構成) URL リクエストの例 params
app/shop/[...slug]/page.tsx /shop/a {slug:['a']}
app/shop/[...slug]/page.tsx /shop/a/b {slug:['a,b']}

Optional Catch-all Segment

[[...slug]] という命名規約でフォルダを作成する。
Catch-all Segment の挙動に加えて、パラメータなしのリクエストにも対応できる。

Route(ディレクトリ構成) URL リクエストの例 params
app/shop/[[...slug]]/page.tsx /shop {}
app/shop/[[...slug]]/page.tsx /shop/a {slug:['a']}
app/shop/[[...slug]]/page.tsx /shop/a/b {slug:['a,b']}

Route Groups

以下の両方を満たすようなユースケースで使用する。

  • いくつかのコンポーネントを、フォルダでまとめたい
  • まとめ用フォルダは URL Path で扱いたくない

Route Groups を使用すると、フォルダの一部を URL Path から除外できる。

フォルダ名を (feature) のように () で囲むことで、Route Groups として認識され、URL Path の Segment として認識されなくなる。

// website を表現する "site" フォルダでまとめたコンポーネント
./src/app/(site)/photos/page.tsx
./src/app/(site)/categories/page.tsx

// 情報提供を表現する "static" フォルダでまとめたコンポーネント
./src/app/(static)/company-info/page.tsx
./src/app/(static)/privacy-policy/page.tsx

これにより、URL Path を参照するソースコードを変更することなく、フォルダによるグループ化を実現できる。

また、Route Group フォルダ (() で囲った名前のフォルダ)にも、構成ファイルを適用できる。

./src/app/(site)/layout.tsx           // (site)用 Layout
./src/app/(site)/photos/page.tsx      // (site)用 Layoutが適用される
./src/app/(site)/categories/page.tsx  // (site)用 Layoutが適用される

./src/app/(static)/layout.tsx                // (static)用 Layout
./src/app/(static)/company-info/page.tsx     // (static)用 Layoutが適用される
./src/app/(static)/privacy-policy/page.tsx   // (static)用 Layoutが適用される

Private Folder とコロケーション

コロケーション (co-location): 特定機能の関連ファイルをまとめること。

Route に影響を与えないフォルダを配置できる。
フォルダ名の先頭に _ をつけるだけ。

特定の Route でしか使用しないコンポーネントを、Route の近くに配置したい場合等で使用する。

/src/app/_components/page.tsx // ルーティング対象外
/src/app/page.tsx // メイン画面

Parallel Routes と Intercepting Routes

いずれも、ソフトナビゲーションを活用した UI の実装で使用する。

Parallel Routes 概要

複数のコンポーネントを、一つのレイアウト内で同時に(または条件付きで)レンダリングできる機能。

Parallel Routes の使い方

@users のように、先頭が @ で始まるフォルダ名を作成する。
この時、 @users を Slot と呼ぶ。

  • 言い換えると、 Slot は、 @xxx という命名規約によって機能する

slot 部分を除いた URL Path に一致するページをレンダリングする際に、 Parallel-routes も一緒にレンダリングされる。

./layout.tsx
./@users/accounts/pages.tsx // slot
./accounts/pages.tsx        // @users slot にヒットする

Slot は Segment として扱われない。
そのため、URL Path に影響を与えない。

Slot は、 Layout コンポーネントで受け取る。
受け取り方は、React Component の Children と同じように Props として受け取る。

export default Layout = (props:{
  children : React.ReactNode; // React Component の Children
  users: React.ReactNode;     // @users というフォルダの情報が渡される
}) => {
  ...
}

Slot フォルダ内で default.tsx を設定してい置くと、 Route Segment が表示されるまでの間、 default.tsx の内容がレンダリングされるようになる。

ユースケース

  • @user Slot と @admin Slot を作成し、権限に応じてレンダリング先を変更する(条件付きルート)
  • 後述する Intercepting-routes と組み合わせたモーダルの実装
  • など

公式ドキュメント: https://ja.next-community-docs.dev/docs/app-router/building-your-application/routing/parallel-routes

Intercepting Routes の概要

Route を横取りする Route 定義。
正しく言うと、現在のページのコンテキストを維持したまま、現在のレイアウト内でルートをロードできる。

モーダルがリンクを持つイメージ。

ソフトナビゲーション時のみ、 Intercepting-routes は機能する。

  • 画面リロードのようなハードナビゲーションでは発動しない

Intercepting Routes の使い方

(..) で始まる命名規約でフォルダを作成する。

Linux のディレクトリ指定とそっくりな挙動。

  • (.) は、同じ階層の Segment とマッチ
  • (..) は、一つ親の Segment とマッチ
  • (..)(..) は、二つ親の Segment とマッチ
  • (...) は、ルート app ディレクトリの Segment にマッチ
/feed/(..)photo/[id]/page.tsx // /photo/[id]/page.tsxの中身をインターセプト
/photo/[id]/page.tsx

公式ドキュメント: https://ja.next-community-docs.dev/docs/app-router/building-your-application/routing/intercepting-routes

Route のメタデータ

静的、および動的メタデータを定義する API が用意されている。
主に SEO の観点で重要となる。

静的・動的メタデータともに、基本的には Metadata オブジェクトを、任意の階層で Export することになる。

静的メタデータ

固定のメタデータを出力する。

Metadata オブジェクトを Export するだけ。

import type { Metadata } from 'next';

export const metadata:Metadata = {
  title:'hoge',
  description: 'fuga',
}

これで、レンダリング後の HTML に、メタデータが書き出される。

動的メタデータ

generateMetadata 関数経由で Metadata オブジェクトを Exportする。

export generateMetadata = async ({params}):Promise<Metadata> => {
  /** 任意の非同期処理 */
  return {
    title: asyncData.name,
    description: asyncData.description,
  }
}

メタデータの継承

Next JS では、親Segment から Route Segment までたどり、各メタデータと結合してくれる。
このため、全てのSegment でメタデータを設定する必要はない。

  • 親で定義したメタデータに挿入・上書きしていくイメージ

親から継承したメタデータは、 ResolvingMetadata 変数を使用することで参照できる。

Next.js

2024年05月19日(日)

2.0時間