サーバーコンポーネント
React サーバーコンポーネントを使用すると、サーバー上でレンダリングおよびオプションでキャッシュできる UI を作成できます。Next.js では、ルートセグメントごとにレンダリング作業がさらに分割され、ストリーミングと部分的なレンダリングが可能になり、3 つの異なるサーバーレンダリング戦略があります:
このページでは、サーバーコンポーネントの仕組み、使用するタイミング、および異なるサーバーレンダリング戦略について説明します。
サーバーレンダリングの利点
サーバー上でレンダリング作業を行うことには、いくつかの利点があります:
- データ取得:サーバーコンポーネントにより、データ取得をデータソースに近いサーバー側に移動できます。これにより、レンダリングに必要なデータを取得する時間を短縮し、クライアントが行うリクエスト数を削減できます。
- セキュリティ:サーバーコンポーネントを使用すると、トークンや API キーなどの機密データとロジックをサーバー上に保持し、クライアントに公開されるリスクを回避できます。
- キャッシュ:サーバー上でレンダリングすることで、結果を後続のリクエストや異なるユーザー間で再利用できます。これにより、各リクエストでのレンダリングとデータ取得の量を削減し、パフォーマンスとコストを改善できます。
- パフォーマンス:サーバーコンポーネントは、ベースラインからパフォーマンスを最適化するための追加ツールを提供します。例えば、完全にクライアントコンポーネントで構成されたアプリから始める場合、非インタラクティブな UI の部分をサーバーコンポーネントに移動することで、必要なクライアント側の JavaScript の量を削減できます。これは、インターネット接続が遅いまたは性能の低いデバイスを使用するユーザーにとって有益です。ブラウザがダウンロード、解析、実行する必要のあるクライアント側の JavaScript が少なくなるためです。
- 初期ページ読み込みと最初のコンテンツフル描画(FCP):サーバー上で、ページをレンダリングするために必要な JavaScript をクライアントがダウンロード、解析、実行するのを待つことなく、ユーザーがすぐにページを表示できる HTML を生成できます。
- 検索エンジン最適化とソーシャルネットワーク共有性:レンダリングされた HTML は、検索エンジンボットがページのインデックスを作成し、ソーシャルネットワークボットがページのソーシャルカードプレビューを生成するために使用できます。
- ストリーミング:サーバーコンポーネントを使用すると、レンダリング作業をチャンクに分割し、準備ができ次第クライアントにストリーミングできます。これにより、ユーザーはサーバー上で全ページがレンダリングされるのを待つことなく、ページの一部をより早く表示できます。
Next.js でのサーバーコンポーネントの使用
デフォルトでは、Next.js はサーバーコンポーネントを使用します。これにより、追加の設定なしに自動的にサーバーレンダリングを実装でき、必要に応じてクライアントコンポーネントを使用できます。
サーバーコンポーネントはどのようにレンダリングされるか?
サーバー上で、Next.js は React の API を使用してレンダリングを調整します。レンダリング作業は、個々のルートセグメントとサスペンスの境界に分割されます。
各チャンクは 2 つのステップでレンダリングされます:
- React は、サーバーコンポーネントを React サーバーコンポーネントペイロード(RSC ペイロード) と呼ばれる特殊なデータ形式にレンダリングします。
- Next.js は、RSC ペイロードとクライアントコンポーネントの JavaScript 命令を使用して、サーバー上で HTML をレンダリングします。
次に、クライアント上で:
- HTML は、ルートの高速で非インタラクティブなプレビューをすぐに表示するために使用されます - これは初期ページ読み込み時のみです。
- React サーバーコンポーネントペイロードは、クライアントとサーバーのコンポーネントツリーを調整し、DOM を更新するために使用されます。
- JavaScript 命令は、クライアントコンポーネントをハイドレートし、アプリケーションをインタラクティブにするために使用されます。
React サーバーコンポーネントペイロード(RSC)とは?
RSC ペイロードは、レンダリングされた React サーバーコンポーネントツリーのコンパクトなバイナリ表現です。これは、React がクライアントのブラウザの DOM を更新するために使用します。RSC ペイロードには以下が含まれます:
- サーバーコンポーネントのレンダリング結果
- クライアントコンポーネントをレンダリングする場所のプレースホルダーと、それらの JavaScript ファイルへの参照
- サーバーコンポーネントからクライアントコンポーネントに渡される任意のプロップ
サーバーレンダリング戦略
サーバーレンダリングには、スタティック、ダイナミック、ストリーミングの 3 つのサブセットがあります。
スタティックレンダリング(デフォルト)
スタティックレンダリングでは、ルートはビルド時またはデータ再検証後のバックグラウンドでレンダリングされます。結果はキャッシュされ、コンテンツデリバリーネットワーク(CDN)にプッシュできます。この最適化により、レンダリング作業の結果をユーザーとサーバーリクエスト間で共有できます。
スタティックレンダリングは、ルートにユーザー固有ではなく、ビルド時に知ることができるデータがある場合に有効です。例えば、スタティックブログ投稿や製品ページなどです。
ダイナミックレンダリング
ダイナミックレンダリングでは、ルートはリクエスト時に各ユーザー用にレンダリングされます。
ダイナミックレンダリングは、ルートにユーザー固有のデータや、リクエスト時にのみ知ることができる情報(クッキーや URL のサーチパラメータなど)がある場合に有効です。
キャッシュされたデータを持つダイナミックルート
ほとんどのウェブサイトでは、ルートは完全にスタティックまたは完全にダイナミックではありません - それはスペクトルです。例えば、一定間隔で再検証されるキャッシュされた製品データを使用し、キャッシュされていない個人化された顧客データも持つ e コマースページがあります。
Next.js では、キャッシュされたデータとキャッシュされていないデータの両方を持つダイナミックにレンダリングされるルートを持つことができます。これは、RSC ペイロードとデータが別々にキャッシュされるためです。これにより、リクエスト時にすべてのデータを取得するパフォーマンスへの影響を心配することなく、ダイナミックレンダリングを選択できます。
フルルートキャッシュとデータキャッシュの詳細を学びます。
ダイナミックレンダリングへの切り替え
レンダリング中にダイナミック APIまたはキャッシュされていないデータリクエストが検出された場合、Next.js は全ルートを動的にレンダリングします。以下の表は、ダイナミック API とデータキャッシングが、ルートをスタティックまたはダイナミックにレンダリングするかどうかにどのように影響するかをまとめています:
ダイナミック API | データ | ルート |
---|---|---|
No | キャッシュ済 | スタティックにレンダリング |
Yes | キャッシュ済 | ダイナミックにレンダリング |
No | 非キャッシュ | ダイナミックにレンダリング |
Yes | 非キャッシュ | ダイナミックにレンダリング |
上記の表では、ルートを完全にスタティックにするには、すべてのデータをキャッシュする必要があります。ただし、キャッシュされたデータとキャッシュされていないデータの取得の両方を使用するダイナミックにレンダリングされるルートを持つことができます。
開発者として、Next.js が使用される機能と API に基づいて各ルートに最適なレンダリング戦略を自動的に選択するため、スタティックとダイナミックレンダリングの間で選択する必要はありません。代わりに、特定のデータをキャッシュまたは再検証するタイミングを選択し、UI の一部をストリーミングすることもできます。
ダイナミック API
ダイナミック API は、(プリレンダリング中ではなく)リクエスト時にのみ知ることができる情報に依存します。これらの API のいずれかを使用することは、開発者の意図を示し、全ルートをリクエスト時に動的にレンダリングすることになります。これらの API には以下が含まれます:
ストリーミング
ストリーミングにより、サーバーからUIを段階的にレンダリングできます。作業はチャンクに分割され、準備ができ次第クライアントにストリーミングされます。これにより、ユーザーは全コンテンツのレンダリングが完了する前に、ページの一部をすぐに表示できます。
ストリーミングは、Next.jsのApp Routerにデフォルトで組み込まれています。これは、初期ページ読み込みのパフォーマンスと、全ルートのレンダリングをブロックする遅いデータフェッチに依存するUIの両方を改善するのに役立ちます。例えば、製品ページのレビューなどです。
loading.js
とReact SuspenseのUIコンポーネントを使用して、ルートセグメントのストリーミングを開始できます。詳細については、ローディングUIとストリーミングセクションを参照してください。