Next.js 15 の Streaming と Suspense を極める:パフォーマンスガイド
現代のウェブにおいて、パフォーマンスは単なる贅沢品ではありません。それはユーザー維持と SEO の成功を支える基盤です。Next.js 15 は、データ取得と UI レンダリングの処理方法を洗練させることで、この哲学を次のレベルへと引き上げました。React 19 の機能を深く統合することで、Next.js 15 は Streaming(ストリーミング) と Suspense(サスペンス) の洗練されたモデルを提供し、膨大なデータ負荷を扱う場合でも瞬時に動作するように感じられるアプリケーションを可能にします。
このガイドでは、Next.js 15 におけるアーキテクチャの進化、ストリーミングを効果的に実装する方法、そして Partial Prerendering (PPR) のような機能がなぜ「速さ」の境界を再定義しているのかを探ります。
Next.js における Streaming とは?
従来のサーバーサイドレンダリング (SSR) では、サーバーがページのすべてのデータを取得し、HTML 全体をレンダリングしてからクライアントに送信する必要がありました。この「全か無か」のアプローチはボトルネックを生んでいました。ユーザーは、最も遅いデータ取得が完了するまで、画面に何も表示されない状態で待たなければならなかったのです。
Streaming は、ページを小さな「チャンク(塊)」に分割します。これにより、サーバーはページの静的なシェルを即座に送信し、データが準備できた動的な部分を順次ストリーミングすることができます。
Streaming が重要な理由
- Time to First Byte (TTFB) の短縮: 静的な部分の準備ができ次第、サーバーは HTML の送信を開始します。
- First Contentful Paint (FCP) の向上: ユーザーはレイアウトやナビゲーションをほぼ瞬時に目にすることができます。
- 知覚パフォーマンスの改善: 空白の画面の代わりに「ローディングスケルトン」が表示されるため、アプリの反応がより速く感じられます。
Suspense Boundaries(境界)の実装
React Suspense は、Next.js におけるストリーミングを支えるメカニズムです。これにより、データ取得などの非同期アクションを実行するコンポーネントをラップし、そのアクションの実行中に表示するフォールバック UI を提供できます。
きめ細やかな(Granular)アプローチ
Next.js 15 で Suspense を使用する最も効果的な方法は、データ取得をコンポーネントレベルまで落とし込むことです。
// page.tsx
import { Suspense } from 'react';
import { ProductGallery } from './components/ProductGallery';
import { GallerySkeleton } from './components/Skeletons';
export default function Page() {
return (
<main>
<h1>最新トレンドをチェック</h1>
{/* 上部の静的コンテンツは即座にレンダリングされます */}
<Suspense fallback={<GallerySkeleton />}>
<ProductGallery />
</Suspense>
</main>
);
}
この例では、H1 タイトルとナビゲーション(レイアウトの一部である場合)は即座にユーザーに送信されます。ProductGallery コンポーネントはサーバー上で独自のデータを取得し、それが「一時中断(suspending)」されている間は GallerySkeleton が表示されます。
破壊的変更:Async Request APIs
Next.js 15 における最も重要なアップデートの一つは、リクエスト固有の API が非同期(asynchronous)に移行したことです。この変更は、Partial Prerendering のようなより強力な最適化をサポートするために必要でした。
以下の API は、Promise を返すようになりました:
cookies()headers()params(page/layout の props 内)searchParams(page の props 内)
適応方法:
// Next.js 15 での実装
export default async function Page({
params,
searchParams,
}: {
params: Promise<{ slug: string }>;
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}) {
const { slug } = await params;
const { query } = await searchParams;
return <div>投稿:{slug}</div>;
}
これらの API を非同期にすることで、Next.js はレンダリングプロセスをいつ「一時中断」するかをより適切に調整できるようになり、動的データが静的なセグメントの生成を妨げないようにしています。
Partial Prerendering (PPR):究極の最適化
Partial Prerendering は、静的レンダリングと動的レンダリングの長所を組み合わせた、Next.js 15 の試験的(experimental)機能です。
典型的な App Router の設定では、ルートは完全に静的か、完全に動的かのいずれかです。cookies() のような動的関数を使用すると、ルート全体が動的になります。PPR を使用すると、単一のルート内に静的な部分と動的な部分の両方を共存させることができます。
PPR と Suspense の仕組み
- Next.js は、ビルド時にページの静的な「シェル」を生成します。
- このシェルには、Suspense でラップされた部分以外のすべてが含まれます。
- ユーザーがページを訪れると、静的なシェルがエッジから即座に提供されます。
- Suspense でラップされた動的コンポーネントは「穴あき(holed out)」の状態であり、サーバーが処理を進めるにつれて埋められていきます。
これにより、静的サイトのような読み込み速度を持ちながら、完全に動的なアプリケーションのパワーを兼ね備えたページが実現します。
Next.js 15 パフォーマンスのベストプラクティス
1. スピナーよりもスケルトン
読み込み中のスピナー(ぐるぐる)は、ユーザーに中断を感じさせることがあります。スケルトンスクリーン(表示されるコンテンツのレイアウトを模したグレーのボックス)を使用することで、よりスムーズな遷移を提供し、レイアウトシフト (CLS) を抑えることができます。
2. 境界の戦略的な配置
ページ全体を単一の Suspense 境界でラップしないでください。代わりに、データ取得の独立した「単位」を特定してください。ダッシュボードであれば、「ユーザー統計」「最近の活動」「通知」ごとに別々の境界を設けるのが理想的です。
3. データ取得をコンポーネントへ
トップレベルの layout.tsx や page.tsx で全データを取得するのは避けましょう。これではルート全体が待機状態になってしまいます。代わりに、各コンポーネントに自身のデータを取得させてください。
4. 'use cache' ディレクティブの使用
Next.js 15 では、負荷の高い計算やデータ取得の結果を複数のリクエスト間でキャッシュできるようにする use cache ディレクティブ(試験的)が導入されました。これにより、サーバーの待機時間をさらに削減できます。
FAQ: Next.js 15 の Streaming と Suspense
Q1. ストリーミングは Pages Router でも動作しますか?
いいえ。完全なストリーミングときめ細やかな Suspense サポートは、App Router 専用です。Pages Router は引き続きサポートされますが、これらの高度なアーキテクチャの改善は適用されません。
Q2. ストリーミングは SEO に悪影響を与えますか?
実際には、プラスに働きます。Google などの検索エンジンは、ストリーミングされたコンテンツをクロールできます。ストリーミングによって FCP やその他の Core Web Vitals が向上するため、検索順位に良い影響を与える可能性があります。
Q3. ストリーミングを使うべきでないのはどのような時ですか?
コンテンツが非常に小さく、データ取得がほぼ瞬時に完了する場合(例:ローカルデータベースからの単純なテキスト)は、ストリーミングのオーバーヘッドに見合わない可能性があります。しかし、現代のウェブアプリの 90% において、ストリーミングは推奨される選択肢です。
Q4. Client Components で Suspense を使用できますか?
はい、可能ですが、挙動が異なります。クライアント側の Suspense はブラウザでの非同期コンポーネントを処理しますが、サーバー側の Suspense(Server Components 内)はサーバーからの HTML の段階的な配信を処理します。
Q5. Partial Prerendering (PPR) は本番環境で安全ですか?
Next.js 15 の時点では、PPR はまだ experimental(試験的) とされています。多くのプロジェクトで十分に安定していますが、重要な本番環境にデプロイする前には徹底的なテストを行う必要があります。
Q6. PPR を有効にするにはどうすればよいですか?
next.config.js で設定できます:
const nextConfig = {
experimental: {
ppr: 'incremental',
},
};
'incremental' オプションを使用すると、特定のレイアウトやページで個別に有効化(オプトイン)できます。
結論
Next.js 15 は、ウェブパフォーマンスの転換点となります。Streaming と Suspense をマスターし、Async Request APIs や Partial Prerendering への移行を受け入れることで、ユーザーの期待を超えるスピードのアプリケーションを構築できます。
ウェブは「静的 vs 動的」という二項対立から離れようとしています。Next.js 15 と共に、すべてのバイトが最適なタイミングで配信される、真のハイブリッドレンダリングの時代へと踏み出しましょう。今日からデータ負荷の高いコンポーネントのリファクタリングを始め、アプリケーションのレスポンスの劇的な違いを体感してください。
さらに詳しく知りたいですか? React 19 パフォーマンス:Server Components と Actions ガイド や 開発者のためのエンコーディングの基礎 についての他のガイドもぜひチェックしてください。