Closed29
nextjs の公式を読む(App Router)
ルーティングの基礎
App Router
- app ディレクトリで動作。
- 旧 Page Router の pages ディレクトリと併用可能
- 一部のみを App Router に移行するなどして部分的な移行が可能。
- Page Router より App Router が優先される
- Page Router と APp Router で URL の競合が発生する場合はビルド時にエラーが発生する
- デフォルトでは React Server Components が有効。
フォルダとファイルの役割
- フォルダはルートを定義するために使用する
- ファイルはUIを作成するために使用される。
ファイル規約
- layout 共有UI
- page ルートの一般公開
- loading ローディング
- not-found not-found
- error エラー
- global-error グローバルエラー
- route サーバーAPIエンドポイント
- template テンプレート 専用にリレンダリングされたレイアウトUI
- default 並行ルートのフォールバックUI
コロケーション
- ファイル規約以外のファイル(コンポーネント、スタイル、テストなど)をフォルダ内に配することが可能
ルートの定義
ルートの作成
- フォルダで URL セグメントを表現する
- app/dashboard/settings/ -> /dashboard/settings
- page ファイルを作成すると一般公開される
- .js, .jsx, tsx が拡張子として使用できる
ページとレイアウト
ページ
- page.js からコンポーネントをエクスポートすることでページを定義できる
- ページはデフォルトで Server Component になる。
- ページはデータフェッチができる
- レイアウトはデフォルトで Server Component
- Client Component に設定を変更することができる
レイアウト
- layout.js からコンポーネントをエクスポートすることで定義できる
- 子レイアウト、子ページを入力する
children
prop を受け取る - ナビゲーションの再、レイアウトは状態を保持し、インタラクティブで、 再レンダリングはしない
- レイアウトは入れ子にできる
- レイアウトはデフォルトで Server Component になる
- 親レイアウトと子の間でデータを渡すことはできない
- レイアウトは現在のルートセグメトにアクセスできない。
- useSelectedLayoutSegment / useSelectedLayoutSegments
- レイアウトはデフォルトで Server Component
- Client Component に設定を変更することができる
ルートレイアウト(必須)
- app ディレクトリにはルート・レイアウトが含まれていなければならない
- app ディレクトリのトップレベルで定義する
- html と body タグを含まなければならない
- ルートグループを使って複数のレイアウトを作成できる
- ルートレイアウトはデフォルトで Server Component
- Client Component に設定することはできない
ネスティングレイアウト
- セグメントがアクティブなときのみレンダリングされる
- ルート・レイアウトだけが html / body を含むことができる
テンプレート
- template.js からコンポーネントをエクスポートすることで定義できる
- ナビゲーションの際に子要素ごと新しいインスタンスを作成する
- DOM要素が再作成される
- ステートは保持されない
- エフェクトが再同期される
リンクとナビゲート
プリフェッチ
- Link コンポーネントがビューポートに表示されると自動的にプリフェッチする。
- スタティックルートではデフォルトで true。ルート全体がプリフェッチされキャッシュされる
- ダイナミックルートではデフォルトでは auto。loading.js のみがプリフェッチされ、30秒間キャッシュされる
- router.prefetch() を使う
- 本番でのみ有効
キャッシング
- キャッシュされるもの
- プリフェッチされたルートセグメント
- 訪問したルートの React Server Component Payload
部分レンダリング
- ナビゲーションによって変更されたルートセグメントのみがクライアントで再レンダリングされる
- 共有レイアウトは保持される
ソフトナビゲーション
- ブラウザのページ間遷移はハードナビゲーション
- state やスクロール位置、フォーカスされた要素はリセットされる
- Nextjs ではソフトナビゲーションを使用する
- state やスクロール位置、フォーカスされた要素は保持される
戻る・進む
- デフォルトでスクロール位置を維持する。
- キャッシュを再利用する
ルートグループ
ルートグループ
- () でフォルダ名を囲むことで作成できる
- フォルダをルートグループとしてマークすることで URL パスに含まれないようにすることができる
- パス構造に影響を与えずルートセグメントとプロジェクトファイルを論理的なグループに整理できる
- ルートグループ間で同じ URL パスを持たないようにする
- ルートグループでは URL パスに影響を与えないため、サブツリー以下が同じだとコンフリクトしてしまう
複数のルートレイアウトの作成
- トップレベルの layout.js を削除する
- ルートグループの中に layout.js を作成する
- html / body タグはそれぞれのルートレイアウトに追加する必要がある
- ルートレイアウトをまたがってナビゲートするとフルページ・ロードが発生する。
ダイナミックルート
ダイナミックルート
- [] でフォルダ名を囲む
- 値は layout/page/route/generateMetadata の params prop として取得できる
静的パラメーターの生成
- generateStaticParams
- ビルド時に自動的に静的ルートが生成される
- fetch は自動的にメモ化される
- 複数の generateStaticParams, Layouts, Pages で要求が1度だけ実施される
キャッチオールセグメント
- [...paramName]
- セグメントをすべてキャッチする
オプショナルキャッチオールセグメント
- [[..paramName]]
- パラメータを含まないルートにもマッチ
ローディング UI とストリーミング
インスタントローディングステート
- loading.js
- 同じフォルダ内の layout の中にネストされる
- pageファイルと子要素は自動的に Suspense でラップされる
サスペンスを使ったストリーミング
- 独自のUIコンポーネントに手動で Susppense を使用可能
- すべてのデータを待つことなくページの一部がより早く表示される
- TTFB と FCP 削減できる
SEO
- generateMetadata のデータ取得完了を待ってからストリーミングする
- レスポンスの最初に head タグが含まれることを保証する
ステータスコード
- ストリーミング時には 200 のステータスコードを返す
- redirect や notFound を使ってエラーや問題をクライアントに伝えることができるが、ステータスコードは更新できない
- SEO に影響しない
エラーハンドリング
- error.js からエクスポートされた React コンポーネントがフォールバックコンポーネントとして使用される
- ルートセグメントとそのネストした子要素を Error Boundary で自動的にラップする
- error が含まれる
- フォールバックエラーコンポーネントがアクティブな場合、Error Boundary より上のレイアウトは状態する
エラーからの回復
- props で渡される reset を使用することでエラーから回復することができる。
- 成功した場合、再レンダリングの結果で置き換えられる。
ネストされたルート / Layout エラー / Root Layout エラー
- エラーは最も近い親の Error Boundary で処理される。
- 同じセグメントの layhout コンポーネントでスローされたエラーを処理しない
- 親の階層に error.js を配置する
- Root Layout / template のエラーを処理するためには global-error.js を配置する
- global-error.js には html タグと body タグを定義する必要がある
サーバーエラーの処理
- エラーオブジェクトを最寄りの error.js ファイルに転送する
- 本番環境では機密情報は取り除かれる
- message と digest プロパティーのみ
- 本番環境では機密情報は取り除かれる
Parallel Routes
- @folder
- 同じ階層の layout に props として渡される
マッチしないルート
- ナビゲーション
- 以前のアクティブな状態をレンダリングする
- リロード
- 一致しないスロットの default.js をレンダリングを試み、それができない場合 404 をレンダリング
ルートハンドラー
- route.js
- page.js と同じルートに route.js ファイルを置くことはできない
- export async function GET(request: Request) {}
- サポートHTTPメソッド
- GET / POST / PUT / PATCH / DELETE / HEAD / OPTION
- 未サポートメソッドは 405 Method Not Allowed を返す
振る舞い
- GET メソッド内の fetch はデフォルトでキャッシュされる
キャッシュのオプトアウト
- GET で request を使用する
- GET 以外のHTTP メソッドを使用する
- Dynamic Functions (cookies, headers) を使用する
- Segment Config Option で dynamic mode を指定する
ミドルウェア
- プロジェクトルート(pages/app と同じ階層もしくは src の直下)に middleware.js を作成する
マッチングパス
- ミドルウェアはすべてのルートから呼び出される
- 呼び出される順序
- headers from next.config.js
- redirects from next.config.js
- Middleware (rewrites, redirects, etc.)
- beforeFiles (rewrites) from next.config.js
- Filesystem routes (public/, _next/static/, pages/, app/, etc.)
- afterFiles (rewrites) from next.config.js
- Dynamic Routes (/blog/[slug])
- fallback (rewrites) from next.config.js
マッチャー
- config.matcher を公開することで middleware が実行されるパスを指定できる
- 単一の文字列式か、配列で複数の文字列式を指定できる
- 完全な正規表現を使用可能
- matcher はビルド時に静的解析できるように定数である必要がある
-
-
で始まる必要がある - :で始まる名前付きパラメーターを含めることができる。
- 名前付きパラメーターには修飾子をつけることができる(*,?,+)
- /a/:path* で 0個以上のパスにマッチする
- /a
- /a/b
- /a/b/c
- /a/:path* で 0個以上のパスにマッチする
- /a/:path? で 0〜1個のパスにマッチする
- /a/:path?
- /a
- /a/b
- /a/:path?
- /a/:path+ で 1個以上のパスにマッチする
- /a/:path+
- /a/b
- /a/b/c
- /a/:path+
- () で囲まれた正規表現が使える /a/(.) は /a/:path と同じ
NextResponse
- 別のURL へ redirect する
- ディスプレイ URL を rewrite する
- API Routes, getServerSideProps, rewrite 先のヘッダを設定する
- レスポンスクッキーを設定する
- レスポンスヘッダーを設定する
クッキーを使う
- NextRequest.cookies / NextResponse.cookies を使ってクッキーへのアクセス、操作ができる
- 入力リクエスト
- get, getAll, set, delete, has, clear
- 出力レスポンス
- get, getAll, set, delete
ヘッダーを設定する
- NextReponse を使ってレスポンスヘッダとリクエストヘッダを設定できる
レスポンスを生成する
- Response もしくは NextResponse インスタンスを返すことで直接レスポンスを返せる。
アドバンシードミドルウェアフラグ
- skipTrailingSlashRedirect
- デフォルトのリダイレクトを無効化し、末尾のスラッシュを追加、もしくは削除できる
- skipMiddlewareUrlNormalize
- Next.jsの URL 正規化を無効化して、直接アクセスとクライアント遷移を同じにする
プロジェクトの構成とファイルの配置
- デフォルトで安全なコロケーション
- フォルダ階層はルート構造を定義するが、 page.js もしくは route.js が追加されるまで一般公開されない
- ルートが一般公開されている場合でも page.js や route.js が返すコンテツだけがクライアントに送信される
プロジェクト構成の機能
- プライベートフォルダ
- _ で始まるフォルダ名はプライベートフォルダになりルーティングから除外される
- _ で始まる URL を使用したい場合は %5F (_ の URLエンコード) を使用する
src ディレクトリ
- アプリケーションコード(app含む) を src ディレクトリに格納することも可能(オプション)
国際化
Data Fetching, Caching, and Revalidating
あとで読む
サーバーでの fetch
- ネイティブ fetch からキャッシュと再検証の動作を設定できるように拡張されている
- コンポーネントツリーをレンダリングする再 fetch リクエストを自動的にメモ化する
- route ハンドラーはコンポーネントツリーの一部でないのでメモ化されない
- RSC, Route Handler, Server Action では async/await と fetch を一緒に使える
Caching Data
- デフォルトでサーバー上のデータキャッシュに自動的にキャッシュする
- ビルド時、リクエスト時にフェッチされ、再利用される
- POST メソッドは Route Handler 内の fetch リクエスト以外の場合キャッシュされる
再検証
-
時間ベースの再検証
- fetch のオプションで next.revalidate オプションを使用してリソースのキャッシュ有効時間を設定する
- revalidate 変数に設定して公開する
- 静的なレンダリングルートに複数の異なる検証時間が設定された fetch リクエストがある場合、設定された最も短い時間で再検証される
- 動的なレンダリングルートに複数の異なる検証時間が設定された fetch リクエスがある場合、各フェッチリクエストは個別に再検証される
-
オンデマンドの再検証
- Route Handler / Server Action 内から revalidatePath / revalidateTag によって再検証できる
- fetch にオプションでタグ付けすることができる
- fetch('url', {next: { tags: ['tag']}})
- RouteHandler の場合はシークレットを使用して不正な再検証を防ぐ必要がある。
- データの再検証を試みてエラーが発生した場合は最後に生成されたキャッシュが使用される。次のリクエストで再検証する
-
キャッシュの除外
- fetch の cache: 'no-store' もしくは revalidate: 0 オプションを指定した場合
- cookies() や headers() を利用した後に fetch を使用する場合
- export const dynamic = "force-dynamic" オプションを使用した場合
- fetchCache オプションでキャッシュをスキップするように設定した場合
- The fetch request uses Authorization or Cookie headers and there's an uncached request above it in the component tree. →よく意味が分からない
サードパーティライブラリによるサーバー上のデータ取得
- CMS や ORM、データベースなどの fetch をサポートしないクライアントの場合 React の cache function を使用できる
- ルートセグメントが
- 静的な場合:キャッシュされる
- 動的な場合:リクエストごとに再フェッチされる
- next が提供する unstable_cache もある。
このスクラップは2023/11/18にクローズされました