Next.js · LEARN AT YOUR OWN PACE今日も、一歩ずつ。

LESSON 10 · 約25分

いつ表示を作る? レンダリング入門

事前生成・リクエスト時の処理・ブラウザーの操作を分けて考えます。

コードを試す前に

基本演習はApp Router・JavaScript/JSX・Cache Components無効で進めます。11の有効化例は独立した発展実験です。01〜04は先に読んで、コードの実行は05の環境構築後に戻って試せます。

短い学習用の例です。各例は段階ごとの独立した例であり、全コードを一つのプロジェクトへ順に上書きして完成する形式ではありません。必要なファイル・依存関係・前提条件は注記に記載しています。

開発環境の準備を確認する →

このレッスンでわかること

  • 静的生成とリクエスト時処理を区別できる
  • Suspenseで遅い部分の待機UIを作れる

「場所」と「タイミング」は別の軸

Server Componentはサーバー側で実行する仕組みですが、実行タイミングはビルド時にもリクエスト時にもなり得ます。静的なURL、動的なURLという分類も、生成タイミングと同じではありません。

すべてを待たず、できた部分から届ける

ストリーミングでは、準備できたUIから順に届けます。Suspenseのfallbackで待ち時間を表現すると、ページの見出しを表示しながら遅い一覧を待てます。ページ単位の待機UIにはloading.jsxという規約もあります。

キャッシュ設定によって組み合わせが変わる

Cache Componentsを有効にすると、静的・キャッシュ済みの部分と、リクエスト時に完成する部分を組み合わせるモデルになります。オンとオフでは規則が違うので、「Next.jsは全部SSR」や「全部静的」と一括りにしないことが大切です。

開発時に待機表示を確かめる

app/page.jsx
import { Suspense } from 'react'
import { connection } from 'next/server'

async function LatestNotes() {
  await connection()
  // 待機UIを観察するためだけの、開発時限定の遅延です。
  if (process.env.NODE_ENV === 'development') {
    await new Promise((resolve) => setTimeout(resolve, 1500))
  }
  const response = await fetch('https://api.vercel.app/blog')
  if (!response.ok) throw new Error('読み込みに失敗しました')
  const posts = await response.json()
  return <ul>{posts.map((post) => <li key={post.id}>{post.title}</li>)}</ul>
}

export default function Page() {
  return (
    <main>
      <h1>最新の学習ノート</h1>
      <Suspense fallback={<p role="status">ノートを読み込み中…</p>}>
        <LatestNotes />
      </Suspense>
    </main>
  )
}

connection()以降をリクエスト時に処理する観察用の例です。npm run devで約1.5秒の人工的な待機を作ります。遅延は学習後に取り除いてください。ブラウザーの通信制限はサーバーから外部APIへの通信を遅くしないため、代わりに開発時の遅延を使います。

TRY IT YOURSELF

待つ範囲を設計する

  1. この観察用コードでnpm run devを起動する
  2. ページを開き直して見出しとfallbackの表示を確認する
  3. 開発時限定の遅延を取り除き、表示が変わるか比較する

できたらOK:遅い通信でも、ページの目的と待っている部分が分かる

QUICK CHECK

理解を確かめよう

Suspenseの主な役割は?

公式資料でもう少し詳しく

ここまで読めたら、ひとつ前進。