Sponsor
ChatHubChatHub Use GPT-4, Gemini, Claude 3.5 and more chatbots side-by-side
ここをクリック
Menu

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

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

Loading UI

即時ローディング状態

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

フォルダ内にloading.jsファイルを追加することでローディング状態を作成できます。

loading.js special file
app/dashboard/loading.tsx
TypeScript
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によるストリーミングをサポートしています。

補足:

  • 一部のブラウザはストリーミングレスポンスをバッファリングします。レスポンスが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

これにより、すべてのデータがロードされるのを待たずに、ページの一部を先に表示できるようになります。

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

ステータスコード

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

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