レビュー済み·難易度: 初級·更新: 2026-04-17

Next.js の dynamic import でコンポーネントを遅延読み込みする

next/dynamic を使い、重いコンポーネントや SSR 不要なコンポーネントを遅延読み込みしてバンドルサイズを削減する実装例。

nextjsperformance

対応バージョン

nextjs 15react 19

前提環境

Next.js App Router のページ・コンポーネント構成を理解していること

概要

next/dynamic を使うと、コンポーネントを初期バンドルから分離して必要なタイミングで読み込める。 ssr: false で SSR をスキップでき、window オブジェクトを参照するライブラリや重いビジュアライゼーション系コンポーネントに有効。

インストール

# 追加インストールは不要

基本的な遅延読み込み

// src/app/dashboard/page.tsx
import dynamic from "next/dynamic";

// HeavyChart は初期バンドルに含まれず、必要時に読み込まれる
const HeavyChart = dynamic(() => import("@/components/HeavyChart"), {
  loading: () => <p className="text-sm text-gray-400">グラフを読み込み中...</p>,
});

export default function DashboardPage() {
  return (
    <main className="p-6">
      <h1 className="mb-4 text-lg font-bold">ダッシュボード</h1>
      <HeavyChart />
    </main>
  );
}

SSR を無効化する(クライアント専用コンポーネント)

// src/app/editor/page.tsx
import dynamic from "next/dynamic";

// window / document を参照するコンポーネントは SSR をスキップする
const RichTextEditor = dynamic(() => import("@/components/RichTextEditor"), {
  ssr: false,
  loading: () => <div className="h-40 animate-pulse rounded bg-gray-100" />,
});

export default function EditorPage() {
  return (
    <main className="p-6">
      <h1 className="mb-4 text-lg font-bold">エディタ</h1>
      <RichTextEditor />
    </main>
  );
}

名前付きエクスポートの遅延読み込み

// src/components/HeavyChart.tsx(名前付きエクスポート)
export function HeavyChart() {
  return <div>グラフ</div>;
}

// 使う側
const HeavyChart = dynamic(
  () => import("@/components/HeavyChart").then((mod) => mod.HeavyChart),
  { loading: () => <p>読み込み中...</p> }
);

ポイント

  • dynamic() でラップするだけで自動的にコードスプリットされる
  • ssr: falsewindow / document を参照する外部ライブラリに必須
  • loading オプションに渡したコンポーネントが読み込み中に表示される(loading.tsx と役割は同じ)
  • 名前付きエクスポートは .then((mod) => mod.ExportName) で取り出す
  • App Router では React.lazy + Suspense でも同様のことができるが、next/dynamic は Next.js との統合が深くオプションが豊富

注意点

ssr: false を指定するとサーバーサイドレンダリングをスキップできる。window オブジェクトを参照するライブラリや重いチャートコンポーネントに有効。loading オプションでローディング UI も指定できる。

関連サンプル