Next.jsのデプロイ — VercelとCloudflare Workersの違いを理解する
この章の目次開く
ここまでで、ページ、Route Handlers、Proxy、Server Actions まで一通り扱いました。最後に必要なのが、作ったNext.jsアプリを本番環境へデプロイすることです。
Next.jsはVercel製のフレームワークですが、Vercelでしか動かないわけではありません。Node.jsサーバー、Docker、静的ホスティング、Cloudflare Workersなど、複数の選択肢があります。ただし、使える機能や必要な設定はデプロイ先によって変わります。
学習者Next.jsってVercelにデプロイするもの、という印象があるけど、Cloudflareや普通のサーバーでも動かせるの?
先生動かせるよ。ただしVercelはNext.js向けに最適化されていて、Cloudflare Workersのようなエッジ環境ではOpenNext adapterなど追加の工程が必要になる。違いを理解して選ぼう。

Next.jsのデプロイ先の全体像
Next.js公式では、主なデプロイ形態として Node.jsサーバー、Docker、static export、Adapterによる各プラットフォーム対応 が示されています。
| デプロイ先 | 向いているケース | 注意点 |
|---|---|---|
| Vercel | Next.jsを最短で本番公開したい | Vercelの料金・制限・運用ルールを理解する |
| Node.jsサーバー | VPS、Render、Railway、社内基盤などで動かしたい | プロセス管理、ログ、スケールを自分で考える |
| Docker | Cloud Run、ECS、Kubernetesなどに載せたい | コンテナ設計と環境変数管理が必要 |
| static export | 完全な静的サイトとして配信したい | SSR、Route Handlers、Server Actionsなどは使えない |
| Cloudflare Workers | エッジ寄りの環境で配信したい | OpenNext adapter、Wrangler、workerd での確認が必要 |
Vercelにデプロイする基本の流れ
Vercelでのデプロイは、GitHubなどのリポジトリを連携するのが最も一般的です。
最小限の流れは次のとおりです。
- GitHubにNext.jsプロジェクトをpushする
- Vercelで「New Project」からリポジトリを選ぶ
- Framework PresetがNext.jsになっていることを確認する
- 必要な環境変数を設定する
- Deployする
VercelはNext.jsプロジェクトを自動判定し、npm run build 相当のビルドを実行します。Vercel公式の Next.js on Vercel でも、Vercelへのデプロイはゼロ設定で、スケーラビリティ・可用性・グローバルパフォーマンス面の追加最適化があると説明されています。
Vercelで特に楽になること
VercelはNext.jsの開発元が提供するプラットフォームなので、Next.jsの機能とかなり密に統合されています。
| 機能 | Vercelで楽になる理由 |
|---|---|
| Preview Deployment | Pull Requestごとに確認URLができる |
| Production Deployment | mainブランチへの反映を本番公開にしやすい |
| SSR | Vercel Functionsとして自動的に実行される |
| Streaming | Route Handlers、Vercel Functions、React Server Componentsで扱いやすい |
| Image Optimization | next/image の最適化を追加サービスなしで使いやすい |
| Cache-Control / ISR | Next.jsのキャッシュ戦略とVercel CDNがつながりやすい |
| 環境変数 | Production / Preview / Developmentで分けて管理できる |
| ロールバック | 過去のDeploymentへ戻しやすい |
データ取得とキャッシュ で扱った静的レンダリング、再検証、キャッシュの考え方は、デプロイ先のCDNやランタイムと密接に関係します。Vercelではこの接続がNext.js向けに設計されているため、最初のデプロイ先として選びやすいです。
Vercelでしかできないことはあるのか
結論から言うと、Next.jsの基本機能そのものがVercelでしか使えない、というわけではありません。Node.jsサーバーやDockerでもNext.jsは動きます。
ただし、Vercelには「Vercelのプラットフォーム機能」として使えるものがあります。
| 分類 | 例 | Vercel以外ではどうなるか |
|---|---|---|
| デプロイ体験 | Git連携、Preview URL、Production昇格 | 各プラットフォームやCI/CDで自分で構成する |
| Vercel CDN | ISR、Cache-Control、画像最適化との統合 | CDNや画像基盤を別途設計する |
| Vercel Functions | SSRやRoute Handlerの実行基盤 | Node.jsサーバー、Lambda、Workersなど別ランタイムに載せる |
| Observability | ログ、メトリクス、Web Vitals系の統合 | Datadog、Sentry、Cloudflare Analyticsなどを選ぶ |
| Vercel固有サービス | Blob、KV、Postgres、Edge Configなど | 他社DBやストレージで代替する |
つまり、「VercelでしかNext.jsをデプロイできない」のではなく、VercelではNext.js向けの周辺機能が最初からつながっていると考えるのが正確です。
Vercel以外に出す場合は、Next.jsの機能をそのプラットフォームのビルド・キャッシュ・ランタイムへどう対応させるかを確認する必要があります。Node.jsサーバーやDockerにデプロイする場合
Next.jsはNode.jsサーバーとして起動できます。package.json に次のようなスクリプトがあれば、本番用ビルドと起動ができます。
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}npm run build
npm run startこの形は、VPS、Render、Railway、Fly.io、社内のNode.js実行基盤などに向いています。Docker化する場合は、next.config.ts に output: 'standalone' を設定して、実行に必要なファイルだけをまとめる構成がよく使われます。
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'standalone',
};
export default nextConfig;standaloneとは何か
standalone は、Next.jsアプリを Node.jsサーバーとして本番実行するために必要なファイルだけをまとめる出力形式 です。
通常のプロジェクトには、ソースコード、開発用パッケージ、ビルドツール、テスト関連ファイルなど、本番起動には不要なものも多く含まれています。Next.js公式の output 設定 でも説明されているように、output: 'standalone' を有効にすると、next build 時にNext.jsが各ページやRoute Handlerの依存関係を解析し、実行に必要なファイルだけを .next/standalone にコピーします。
ビルド後のイメージは次のようになります。
.next/
├── standalone/
│ ├── server.js
│ ├── package.json
│ ├── .next/
│ └── node_modules/ // 本番実行に必要な一部だけ
└── static/server.js はNext.jsが生成する最小限の起動ファイルです。通常の next start の代わりに、次のように起動できます。
node .next/standalone/server.js本番環境でポートやホストを指定したい場合は、環境変数を使います。
PORT=8080 HOSTNAME=0.0.0.0 node .next/standalone/server.js設定ファイルで意識すること
output: 'standalone' は next.config.ts または next.config.js に書きます。この設定は ビルド時 に効くため、変更したら npm run build をやり直す必要があります。
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'standalone',
};
export default nextConfig;standalone は必要なファイルを自動で追跡しますが、fs で読み込む設定ファイル、テンプレート、証明書、外部バイナリなどは追跡から漏れることがあります。その場合は、outputFileTracingIncludes で明示的に含めます。
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'standalone',
outputFileTracingIncludes: {
'/*': ['src/config/runtime/**/*.json'],
},
};
export default nextConfig;反対に、不要な大きいファイルが含まれてしまう場合は outputFileTracingExcludes で除外できます。Dockerイメージが大きくなりすぎる場合は、まず .next/standalone の中身を確認すると原因を追いやすいです。
また、public と .next/static は .next/standalone に自動コピーされません。CDNやリバースプロキシで配信するのが理想ですが、単体のNode.jsサーバーで配信したい場合は、ビルド後にコピーします。
cp -r public .next/standalone/
cp -r .next/static .next/standalone/.next/Dockerでは、ビルドステージで npm run build したあと、実行ステージに .next/standalone、.next/static、public をコピーする構成がよく使われます。
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
CMD ["node", "server.js"]開発時との違い
開発中の npm run dev は、standalone の仕組みを使いません。開発サーバーはソースコードを監視し、変更を即時反映するために動いています。
一方、standalone は本番用に next build した後の成果物です。主な違いは次のとおりです。
| 項目 | 開発時 | standalone本番 |
|---|---|---|
| 起動コマンド | npm run dev | node server.js |
| 入力 | ソースコード全体 | .next/standalone の成果物 |
| 変更反映 | ファイル保存で即時反映 | 再ビルドと再デプロイが必要 |
| 目的 | 開発・デバッグ | 小さい成果物で本番実行 |
node_modules | 開発依存も含めて存在 | 実行に必要な一部だけをコピー |
ローカルで本番に近い確認をしたい場合は、次の順で確認します。
npm run build
node .next/standalone/server.jsこの確認は npm run dev とは別物です。next.config.ts の本番向け設定、環境変数、静的ファイルのコピー漏れ、Docker上での起動パスなどは、standalone の成果物で確認しないと気づきにくいことがあります。
Node.jsサーバーやDockerは、Next.js機能の自由度が高い一方で、次の運用を自分で考える必要があります。
- プロセス管理
- ログ収集
- ヘルスチェック
- スケールアウト
- CDN
- 環境変数
- DBコネクション
- HTTPS / ドメイン
DockerビルドはコンテナでやるべきかCIでやるべきか
Next.jsのDockerイメージを作るとき、「コンテナ内で npm run build する(multi-stage build)」のか「CIで先にビルドして成果物だけコピーする」のか、迷うことがあります。
学習者CI側でビルドしてDockerにはCOPYだけ、のほうがシンプルに思えるけど、どっちが正解なの?
先生どちらも動くけど、公式が推奨しているのはコンテナ内でビルドするmulti-stage buildだよ。Docker公式・Next.js公式ともにこの構成で案内している。理由は「誰がどこでビルドしても同じ結果になる」再現性の高さだね。
| 観点 | コンテナ内ビルド(multi-stage) | CIでビルド → COPYのみ |
|---|---|---|
| 公式推奨 | Yes(Docker公式・Next.js公式ともに) | No(公式ドキュメントに記載なし) |
| 再現性 | 高い — 環境差異がない | CIとDockerの環境差で壊れうる |
| ビルド速度 | Dockerレイヤキャッシュに依存 | CIキャッシュが効きやすく速い場合がある |
| Dockerfile | multi-stage(deps → build → runner の3段階) | 単純な COPY のみ |
| デバッグ | Dockerfileの中で完結する | CI設定とDockerfileの両方を見る必要がある |
multi-stage buildの構成例
Next.js公式の Docker Example で紹介されている構成は、大まかに次の3段階です。
# 1. deps — 依存だけインストール
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# 2. builder — ソースをコピーしてビルド
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# 3. runner — 実行に必要なファイルだけ持ってくる
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
CMD ["node", "server.js"]
学習者3段階に分ける理由は何?全部1つのステージでやったらダメなの?
先生最終イメージに開発用の node_modules やソースコードが残らないようにするためだよ。runnerステージにはビルド済みの成果物しか入らないから、イメージサイズが小さくなるし、本番に不要なファイルが漏れるリスクも減る。
static exportで静的サイトとして配信する場合
完全な静的サイトでよければ、output: 'export' を使ってHTML/CSS/JSだけを書き出せます。
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'export',
};
export default nextConfig;この場合、S3、Nginx、Apache、GitHub Pagesのような静的ホスティングでも配信できます。
ただし、static exportではサーバーが必要な機能は使えません。
| 使える / 使いやすい | 使えない / 制限されやすい |
|---|---|
| 静的なページ | SSR |
| 静的生成されたブログ | Route Handlers |
| クライアント側だけで完結する画面 | Server Actions |
| 外部APIをブラウザから直接呼ぶ構成 | Proxy |
| 画像を事前に最適化する構成 | 動的な画像最適化 |
Route Handlers や Server Actions を使うアプリは、基本的にstatic exportではなく、サーバー機能を持つデプロイ先を選びます。
Cloudflare Workersにデプロイする場合
Cloudflare Workersは、Node.jsサーバーではなく workerd というWorkers Runtimeで動きます。そのため、Next.jsアプリをそのまま next start で動かすのではなく、Cloudflare向けに変換する工程が必要です。
Cloudflare公式では、Next.jsアプリをWorkersへデプロイする方法として OpenNext adapter を使う流れが案内されています。
新規プロジェクトなら、CloudflareのCLIからNext.js向けに作成できます。
npm create cloudflare@latest -- my-next-app --framework=next既存プロジェクトなら、現在のCloudflareドキュメントでは wrangler deploy による自動検出、または手動設定が案内されています。
npx wrangler deploy手動で構成する場合は、概ね次のような工程になります。
@opennextjs/cloudflareを入れるwranglerを入れるwrangler.jsoncまたはwrangler.tomlを作るcompatibility_flagsにnodejs_compatを設定するopen-next.config.tsを作るpreview/deployスクリプトを追加するnpm run previewでWorkers Runtimeに近い環境で確認するnpm run deployで公開する
{
"scripts": {
"preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
"deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy"
}
}Cloudflare OpenNext adapterは多くのNext.js機能をサポートしていますが、Node.jsランタイム前提の機能や一部の新機能は対応状況を確認する必要があります。たとえばCloudflare公式ドキュメントでは、Node.js in Middlewareは「not yet supported」とされています。これは ProxyとMiddleware で触れたランタイム差分とつながる話です。
詳細はCloudflare公式の Next.js on Cloudflare Workers と、OpenNextの Cloudflare adapter documentation を確認してください。
エッジ環境へ出すときの注意点
Cloudflare Workers、Vercel Edge、Deno Deployのようなエッジ寄りの環境は、ユーザーに近い場所で軽く処理できるのが強みです。一方で、Node.jsサーバーとは前提が違います。
| 観点 | Node.jsサーバー | エッジ環境 |
|---|---|---|
| 実行環境 | Node.js | Web標準API中心のランタイム |
| ファイル操作 | fs が使える | 使えないことが多い |
| npmパッケージ | Node.js前提でも動きやすい | Edge対応が必要 |
| DB接続 | TCP接続しやすい | HTTPベースや専用接続が向きやすい |
| 確認方法 | next start に近い | adapterのpreviewで確認する |
ProxyとMiddleware でも説明した通り、エッジ環境は「Node.jsをそのまま小さくしたもの」ではありません。fs、ネイティブモジュール、Node.js専用APIに依存するライブラリは、本番で動かない可能性があります。
学習者ローカルでは動いたのにCloudflareに出したら落ちる、というのはランタイム差分が原因になりやすいんだね。
先生そう。だからCloudflare Workersへ出すなら、npm run preview のように本番ランタイムに近い確認を必ず挟む。Vercel以外では特に大事だよ。
環境変数と本番ビルドの注意点
Next.jsでは、環境変数が「ビルド時に必要なもの」と「実行時に必要なもの」に分かれます。
| 種類 | 例 | 注意点 |
|---|---|---|
| ビルド時に必要 | SSGで使うAPIキー、NEXT_PUBLIC_... | ビルド環境に設定する |
| 実行時に必要 | DB URL、外部APIの秘密鍵 | Runtime側に設定する |
| ブラウザに出る | NEXT_PUBLIC_ANALYTICS_ID | 秘密情報を入れない |
| サーバーだけ | DATABASE_URL | クライアントコードへ渡さない |
特にCloudflare Workers BuildsやCI/CDでは、ビルド時に必要な環境変数が設定されていないと、静的生成やビルド内のデータ取得で失敗します。VercelでもCloudflareでも、Production / Preview / Developmentで値を分けることを意識しましょう。
デプロイ前チェックリスト
本番公開前に、最低限ここを確認しましょう。
| チェック項目 | 見るポイント |
|---|---|
npm run build が通る | 型・Lint・静的生成エラーを確認 |
| 環境変数が設定されている | Production / Previewで不足がないか |
| DB接続先が本番向け | ローカルDBやテストDBを参照していないか |
| 認証・認可がサーバー側にある | Server Actions / Route Handlers で確認 |
robots.txt / sitemap.xml | SEO公開範囲が意図通りか |
| OGP / metadata | メタデータとSEO の設定が本番URLになっているか |
| エラー監視 | Sentryなどで本番エラーを拾えるか |
| ログ | APIエラーや認証エラーを追えるか |
| ロールバック手段 | 失敗時に戻せるか |
まとめ
- Next.jsはVercel専用ではなく、Node.jsサーバー、Docker、static export、Adapter経由の各プラットフォームへデプロイできる
- VercelはNext.js向けのゼロ設定デプロイ、Preview Deployment、Vercel Functions、画像最適化、キャッシュ統合などが強い
- Vercel固有の運用機能は便利だが、他プラットフォームではCI/CD、CDN、画像最適化、ログ監視などを別途組み合わせる
- static exportは静的配信に向くが、Route Handlers、Server Actions、SSR、Proxyなどサーバー機能は使えない
- Cloudflare Workersへ出す場合はOpenNext adapterやWranglerを使い、
workerdランタイムでpreviewする - エッジ環境はNode.jsと同じではないため、Node.js API依存・DB接続・Middleware/Proxyの対応状況に注意する
- 本番前には
npm run build、環境変数、認証・認可、SEO、ログ、ロールバックを確認する
これでNext.js App Routerの基礎から、API、Proxy、Server Actions、デプロイまで一通りつながりました。実際のアプリでは、ここから認証、DB設計、テスト、監視を少しずつ足していくと、本番運用できる形に近づきます。
