✏️

Next.js + Vercel で学ぶアーキテクチャ設計とビルド最適化の実践

に公開

この記事では、Next.js + Vercel の構成をベースに、アーキテクチャの分担構造・ビルド工程・モジュール方式・軽量化の実践例をまとめます。

🌐 全体像:処理を分散するWebアーキテクチャ

Next.js + Vercelでは、**「どこで何を処理するか」**を明確に分けた多層構造で動作します。

1️⃣ ユーザー/CDN 層

  • 役割:静的アセット(HTML, CSS, JS, 画像)を最寄りのCDN拠点から高速配信。
  • 特徴:読み込みが速く、世界中のユーザーに均一な体験を提供。

2️⃣ エッジ層(Edge Function/Middleware)

  • 役割:リクエスト直後に軽量ロジックを実行。
    例:URL書き換え・簡易認証・A/Bテスト分岐・ヘッダー制御。
  • 特徴:超低遅延だが、サイズ上限(例:1 MB)Node専用API不可など制約がある。
    → 重い依存(Prisma, bcrypt など)は避ける。

3️⃣ サーバレス/API 層(Route Handler, app/api/*)

  • 役割:DBアクセス・外部API連携・本格的な認証処理など重い処理を担当。
  • 特徴:必要時のみ起動(スケーラブル)だが、コールドスタート遅延あり。

4️⃣ SSR 層(Server Components など)

  • 役割:サーバーでHTMLを生成して配信。ユーザー固有データ(例:ダッシュボード)に最適。
  • 注意:初回描画が重くなりやすいため、キャッシュ戦略と分割設計が重要。

5️⃣ データ層(Postgres / Prisma)

  • 役割:DB接続・ORM管理。
  • 特徴:接続URLは環境変数で安全に管理(例:DATABASE_URL)。
    サーバレス環境ではプーリングドライバで遅延を緩和。

🧩 ビルドとデプロイ:本番用に最適化

ビルド=「作品を完成版に仕上げるプロセス」
開発中のコード・設定・素材をまとめ、軽量化・検証・配布準備を行う。

  1. 依存準備と検査

    • 必要なライブラリを収集・整合性確認。環境変数不足などがあれば停止。
  2. 最適化とバンドル

    • ファイルを用途別にまとめ、無駄を削減・圧縮。
  3. 役割別ビルド出力

    • 静的ページ、SSR、Edge Middleware など実行場所別に生成。
  4. 検証とエラーチェック

    • データ取得やレンダリングエラーを事前に検出。
  5. 配布とログ出力

    • 成果物をCDN/サーバーに配置。

      • ビルド時 → Deployment Logs
      • 実行時 → Runtime Logs

注意点:

  • Edge Middleware は 1 MB上限
  • 重い依存を含むとビルドエラーの原因に。

📦 モジュール方式(CJS と ESM)

CommonJS(CJS)

  • 構文require() / module.exports
  • 特徴:Node.jsで長く採用。動的ロード可能。解析・最適化は苦手。

ECMAScript Modules(ESM)

  • 構文import / export
  • 特徴:ブラウザ標準。静的解析が可能で最適化(ツリーシェイキング)に強い。
比較項目 CJS ESM
読み込み方式 同期的 (require) 静的 (import)
解析・最適化 難しい 容易
拡張子設定 .js (既定) .mjs or "type": "module"
Next.js 推奨 next.config.js next.config.mjs/ts

👉 プロジェクト内ではどちらか一方に統一するのが基本。


⚙️ 実践対応の記録

✅ Middleware サイズ超過の解消

  • 原因middleware.tsauth.ts を再エクスポートし、Prisma / bcrypt / Zod がEdgeバンドルに含まれていた(1.07 MB超過)。

  • 対策

    • auth.config.ts に共有設定を分離。
    • Middleware では軽量設定のみ参照。
    • サーバー側 (API/SSR) では引き続き重い依存を利用可。
  • 結果:Edge Functionが軽量化し、lintも通過。

その他 Next.js 15 対応(params の Promise化)

  • 変更params が Promise で渡される仕様へ更新。
  • 対応:全ダイナミックルートで const { id } = await params; に統一。
    params が Promise で渡される Next.js 15 の仕様に合わせ、/dashboard/posts/[id], /posts/[id], /posts/[id]/edit, /users/[id] の各ページで params を await してから利用するよう型と実装を統一
    Next.js 公式の該当解説: https://nextjs.org/docs/messages/sync-dynamic-apis
  • 結果:ビルド成功、型エラー・ランタイム警告解消。

⚖️ サイズ・依存の可視化ツールまとめ

ツール名 主な用途 特徴
Import Cost エディタで import のサイズを即時表示 開発中の即時フィードバックに最適
Package Phobia npm パッケージの publish/install サイズを確認 ディスク使用量を事前チェック
Bundle Phobia バンドル後の圧縮サイズや依存関係を分析 フロント配信サイズの影響を評価
bundlejs 実際に esbuild でバンドルし gzip/brotli サイズを測定 複数パッケージ比較・可視化に便利

🧭 まとめ:学びの要点

  • 処理は「軽重・場所」で分担:CDN → Edge → API/SSR → DB
  • エッジは軽く、サーバーで重くが原則。
  • ビルド工程は依存・構成・エラーを早期検出する安全装置。
  • **モジュール方式(CJS/ESM)**は構文と最適化の基本ルール。
  • 軽量化ツールを活用して「追加前に重さを把握」するのが効率的。

参考

パッケージバンドルを最適化する方法: https://nextjs.org/docs/pages/guides/package-bundling
Next.js:middleware.ts に入門する: https://zenn.dev/cloud_ace/articles/a30c75dbe220f3

Next.js 公式(APIリファレンス):https://nextjs.org/docs/pages/api-reference/file-conventions/middleware
Next.js 公式「Middleware」仕組み: https://nextjs.org/docs/app/building-your-application/routing/middleware
Auth.js(NextAuth v5)「Middleware / Auth Helpers」: https://authjs.dev/guides/basics/nextjs#middleware

Discussion