Menu

loading.js

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

Loading UI
app/feed/loading.tsx
TypeScript
export default function Loading() {
  // またはカスタムローディングスケルトンコンポーネント
  return <p>Loading...</p>
}

loading.js ファイル内では、軽量なLoading UIを追加できます。React Developer Toolsを使用してSuspense境界を手動で切り替えると便利かもしれません。

デフォルトでは、このファイルはServer Componentですが、"use client" ディレクティブを使用してClient Componentとしても使用できます。

リファレンス

パラメータ

Loading UIコンポーネントはパラメータを受け入れません。

動作

ナビゲーション

  • フォールバックUIはプリフェッチされるため、プリフェッチが完了していない場合を除き、ナビゲーションは即座に行われます。
  • ナビゲーションは中断可能です。つまり、ルートを変更するときにルートのコンテンツが完全に読み込まれるのを待つ必要がありません。
  • 共有レイアウトは、新しいルートセグメントが読み込まれている間、対話性を維持します。

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

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

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

loading.js特殊ファイル
app/dashboard/loading.tsx
TypeScript
export default function Loading() {
  // Loading内に任意のUIを追加できます。Skeletonを含むこともできます。
  return <LoadingSkeleton />
}

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

loading.jsの概要

SEO

  • Twitterbotなど、フルブラウザのようにJavaScriptを実行できない静的HTMLのみをスクレイピングするボットの場合、Next.jsはストリーミングUIの前にgenerateMetadataを解決し、メタデータは初期HTMLの <head> に配置されます。
  • それ以外の場合は、ストリーミングメタデータが使用される可能性があります。Next.jsは自動的にユーザーエージェントを検出して、ブロッキング動作とストリーミング動作の間で選択します。
  • ストリーミングはサーバーレンダリングされるため、SEOに影響しません。GoogleのRich Results Testツールを使用して、ページがGoogleのウェブクローラーにどのように表示されるか、およびシリアル化されたHTMLを確認できます(出典)。

ステータスコード

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

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

例えば、404ページがクライアントにストリーミングされるとき、Next.jsはストリーミングされたHTML内に <meta name="robots" content="noindex"> タグを含めます。これにより、HTTPステータスが200であっても、検索エンジンがそのURLをインデックス化するのを防ぎます。robots メタタグに関するGoogleのガイダンスを参照してください。

一部のクローラーは、これらのレスポンスを「ソフト404」とラベル付けする場合があります。ストリーミングの場合、ページはHTMLで明示的に noindex とマークされているため、インデックス化にはつながりません。

コンプライアンスまたは分析のために404ステータスが必要な場合は、リソースが応答本文がストリーミングされる前に存在することを確認して、サーバーがHTTPステータスコードを設定できるようにします。

このチェックをproxyで実行して、見つからないスラッグをnot-foundルートに書き換えるか、404レスポンスを生成できます。proxyチェックを高速に保ち、そこでフルコンテンツをフェッチすることを避けます。

レスポンス本文がストリーミングされるのはいつですか?

レスポンス本文は、Suspenseフォールバック(例えば、loading.tsx)がレンダリングされるか、Server ComponentがSuspense境界の下でサスペンドするときにストリーミングを開始します。notFound() をそれらの境界の前に、サスペンドする可能性のある await の前に配置します。

ストリーミングを開始するには、レスポンスヘッダーを設定する必要があります。これが、ストリーミング開始後にステータスコードを変更できない理由です。

ブラウザの制限

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

プラットフォームサポート

デプロイオプションサポート
Node.jsサーバーはい
Dockerコンテナはい
静的エクスポートいいえ
アダプタープラットフォーム依存

Next.jsをセルフホスティングする場合のストリーミングの設定方法について説明します。

Suspenseでのストリーミング

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

<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のドキュメントを参照してください。

バージョン履歴

バージョン変更内容
v13.0.0導入時期:loading