コンテンツにスキップ
アプリケーションの構築ルーティング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 Boundary を手動で作成することもできます。App Router は Suspense を使用したストリーミングをサポートしています。

知っておくと良いこと:

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

ストリーミングとは?

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 のウェブクローラーにページがどのように表示されるかを確認し、シリアライズされた HTML (ソース) を表示するには、Google の リッチリザルトテストツールを使用できます。

ステータスコード

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

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