サーバーコンポーネント

React サーバーコンポーネントを使用すると、サーバーでレンダリング可能な UI を作成でき、オプションでキャッシュも可能です。Next.js では、レンダリング作業がルートセグメントごとに分割され、ストリーミングと部分的なレンダリングが可能になります。また、3つの異なるサーバーレンダリング戦略があります:

このページでは、サーバーコンポーネントの動作方法、使用するタイミング、およびさまざまなサーバーレンダリング戦略について説明します。

サーバーレンダリングの利点

サーバーでレンダリング作業を行うことには、次のような利点があります:

  • データフェッチ (Data Fetching): サーバーコンポーネントを使用すると、データフェッチをサーバーに移行し、データソースに近づけることができます。これにより、レンダリングに必要なデータの取得時間とクライアントが行う必要のあるリクエスト数を減らすことでパフォーマンスが向上します。
  • セキュリティ (Security): サーバーコンポーネントを使用すると、トークンやAPIキーなどの機密データやロジックをクライアントに公開するリスクなしにサーバー上に保持できます。
  • キャッシュ (Caching): サーバーでレンダリングすることで、結果をキャッシュし、後続のリクエストやユーザー間で再利用できます。これにより、各リクエストで行われるレンダリングとデータフェッチの量を減らすことで、パフォーマンスが向上し、コストが削減されます。
  • パフォーマンス (Performance): サーバーコンポーネントは、ベースラインからパフォーマンスを最適化するための追加ツールを提供します。たとえば、完全にクライアントコンポーネントで構成されたアプリから始める場合、非インタラクティブなUI部分をサーバーコンポーネントに移行することで、必要なクライアントサイドJavaScriptの量を減らせます。これは、インターネットが遅いユーザーや処理能力が低いデバイスにとって有益で、ブラウザがダウンロード、解析、実行するクライアントサイドJavaScriptが少なくなります。
  • 初期ページロードと First Contentful Paint (FCP): サーバー上でHTMLを生成できるため、ユーザーはページを即座に表示でき、クライアントがページをレンダリングするために必要なJavaScriptをダウンロード、解析、実行するのを待つ必要がありません。
  • 検索エンジン最適化 (SEO) とソーシャルネットワーク共有: レンダリングされたHTMLは、検索エンジンボットがページをインデックスしたり、ソーシャルネットワークボットがページのソーシャルカードプレビューを生成するために使用できます。
  • ストリーミング (Streaming): サーバーコンポーネントを使用すると、レンダリング作業をチャンクに分割し、準備ができ次第クライアントにストリーミングできます。これにより、ユーザーはサーバーでページ全体がレンダリングされるのを待たずに、ページの一部を早期に表示できます。

Next.js でのサーバーコンポーネントの使用

Next.js では、デフォルトでサーバーコンポーネントが使用されます。これにより、追加の設定なしで自動的にサーバーレンダリングを実装でき、必要に応じてクライアントコンポーネントを使用することを選択できます。詳細は クライアントコンポーネント を参照してください。

サーバーコンポーネントのレンダリング方法

サーバー上では、Next.js は React の API を使用してレンダリングを調整します。レンダリング作業は個々のルートセグメントと Suspense Boundaries によってチャンクに分割されます。

各チャンクは2つのステップでレンダリングされます:

  1. React はサーバーコンポーネントを React Server Component Payload (RSC Payload) と呼ばれる特別なデータ形式にレンダリングします。
  2. Next.js は RSC Payload とクライアントコンポーネントの JavaScript 命令を使用して、サーバー上で HTML をレンダリングします。

次に、クライアント側では:

  1. HTML はルートの高速な非インタラクティブプレビューを即座に表示するために使用されます - これは初期ページロードのみです。
  2. React Server Components Payload は、クライアントとサーバーコンポーネントツリーを調整し、DOM を更新するために使用されます。
  3. JavaScript 命令は、クライアントコンポーネントを ハイドレート し、アプリケーションをインタラクティブにするために使用されます。

React Server Component Payload (RSC) とは?

RSC Payload は、レンダリングされた React サーバーコンポーネントツリーのコンパクトなバイナリ表現です。React がクライアントでブラウザの DOM を更新するために使用します。RSC Payload には以下が含まれます:

  • サーバーコンポーネントのレンダリング結果
  • クライアントコンポーネントがレンダリングされるべき場所のプレースホルダーとそれらのJavaScriptファイルへの参照
  • サーバーコンポーネントからクライアントコンポーネントに渡されるプロパティ

サーバーレンダリング戦略

サーバーレンダリングには、静的、動的、ストリーミングの3つのサブセットがあります。

静的レンダリング (デフォルト)

静的レンダリングでは、ルートは ビルド時 または データ再検証 後にバックグラウンドでレンダリングされます。結果はキャッシュされ、Content Delivery Network (CDN) にプッシュできます。この最適化により、レンダリング作業の結果をユーザー間やサーバーリクエスト間で共有できます。

静的レンダリングは、ユーザーごとにパーソナライズされていないデータがあり、ビルド時に既知であるルート(静的ブログ投稿や商品ページなど)に有用です。

動的レンダリング

動的レンダリングでは、ルートは各ユーザーに対して リクエスト時 にレンダリングされます。

動的レンダリングは、ユーザーごとにパーソナライズされたデータがあるルートや、リクエスト時にのみ知り得る情報(クッキーやURLの検索パラメータなど)があるルートに有用です。

キャッシュされたデータを持つ動的ルート

ほとんどのウェブサイトでは、ルートは完全に静的でも動的でもありません - それは連続体です。たとえば、一定間隔で再検証されるキャッシュされた商品データを使用するが、キャッシュされていないパーソナライズされた顧客データもあるeコマースページを持つことができます。

Next.js では、キャッシュされたデータとキャッシュされていないデータの両方を持つ動的にレンダリングされるルートを持つことができます。これは、RSC Payload とデータが別々にキャッシュされるためです。これにより、リクエスト時にすべてのデータをフェッチすることによるパフォーマンスへの影響を心配することなく、動的レンダリングを選択できます。

フルルートキャッシュデータキャッシュ について詳しく学びます。

動的レンダリングへの切り替え

レンダリング中に 動的関数 または キャッシュされていないデータリクエスト が検出されると、Next.js はルート全体を動的にレンダリングするように切り替えます。この表は、動的関数とデータキャッシュがルートの静的または動的レンダリングにどのように影響するかをまとめたものです:

動的関数データルート
なしキャッシュ済静的レンダリング
ありキャッシュ済動的レンダリング
なし未キャッシュ動的レンダリング
あり未キャッシュ動的レンダリング

上記の表で、ルートが完全に静的であるためには、すべてのデータがキャッシュされている必要があります。ただし、キャッシュ済みと未キャッシュのデータフェッチの両方を使用する動的にレンダリングされるルートを持つことができます。

開発者として、静的レンダリングと動的レンダリングの間で選択する必要はありません。Next.js は使用される機能と API に基づいて各ルートに最適なレンダリング戦略を自動的に選択します。代わりに、特定のデータをキャッシュまたは再検証するタイミング を選択し、UIの一部を ストリーミング することを選択できます。

動的関数

動的関数は、ユーザーのクッキー、現在のリクエストヘッダー、URLの検索パラメータなど、リクエスト時にのみ知り得る情報に依存します。Next.js では、これらの動的関数は:

  • cookies()headers(): サーバーコンポーネントでこれらを使用すると、ルート全体がリクエスト時に動的レンダリングに切り替わります。
  • searchParams: PagesearchParams プロパティを使用すると、ページがリクエスト時に動的レンダリングに切り替わります。

これらの関数のいずれかを使用すると、ルート全体がリクエスト時に動的レンダリングに切り替わります。

ストリーミング

ストリーミング中のルートセグメントの並列化を示す図。個々のチャンクのデータフェッチ、レンダリング、ハイドレーションを示しています。

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

クライアント側で部分的にレンダリングされたページを示す図。ストリーミング中のチャンクのローディングUIが表示されています。

ストリーミングは Next.js の App Router にデフォルトで組み込まれています。これにより、初期ページ読み込みパフォーマンスと、ルート全体のレンダリングをブロックする遅いデータフェッチに依存するUIの両方が改善されます。たとえば、商品ページのレビューなどです。

loading.jsReact Suspense を使用して、ルートセグメントのストリーミングを開始できます。詳細については、ローディングUIとストリーミング セクションを参照してください。