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)。
サーバレス環境ではプーリングドライバで遅延を緩和。
🧩 ビルドとデプロイ:本番用に最適化
ビルド=「作品を完成版に仕上げるプロセス」
開発中のコード・設定・素材をまとめ、軽量化・検証・配布準備を行う。
-
依存準備と検査
- 必要なライブラリを収集・整合性確認。環境変数不足などがあれば停止。
-
最適化とバンドル
- ファイルを用途別にまとめ、無駄を削減・圧縮。
-
役割別ビルド出力
- 静的ページ、SSR、Edge Middleware など実行場所別に生成。
-
検証とエラーチェック
- データ取得やレンダリングエラーを事前に検出。
-
配布とログ出力
-
成果物を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.tsがauth.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