サーバーコンポーネント
Reactサーバーコンポーネントを使用すると、サーバーでレンダリングおよびオプションでキャッシュできるUIを作成できます。Next.jsでは、レンダリング作業はルートセグメントによってさらに分割され、ストリーミングと部分的なレンダリングが可能になり、3つの異なるサーバーレンダリング戦略があります。
このページでは、サーバーコンポーネントのしくみ、使用する場合、およびさまざまなサーバーレンダリング戦略について説明します。
サーバーレンダリングの利点
サーバーでレンダリング作業を行うことの利点はいくつかあります。これらには以下が含まれます。
- データフェッチ: サーバーコンポーネントを使用すると、データフェッチをサーバーに、データソースの近くに移動できます。これにより、レンダリングに必要なデータの取得にかかる時間を短縮し、クライアントが必要とするリクエスト数を減らすことで、パフォーマンスを向上させることができます。
- セキュリティ: サーバーコンポーネントを使用すると、トークンやAPIキーなどの機密データとロジックをサーバー上に保持できるため、クライアントに公開するリスクを回避できます。
- キャッシング: サーバーでレンダリングすることで、その結果はキャッシュされ、後続のリクエストやユーザー間で再利用できます。これにより、各リクエストで実行されるレンダリングとデータフェッチの量を減らすことで、パフォーマンスを向上させ、コストを削減できます。
- パフォーマンス: サーバーコンポーネントは、ベースラインからパフォーマンスを最適化するための追加ツールを提供します。たとえば、完全にクライアントコンポーネントで構成されるアプリから始めて、UIの非インタラクティブな部分をサーバーコンポーネントに移動すると、必要なクライアント側のJavaScriptの量を削減できます。これは、インターネットが遅いユーザーや処理能力の低いデバイスのユーザーにとって有益です。ブラウザはダウンロード、解析、実行するクライアント側のJavaScriptが少なくて済みます。
- 最初のページ読み込みとFirst Contentful Paint (FCP): サーバーでは、ページのJavaScriptのダウンロード、解析、実行を待つことなく、ユーザーがすぐにページを表示できるようにHTMLを生成できます。
- 検索エンジン最適化とソーシャルネットワークの共有可能性: レンダリングされたHTMLは、検索エンジンのボットがページをインデックス付けし、ソーシャルネットワークのボットがページのソーシャルカードプレビューを生成するために使用できます。
- ストリーミング: サーバーコンポーネントを使用すると、レンダリング作業をチャンクに分割し、準備が整い次第クライアントにストリーミングできます。これにより、ユーザーはサーバーでページ全体がレンダリングされるのを待つことなく、ページの一部を早く見ることができます。
Next.jsでのサーバーコンポーネントの使用
デフォルトでは、Next.jsはサーバーコンポーネントを使用します。これにより、追加の設定なしでサーバーレンダリングを自動的に実装できます。必要に応じてクライアントコンポーネントの使用を選択できます。クライアントコンポーネントを参照してください。
サーバーコンポーネントはどのようにレンダリングされますか?
サーバーサイドで、Next.js はReactのAPIを使用してレンダリングをオーケストレーションします。レンダリング作業はチャンクに分割されます。個々のルートセグメントとSuspense Boundariesです。
各チャンクは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 | データ | ルート |
---|---|---|
なし | キャッシュ済み | 静的にレンダリング済み |
あり | キャッシュ済み | 動的にレンダリング済み |
なし | キャッシュされていない | 動的にレンダリング済み |
あり | キャッシュされていない | 動的にレンダリング済み |
上記の表では、ルートを完全に静的にするには、すべてのデータがキャッシュされている必要があります。ただし、キャッシュされたデータフェッチとキャッシュされていないデータフェッチの両方を使用する動的にレンダリングされたルートを持つことができます。
開発者として、静的レンダリングと動的レンダリングのどちらかを選択する必要はありません。Next.jsは、使用されている機能とAPIに基づいて、各ルートに最適なレンダリング戦略を自動的に選択します。代わりに、キャッシュするタイミングまたは特定のデータを再検証するタイミングを選択し、UIの一部をストリーミングすることもできます。
動的API
動的APIは、プリレンダリング中に事前に(事前に)知ることができない情報に依存しています。これらのAPIを使用すると、開発者の意図が示され、リクエスト時にルート全体が動的レンダリングに切り替わります。これらのAPIには以下が含まれます。
ストリーミング


ストリーミングを使用すると、サーバーからUIを段階的にレンダリングできます。作業はチャンクに分割され、準備が整い次第クライアントにストリーミングされます。これにより、ユーザーはコンテンツ全体がレンダリングを完了する前に、ページの一部をすぐに表示できます。


ストリーミングは、Next.js App Routerにデフォルトで組み込まれています。これにより、最初のページの読み込みパフォーマンスと、ルート全体のレンダリングをブロックする遅いデータフェッチに依存するUI(たとえば、製品ページのレビュー)の両方が向上します。
loading.js
とReact Suspenseを使用して、ルートセグメントのストリーミングを開始できます。詳細については、「Loading UI and Streaming」セクションを参照してください。
これは役に立ちましたか?