Next.js パフォーマンス最適化:完全な 2026 年版ガイド

過去 4 年間、年間 5000 万ドルの売上を上げる e コマース ストアから 10 万人以上の日次アクティブユーザーを持つ SaaS ダッシュボードまで、様々なクライアント向けに Next.js アプリケーションのパフォーマンス最適化に取り組んできました。学んだことの一部はドキュメントと完全に一致していますが、多くはそうではありません。これは、私が始めたときに誰かから受け取りたかったガイドです — Next.js 15 と 2026 年に実際に重要なパターンに更新されています。

パフォーマンスは最後に付け加える機能ではありません。それは初日から行う一連の決定であり、それぞれが複合的に作用します。初期段階でいくつかの決定を逃すと、書き直しが必要になります。正しく判断すれば、アプリはユーザーのローカルマシンで実行されているように感じます。

始めましょう。

目次

Next.js Performance Optimization: The Complete 2026 Guide

Next.js 15 パフォーマンスの基本を理解する

Next.js 15(2025 年後期から安定版)は、パフォーマンスがどのように機能するかについて大きな変更をもたらしました。Turbopack バンドラーは、開発ビルドと本番ビルドの両方のデフォルトになりました。App Router は完全に成熟しています。そして、Next.js 14 でほぼ全員を混乱させたキャッシング動作が合理化されました。

内面化する必要があることは次のとおりです:Next.js は複数のレンダリング戦略を提供し、特定のページに対して間違ったものを選択することは、私が見る最も一般的なパフォーマンス誤りです。静的生成、サーバーサイドレンダリング、インクリメンタル静的再生成、部分的なプリレンダリング、ストリーミング — それぞれに特定のユースケースがあります。週に 1 回変わるマーケティングページに SSR を使用することは、理由もなくコンピュートを消費しているだけです。

パフォーマンスのメンタルモデル

Next.js のパフォーマンスを 3 つのレイヤーで考えてください:

  1. ビルド時の決定 — 何が事前レンダリングされるか、何が動的であるか、コード分割の方法
  2. サーバー実行時 — サーバーがどのくらい速く応答するか、キャッシング、エッジ対オリジン
  3. クライアント体験 — バンドルサイズ、ハイドレーションコスト、インタラクション準備

各レイヤーは他のレイヤーを乗算します。高速なサーバー応答は、500KB の JavaScript を配送していて、ミッドレンジの Android フォンでハイドレーションに 3 秒かかる場合は意味がありません。

実際に重要なことを測定する

何かを最適化する前に、測定する必要があります。そして、正しいものを測定する必要があります。

Core Web Vitals は 2026 年もGoogle のランキングシグナルのままですが、閾値は厳しくなっています。状況は次のとおりです:

メトリック 良好 改善が必要 低い
LCP(最大の内容絵画) ≤ 2.0s 2.0s – 3.5s > 3.5s
INP(次の絵画へのインタラクション) ≤ 150ms 150ms – 300ms > 300ms
CLS(累積レイアウトシフト) ≤ 0.1 0.1 – 0.25 > 0.25
TTFB(最初のバイトまでの時間) ≤ 400ms 400ms – 800ms > 800ms

実際に使用するツール

  • Vercel Speed Insights — Vercel を使用している場合、これは検討の余地があります。合成ではなく、実ユーザーデータです。
  • next/bundle-analyzer — 週に 1 回実行してください。目を離すとバンドルサイズが増加します。
  • Chrome DevTools パフォーマンスタブ — ハイドレーション問題のデバッグに依然として最適です。
  • WebPageTest — 実際の場所から実際のデバイスでテストします。フィルムストリップビューは非常に価値があります。
  • Sentry Performance Monitoring — 本番環境で実際の API 応答時間とサーバーコンポーネントレンダーの持続時間を追跡します。
# プロジェクトにバンドルアナライザーを追加
npm install @next/bundle-analyzer
// next.config.mjs
import withBundleAnalyzer from '@next/bundle-analyzer';

const config = withBundleAnalyzer({
  enabled: process.env.ANALYZE === 'true',
})({
  // your config here
});

export default config;

ANALYZE=true npm run build を実行して、実際に出力を確認してください。少なくとも 1 つのライブラリが予想より大幅に大きいことを確認できると保証します。

サーバーコンポーネント:おそらく過小利用されている最大の勝利

サーバーコンポーネントは、モダン Next.js における最大のパフォーマンス改善です。クライアントに 0 バイトの JavaScript を送信します。0 です。HTML はサーバーでレンダリングされ、ブラウザーにストリーミングされ、コンポーネントはハイドレーションされません。

しかし、ここが人々が誤る場所です:彼らは 'use client' を早急に追加します。'use client' ディレクティブが 80% のコンポーネントで設定されているコードベースをレビューしました。これは開発者が古い Pages Router メンタルモデルに慣れていたためです。すべての 'use client' ディレクティブはハイドレーション境界です。すべてのハイドレーション境界はブラウザーが ダウンロード、解析、実行する必要がある JavaScript です。

従う規則

デフォルトではコンポーネントをサーバーコンポーネントのままにしてください。次の場合にのみ 'use client' を追加してください:

  • イベントハンドラー(onClick、onChange など)
  • useState、useEffect、useRef
  • ブラウザ専用 API(localStorage、window など)
  • フックを使用するサードパーティクライアントライブラリ

構成パターン

大きなコンポーネントの小さな部分にインタラクティブ性が必要な場合、全体をクライアントコンポーネントにしないでください。代わりに:

// app/product/[id]/page.tsx (サーバーコンポーネント)
import { getProduct } from '@/lib/products';
import { AddToCartButton } from '@/components/AddToCartButton';
import { ProductReviews } from '@/components/ProductReviews';

export default async function ProductPage({ params }: { params: { id: string } }) {
  const product = await getProduct(params.id);

  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      {/* この小さなボタンのみがクライアントコンポーネント */}
      <AddToCartButton productId={product.id} price={product.price} />
      {/* このレビューセクション全体はサーバーに留まる */}
      <ProductReviews productId={product.id} />
    </div>
  );
}
// components/AddToCartButton.tsx
'use client';

export function AddToCartButton({ productId, price }: { productId: string; price: number }) {
  const handleClick = () => {
    // cart logic
  };

  return <button onClick={handleClick}>Add to Cart -- ${price}</button>;
}

このパターンだけで、我々が取り組んだプロジェクトではバンドルサイズが 40~60% 削減されました。Next.js 開発実践を通じて。

Next.js Performance Optimization: The Complete 2026 Guide - architecture

バンドルサイズの最適化

Next.js 15 の Turbopack は webpack が行ったことよりも優れたツリーシェイキングを処理しますが、不正なインポートから救うことはできません。

名前付きインポートが重要

// 悪い — ライブラリ全体をインポート
import _ from 'lodash';
const sorted = _.sortBy(items, 'name');

// 良い — 必要なものだけをインポート
import sortBy from 'lodash/sortBy';
const sorted = sortBy(items, 'name');

// 最高 — lodash は本当に必要?
const sorted = items.toSorted((a, b) => a.name.localeCompare(b.name));

2026 年の一般的なバンドルブロッター

ライブラリ 一般的なサイズ(gzip) 代替 サイズ削減
moment.js 72KB date-fns(ツリーシェイク可能) ~60KB
lodash(完全) 71KB ネイティブ JS / lodash-es ~65KB
chart.js 65KB lightweight-charts ~45KB
react-icons(すべて) 40KB+ 個別アイコンパッケージ ~35KB
framer-motion 44KB motion(ライト)または CSS ~30KB

重いコンポーネントの動的インポート

import dynamic from 'next/dynamic';

const HeavyChart = dynamic(() => import('@/components/Chart'), {
  loading: () => <div className="h-64 animate-pulse bg-gray-100 rounded" />,
  ssr: false, // サーバーでレンダリングしない場合、ブラウザのみ
});

20KB を超えてページ上部にないものには、動的インポートを使用します。チャート、リッチテキストエディター、マップ、複雑なモーダル — すべて遅延読み込み。

画像とメディアの最適化

next/image コンポーネントは Next.js 15 で大幅に改善されました。デフォルトで AVIF をサポートし(WebP と並行して)、自動サイジング検出がより信頼性が高くなっています。

重要な画像最適化

import Image from 'next/image';

// ヒーロー画像 — ページ上部、優先度が必要
<Image
  src="/hero.jpg"
  alt="Product showcase"
  width={1200}
  height={630}
  priority // この画像をプリロード
  sizes="100vw"
  quality={80} // 80 は通常、最適な値
/>

// ページ下部の画像 — デフォルトで遅延読み込み
<Image
  src="/feature.jpg"
  alt="Feature detail"
  width={600}
  height={400}
  sizes="(max-width: 768px) 100vw, 50vw"
  placeholder="blur"
  blurDataURL={feature.blurHash}
/>

`sizes` 属性は必須ではありません

これが常にスキップされるのを見ます。適切な sizes 属性がないと、ブラウザはビューポートに関係なく最大の画像バリアントをダウンロードします。モバイルでは、375px の画面用に 2400px 幅の画像を潜在的に読み込んでいます。サイズを指定してください。毎回。

ビデオ最適化

ビデオについては、大規模な MP4 を持つ <video> タグを使用しないでください。2026 年の動きは:

  1. FFmpeg または Mux のようなサービスを使用して複数の品質にトランスコード
  2. 10 秒以上のものに HLS ストリーミングを使用
  3. 短いアニメーションについては、WebM または アニメーション AVIF を検討
  4. IntersectionObserver を持つページ下部の遅延読み込みビデオ

データフェッチングとキャッシング戦略

Next.js 15 は、14 の混乱する デフォルトと比較してキャッシングを簡素化しました。重要な変更:デフォルトでは何もキャッシュされません。明示的にキャッシングをオプトインします。これははるかに合理的です。

`use cache` ディレクティブを使用したキャッシング

Next.js 15 は use cache ディレクティブを導入しました(現在カナリア版、15.2 で安定版に正式リリース予定):

async function getProducts() {
  'use cache';
  const products = await db.products.findMany();
  return products;
}

fetch API の場合、キャッシングは明示的に制御されます:

// キャッシングなし(Next.js 15 のデフォルト)
const data = await fetch('https://api.example.com/data');

// 手動で再検証されるまでキャッシュ
const data = await fetch('https://api.example.com/data', {
  cache: 'force-cache',
});

// 60 秒ごとに再検証
const data = await fetch('https://api.example.com/data', {
  next: { revalidate: 60 },
});

コンテンツタイプ別のキャッシング戦略

コンテンツタイプ 戦略 再検証
マーケティングページ 静的(ビルド時) デプロイ時 ホームページ、について
商品リスト ISR 60~300 秒 カテゴリーページ
ユーザーダッシュボード 動的(キャッシュなし) 毎回のリクエスト アカウント設定
ブログ記事 ISR 3600 秒 CMS 駆動コンテンツ
検索結果 動的 + クライアントキャッシュ SWR パターン 検索ページ
API データ サーバー + CDN キャッシュ 様々 REST/GraphQL

ヘッドレス CMS を使用するプロジェクトの場合、これはほとんどが我々がヘッドレス CMS 開発実践で構築していますが、ISR とウェブフック駆動再検証は業界標準です。コンテンツアップデートはサイト全体を再構築することなく数秒以内に表示されます。

エッジランタイムとミドルウェアのパフォーマンス

Edge Runtime はコードを CDN ノード上で、ユーザーに近い場所で実行します。TTFB は劇的に低下します — エッジから 50~150ms のTTFB 対 単一リージョンオリジンから 300~800ms の測定値があります。

しかし、落とし穴があります:Edge Runtime はすべての Node.js API をサポートしていません。fs がなく、限定された crypto、ネイティブモジュールがありません。コードは完全な Node.js プロセスではなく、V8 アイソレート内で実行されます。

エッジを使用する場合

  • ミドルウェア(認証チェック、リダイレクト、A/B テスト)
  • データベース接続を必要としないシンプルな API ルート
  • パーソナライゼーション必要で静的にキャッシュできないページ

エッジを避ける場合

  • 重いデータベースクエリ(接続プーリングはエッジではうまく機能しません)
  • Node.js 固有のライブラリを使用するルート
  • 25ms 以上の CPU 時間が必要なもの(エッジ関数には厳密な制限があります)
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  // 高速な地理的リダイレクト — エッジで実行
  const country = request.geo?.country;

  if (country === 'DE' && !request.nextUrl.pathname.startsWith('/de')) {
    return NextResponse.redirect(new URL('/de' + request.nextUrl.pathname, request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};

ミドルウェアを軽く保ってください。ミドルウェアの 1 ミリ秒は すべての単一ページ読み込みに追加されます。

データベースと API レイヤーの最適化

接続プーリング

サーバーレス関数は絶えず立ち上がり、シャットダウンします。接続プーリングがないと、各呼び出しは新しいデータベース接続を開きます。規模で、これはデータベースを殺します。

接続プーラーを使用:

  • PgBouncer PostgreSQL の場合(Supabase と Neon に含まれる)
  • Prisma Accelerate Prisma を使用している場合(接続プール + グローバルキャッシュを追加)
  • Drizzle postgres.js で接続を効率的に処理

クエリ最適化パターン

// 悪い — N+1 クエリ問題
const posts = await db.post.findMany();
for (const post of posts) {
  post.author = await db.user.findUnique({ where: { id: post.authorId } });
}

// 良い — 結合を伴う単一クエリ
const posts = await db.post.findMany({
  include: { author: true },
});

// 最高 — 必要なフィールドのみ選択
const posts = await db.post.findMany({
  select: {
    id: true,
    title: true,
    slug: true,
    author: {
      select: { name: true, avatar: true },
    },
  },
});

並列データフェッチング

これは最も影響のあるパターンの 1 つであり、犯罪的に過小利用されています:

// 悪い — シーケンシャル(総時間 = すべてのフェッチの合計)
const products = await getProducts();
const categories = await getCategories();
const banners = await getBanners();

// 良い — 並列(総時間 = 最も遅いフェッチ)
const [products, categories, banners] = await Promise.all([
  getProducts(),
  getCategories(),
  getBanners(),
]);

この単一の変更がページ読み込み時間を半分にカットしているのを見ました。

レンダリング戦略の選択

Next.js 15 は 5 つのレンダリング戦略を提供します。こうして決定します:

部分的なプリレンダリング(PPR)

PPR は最新で最も興味深いオプションです。ビルド時にページのシェルを静的にプリレンダリングし、動的コンテンツをストリーミングします。ユーザーは、パーソナライズされたコンテンツが読み込まれている間に、即座の静的応答を見ます。

// app/page.tsx — PPR 有効
import { Suspense } from 'react';
import { StaticHero } from '@/components/StaticHero';
import { PersonalizedRecommendations } from '@/components/Recommendations';

export default function HomePage() {
  return (
    <div>
      {/* 静的シェル — CDN から即座に提供 */}
      <StaticHero />

      {/* 動的コンテンツ — ストリーミング */}
      <Suspense fallback={<RecommendationsSkeleton />}>
        <PersonalizedRecommendations />
      </Suspense>
    </div>
  );
}

設定で PPR を有効にする:

// next.config.mjs
export default {
  experimental: {
    ppr: 'incremental',
  },
};

e コマースと コンテンツ主導のサイトの場合、PPR は最高の両方を与えます — パーソナライズされたコンテンツを持つ CDN スピード初期負荷。

サードパーティスクリプト管理

サードパーティスクリプトはサイレントなパフォーマンスキラーです。アナリティクス、チャットウィジェット、広告トラッカー、A/B テストツール — それらは速くなります。

`next/script` を戦略的に使用

import Script from 'next/script';

// アナリティクス — ページがインタラクティブになった後に読み込み
<Script
  src="https://www.googletagmanager.com/gtag/js?id=G-XXXXX"
  strategy="afterInteractive"
/>

// チャットウィジェット — アイドル時に読み込み
<Script
  src="https://widget.intercom.io/widget/xxxxx"
  strategy="lazyOnload"
/>

// 重要な A/B テスト — ペイントの前に読み込む必要がある
<Script
  src="https://cdn.optimizely.com/js/xxxxx.js"
  strategy="beforeInteractive"
/>

容赦なくいてください。追加するすべてのスクリプトは、ユーザーの時間でコストを計算します。少なくとも四半期ごとにサードパーティスクリプトを監査することをお勧めします。最低でも時間の半分、誰もがチームで使用しなくなったツール用のスクリプトを見つけます。

Partytown で Workers ベースの読み込み

重要でない サードパーティスクリプトについては、Partytown を検討します。Web Worker にスクリプトを移動し、メインスレッドを無料に保ちます:

<Script
  src="https://example.com/analytics.js"
  strategy="worker" // Partytown 経由の Web Worker で実行
/>

インフラストラクチャとデプロイメント

どこにデプロイするか、そしてどのように デプロイするかは、ほとんどの開発者が思う以上に重要です。

2026 年の Next.js のプラットフォーム比較

プラットフォーム SSR サポート エッジ関数 コールドスタート 開始価格
Vercel 完全 はい(グローバル) ~50ms $20/月(Pro)
Cloudflare Pages 完全(OpenNext 経由) はい(グローバル) ~10ms $5/月
AWS Amplify 完全 限定 ~200ms 使用量に応じて支払い
Netlify 完全 はい(Deno) ~100ms $19/月(Pro)
自己ホスト(Docker) 完全 いいえ N/A サーバーコスト
Coolify / SST 完全 依存 ~150ms サーバーコスト

Vercel は依然として Next.js の摩擦最小パスです。彼らはフレームワークを構築し、それに対してプラットフォームを最適化します。しかし、OpenNext を備えた Cloudflare Pages は 2026 年で真摯な競争相手になっています。特にコスト意識の高いプロジェクトの場合。

自ホスト デプロイメントが必要なクライアントの場合、CDN の背後にある Docker コンテナーで良い結果が得られました。セットアップ時間がかかりますが、インフラストラクチャを完全にコントロールできます。異なるデプロイメントシナリオについて話したい場合は、価格ページがカバーされます。

CDN とエッジキャッシング

プラットフォームに関係なく、すべての前に CDN を配置してください。静的アセットには不変キャッシュヘッダーが必要です。ISR ページは stale-while-revalidate を使用する必要があります。API 応答は適切にキャッシュする必要があります。

// キャッシュできる API ルートの場合
export async function GET() {
  const data = await getPopularProducts();

  return Response.json(data, {
    headers: {
      'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
    },
  });
}

実世界のベンチマークとケーススタディ

ここに過去 1 年間に最適化したプロジェクトからの実際の数字があります:

e コマースサイト(Shopify ヘッドレス + Next.js 15)

  • LCP 4.2s、INP 380ms、バンドル 487KB
  • LCP 1.4s、INP 89ms、バンドル 156KB
  • 重要な変更 商品ページのサーバーコンポーネント、画像最適化、4 つの未使用サードパーティスクリプト削除、クライアント側カートからサーバーアクションに切り替え
  • ビジネスへの影響 コンバージョン率 23% 増加

SaaS ダッシュボード(Next.js 14 → 15 マイグレーション)

  • 初期読み込み 6.8s、TTI 8.2s
  • 初期読み込み 2.1s、TTI 2.8s
  • 重要な変更 App Router への マイグレーション、データ主導テーブルストリーミング実装、混合静的/動的ページの PPR 追加、並列データフェッチング

コンテンツプラットフォーム(ヘッドレス CMS + Next.js)

  • TTFB 890ms(SSR)、LCP 3.1s
  • TTFB 120ms(ISR + エッジ)、LCP 1.1s
  • 重要な変更 SSR から ISR へ切り替え オンデマンド再検証、エッジへのデプロイ、CMS クエリ最適化

これらはチェリーピック番号ではありません。このガイドのパターンを体系的に適用するとき達成可能な代表的なものです。

Next.js の代わりに Astro で構築されたプロジェクト — 特に JavaScript 要件が最小であるコンテンツ主導サイト — の場合、数字はさらに印象的である可能性があります。Astro 開発機能でそれをカバーします。

FAQ

Next.js パフォーマンス最適化の一般的なコストはいくらですか?

アプリケーションのサイズと複雑さに大きく依存します。率直なサイトの場合、1~2 週間の焦点を絞った最適化スプリントで劇的な結果を達成できます。大規模なアプリケーションで深いアーキテクチャ問題の場合、4~8 週間のリファクタリングを計画してください。ROI は通常、コンバージョン率の向上とインフラストラクチャコストの削減を通じて支払う。お問い合わせページで特定の見積もりをしたい場合は、お気軽にお問い合わせください。

Next.js 15 は Next.js 14 より速いですか?

はい、測定可能に速いです。デフォルトのバンドラーとしての Turbopack は、ビルド時間を 30~50% カット し、やや小さいバンドルを生産します。簡素化されたキャッシング モデルは不要なサーバー負荷を減らします。そして部分的なプリレンダリング、正しく使用すると、認識されたパフォーマンスを大幅に向上させます。マイグレーション後、平均して 15~25% TTFB 改善が見られました。

2026 年では Pages Router または App Router を使用する必要がありますか?

App Router、完全に。Pages Router はまだ機能し、引き続きサポートされていますが、すべてのパフォーマンスイノベーションは App Router で発生しています。サーバーコンポーネント、ストリーミング、PPR、サーバーアクション — これらのいずれも Pages Router では利用できません。新しいプロジェクトを開始している場合、Pages Router を使用する理由はありません。

Next.js バンドルサイズを迅速に削減するにはどうすればよいですか?

まずバンドルアナライザーを実行します — これは重さがどこにあるかを正確に表示します。次に:重いライブラリをより軽い代替品に置き換え、ページ下部のコンポーネント用に動的インポートを使用し、ツリーシェイク可能なライブラリから名前付きインポートを使用していることを確認し、'use client' ディレクティブを監査します。これら 4 つの手順だけで、通常、バンドルサイズが 30~50% 削減されます。

ホスティングプラットフォームは本当に Next.js パフォーマンスに影響しますか?

予想より多くです。Vercel のインフラストラクチャは Next.js 専用に調整されています — エッジネットワーク、ISR 実装、画像最適化 CDN は密接に統合されています。他のプラットフォームもうまく機能しますが、Vercel が自動的に処理するものを手動で設定する必要があるかもしれません。最大の要因は地理的分布です — ユーザーがグローバルの場合、プラットフォームに関係なく、エッジデプロイメントまたは CDN が必要です。

あなたが見ている最大の Next.js パフォーマンスミスは何ですか?

すべてをクライアントコンポーネントにします。開発者が古い Pages Router メンタルモデルに慣れているため、全ページツリーが 'use client' でラップされているコードベースを監査しました。これにより、ブラウザは everything をダウンロードしてハイドレーションすることを強制され、Next.js を高速にするサーバーコンポーネント利点を完全に無効化します。クライアントコンポーネントが小さく、リーフレベルのノードになるように、コンポーネントツリーを再構成してください。

部分的なプリレンダリング(PPR)は通常の ISR とどのように比較されていますか?

ISR はビルド時にページ全体を生成し、定期的に再検証します。PPR はビルド時に静的シェルをプリレンダリングしますが、リクエスト時にストリーミングで満たされた動的「穴」を残します。PPR は、静的コンテンツとパーソナライズされたコンテンツを混ぜるページに優れています — 説明が静的ですが推奨製品がパーソナライズされた製品ページを考えます。初期応答はシンプルな静的と同じくらい高速ですが、動的コンテンツはページ全体を読み込むことなく表示されます。

Vercel なしで Next.js パフォーマンスを最適化できますか?

完全に。このガイドの最適化は、ホスティングプラットフォームに関係なく機能します。サーバーコンポーネント、バンドル最適化、画像最適化、キャッシング戦略、並列データフェッチング — これらはアプリケーションレベルの関心事です。Vercel が組み込み ISR サポートなどのエッジ関数をサポートするなど、プラットフォーム固有の機能が異なります。しかし OpenNext のようなツールは、Cloudflare、AWS、他のプラットフォームでシミラーパフォーマンス特性を持つ完全な機能 Next.js を実行することを可能にします。