Menu

Next.jsをCloudflare Workersにデプロイする

Vercelは開発者体験に優れたデプロイプラットフォームですが、トラフィックが増えるとコストが急激に膨らみます。DokployやCoolifyはVPS1台で無制限にデプロイできる優れたセルフホスティングツールですが、サーバーのセキュリティ管理は自分で行う必要があります。

Cloudflare Workersは月額$5のサブスクリプションで、月間1,000万リクエストと3,000万ミリ秒のCPU時間が利用できます。Vercelと比べてコストパフォーマンスが大幅に優れており、Cloudflare Workersへの移行を検討する開発者が増えています。

ただし、デプロイ体験は決して簡単ではありません。公式ドキュメントやコミュニティの情報をしっかり読み込まないと、なかなかうまくいかないのが現状です。

NEXTY.DEVテンプレートでは、こうした手間を減らすため、Cloudflare Workers + Postgresデプロイに特化したcf-pgブランチを用意しています。Neon・Supabase・セルフホストのPostgresに対応しています。

この記事では、NEXTY.DEVテンプレートのcf-pgブランチをCloudflare Workersにデプロイする手順を解説します。

ステップ1:CLIの準備

作業を始める前に、wrangler(CloudflareのCLIツール)がインストール済みで、アカウントにログインしていることを確認してください。

npx wrangler login

実行するとブラウザが開き、認証を完了できます。以降のR2・D1・デプロイ操作はすべてこの認証が必要です。

ステップ2:wrangler.jsoncの作成

cf-pgブランチにはwrangler.example.jsoncが雛形として用意されています:

{
	"$schema": "node_modules/wrangler/config-schema.json",
	"name": "<YOUR_WORKER_APP_NAME>",
	"main": ".open-next/worker.js",
	// プロジェクトを開始する際は、compatibility_dateを現在の日付に設定してください
	// https://developers.cloudflare.com/workers/configuration/compatibility-dates/
	"compatibility_date": "2026-02-22",
	"compatibility_flags": [
		"nodejs_compat",
		"global_fetch_strictly_public"
	],
	// Cloudflare Account ID: Cloudflare Dashboard → Workers & Pages → Overview → Account ID
	"account_id": "<YOUR_ACCOUNT_ID>",
	"assets": {
		"directory": ".open-next/assets",
		"binding": "ASSETS"
	},
	"services": [
		{
			// @opennextjs/cloudflareのISR/再検証に必要
			"binding": "WORKER_SELF_REFERENCE",
			"service": "<YOUR_WORKER_APP_NAME>"
		}
	],
	"images": {
		"binding": "IMAGES"
	},
	"observability": {
		"logs": {
			"enabled": true,
			"invocation_logs": true
		}
	},
	"vars": {
		"DEPLOYMENT_PLATFORM": "cloudflare"
	},
	// --- Incremental Cache (R2) ---
	// ISR/SSGキャッシングに必要
	"r2_buckets": [
		{
			"binding": "NEXT_INC_CACHE_R2_BUCKET",
			"bucket_name": "<YOUR_BUCKET_NAME>"
		}
	],
	// --- Queue (Durable Objects) ---
	// 時間ベースの再検証(ISR)に必要
	"durable_objects": {
		"bindings": [
			{
				"name": "NEXT_CACHE_DO_QUEUE",
				"class_name": "DOQueueHandler"
			}
		]
	},
	"migrations": [
		{
			"tag": "v1",
			"new_sqlite_classes": [
				"DOQueueHandler"
			]
		}
	],
	// --- Tag Cache (D1) ---
	// オンデマンド再検証(revalidatePath/revalidateTag)に必要
	// D1データベースの作成: npx wrangler d1 create <YOUR_D1_DATABASE_NAME>
	// 作成後、以下のdatabase_idを更新してください
	"d1_databases": [
		{
			"binding": "NEXT_TAG_CACHE_D1",
			"database_name": "<YOUR_D1_DATABASE_NAME>",
			"database_id": "<YOUR_D1_DATABASE_ID>"
		}
	],
  // TCPベースのPostgreSQL接続(Supabase・セルフホスト・TCP経由のNeon)にはHyperdriveを使用します。
  // プロバイダー固有のHTTPドライバー(@neondatabase/serverless など)を使う場合は省略できます。
	"hyperdrive": [
		{
			"binding": "HYPERDRIVE",
			"id": "<YOUR_HYPERDRIVE_ID>",
			"localConnectionString": "<YOUR_POOLER_CONNECTION_STRING>"
		}
	]
}

このファイルをコピーしてwrangler.jsoncとして保存し、以下の項目を編集してください:

  1. name:Workerの名前を任意で設定

  2. compatibility_date:プロジェクト作成日を設定

  3. account_idCloudflare Dashboard → Workers & Pages → Overview → Account IDからコピー

  4. WORKER_SELF_REFERENCE servicenameフィールドと同じ値を設定

  5. NEXT_INC_CACHE_R2_BUCKET bucket_name

npx wrangler r2 bucket create <YOUR_BUCKET_NAME>を実行します(<YOUR_BUCKET_NAME>は任意の名前に変更してください)。作成後に表示されるbucket_nameをここにコピーします。bindingは変更不要です。

  1. d1_databases

npx wrangler d1 create <YOUR_D1_DATABASE_NAME>を実行します(<YOUR_D1_DATABASE_NAME>は任意の名前に変更してください)。作成後に表示されるdatabase_namedatabase_idをコピーします。bindingは変更不要です。

  1. hyperdrive

Neonを使用する場合は、hyperdriveの設定をコメントアウトしてください。Neonはサーバー側でプロキシを設定済みで、@neondatabase/serverlessドライバーによってサーバーレス環境に最適化されているため、Hyperdriveは不要です。

SupabaseやセルフホストのPostgresを使用する場合は、Hyperdriveを有効にしてください。これらは標準的なPostgresサービスであり、接続数の上限やTCPレイテンシの問題があります。以下の手順で設定します:

a. Hyperdriveの作成:Cloudflareダッシュボードの Workers & Pages → Hyperdriveからインスタンスを作成します。

create-hyperdrive
create-hyperdrive

b. Supabaseの設定:ポート5432の直接接続文字列を使用してください(ポート6543のプーラーは使用しないこと)。HyperdriveはすでにコネクションプールなのでSupabaseのプーラー(6543)と組み合わせると二重プールになり、動作が不安定になります。

connect-string

直接接続文字列をHyperdriveに貼り付け、Enable cachingのチェックを外します。

create-hyperdrive

c. IDの設定:生成されたHyperdrive IDをwrangler.jsoncに貼り付けます。

create-hyperdrive

d. ローカル開発localConnectionStringにはポート6543の接続文字列(プーラーURL)を設定します。DATABASE_URL環境変数も同様にポート6543を使用してください。

ステップ3:デプロイと初期設定

NeonでもSupabaseでも手順は同じです。

プロジェクトを作成してデプロイします。

create-application

Project Nameはwrangler.jsoncnameフィールドと一致させてください。

create-application

最初のビルドは必ず失敗します。これは想定内なので心配不要です。

Settingsを開き、ページ下部までスクロールしてGitHub設定を変更します:

  • 本番環境の環境変数をすべて追加します。この作業は手動で行う必要があります。NEXT_PUBLIC_で始まる変数はそのまま追加し、それ以外の変数はEncryptボタンをクリックして暗号化してください。値を入力する際、前後の引用符は含めないでください。
  • Build cacheDisabledに設定します。
create-application

特定のブランチのみビルドをトリガーしたい場合は、Branch controlBuilds for non-production branchesのチェックを外してから、ブランチをプッシュしてください。

create-application

ページ上部に戻り、Domains & Routesでカスタムドメインを追加します。

create-application

ランタイム環境変数の設定も必要です。ダッシュボードでは1件ずつ手動で追加する必要がありますが、テンプレートには一括同期スクリプトが組み込まれています。以下のコマンドを実行するだけで、.envの内容をWorkerに反映できます:

node scripts/sync-env-to-cloudflare.mjs .env

.envの部分を.env.localなどに変更することで、対象のファイルを指定できます。

NEXT_PUBLIC_で始まる変数はBuild環境変数に追加済みのため、ランタイム環境変数への追加は不要です。

環境変数の設定が完了したら、再ビルドします。コードをプッシュするか、Deploymentsから最新のビルドを選択してRetry Buildをクリックしてください。

以上で完了です。カスタムドメインでアプリにアクセスできるようになります。