メインコンテンツへスキップ
kt-tech.blog

【トラブルシューティング】Cloudflare Pages デプロイCI/CDで踏んだ地雷5選

トラブルシューティング9分で読めます

この記事でわかること

  • next-on-pages に --skip-build を付けると壊れる理由(出力先が違う)
  • peer dependency conflict が CI だけで起きる原因と .npmrc での回避
  • nodejs_compat 未設定で 503、ランタイム環境変数未設定で 500 になる切り分け
  • 日本語コミットメッセージだけでデプロイが拒否される件

Next.js を Cloudflare Pages に GitHub Actions でデプロイしようとしていること。なお next-on-pages は現在非推奨です(本文冒頭の注記を参照)。

📌 概要: Cloudflare PagesにNext.jsをGitHub Actions経由でデプロイするCI/CDを構築した際に踏んだ地雷を5つ紹介。.vercel/outputが見つからない、peer dep conflict、nodejs_compat未設定、環境変数の罠、日本語コミットメッセージ拒否など、全てのエラーと解決策をまとめました。

はじめに

Cloudflare PagesへのNext.jsデプロイをGitHub Actionsで自動化しようとしたところ、ビルドは通るのにデプロイが通らない、デプロイは通るのにサイトが動かない、という問題に連続で遭遇した。

1つずつ解決していった記録をまとめる。

注意
これは 2026 年 3 月時点の記録です。現在 @cloudflare/next-on-pages非推奨になり、Cloudflare は OpenNext アダプタへの移行を案内しています。これから新規で組むなら OpenNext で Workers にデプロイする手順 の方を見てください。ただし地雷 3・4・5(nodejs_compat、ランタイム環境変数、コミットメッセージ)は今でも踏みます

地雷1: .vercel/output/config.json が見つからない

エラー

⚡️ 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にビルドを一括で任せる。

YAML
# ❌ 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 }}

地雷2: peer dependency conflict(ERESOLVE)

エラー

npm error ERESOLVE could not resolve
npm error peer next@"~15.0.8 || ~15.1.12" from @opennextjs/[email protected]

原因

next-on-pagesは内部でnpx vercel buildを実行し、そこでnpm installが走る。このとき.npmrclegacy-peer-deps設定が効かず、peer dependency conflictが発生。

不要な@opennextjs/cloudflarepackage.jsonに残っていたのも原因の一つ。

解決策

  1. 不要な依存を削除(@opennextjs/cloudflare, esbuild等)
  2. .npmrcファイルをプロジェクトルートに追加
JavaScript
legacy-peer-deps=true

これでvercel build内部のnpm installでもlegacy-peer-depsが効く。

地雷3: nodejs_compat 未設定で503

エラー

サイトにアクセスすると以下のHTMLが返る:

Error - no nodejs_compat compatibility flag

原因

Cloudflare PagesプロジェクトにNode.js互換フラグが設定されていない。Next.jsはNode.js APIを使うため必須。

解決策

Cloudflare API経由で設定:

Bash
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

地雷4: Pages環境変数が未設定で500

エラー

TOPページは表示されるが、記事詳細ページでInternal Server Error

原因

GitHub Actionsのビルド時にはsecretsで環境変数を渡しているが、Pagesのランタイム(Worker実行時)には環境変数が設定されていない。Edge RuntimeのSSRではリクエスト時にNotion APIを呼ぶため、ランタイムにもNOTION_API_KEY等が必要。

解決策

Cloudflare API経由でPages環境変数を設定:

Bash
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"}}}}}'
重要
ビルド時の環境変数(GitHub Secrets)とランタイムの環境変数(Pages Settings)は別物です。両方設定が必要。ビルドは通るのにページを開くと 500、というときはまずこれを疑ってください。

地雷5: 日本語コミットメッセージで deploy 失敗

エラー

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文字のみのメッセージを明示的に指定:

YAML
- 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 }}"

最終的なワークフロー

YAML
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 }}

Tips

Tips
.npmrc はプロジェクトルートに置く。vercel build が内部で npm install を走らせる際にも読み込まれる
Tips
nodejs_compat と環境変数は、設定しても再デプロイしないと反映されない。設定を直したのに直らないときはこれが原因
Tips
--commit-dirty=true を付けないと警告が出る。ビルド生成物が uncommitted として検出される

参考リンク

まとめ

  • next-on-pagesには--skip-buildを付けず一括ビルドさせる
  • .npmrcでpeer dep conflictを回避
  • nodejs_compatフラグとランタイム環境変数は別途設定が必要
  • 日本語コミットメッセージはwranglerで拒否される
  • 全て解決すれば安定したCI/CDパイプラインが構築できる

更新履歴

  1. next-on-pages が非推奨になったことを冒頭に注記し、それでも残る地雷(3・4・5)を明示。エラーメッセージのコードブロックの言語指定を javascript から text / ini に修正。引用形式のポイントと、太字が壊れていた Tips を callout に統一。参考リンクの節を新設し、関連記事を追加。自動目次を追加。「この記事でわかること」「対象読者」「前提条件」を概要プロパティへ移動。