本文へ移動
verified onnext@16.3.5react@19
最終検証日 2026-09-26
Next.js道場

Next.js の loading と Suspense。最小構成サンプル

待たせ方には2つあります。

動いているものを触る/demo/loading

ファイル構成

並んでいるのは、上の画面をいま動かしている本物のファイルです。名前を押すと中身が出ます。

ファイル構成
  • app/
app/layout.tsxBuild

全ページの外側。本物のプロジェクトでは html と body をここで書きます

import type { Metadata } from "next";
 
export const metadata: Metadata = {
  title: "待たせる画面の最小構成",
};
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return <main>{children}</main>;
}
.tsx
画面を返すファイル。HTML のような書き方ができます
.ts
画面を返さないファイル。処理とデータだけを置きます。ここに画面を書くと原因を名指ししないエラーで落ちます
Build
ビルド時に一度だけ動きます
Server
アクセスのたびにサーバーで動きます
Browser
利用者の手元で動きます

待たせ方は2つある

どちらも Client Component は要らない
書くもの待たせる範囲いつ出るか
loading.tsxページ全体そのページへ移るとき
Suspense囲んだ中だけそのページを描いている最中

loading.tsx はファイルを置くだけです。自分で Suspense を書く必要はありません。Next.js がそのページを囲んでくれます。

待たせる前に、待つ必要があるか

このサンプルには1行だけ、変わった行があります。

export const dynamic = "force-dynamic";

これが無いと、待ち時間はビルドの中で終わります。

実機で確かめました。この行を書く前は、0.6 秒の待ちがビルド時に消化され、出来上がった HTML に値が焼き込まれていました。開いた人は待ちません。待たせる話をする前に、そもそも待つ必要がなかったわけです。

遅い部分だけを囲む

<p>この行はすぐに出ます。</p>
 
<Suspense fallback={<p>この部分だけ読み込んでいます</p>}>
  <Slow />
</Suspense>

実機で確かめました。応答は 0.69 秒かかりますが、届く順番が違います。

1つ目に届いたもの   この行はすぐに出ます
2つ目に届いたもの   この部分だけ読み込んでいます     ← 待っている間の表示
3つ目に届いたもの   0.6秒かけて取ってきた値         ← 0.6秒後に追いついた

囲まなければ、この 0.6 秒のあいだページに何も出ません。囲めば、速い部分だけ先に出ます。

1回のリクエストで、何が順に届くか
  1. Server
    速い部分を先に送る

    遅い部分の場所には、待っている間の表示を入れておく。

  2. Browser
    先に届いた分を描く

    読める部分はここでもう読める。

  3. Server
    遅い部分が終わったら送る

    同じ1回の通信の続きとして届く。

  4. Browser
    その部分だけ差し替わる

    ページは開き直されない。

2つの使い分け

同じ「待たせる」でも、範囲が違う
ページ全体を待たせる
// app/loading.tsx を置くだけ
export default function Loading() {
  return <p>読み込んでいます</p>
}

移った瞬間に何か出る。ただし全部が揃うまで中身は出ない。

遅い部分だけを待たせる
// 遅いところだけ囲む
<p>すぐ出る部分</p>
 
<Suspense fallback={<p>待機中</p>}>
  <Slow />
</Suspense>

速い部分は先に出る。囲む範囲を小さくするほど、早く読める。

両方を書いて構いません。このサンプルは両方あります。移った瞬間は loading.tsx が出て、ページが描かれ始めると遅い部分だけが Suspense で待たされます。

待ち時間は短く

ここから足していくとき

  • 骨組みを見せる。fallback に四角を並べて、出来上がりの形を先に見せます
  • 失敗したときの表示。取得が失敗する経路には error.tsx を置きます。そちらは Client Component です
  • 囲む範囲を分ける。遅いものが複数あるなら、別々に囲むと早いものから出ます

囲む範囲を小さくするほど、読める時間が早くなります。ページ全体を囲むのは、いちばん粗い使い方です。

入れていないもの

このまま本番に持っていかないでください。省いてあるのは次の点です。

  • 本物の遅い処理。0.6秒待つふりをしているだけです
  • 失敗したときの表示。取得が失敗する経路を作っていません
  • 待ち時間の計測。どこで時間がかかったかは残していません
  • 骨組みの表示。四角を並べて待たせる形にはしていません

出典

このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。

理解できたか試す

では、このコードはどうなりますか。

error.tsx には use client が要りました。同じ予約ファイルの loading.tsx にサーバー専用の印を付けると、ビルドはどうなりますか。

この問題を解くこのテーマの問題 3 問