takepepeさんの新しい本『実践Next.js』を読んだのでメモ
AppRouterは使ったことがなかったので、この本で情報のキャッチアップをしたい
本の内容は4章まではAppRouterの基礎情報で、それ以降はかなり実践的なサンプルアプリの実装の話
自分としては以前からNext.jsのPagesRouterは使っていたので、あの機能はAppRouterではどうなるのかという差分を中心に読んでいった
全体的にかなり分かりやすくまとまっていたので、とても読みやすかった
以下はメモ
- ハイドレーション:任意のDOMにイベントハンドラーをアタッチすること
- Client Componentからimportされるコンポーネントや関連ファイルもブラウザ向けにバンドルされる
- 全部に"use client"をつける必要はない→親がClient Componentなら不要
- usePathnameを使うならClient Componentにする
- 汎用性の高いコンポーネントは親がServerかClientのどちらにもなりうるので、"use client"は最小限に留める
- fetch関数のデフォルトのキャッシュ設定
- 更新頻度が低い:静的データ(何も設定しなければこれとして扱われる)
- 更新頻度が高い:動的データ(
fetch(url, { cache: 'no-store' }
) を指定すると毎回取得する)
- devモードでサーバー立ち上げるとキャッシュの挙動が把握できないので、ビルドして起動する
→その前にキャッシュの破棄(.next/cache/fetch-cacheを消す)をすること - Routeのレンダリング
- 動的レンダリングRouteになる要因は3つ
import { notFound } form "next/navigation"
知らなかった- route.tsを使うとWeb APIになる
- global-error.tsはハンドリングされなかった例外が最後に行き着く場所("use client"が必要)
Route Groups:グルーピングのためにフォルダを作りたいが、パスの一部としたくないフォルダはフォルダ名を
()
で囲む- この下にlayout.tsxをとかおくと、それぞれのLayoutが適用される
- 全くリーティング対象にしたくない場合は
_
をフォルダ名の接頭辞につける(例:_components)
3.3 Parallel RoutesとIntercepting Routesは新しい考え方
- @を接頭辞につけたフォルダはURLのパスとして無視される
- 「slot」と呼ばれるノードがchildrenのようにpropsで渡される
- @配下のSubtreeと表示しているRoute Segmentが一致したらそのノードがレンダリングされる
- default.tsxは一致するまでの間のslotとして表示される(返すものがなければnullを返す)
- Intercepting RoutesはRouteを「横取り」するRoute定義でParallelと合わせると、@配下のSubtreeと表示しているRoute Segmentが一致したらそのRoutesを横取りする
- (.)とか (..) とか相対パスのように定義する
3.4 静的なメタデータはmetadataオブジェクトをexportすれば良い、動的の場合は
generateMetadata
関数をexportする4.1 page.tsxとroute.tsは同じフォルダに入れるとコンフリクトを起こす
4.2 画面と同様にビルド時に以下の要因が検出されると動的Route Handleとみなされる
- Dynamic Segment値の参照 (※第二引数にDynamicSegmentのparamsがある)
- Requestオブジェクトの参照(※第一引数にRequestオブジェクトがある)
- 動的関数の使用(cookies関数とか)
- GETとHEAD以外のHTTP関数のexport(POSTとか)
- Segment Config Optionsの指定( export const dynamic = "force-dynamic";)
- 4.3 Route Handlerの良いところはNext.js自身が認証認可機能を備えたWebサーバーなので、画面側からのリクエストにユーザー情報を含めなくてもCookieを頼りにログインユーザーを参照できる
- 6.4 Next.jsは「Incremental Cache」というデータ取得結果をキャッシュし、必要に応じて更新する組み込みキャッシュシステムが存在する。
→デフォルトでオン。一年間有効。 fetch("url", { next: { revalidate: 60 * 60 }})
で有効期間変更
このように有効期間を指定するRevalidateを Time-based Revalidation という- 6.6 cache関数を使うとfetch関数以外での「Requestのメモ化」ができる
- Reactコンポーネント内では使わないこと
- データ取得関数の引数はプリミティブ値でなければならない
import { cache } from "react"; ... export const getProfileFromScreenName = cache(() => {});
- 6.7 fetch関数以外のデータキャッシュをしたい場合は、 unstable_cache を使う
- fetchData: キャッシュされるデータを取得するための非同期関数
- keyPars: キャッシュを一意に識別するためのキーとして使われる文字列の配列
- options: キャッシュの動作を制御するオブジェクト
- Reactコンポー内で利用可能
import { unstable_cache }. from "next/cache"; ... const data = unstable_cache(fetchData, keyParts, options)();
ここまでが8章で、9章以降は別の機会に書く