Featured image of post Next.js App Routerでの表示速度最適化のポイント Featured image of post Next.js App Routerでの表示速度最適化のポイント

Next.js App Routerでの表示速度最適化のポイント

Next.js App Routerを使ったWebフロントエンドのパフォーマンス最適化テクニックを解説。RSCや画像の最適化など。

React 18の機能を全面的に取り入れた Next.jsのApp Router は、高速なWebフロントエンドを構築するための強力なアーキテクチャです。

しかし、Server ComponentsとClient Componentsの境界設計や、レンダリングとキャッシュの仕組みを誤って理解していると、逆にパフォーマンス(表示速度)が低下してしまうことがあります。本記事では、App Routerを採用したWebアプリケーションを爆速にするための最適化手法を詳しく解説します。


1. React Server Components(RSC)を主役に据える

App Routerの最大の利点は、コンポーネントがデフォルトでサーバー側でレンダリング(RSC)される点です。これにより、クライアントに送信されるJavaScriptのファイルサイズを最小限に抑えることができます。

💡 最適化のルール:use client は「末端」に配置する

use client ディレクティブをファイルの上部に宣言すると、そのファイル以降のインポートツリー全体がクライアント側でダウンロード・実行されます。 表示速度を上げるためには、インタラクティブな機能(ボタンのクリックイベント、フォーム入力、StateやEffectの使用)が必要な最小限のコンポーネントだけをClient Componentとして切り出し、ツリーの末端に配置します。

// ✕ 避けるべき例: ページ全体をクライアント化してしまう
'use client'
export default function Page() {
  const [data, setData] = useState(null)
  return <div>{/* 重たい表示ロジック */}</div>
}

// ◯ 推奨される例: ロジックのみをClient Componentに切り出す
import HeavyStaticContent from './HeavyStaticContent' // RSC
import ClientInteractiveButton from './ClientInteractiveButton' // Client

export default function Page() {
  return (
    <div>
      <HeavyStaticContent />
      <ClientInteractiveButton />
    </div>
  )
}

2. next/image の賢い使い分けと LCP 対策

画像(特にファーストビュー内の大きな画像)は、ページの主要コンテンツの表示時間(LCP: Largest Contentful Paint)の数値を大きく左右します。

💡 priority 属性によるプリロード

ページを開いた瞬間に目に入るロゴやメインビジュアルには、必ず priority 属性を付与します。これにより、ブラウザに対して画像を最優先でロードするよう指示が出されます。

import Image from 'next/image'

export default function Hero() {
  return (
    <div className="hero-banner">
      <Image
        src="/images/hero-visual.png"
        alt="Hero Image"
        width={1200}
        height={630}
        priority // プリロードを強制
        sizes="(max-width: 768px) 100vw, 1200px"
      />
    </div>
  )
}

また、sizes 属性を正確に記述することで、モバイル端末のアクセス時に必要以上に巨大なPC用の画像がダウンロードされるのを防ぎます。


3. レンダリング・キャッシュの制御(静的 vs 動的)

Next.js App Routerは、ページごとに 静的レンダリング(Static Rendering) または 動的レンダリング(Dynamic Rendering) を自動で判定します。

  • 静的(ビルド時に生成): 表示が非常に高速。可能な限りこちらに寄せます。
  • 動的(リクエスト時に生成): ヘッダー情報やクエリパラメータを読み込むと自動で切り替わりますが、サーバー側での処理時間が発生します。

💡 動的なコンポーネントの遅延ロード

重たいライブラリや、特定のボタンを押した後にしか表示されないダイアログなどは、next/dynamic を使用してクライアントでの読み込みを遅延させます。

import dynamic from 'next/dynamic'

// モーダルコンポーネントをユーザーがクリックするまでロードしない
const HeavyModal = dynamic(() => import('./HeavyModal'), {
  ssr: false, // サーバーサイドレンダリングからも除外して軽量化
})

4. まとめ:計測とチューニングの継続

App Routerのパフォーマンス改善は、Chrome DevToolsLighthouse でクライアントサイドJSの容量とサーバー応答速度(TTFB)を常に監視することから始まります。RSCの力を最大限に活かし、クリーンで高速なフロントエンドを実現しましょう。