Cloudflare Workers 静的サイトホスティング - リクエストの流れと課金基準
要約: Workers Static Assetsとは何か、リクエストがどの順序で流れるのか。いつWorkerが動き、いつ課金されるのか。静的サイトに動的処理を重ねる前に知っておくべきこと。

概要
この記事は Cloudflare Workers 静的サイトガイド - デプロイからSEOまで シリーズの一部です。
静的サイトをCloudflareに載せる方法として Workers Static Assets があります。ビルド成果物(dist/)をアップロードすると全世界のエッジでサービングされ、必要なら その前にコードを一枚重ねることができます。
静的ホスティングとして使っているうちに「レスポンスを少し直したい」という要求が生まれたとき、サーバーを新しく立てずに解決できる道です。
この記事で扱うこと
- Workers Static Assetsの構造 — アセットとWorkerコードが一単位でデプロイされる
- リクエストがどの順序で流れるのか — いつWorkerが動き、いつ動かないのか(シーケンス図)
- 課金がどこで発生するのかと無料プランの制限
続きの記事
この記事は構造とデプロイを扱います。残りは別にあります。
- wrangler 使い方 - Cloudflare Workers のローカル開発とデプロイ — インストール · 型設定 ·
wrangler dev· デプロイ - Cloudflare Workers キャッシュ設定方法 - エッジキャッシュとTiered Cache — エッジキャッシュ · Tiered Cache
- React SPA SEO 改善方法 - Cloudflare WorkersでメタタグからSSRまで — メタタグの注入 · サーバーレンダリング
KV・R2・D1のような他のバインディング、Durable Objects、Cron Triggersは範囲外です。
前提
Cloudflareのアカウントがあり、静的サイトをビルドできること(npm run build → dist/)以外に必要な事前知識はありません。
Workers Static Assets とは
一文で言うと「静的ファイルの束 +(任意の)Workerコード」を一単位でデプロイすることです。
1my-worker
2├─ static assets dist/** HTML · JS · CSS · images
3└─ worker code src/worker.ts optional
Workerコードを入れなければ、ただの静的ホスティングです。入れれば、リクエストがアセットに届く前または後にコードを挟み込めます。
Pages と何が違うのか
Cloudflare Pagesも静的ホスティングです。ただしCloudflareが新規の静的ホスティングをWorkers側に寄せているため、アカウントによってはダッシュボードにPages作成の導線がまったく表示されないこともあります。新しく始めるならWorkers Static Assetsの方が無難です。
設定ファイル
wrangler.jsonc 一つで定義します。使えるキーは Configuration ドキュメント にすべてあります。
1{
2 "name": "my-site",
3 "compatibility_date": "2026-09-08",
4
5 // Optional. Omit for pure static hosting.
6 "main": "./src/worker.ts",
7
8 "assets": {
9 // Name of env.ASSETS inside the worker
10 "binding": "ASSETS",
11 // Overridable with --assets
12 "directory": "./dist",
13 "not_found_handling": "single-page-application"
14 }
15}
compatibility_date とは何か
ランタイム動作の基準日(ドキュメント)です。この日付の動作に固定されます — CloudflareがランタイムをアップデートしてもこのWorkerはそのまま動きます。
言い換えると、日付を上げることが「新しい動作を受け入れる」という意思表示です。デプロイのたびに今日の日付へ自動的に変わってはいけません。同じコードを再デプロイするだけで動作が変わってしまうと、ロールバックがロールバックでなくなります。
上げるときは、日付を直す → ローカルで確認する → デプロイする、という順序で人が意図して上げます。
リクエストはどう流れるのか
ここがこの記事の核心です。いつWorkerが動き、いつ動かないのかを知ってはじめて、課金も動作も理解できます。
基本 — Workerコードがないとき
単純です。ファイルがあれば返します。
SPAなら — 存在しないパスをindex.htmlへ
SPAは /products/1234 のようなパスに実際のファイルがありません。ブラウザがJSで描画するからです。そのままにしておくと404です。
not_found_handling: "single-page-application" がこれを解決します。
404ではなく200で index.html を返すという点が重要です。404で返すと検索エンジンがインデックスしません。
Workerコードを重ねると
基本ルールは**「アセットがあればWorkerは動かない」**です。Workerはアセットがないときだけ実行されます。
ところがこの基本ルールには罠があります。/products/1234 のようなSPAパスでWorkerを動かしたくても、アセットルーティングが先に index.html として処理してしまうためWorkerが動きません。そして / は index.html が実際に存在するので、そもそもWorkerを通りません。
run_worker_first — Workerを先に通す
特定のパスでアセットより先にWorkerを実行するよう指定できます。
1{
2 "assets": {
3 "binding": "ASSETS",
4 "not_found_handling": "single-page-application",
5 "run_worker_first": ["/", "/products/*"]
6 }
7}
この構造でWorkerはアセットを代わりにサービングするのではなく、受け取って直して送り出します。 env.ASSETS.fetch(request) がその通路です。
全体の判断順序
SPAルーティングのドキュメント に書かれた順序を整理するとこうなります。
match?} B -->|yes| W[Invoke worker] B -->|no| C{asset exists?} C -->|yes| D[Serve asset
not billable] C -->|no| E{worker script?} E -->|yes| W E -->|no| F{not_found_handling} F -->|single-page-application| G["index.html · 200"] F -->|404-page| H[404 page] F -->|none| I[404]
課金はどこで発生するのか
Billing and limitations の表現が明確です。
Requests are only billable if a Worker script is invoked.
つまり静的アセットのリクエスト自体は課金されません。 JS・CSS・画像をいくらダウンロードされてもリクエスト数にカウントされません。
課金されるのはWorkerが実行されたリクエストだけです。無料プランは1日10万リクエストで、ここにカウントされるのもWorkerが動いたものだけです。
そのため run_worker_first を広く取ると、そのままコストになります。
1// Bad: even /assets/*.js goes through the worker, and becomes billable.
2"run_worker_first": true
3
4// Good: HTML routes only.
5"run_worker_first": ["/", "/products/*"]
無料プランの他の制限も知っておくとよいです(Limits · Pricing)。
| 無料 | 有料($5/月〜) | |
|---|---|---|
| リクエスト | 10万/日 | 1千万/月を含む |
| CPU時間 | 10ms/リクエスト | デフォルト30秒 |
| サブリクエスト | 50/リクエスト | 10,000/リクエスト |
| メモリ | 128MB | 128MB |
CPU 10ms が最もよく引っかかります。ただし名前の通りCPUを実際に使った時間であって、レスポンスにかかった時間ではありません。
CPU time measures how long the CPU spends executing your Worker code. Waiting on network requests (such as
fetch()calls, KV reads, or database queries) does not count toward CPU time.
await fetch(...) でオリジンを待つ時間は上限にカウントされない、という意味です。HTTPリクエストにはduration制限も別途ないので、オリジンが300msかかってもそれ自体は問題になりません。
ヘッダーを直したりタグを挟み込んだりする程度のWorkerなら、CPUはほとんど使いません。サーバーレンダリングのように計算が入るときだけ際どくなります。実際の値が気になるなら推測せず Monitoring CPU usage を見ましょう — Workers Logsのinvocation logにCPU timeとwall timeが並んで記録されます。
まとめ
- Workers Static Assets は静的ファイルの束とWorkerコードを一単位でデプロイするものです。
- 基本ルールは**「アセットがあればWorkerは動かない」**。アセットのパスでWorkerを通したいなら
run_worker_firstで指定します。 - 静的アセットのリクエストは課金されません。 Workerが実行されたリクエストだけがカウントされます。そのため
run_worker_firstを狭く取ることがそのままコストになります。 - CPU 10ms はレスポンス時間ではなくCPUを使った時間です。APIの待ち時間はカウントされません。
次の記事
- wrangler 使い方 - Cloudflare Workers のローカル開発とデプロイ — ローカルで立ち上げてデプロイする方法
- Cloudflare Workers キャッシュ設定方法 - エッジキャッシュとTiered Cache — 外部APIを呼び始めたなら
- React SPA SEO 改善方法 - Cloudflare WorkersでメタタグからSSRまで — メタタグの注入からサーバーレンダリングまで
参考
Static Assets
- Static Assets 概要
- SPAルーティング — リクエストの判断順序
- Assetsバインディング —
env.ASSETS - Billing and limitations — 何が課金されるのか
設定
- Wrangler configuration —
wrangler.jsoncのキー全体 - Compatibility dates
制限