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

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() {
// スケルトンを含む、Loading内に任意のUIを追加できます。
return <LoadingSkeleton />
}

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

loading.js概要loading.js概要

Good to know:

  • サーバー中心のルーティングを使用してもナビゲーションは即座に行われます。
  • ナビゲーションは中断可能であり、ルートを変更してもルートのコンテンツが完全にロードされるのを待つ必要はありません。
  • 新しいルートセグメントがロードされても、共有レイアウトは対話可能なままです。

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

Suspenseによるストリーミング

loading.jsに加えて、独自のUIコンポーネントのためのSuspense境界を手動で作成することもできます。App Router は、Node.jsおよびEdgeランタイム向けに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をより小さなチャンクに分割し、サーバーからクライアントにそれらのチャンクを順次送信できます。

ストリーミングでサーバーレンダリングがどのように機能するかストリーミングでサーバーレンダリングがどのように機能するか

これにより、すべてのデータがロードされる前にページの一部を早く表示することができ、どのUIもレンダリングできないという事態を回避します。

ストリーミングは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に影響しません。