

.vercel/outputが見つからない、peer dep conflict、nodejs_compat未設定、環境変数の罠、日本語コミットメッセージ拒否など、全てのエラーと解決策をまとめました。Cloudflare PagesへのNext.jsデプロイをGitHub Actionsで自動化しようとしたところ、ビルドは通るのにデプロイが通らない、デプロイは通るのにサイトが動かない、という問題に連続で遭遇した。
1つずつ解決していった記録をまとめる。
@cloudflare/next-on-pagesのビルドフローの仕組み
peer dependency conflictの根本原因と解決策
Cloudflare Pages固有の設定(nodejs_compat, 環境変数)
wranglerコマンドの落とし穴
Cloudflare PagesにNext.jsをCI/CDでデプロイしたい方
GitHub Actionsでのデプロイが失敗して困っている方
Next.js 15.x + @cloudflare/next-on-pages
GitHub Actions
wrangler CLI
⚡️ Could not read the '.vercel/output/config.json' file.
⚡️ Please report this at https://github.com/cloudflare/next-on-pages/issues.
npm run build(= next build)は.next/に出力する。@cloudflare/next-on-pages --skip-buildは.vercel/output/を前提とする。この2つは互換性がない。
--skip-buildを外して、next-on-pagesにビルドを一括で任せる。
# ❌ NG: 2段階ビルド
- run: npm run build
- run: npx @cloudflare/next-on-pages --skip-build
# ✅ OK: next-on-pagesに一括
- run: npx @cloudflare/next-on-pages
env:
NOTION_API_KEY: ${{ secrets.NOTION_API_KEY }}
npm error ERESOLVE could not resolve
npm error peer next@"~15.0.8 || ~15.1.12" from @opennextjs/cloudflare@1.17.1
next-on-pagesは内部でnpx vercel buildを実行し、そこでnpm installが走る。このとき.npmrcのlegacy-peer-deps設定が効かず、peer dependency conflictが発生。
不要な@opennextjs/cloudflareがpackage.jsonに残っていたのも原因の一つ。
不要な依存を削除(@opennextjs/cloudflare, esbuild等)
.npmrcファイルをプロジェクトルートに追加
legacy-peer-deps=true
これでvercel build内部のnpm installでもlegacy-peer-depsが効く。
サイトにアクセスすると以下のHTMLが返る:
Error - no nodejs_compat compatibility flag
Cloudflare PagesプロジェクトにNode.js互換フラグが設定されていない。Next.jsはNode.js APIを使うため必須。
Cloudflare API経由で設定:
curl -X PATCH "https://api.cloudflare.com/client/v4/accounts/{account_id}/pages/projects/{project_name}" \
-H "Authorization: Bearer {api_token}" \
-H "Content-Type: application/json" \
-d '{"deployment_configs":{"production":{"compatibility_flags":["nodejs_compat"],"compatibility_date":"2024-09-23"}}}'
またはダッシュボードから: Workers & Pages → プロジェクト → Settings → Functions → Compatibility flags
TOPページは表示されるが、記事詳細ページでInternal Server Error。
GitHub Actionsのビルド時にはsecretsで環境変数を渡しているが、Pagesのランタイム(Worker実行時)には環境変数が設定されていない。Edge RuntimeのSSRではリクエスト時にNotion APIを呼ぶため、ランタイムにもNOTION_API_KEY等が必要。
Cloudflare API経由でPages環境変数を設定:
curl -X PATCH "https://api.cloudflare.com/client/v4/accounts/{account_id}/pages/projects/{project_name}" \
-H "Authorization: Bearer {api_token}" \
-H "Content-Type: application/json" \
-d '{"deployment_configs":{"production":{"env_vars":{"NOTION_API_KEY":{"value":"[API_KEY]","type":"secret_text"},"NOTION_DATABASE_ID":{"value":"[DB_ID]","type":"plain_text"}}}}}'
A request to the Cloudflare API failed.
Invalid commit message, it must be a valid UTF-8 string. [code: 8000111]
wrangler pages deployがgitのコミットメッセージを自動取得してCloudflare APIに送信する。日本語のコミットメッセージがCloudflare API側で拒否される。
--commit-messageオプションでASCII文字のみのメッセージを明示的に指定:
- name: Deploy to Cloudflare Pages
run: npx wrangler pages deploy .vercel/output/static \
--project-name=my-project \
--commit-dirty=true \
--commit-message="deploy ${{ github.sha }}"
name: Deploy to Cloudflare Pages
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci --legacy-peer-deps
- name: Build for Cloudflare Pages
run: npx @cloudflare/next-on-pages
env:
NOTION_API_KEY: ${{ secrets.NOTION_API_KEY }}
NOTION_DATABASE_ID: ${{ secrets.NOTION_DATABASE_ID }}
- name: Deploy
run: npx wrangler pages deploy .vercel/output/static --project-name=my-project --commit-dirty=true --commit-message="deploy ${{ github.sha }}"
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
.npmrcはプロジェクトルートに置く。 vercel buildが内部でnpm installを走らせる際にも読み込まれる
nodejs_compatと環境変数はデプロイ後に設定しても再デプロイが必要。 設定変更だけでは既存デプロイに反映されない
--commit-dirty=trueを付けないと警告が出る。 ビルド生成物がuncommittedとして検出される
next-on-pagesには--skip-buildを付けず一括ビルドさせる
.npmrcでpeer dep conflictを回避
nodejs_compatフラグとランタイム環境変数は別途設定が必要
日本語コミットメッセージはwranglerで拒否される
全て解決すれば安定したCI/CDパイプラインが構築できる