コンテンツへスキップ
アプリケーションの構築ルーティングローディングUIとストリーミング

ローディングUIとストリーミング

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

Loading UI

インスタントローディング状態

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

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

loading.js special file
app/dashboard/loading.tsx
export default function Loading() {
  // You can add any UI inside Loading, including a Skeleton.
  return <LoadingSkeleton />
}

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

loading.js overview

知っておくと良いこと:

  • サーバー中心のルーティングでも、ナビゲーションは即時です。
  • ナビゲーションは中断可能であり、別のルートにナビゲートする前に、ルートのコンテンツが完全にロードされるのを待つ必要はありません。
  • 新しいルートセグメントがロードされている間、共有レイアウトはインタラクティブなままです。

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

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

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

知っておくと良いこと:

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

ストリーミングとは?

ReactとNext.jsでのストリーミングの仕組みを理解するには、サーバーサイドレンダリング(SSR)とその制限を理解すると役立ちます。

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

  1. まず、特定のページのすべてのデータがサーバーでフェッチされます。
  2. 次に、サーバーはページのHTMLをレンダリングします。
  3. ページのHTML、CSS、およびJavaScriptがクライアントに送信されます。
  4. 生成されたHTMLとCSSを使用して、非対話型のユーザーインターフェイスが表示されます。
  5. 最後に、Reactはユーザーインターフェイスをハイドレートして、インタラクティブにします。
Chart showing Server Rendering without Streaming

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

ReactとNext.jsを使用したSSRは、できるだけ早く非対話型のページをユーザーに表示することで、認識されるローディングパフォーマンスを向上させるのに役立ちます。

Server Rendering without Streaming

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

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

How Server Rendering with Streaming Works

これにより、すべてのデータが読み込まれるのを待ってUIをレンダリングするのではなく、ページの一部をより早く表示できます。

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

Chart showing Server Rendering with Streaming

ストリーミングは、長いデータリクエストがページのレンダリングを妨げるのを防ぎたい場合に特に役立ちます。これは、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は、クライアントにUIをストリーミングする前に、generateMetadata 内のデータ取得が完了するのを待ちます。これにより、ストリームされた応答の最初の部分に <head> タグが含まれることが保証されます。
  • ストリーミングはサーバーレンダリングされるため、SEOに影響はありません。Googleのリッチリザルトテストツールを使用して、GoogleのWebクローラーにページがどのように表示されるかを確認し、シリアライズされたHTMLを表示できます (出典)。

ステータスコード

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

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