友とコーヒーと嘘と胃袋

  • OpenNextアダプター移行記

    私がCloudflareでホスティングしているNext.jsで作成したアプリのOpenNextアダプター移行が全て完了したので、つらつらと備忘録を記載する。

    背景

    CloudflareプラットフォームにNext.jsをホスティングする場合、Cloudflare Pagesを利用した「@cloudflare/next-on-pages」が定番だった。

    2023年頃より「OpenNext」と呼ばれるVarcel以外のプラットフォームへのデプロイアダプターを提供するプロジェクトが発足され、現在Cloudflareもスポンサードしている。

    上記をスポンサードしていることにより、2025年8月以降「@cloudflare/next-on-pages」が非推奨・アーカイブ化されたので、
    「@cloudflare/next-on-pages」の利用者は、「@opennextjs/cloudflare」ならびにCloudflare Workerへの移行が必要となった。

    The next-on-pages package is deprecated, if you want to deploy a Next.js application on Cloudflare, please use the OpenNext Cloudflare adapter instead.
    (next-on-pages パッケージは非推奨です。Cloudflare に Next.js アプリケーションをデプロイする場合は、代わりにOpenNext Cloudflare アダプターを使用してください。)

    If you have a Next.js application that already uses next-on-pages the OpenNext getting started guide for existing applications presents instructions on how to migrate to the OpenNext adapter.
    (既に next-on-pages を使用している Next.js アプリケーションがある場合は、既存アプリケーション向けの OpenNext 入門ガイドにOpenNext アダプターへの移行方法が記載されています。)

    https://github.com/cloudflare/next-on-pages/blob/main/README.md

    移行理由

    • 2025年8月以降に「@cloudflare/next-on-pages」がアーカイブ化されたことにより、左記以降のメンテナンスが実施されなくなったため。
    • 上記により、Next.js 16以降のアップデートによる不具合が顕在されるようになったため。(もちろん、「@cloudflare/next-on-pages」はNext.js 15以降のサポートは実施していない)
    • 昨今のNext.js 脆弱性問題もあり、「@cloudflare/next-on-pages」を使いづづけることができなくなったため。

    移行方法

    基本的には以下の移行ガイドに従う方針で、移行用ブランチとWorkerを作成した。
    https://opennext.js.org/cloudflare/get-started

    移行用ブランチで検証が完了後、開発環境→本番環境の順番にPages→Workerへの移行を実施した。
    (カスタムドメインをPagesからWorkerに当て直す形で移行したので、移行失敗時は直ぐに切り戻せる)

    最後に旧Pagesの削除を実施し、移行が完了となった。

    移行時の落とし穴

    環境変数の取り扱い

    Pagesでは環境変数の設定箇所は1つだが、Wokersはビルド時に利用する環境変数と、Worker実行時に利用する環境変数の2種類がある。

    現状のアプリのロジックで、ビルド時に利用する環境変数とリクエスト時に利用する環境変数が混在していたので、
    それらを整理する必要があった。※ここが一番大変だった。

    また、ビルド用環境変数については、wrangler.jsonで定義することができないので、注意すること。

    Pagesにデプロイが100以上存在すると、削除できない

    最後にPagesのプロジェクトを削除しようとしたところ、デプロイ数が多すぎるため削除できない旨をエラーが発生した。

    公式ドキュメント曰く既知の問題で、デプロイメントを手動で削除してから、プロジェクトを削除しないといけないらしい。
    https://developers.cloudflare.com/pages/platform/known-issues/#delete-a-project-with-a-high-number-of-deployments

    300以上存在したので、シェルスクリプトを配置して、デプロイメントを一括削除してからプロジェクトを削除することで、正常に削除できた。

    prod_id=""
    while :; do
      ids=$(npx wrangler pages deployment list --project-name <PROJECT_NAME> --json | jq -r '.[].Id')
      to_delete=$(echo "$ids" | grep -v -F -x "$prod_id" | grep .)
      [ -z "$to_delete" ] && { echo "Done. Production: $prod_id"; break; }
      echo "Deleting $(echo "$to_delete" | wc -l | tr -d ' ') deployments..."
      while IFS= read -r id; do
        if ! npx wrangler pages deployment delete "$id" --project-name <PROJECT_NAME> --force 2>&1 | tee /tmp/wrangler-del.log | grep -q "Successfully deleted"; then
          grep -q "active production deployment" /tmp/wrangler-del.log && prod_id="$id"
        fi
      done <<< "$to_delete"
    done