比較
Cloudflare Pages vs Workers(2026年版): 静的サイトはどちらに置くべきか
· 読了まで約16分
目次
2020年代の大半、「静的サイトを Cloudflare に置く」の答えは一言、Pages でした。Git 連携、無料の帯域、プレビューデプロイ。迷ったらこれ、という定番であり、無数のブログ記事がそう書いてきました。
その答えはもう古くなっています。Cloudflare は新規プロジェクトに Workers を推奨し、Pages への新機能投資はしないと明言しました。この2年は、「Pages を選ぶ理由」だった差分をひたすら埋め続けています。このブログを立ち上げたとき、どこを調べても反射的に Pages と書いてありましたが、私は Workers の静的アセットを選びました。以来、その判断を疑う場面は一度もありません。
この記事は、当時の自分が欲しかった比較です。2026年時点でそれぞれが何なのか、機能ごとの比較表、移行に何が要るのか、そして正直な比較には欠かせない「Pages のままで構わないケース」まで扱います。
結論だけ先に
| 状況 | 選ぶもの |
|---|---|
| 新規の静的サイト | Workers(静的アセット) |
| SSR ルートを含む新規サイト | Workers + フレームワークのアダプタ |
| Pages で問題なく動いている既存サイト | Pages のまま。移行は急がず都合のよいときに |
| Cron Triggers・Queue コンシューマ・段階的ロールアウト・Durable Objects の定義が要る | Workers(Pages には最後まで入りませんでした) |
Pages は非推奨になったのか
違います。そして Pages でサイトを動かしている人には、この区別が実務的な意味を持ちます。Cloudflare は終了日を告知していないし、既存プロジェクトのビルドも配信も止めていない。ドキュメントの Pages のリファレンスも維持されたままです。言われているのは「新機能の開発は Workers に向かう」ことだけです。
非推奨というのは、期限が動き出しているという意味です。ここでは何も動いていません。正確な言葉は凍結でしょう。Pages は2年前と同じことを今日もやるし、これからもやる。ただ、新しいものは全部よそに着地する。移行の期限を心配してこの記事に来たなら、そんなものはありません。この先は落ち着いて比較として読んでください。
Pages に何が起きたのか
Pages が存在したのは、Workers が長らく素のファイルを配れなかったからです。Worker はあくまでスクリプトで、HTML のフォルダをホストしたければ、ファイル配信のコードを自分で書いてアセットを KV に詰めるか、そのために作られた製品を使うかの二択でした。Pages がその製品です。git 連携のビルド、出力ディレクトリの CDN 配信、後には動的な処理のための Pages Functions が加わりました。
そして Workers が、唯一できなかったことをできるようになりました。静的アセット(static assets) です。Worker がファイルのディレクトリを同梱し、Cloudflare がそれを CDN から直接配信する。Worker のコードは不要で、これらのファイルへのリクエストは Free を含む全プランで無料・無制限です。これが入った瞬間、Pages は「ファイルをホストする唯一の方法」から「機能が凍結されたもう1つの方法」になりました。
Cloudflare 自身がはっきり言っています。新規プロジェクトは Workers で始めるべきで、機能投資もそちらへ向かう、と。ドキュメントにも公式の移行ガイドと、Pages の全機能に対する互換表が揃っています。向かう先は2つのプラットフォームではなく、1つです。
それぞれの正体
Pages はホスティング製品です。git リポジトリを繋ぐ(またはフォルダをアップロードする)と Cloudflare がビルドし、出力を CDN から配信します。サーバーサイドのコードは Pages Functions に書きます。functions/ ディレクトリに置いたファイルを、Cloudflare が裏で Worker にコンパイルする仕組みです。
Workers の静的アセットは構図が逆です。すべては Worker であり、その Worker がファイルのディレクトリを持てるようになった。完全な静的サイトなら「Worker」は設定だけの存在で、スクリプトもコールドスタートも実行課金もありません。このブログのデプロイ設定は実質このファイルだけで、これにカスタムドメインのブロックを足せば全部です。
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-site",
"compatibility_date": "2026-07-27",
"assets": {
"directory": "./dist",
"not_found_handling": "404-page"
}
}
後からサーバーサイドのルートが必要になったら、main スクリプトを足すだけで「ファイルも配信する普通の Worker」になります。D1、KV、R2、Queues、Cron Triggers、Durable Objects と、プラットフォームの全部が付いてくる。Workers で始める最大の理由は、個々の機能よりこのアップグレード経路です。
機能比較
| Pages | Workers(静的アセット) | |
|---|---|---|
| 静的ファイル配信 | 無料・無制限 | 無料・無制限 |
| ファイル数上限 | Free 20,000 / 有料 100,000、1ファイル 25MiB | Free 20,000 / 有料 100,000、1ファイル 25MiB |
| git 連携ビルド | あり(Pages CI、Free は月 500 ビルド) | あり(Workers Builds、ビルド時間で計測) |
| プレビューデプロイ | コミットごとのプレビュー URL | バージョンごとのプレビュー URL |
| サーバーサイドコード | Pages Functions(ファイルベースルーティング) | 普通の Worker。変換レイヤーなし |
| Cron Triggers | なし | あり |
| Queue コンシューマ | なし | あり |
| Durable Objects | 既存へのバインドのみ | 定義もバインドも可 |
| 観測性(Workers Logs・Logpush・Tail Workers) | なし | あり |
| スタックトレースのソースマップ | なし | あり |
| Email Workers・Rate Limiting・Image Resizing | なし | あり |
| 段階的デプロイ | なし | あり(バージョン間でトラフィックを配分) |
| ロールバック | あり | あり |
| ブランチごとの固定プレビュー URL | あり | まだ |
| 外部 DNS でのカスタムドメイン | あり(サブドメインのみ) | なし |
| Web Analytics のビーコンが HTML に注入される | される(プロジェクト単位) | されない |
| プラットフォームの新機能 | もう入らない | すべてがまず届く場所 |
4つの行には補足が要ります。
Pages Functions と素の Worker。 Pages Functions は昔から中身は Worker でしたが、変換レイヤーが完全には隠れてくれませんでした。一部のバインディングは遅れて届くか、最後まで来なかった。デバッグは実際に動くものから一段離れた場所で行うことになり、フレームワークのアダプタはこのプラットフォームだけ特別扱いする必要がありました。Workers にはレイヤーがありません。書いたものがそのまま動きます。ツール側も追随していて、アダプタや C3 のテンプレートは今や Workers を最初のターゲットにしています。
段階的デプロイ。 Pages のデプロイは全か無かでした。Workers はトラフィックを2つのバージョンに割合で振り分けられるので、「デプロイして祈る」が「5% に出して様子を見る」に変わります。静的ブログには正直ぜいたく品ですが、サーバーコードのあるサイトでは、障害になるかならないかの分かれ目です。
ビーコンの行。 Pages はプロジェクトで Web Analytics が有効になっていると、配信時に beacon.min.js を HTML へ差し込みます。Workers static assets のレスポンスには、うちのアカウントでは 1 つも入っていませんでした。2 ゾーン 8 ホストを実測して確かめた差で、どちらの製品ドキュメントにも書かれていません。厳格な CSP を敷いたサイトを移すなら、許可すべきサードパーティスクリプトが 1 つ減ります。ただし Bot Fight Mode 由来の注入のほうは両方に入ります。
観測性。 サーバーコードを動かすなら、この行をいちばん重く見ます。そして多くの人が最後に気づく行でもあります。Workers Logs も Logpush も Tail Workers も Workers 専用で、Pages Functions 側のデバッグ手段はそれより貧弱です。ソースマップも効かないので、本番で出るスタックトレースはバンドル後の出力を指したままです。
静的サイトなら、どちらも無料
静的サイトについての答えは短くて、どちらもゼロ、料金は判断材料になりません。静的アセットへのリクエストは両方とも無料・無制限で、Free プランでも同じです。ファイルだけで配信するブログは、どちらの製品に載せてもメーターに触れません。
費用が出るのはサーバーコードが動いたときで、そこから先は両者とも同じ請求になります。Pages Functions へのリクエストは、Workers のリクエストとして課金されるからです。
| Workers Free | Workers 有料 | |
|---|---|---|
| 料金 | $0 | 月 $5 から |
| リクエスト | 1日 10万(UTC 0時にリセット) | 月 1,000万まで込み、超過分は 100万あたり $0.30 |
| CPU 時間 | 1回の呼び出しにつき 10ms | 月 3,000万 CPU-ms まで込み、超過分は 100万あたり $0.02 |
| 1回あたりの CPU 上限 | 10ms | 既定 30秒、最大 5分 |
はっきり差が出るのはビルドのほうです。Pages は Free プランに月 500 ビルド、同時実行1本、タイムアウト20分という枠を与えます。数え方が単純で見通しが立つ。Workers Builds はビルド時間(分)で計測するので、ブログなら実用上問題ないものの、ビルドの多いリポジトリなら先に確かめておくべきです。
この差には簡単な抜け道があって、このサイトが実際にやっているのがそれです。GitHub Actions でビルドして wrangler deploy で送るだけ。ビルドは Cloudflare 側のメーターに一切乗らないので、Pages と Workers のどちらを選んでも請求は変わりません。
それでも Pages でよい場合、むしろ有利な場合
正直に挙げると短いリストですが、確かに存在します。
- 動いている本番サイトは、それ自体が理由になります。 移行は実作業で、切り替えのリスクも実在します。純粋な静的サイトで得られる見返りは、ほぼ将来への備えだけ。Cloudflare も期限を切っていないので、待っている間に Pages の配信が変わることはありません。
- オンボーディングの磨き込み。 リポジトリを繋ぐだけの Pages のフローは、業界でも指折りのスムーズさで知られています。繋ぐリポジトリとフレームワークのプリセットを選んで終わり。設定ファイルは1つも要りません。Workers Builds もその差をほぼ埋めたようですが、Workers は
wrangler.jsoncをコミットしておく前提です。 - DNS を外部で管理している場合。 Workers のカスタムドメインは、ゾーンのネームサーバーが Cloudflare にあることを要求します。Pages なら外部の DNS からの CNAME でカスタムドメインを張れました(ただしサブドメインのみ。apex ドメインは Pages でも Cloudflare のネームサーバーが必要です)。ネームサーバーを動かせない事情があるなら、それだけで決まりです。
- 無料枠のビルド回数。 月 500 ビルドという固定枠は、分単位の計測より数えやすい。前述のとおり、ビルドを外に出してしまえば関係なくなる話ではあります。
- ブランチごとの固定プレビュー URL。 Pages はブランチに変わらないホスト名を割り当てるので、レビュアーにそのまま渡せます。Workers のプレビュー URL はデプロイのたびに変わる。Cloudflare は対応予定に挙げていますが、まだ来ていません。
逆に、外部 DNS とブランチのエイリアスを除けば「Pages にはあって Workers にない機能」はありません。差がつくのは常に Workers の側で、その差は開き続けています。
移行で実際にやること
思うより少なく済みます。どちらも同じビルド出力を配信するので、フレームワークの設定も HTML も _headers も _redirects もそのまま。変わるのはデプロイ設定だけです。
# 移行前: Pages の wrangler.toml
name = "my-site"
pages_build_output_dir = "./dist"
// 移行後: Workers の wrangler.jsonc
{
"name": "my-site",
"compatibility_date": "2026-07-27",
"assets": { "directory": "./dist", "not_found_handling": "404-page" }
}
残りのチェックリストは、Cloudflare の移行ガイドそのままです。
- 404 の扱いが明示的になります。 Pages は 404 ページを自動検出しましたが、Workers では
not_found_handling: "404-page"と書きます。 - 環境変数は付いてきません。 ビルド時の変数はビルドを回す場所で宣言し直し、ランタイムのシークレットは
wrangler secret putで入れ直します。 - カスタムドメインには Cloudflare のネームサーバーが要ります(前述のとおり)。まず
workers.devの URL で Worker の動作を確かめてからホスト名を移す。並行稼働ではなく切り替えとして扱ってください。 - ローカル開発のポートが変わります。
wrangler devは 8787、wrangler pages devは 8788 でした。ハードコードしていた箇所を更新します。 - Pages Functions はそのままでは移りません。
functions/ディレクトリはwrangler pages functions buildでコンパイルし、その出力を Worker のmainに指定します。アセットを配る前に走らせたい処理(認証チェックやログ)があるならrun_worker_first: trueも要ります。アセットを持つ Worker は、既定では自分のコードを呼ばずにファイルを返すからです。
wrangler の設定から独自ドメインの接続、末尾スラッシュの罠まで、ゼロから始める Workers セットアップの一式は、このブログを例にした手順を追ったデプロイガイドに書いてあります。
移行後に手に入るもの
「ただの Worker」であることの地味な利点は、プラットフォームの全機能が製品境界の向こうではなく、設定ブロック1つ先にあることです。
最初に手が伸びるのはレスポンスヘッダーでしょう。_headers ファイルはそのまま動きます。このサイトの Content-Security-Policy もその方式で、スクリプトのハッシュ込みで Worker のコードはゼロです。兄弟分の _redirects も同じ方式で、このサイトの 301 リダイレクトはテキストファイル1枚です。それで足りなくなったら(ルートごとのロジックや nonce が要るなら)、同じデプロイに数行の Worker コードを足すだけで、どこにも引っ越しません。次の一歩は小さな API エンドポイントです。このサイトのトラフィックを返す GA4 の集計エンドポイントは、同じアカウントに同じ CLI でデプロイした小さな Worker です。
その延長線の先にハイブリッド構成があります。静的ページはアセットから無料で配信し、サーバーランタイムは本当に必要な場所にだけ置く。私のディレクトリテーマ Almanac がその形で、閲覧ページは静的、検索と投稿は D1 を使って Worker 側で動いています。似た構成を検討しているなら、このスタックの組み方(英語)にまとめてあります。コンテンツ自体をどこに置くか、git かヘッドレス CMS か D1 かは、別の記事で比較しています。どれも、静的サイトを最初に置いたプラットフォームを離れずに済みました。Workers で始めることの意味は、まさにここにあります。
要するに
Pages は悪くありません。完成しているだけです。今もこれまでどおり動きますし、既存サイトに緊急事態はありません。ただ、Pages をデフォルトにしていた根拠(無料の静的ホスティング、git デプロイ、プレビュー URL)は、今やすべて Workers にも当てはまります。逆に Pages へ最後まで入らなかったもの(Cron、Queues、Durable Objects、段階的ロールアウト、そしてこの先に出てくる何か)は Workers 専用です。
新規サイトなら Workers で始めて、移行そのものをスキップする。既存の Pages サイトなら、次にデプロイ設定を触るついでに移す。設定の差分は十数行で、その先にあるのは Cloudflare が実際に開発を続けているプラットフォームです。