あづみのメモ帳

個人サイトをCloudflare PagesからCloudflare Workersに移行した話

Webサイトを無料でホストしてくれるサービスとして、Cloudflare Pagesが有名であり、このサイトでもPagesを使っていた。しかし、実は現在Pagesは古いサービスというような扱いになっており、Workersでほぼ完全に代替できるようになっている。公式があまりPagesを使ってほしくなさそうなこと、Pagesは色々と苦しい部分もあることから、このサイトも移行することにした。

PagesとWorkersの違い

機能だけを見れば、WorkersはPagesの上位互換である。Workersはサーバ側で何か処理をするためのものというイメージが強く、Pagesとは排他的な関係にあるように思っていた。もちろんそういう機能もあるが、同時に、Pagesのような静的サイトのホスト機能も存在する。PagesでできるほとんどのことはWorkersでもでき、公式としては移行ページを設けていたり新規作成画面ではPagesを隅に追いやっていたりと、Workersのほうに統一していきたいような雰囲気となっている。

分かりやすい違いとしては無料で使えるサブドメインがあり、Pagesでは*.pages.dev(*はプロジェクト名)と比較的すっきりしたドメインだったのに対し、Workersでは*.*.workers.dev(1つめの*はプロジェクト名、2つめの*はユーザ単位で設定する文字列)と長々しいドメインになっていることがある。また、Pagesではこのドメインを無効にすることはできず、独自ドメインを使う場合はリダイレクトする必要があったのに対し、Workersではこのドメインを無効にすることができる。*.pages.devは一見魅力的だが、後述する問題のため独自ドメインを使うことがほぼ必須であるため、これをもってPagesを選択するのは得策ではない。

なんとなくWorkersは難しそうに見えるが、実際はほとんど同じように運用することができる。Pagesは基本的にCloudflare側がビルド、デプロイしてくれることが前提になっており、こちらがすることはGitHubリポジトリにプッシュするだけ、という運用が基本だった。一方、Workersではドキュメントの節々にwranglerコマンドが登場し、ローカルでいろいろ頑張る必要があるような印象を受ける。しかし、実際にはWorkersでもCloudflare側でビルド、デプロイをさせることはできるし、逆に、Pagesでローカルからデプロイすることもできていた。

Pagesでは特にPages用の設定ファイルを用意する必要などはなく、ローカルでビルドできる状態のリポジトリをそのままアップロードし、Webのダッシュボード上でビルドの設定などを行った。一方、WorkersではWeb上の設定のほかwrangler.jsoncという設定ファイルが存在し、設定項目はWebだけで設定できるもの、ファイルだけで設定できるもの、両方で設定できるもの、の3種類存在する。ビルドコマンドをファイルで設定することはできず、ファイルで設定するのは、Workers自体の設定というよりは、デプロイに使用するwranglerコマンドの動作の設定という印象である。静的ファイルのホスト以外にも様々な機能があるため、設定項目も多いのだろう。

項目PagesWorkers
ビルドコマンド、環境変数等Webで設定Webで設定
デプロイWebで成果物ディレクトリを指定Webでコマンドを設定、
ファイルでディレクトリ等指定
無料ドメインの使用強制有効Webまたはファイルで指定
独自ドメインの使用Webで設定Webまたはファイルで指定

Pagesにはこの後挙げるようなかなり苦しい仕様やバグがあり、おそらく今後も放置されるものと思われる。一方、Workersにもちょっとだけ苦しい点がある。非本番ブランチのビルドは、Pagesでは対象ブランチを指定できるが、Workersでは問答無用ですべてのブランチでビルドが走ってしまう。枠は無料でもかなり余裕があるため実害はないが、あまり気分はよくない。また、今回は運用まで漕ぎ着けたので問題ないが、多機能すぎてドキュメントもものすごい量なため、情報の取捨選択が求められる。

設定ファイルを書く

基本的に公式ページに従ってwrangler.jsoncを作る。wranglerコマンドをしばく必要はなく、手動で書けばよい。Astro用のページも用意されているが、Pagesと同様、(静的サイトの場合)ビルドコマンドの指定を除いてAstro専用に何かする必要はない。

自分のサイトでは以下のようなwrangler.jsoncを書いた。ここで、nameは後で作るWorkersプロジェクトの名前と一致させる必要があり、ASCII小文字か数字かハイフンマイナスのみ使用できる。また、preview_urls(プロダクションブランチ以外のデプロイ)、workers_dev(無料サブドメインの使用)、routes(独自ドメインの使用)はWeb上でも設定できる。

{
    "name": "azumino",
    "compatibility_date": "2026-05-25",
    "assets": {
        "directory": "./dist/",
        "not_found_handling": "404-page"
    },
    "preview_urls": true,
    "workers_dev": false,
    "routes": [
        {
            "pattern": "dg7.dev",
            "custom_domain": true
        }
    ]
}

プロジェクトを作る

まずはもとのPagesプロジェクトで余計なビルドが走らないように、自動デプロイを無効にするか違うブランチに設定したうえで、wrangler.jsoncを追加したコミットをプッシュする。

続けて新しいWorkersプロジェクトを作る。GitHubリポジトリを指定し、ビルドコマンドをPagesのときと同じように指定し(自分の場合git fetch --unshallow && bunx --bun astro buildとか入れている)、デプロイコマンドはそのままにする(npx wrangler deploy、後述の理由でbunxはやめたほうがいいかも)。

Pagesですでに使っているドメインをwrangler.jsoncで指定していて有効になっていない(どういう画面だったか覚えてないが)ので、Pagesとドメインとの紐付けを切り離した後、すぐにWorkersで有効化する。もし切り離した状態で問い合わせがありDNSがキャッシュされてしまうと、ネガティブキャッシュ(TTLが設定できず長い)になってしばらく存在しないことになってしまうため、できるだけ素早く切り替える。スクリプトでやってる人もいた。

リダイレクト設定

以上の操作で、独自ドメインを叩けばWorkers上のサイトにアクセスできるようになった。しかし、自分は独自ドメンを取得せず*.pages.devのドメインで運用していた時期があり、各所にこのURLへのリンクが存在してしまっている。このドメインへのアクセスもWorkersに向けなければいけないが、このドメインはPagesプロジェクト以外では利用できないため、リダイレクトのためだけにPagesプロジェクトを一生保持する必要が生じてしまったことになる。このような惨事を防ぐため、これから個人サイトを作る人は独自ドメインを取得しておくことを強くおすすめする。

さて、リダイレクトの方法だが、以下のような_redirectsファイルをルートに配置することで、*.pages.dev上のすべてのページから対応する独自ドメインのURLにリダイレクトさせることができる。

/* https://dg7.dev/:splat 301

配置の方法としては、ブランチを生やしてデプロイ元をそっちに切り替えるか、直接アップロードに切り替えるかすることになる。もしブランチを切り替える方法をとる場合、切り替える前にプッシュしてしまうと、切り替えた後にデプロイを再試行してもproductionに反映されないので注意する。

Gitリポジトリと連携したままにしてあると、自動デプロイが有効でなくてもいちいち一覧の上に上がってきてうざいので、直接アップロードに切り替えるのがよい。しかし驚くべきことに、Pagesではプロジェクトを削除せずにGit連携と直接アップロードとの間を切り替えることはできない。つまり、Pagesプロジェクトを一旦削除して同名で作り直す必要がある。幸い、プロジェクト名はすぐに解放され再利用することができる。

削除するにも一苦労なのがPagesであり、100件を超えるデプロイがあるとプロジェクトを削除できないというわけのわからないバグがある。回避策として、公式がwranglerコマンドでデプロイを削除するスクリプトを用意している。しかし、これはシェルスクリプトであり、また、WSL1ではNode.jsが動かないため、手元の環境では動かせなかった。こんなことのためにWSL2なぞ用意したくないので、JavaScriptで似たようなものを雑に書いてWindows上で動かした。wrangler pages deploy listで取得できるデプロイの数は一度に24件までの制限がある(そうと分かる表示が一切ないので困った)ため、何度もくり返す必要があった(公式スクリプトでもしれっと無限ループで囲まれている)。なお、忘れていただけでArch Linuxの実機環境はあるのでそこでなら公式のスクリプトを回せたはずだし、そうでなくとも、Bunのシェル機能やGit付属の環境やBusyBox for Windowsを使えばWindows上でもシェルスクリプトは使えるはずなので、自力で実装する必要はあまりなかった。

削除できたら、あとは同名でプロジェクトを作り直して、_redirectsファイルだけを直接アップロードすればよい。なお、直接アップロードの場合、内容の変更はダッシュボードからはできず、wranglerコマンドを使う必要がある。特に設定ファイルを用意する必要はなく、npx wrangler pages publish path/to/dir/ --project-name=プロジェクト名でアップロードできる。

ちなみに、wranglerコマンドはbunxだとたまにしかまともに動かないので、Node.jsを入れておく必要がある。Node.jsが入っている環境でbunx--bunなしで叩くと途中でnodeが呼ばれて動いているように見えることもあるため紛らわしい。関連性は不明だが、今回使っていないbun create cloudflare@latestChecking if a newer version is available ...で止まることがあるり、これは--no-auto-updateをつけると回避できる。

あとがき

正直PagesとWorkersとの違いはあまり重要ではなかったが、下手にサービス固有の無料ドメインは使うべきではないというのはひしひしと感じた。これから個人サイトを作ろうという方々も、*.pages.dev目的でPagesを選ぶのはやめて、最初から独自ドメインで運用するか、到達性を捨てる覚悟をしてから使うことをおすすめする。