メインコンテンツまでスキップ

Loading UIとストリーミング

特別なファイルloading.jsは、React Suspenseを使用して意味のあるLoading UIを作成するのに役立ちます。この規約を使用すると、ルートセグメントのコンテンツが読み込まれる間、サーバーから即時のローディング状態を表示できます。新しいコンテンツはレンダリングが完了すると自動的に入れ替わります。

Loading UILoading UI

即時のローディング状態

即時のローディング状態は、ナビゲーション時に即座に表示されるフォールバックUIです。スケルトンやスピナーなどのローディングインジケーター、またはカバーフォトやタイトルなどの将来の画面の小さくても意味のある部分を事前にレンダリングできます。これにより、ユーザーはアプリが応答していることを理解し、より良いユーザー体験を提供します。

フォルダ内にloading.jsファイルを追加してローディング状態を作成します。

loading.js特別なファイルloading.js特別なファイル
app/dashboard/loading.tsx
export default function Loading() {
// スケルトンを含む任意のUIをLoading内に追加できます。
return <LoadingSkeleton />
}

同じフォルダ内で、loading.jslayout.js内にネストされます。これにより、page.jsファイルとその下のすべての子が自動的に<Suspense>境界でラップされます。

loading.jsの概要loading.jsの概要

Good to know:

  • ナビゲーションは、サーバー中心のルーティングでも即時に行われます。
  • ナビゲーションは中断可能であり、ルートのコンテンツが完全に読み込まれるのを待たずに別のルートに移動できます。
  • 共有レイアウトは、新しいルートセグメントが読み込まれる間もインタラクティブなままです。

推奨事項: Next.jsがこの機能を最適化しているため、ルートセグメント(レイアウトとページ)にはloading.js規約を使用してください。

Suspenseを使用したストリーミング

loading.jsに加えて、自分のUIコンポーネント用に手動でSuspense境界を作成することもできます。App Routerは、Suspenseを使用したストリーミングをサポートしています。

Good to know:

  • 一部のブラウザはストリーミングレスポンスをバッファリングします。レスポンスが1024バイトを超えるまでストリーミングされたレスポンスが表示されない場合があります。これは通常、「Hello World」アプリケーションにのみ影響しますが、実際のアプリケーションには影響しません。

ストリーミングとは何か?

ReactとNext.jsでストリーミングがどのように機能するかを理解するには、**サーバーサイドレンダリング(SSR)**とその制限を理解することが役立ちます。

SSRでは、ユーザーがページを見て操作できるようになる前に完了する必要がある一連のステップがあります:

  1. まず、指定されたページのすべてのデータがサーバーで取得されます。
  2. 次に、サーバーがページのHTMLをレンダリングします。
  3. ページのHTML、CSS、およびJavaScriptがクライアントに送信されます。
  4. 生成されたHTMLとCSSを使用して非インタラクティブなユーザーインターフェースが表示されます。
  5. 最後に、Reactがユーザーインターフェースをハイドレートしてインタラクティブにします。
ストリーミングなしのサーバーレンダリングを示すチャートストリーミングなしのサーバーレンダリングを示すチャート

これらのステップは順次かつブロッキングであり、サーバーはすべてのデータが取得されて初めてページのHTMLをレンダリングできます。また、クライアントでは、ページ内のすべてのコンポーネントのコードがダウンロードされて初めてReactがUIをハイドレートできます。

ReactとNext.jsを使用したSSRは、ユーザーにできるだけ早く非インタラクティブなページを表示することで、見た目の読み込みパフォーマンスを向上させます。

ストリーミングなしのサーバーレンダリングストリーミングなしのサーバーレンダリング

しかし、サーバー上でのすべてのデータ取得が完了するまでページをユーザーに表示できないため、依然として遅い場合があります。

ストリーミングは、ページのHTMLを小さなチャンクに分割し、それらのチャンクをサーバーからクライアントに段階的に送信することを可能にします。

ストリーミングを使用したサーバーレンダリングの仕組みストリーミングを使用したサーバーレンダリングの仕組み

これにより、すべてのデータが読み込まれるのを待たずに、ページの一部を早く表示できます。

ストリーミングはReactのコンポーネントモデルと相性が良く、各コンポーネントをチャンクと見なすことができます。優先度の高いコンポーネント(例:製品情報)やデータに依存しないコンポーネント(例:レイアウト)は最初に送信され、Reactはハイドレーションを早く開始できます。優先度の低いコンポーネント(例:レビュー、関連製品)は、データが取得された後に同じサーバーリクエストで送信できます。

ストリーミングを使用したサーバーレンダリングを示すチャートストリーミングを使用したサーバーレンダリングを示すチャート

ストリーミングは、長いデータリクエストがページのレンダリングを妨げるのを防ぎたい場合に特に有益であり、Time To First Byte (TTFB)First Contentful Paint (FCP)を短縮できます。また、特に遅いデバイスでのTime to Interactive (TTI)の改善にも役立ちます。

<Suspense>は、非同期アクション(例:データ取得)を実行するコンポーネントをラップし、その間にフォールバックUI(例:スケルトン、スピナー)を表示し、アクションが完了したらコンポーネントを入れ替えることで機能します。

app/dashboard/page.tsx
import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'

export default function Posts() {
return (
<section>
<Suspense fallback={<p>Loading feed...</p>}>
<PostFeed />
</Suspense>
<Suspense fallback={<p>Loading weather...</p>}>
<Weather />
</Suspense>
</section>
)
}

Suspenseを使用することで、以下の利点があります:

  1. ストリーミングサーバーレンダリング - サーバーからクライアントへのHTMLの段階的なレンダリング
  2. 選択的ハイドレーション - Reactはユーザーの操作に基づいて、どのコンポーネントを最初にインタラクティブにするかを優先します

より多くのSuspenseの例と使用例については、Reactのドキュメントを参照してください。

SEO

  • Next.jsは、generateMetadata内でのデータ取得が完了するまで、UIをクライアントにストリーミングするのを待ちます。これにより、ストリーミングされたレスポンスの最初の部分に<head>タグが含まれることが保証されます。
  • ストリーミングはサーバーレンダリングされるため、SEOに影響しません。Googleのリッチリザルトテストツールを使用して、Googleのウェブクローラーにページがどのように表示されるかを確認し、シリアライズされたHTMLを表示できます(ソース)。

ステータスコード

ストリーミング時には、リクエストが成功したことを示すために200ステータスコードが返されます。

サーバーは、ストリーミングされたコンテンツ内でクライアントにエラーや問題を伝えることができます。たとえば、redirectnotFoundを使用する場合です。レスポンスヘッダーはすでにクライアントに送信されているため、レスポンスのステータスコードを更新することはできません。これはSEOに影響しません。