1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Next.js14】App RouterにおけるServer/Client Componentsの使い分け+データフェッチについてのまとめ。

Last updated at Posted at 2024-12-20

Next.js14(AppRouter)における、Server ComponentsとClient Componentsの使い分け+データフェッチについて、学習目的で自分なりにまとめてみました。

間違いがありましたらご指摘いただけると助かります。

情報源は以下です。

⭐️Server Component

  • 基本的には、Server Componentを使用する。(デフォルト)
    • データフェッチが高速になる。(サーバーがAPIやデータセンターと物理的に近い位置になるから。)
    • クライアント側へのJavaScriptバンドルのサイズを減らして初期表示を早くするため。
    • SEOの向上
      • 完全なHTMLの状態でクライアントに表示される。
      • 初期表示が早くなる。
      • 動的メタデータ(ogpなど)が設定可能。
    • クライアントのスペックに依存しなくなる。
    • セキュリティの強化
      • サーバー側で実行される=クライアント側で漏洩しなくなる。

Server Componentでのデータフェッチ

  • データフェッチは基本的にServer Componentで行う。(Client Componentでは可能な限り行わない。)
    • 初回ページ読み込み速度の向上
    • SEOの向上
    • セキュア
    • キャッシュが利用できる

  • データフェッチは可能な限り末端コンポーネント(リーフ)で行い、Propsのバケツリレーをなくす。
    • トレードオフとして重複リクエストが発生しやすくなるため、Request Memoizationを利用する。(データフェッチ層に分離することで重複を保証させる)
    • N+1問題に気をつける
      • DataLoaderを使用して情報を一括取得し回避
        • https://dummyjson.com/users/?id=1&id=2&id=3…..
      • Eager Loadingパターンで回避
        • N+1の最初の1回のリスエストで関連する必要な情報を全て取得する。

  • 並行データフェッチング(コンポーネントを兄弟分割 or Promise.all())を可能な限り行う。
    • preloadパターン
      • 親子コンポーネントそれぞれで別のフェッチをしてる時は、ウォーターフォールになるため、子でのフェッチをあえて親側でも行うことで、親コンポーネントレンダリング時に並行フェッチすることができる。(子でのフェッチ時はRequest Memoizationが機能する。)
        • 例)親→fetch A, fetchBを並列で実行 子→fetchB(Request Memoizationにより重複リクエスト排除)

  • ユーザー操作に基づくデータフェッチと再レンダリング
    • Server ActionsとuseActionState(Client Components)を利用する。
    • router.replaceなどによってURLを更新しデータを取得する。

  • ストリーミングを使用する。
    • loading.tsx
    • Suspence
    • TTFBの短縮とLayoutShiftのデメリットのバランスを考える。
    • CumulativeLayout Shift(CLS)に注意。

  • 外部APIは細粒度なREST API(Chatty API)と相性が良い。
    • Server Componentsによってデータフェッチのコロケーションや分割が容易になり、コードやロジックの重複が発生しづらくなったため。
    • バックエンドチームには細粒度なREST APIが望ましいことを伝えるべき。

fetch()を使用

  • デフォルトはSSG(レスポンスがData Cacheにキャッシュされる)
  • オプションでSSR / ISR / SSG に変更可能
  • キャッシュ設定が簡単
  • Request Memoization(同一リクエストの重複排除)を適用できる
  • 同プロジェクトのAPIを呼び出す場合は、Route Handler(API)を作成する必要がある。
    • 通信回数が増えるため、APIを噛ませずにORMを直接使用した方が良い。
    • スマホアプリ等からもAPIを叩きたい場合やAPIを公開したい場合はあり。

ORMを使用(Prismaなど)

  • 基本的にfetch()を使用するより、ORMを使用してSever Componentsから直接DBをCRUDした方が通信回数が減る(APIを叩かなくて良い)ため良い。
  • ORMを使用した場合のData Cacheの設定はデフォルトでSSR。変更したい場合は、RouteHandler(API)を介してfetch()で呼びだすか、unstable_cacheを使用する。
  • Request Memoization適用外。
    • 使用したい場合は、React Cacehを使用する。

Server Componentでのデータフェッチにおけるデメリット

  • リアルタイム性に弱い。(状態管理を使用した楽観的UI更新などができない。)
    • Reactアプリケーションでは、クライアントコンポーネントからフェッチ+Reduxを更新して、画面を瞬時に更新する。みたいなことができたが、Server Componentでは難しい。
    • リアルタイム性を要する場面が多いアプリケーションではNext.jsのメリットが発揮できない。

  • ユーザー操作に基づいたデータフェッチに弱い。
    • Server ActionsとuseActionState(Client Components)を利用する必要がある。
    • router.replaceなどによってURLを更新しデータを取得する。(画面の一部のみに検索結果を出したい場合などに向いていない。)

⭐️Client Component

  • 可能な限り使わない。
    • Server Componentsを中心に設計し、必要に応じてClient Componentsを末端に配置したり、Compositionパターンで組み込んで実装を進めていくとよい。

  • ユースケース
    • Hooksを使用するとき(useState, useEffect等)
    • イベントハンドラを利用するとき(onClick, onChange等)
    • ブラウザAPIを利用するとき(localStorage, sessionStorage, window, document等)
    • Client Componentsを提供するサードパーティコンポーネントを利用するとき
    • RSC Payload転送量を減らしたいとき(重いCSSなどがある場合)
    • クライアント操作が多い
      • フォーム
      • 検索
      • タブ切り替え、ハンバーガーメニュー等

  • 子コンポーネントは自動的にClient Componentになる。
    • Client Componentは、Componentツリーの末端で使うと良い。
    • Compositionパターンを使えば回避できる。(Client ComponentのChildrenにServerComponentを渡す)

Client Componentでのデータフェッチ

  • 基本的には非推奨。できる限りServer Componentでデータフェッチをする。
    • パブリックなネットワークに公開されてしまうため。
    • JavaScriptのバンドルファイルが増加するため。
    • 実装コストが高い
      • サードパーティライブラリとNext.jsのキャッシュのrevalidate機能との統合が難しい。
      • サードパーティライブラリの学習コストが高い
      • API側のセキュリティ対策が必要

  • Client Componentでデータフェッチをする場合は、サードパーティライブラリを使用。(useEffect内でのfetch()はキャッシュの設定が難しいため、非推奨)
    • useSWR()
    • TanStack Query

  • Server Componentsでのデータフェッチ時と同様、並行データフェッチング(コンポーネント分割 or Promise.all())を可能な限り行う。

まとめ

以上です。
間違っている箇所等ありましたらご指摘いただけますと幸いです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?