UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【技術本まとめ】実践Next.jsを読んでのメモ - Server Action とパフォーマンス

takepepeさんの新しい本『実践Next.js』を読んだので、Server Action あたりのメモ

読んでいて思ったのは、噂通りApp Routerではキャッシュの仕組みや、設計が大切だと思った

キャッシュを使って以下に早くユーザーに情報を届けるかが重要であるが、キャッシュ更新漏れによって、意図しない画面が気づかず出てしまうことが往々にしてありそう

なので設計時からキャッシュを意識した図やドキュメントが必要だなと感じた

最後の10章は各キャッシュの挙動が整理されていてすごく勉強になるので、これを使って実プロジェクトでも整理していきたい

以下はメモ

  • 9.1 Server Action とは、これまでFormによるデータ更新の実装をAPI Clientを介したAPIの呼び出しによって行ってきたが、これをFormから直接関数を呼び出せるようにする仕組み
    • action属性に非同期関数を渡す仕組みは「Progressive Enhancement」と呼ぶ
    • これにより、API Clientが不要になるのと、ハイドレーションが完了を待たなくても実行できる利点がある
    • 使うためには"use server"ディレクティブをファイルの上位か、関数のスコープの先頭で宣言する必要がある
    • それを普通にClient Componentや Server Componentからimportして使う
  • 9.2 On-demand Revalidationとは任意のタイミングでキャッシュを無効化するプロセス
  • 9.4 useFormStateはFormの状態を保持するHookで、Client Componentでのみ使用可能
    • const [ state, formAction] = useFormSate(fn, initialFormState);のように定義し、formActionをformのaction属性に指定する
    • initialFormStateはFormState型と合わせて使うのが良い(FormStateのプロパティにはerrorMessageなどをもつ)
    • fnは第一引数を FormState | null 型にし、関数がFormState型に適合するオブジェクトを返すようにPromiseを型注釈する決まりがある
  • 9.6 Web APIリクエストが成功する前提で、先んじてUIを更新する手法をOptimistic Update(楽観的更新)と呼ぶ
    • const [ optimisticState, addOptimistic] = useOptimistic(state, updateFn);のように定義する
    • stateにはuseStateなどで保持した状態を、updateFnには楽観的に更新した状態をマージして返す関数を渡す
    • updateFnは、第一引数に更新前の状態と、第二引数に更新する値をとる
    • addOptimisticは楽観的更新をするための関数
  • 9.7 Formのバリデーションにはaction属性に指定するformDispatch関数とは別に、onSubmitイベントにも関数を渡してClientバリデーションを行うようにする
  • 9.8 RevalidateのrevalidateTagは、タグ名が抽象的であれば無効化が楽だが、更新の必要ないページにも影響してしまうためデータソースアクセス効率が良くない。その一方で、タグ名が具体的であれば無効化が手間だが、更新のあったページだけ無効化できるのでデータソースアクセス効率が良い
  • 10.1 コンポーネントが必要とするデータをそのコンポーネント自身で取得することを「コロケーション」と呼ぶ
  • 10.2 fetch関数が動的関数とみなされた場合でも、強制的にキャッシュしたいば場合はfetch(url, { cache: 'force-cache', ... })を指定するとできる
    動的なページで部分的にキャッシュしたい時に利用する
  • 10.3 getServerSessionでは動的Routeになるので、useSessionを使って静的Routeにする方法もある
  • 10.4 SSGでは一つの静的Routeに対し3種のファイル「html, meta, rsc」が出力されており、これらをFull Routeキャッシュと呼ぶ
    • SSG Routeを実装するにはgenerateStaticParams関数を使用する
    • generateStaticParamsは非同期関数での定義が可能なので、DBからとってきた値を使うこともできる
    • ?page=2のようにsearchParamsを参照すると「動的Route」になってしまうので/categories/flower/2のようにURLを設計する
    • SSG Routeで生成された画面は一定期間キャッシュされ、キャッシュ期間はfetchに渡すrevalidate変数で指定ができる(Time-based Revalidation)
      ※page.tsx内でexport const revalidate = 10;としても、同様にキャッシュ期間が指定できる
  • 10.6 next/Imageを使用する際、LCP要素にpriorityPropsを追加すると画像に特別な優先度をつけることができる
  • next.config.mjsremotePatternsに信頼できる画像ホストを指定するとセキュアである
  • 画像キャッシュ期間はnext.config.mjsminimumCacheTTLに指定する(デフォルトでは画像に変化がない限り永続的)
    • minimumCacheTTLとサーバーmax-ageのうち、大きい方が採用される(s-maxageとmax-age両方がある場合はs-maxageが優先される)
    • 開発環境では.next/cache/imagesフォルダを削除するとキャッシュを無効にできる
    • キャッシュ状態はx-nextjs-cacheレスポンスヘッダーを参照すると判断できる