Cloudflare Workerで数本のAPIを作るだけなら、標準のfetch() handlerだけでも実装できる。
それでもルートが増えると、path parameter、middleware、共通エラー処理のためにrouterやframeworkを置きたくなる。
ここでHonoを選ぶと、実際のworker bundleにはどれだけコードが増えるのだろうか。 package全体の展開サイズではなく、同じAPIをbundleした生成物で比べた。
比較対象はraw Worker、itty-router、Honoの三つである。 Honoだけをraw handlerと比べると中間の選択肢が抜けるため、小さなrouterとしてitty-routerも同じ条件に入れた。
四つのレスポンス契約をそろえる
Cloudflare Workersでは、受け取ったRequestに対してResponseを返すfetch() handlerがHTTPリクエストの入口になる。
HonoのCloudflare Workers向け手順もHono applicationをdefault exportする形を示し、itty-routerもfetchを持つrouterをWorker向けにexportできる。
今回は三つの実装に同じ四経路を持たせた。
| リクエスト | 期待する結果 |
|---|---|
GET /health |
200 { ok: true } |
GET /users/alice%20smith |
200 { id: "alice smith" } |
POST /echo |
JSON bodyをvalueとして返す |
| 存在しないpath | 404 { error: "Not found" } |
bundleサイズだけを合わせても挙動が違えば比較にならない。 計測スクリプトは生成後の各bundleをimportし、この四リクエストを実際に通してstatusとJSONを照合する。
最初の実行ではitty-routerのpath parameterがalice%20smithのまま返ったため、実装側でdecodeURIComponentを明示して契約をそろえた。
この差もrouterを置けばWeb APIの細部がすべて同じになるわけではないことを示している。
同じesbuild設定で一つのESMへまとめる
計測時の依存関係はHono 4.13.3、itty-router 5.0.24、esbuild 0.28.2である。
三つとも次の条件でbundleした。
bundle true
minify true
format esm
platform browser
target es2022
treeShaking true
legalComments none
gzip level 9
platform: browserを使ったのは、三実装がRequest、Response、URLなどのWeb APIだけで動く条件をそろえるためである。
Cloudflareの実際のdeploy pipelineそのものを再現した測定ではない。
再現コマンドは一つである。
pnpm benchmark:worker-routing
生の計測結果はreport.jsonへ生成する。
通常のpnpm buildでも同じbenchmarkを先に実行するため、依存versionだけ更新して古い測定値を残すことはできない。
raw 284 bytesに対してHonoは7,808 bytesだった
2026年8月21日の生成結果は次のようになった。
| 実装 | minify後 | gzip後 | raw比のgzip増加 |
|---|---|---|---|
| Raw Worker | 394 bytes | 284 bytes | 0 bytes |
| itty-router | 1,579 bytes | 851 bytes | +567 bytes |
| Hono | 18,825 bytes | 7,808 bytes | +7,524 bytes |
raw Workerが284 bytesしかないため、比率で見るとitty-routerは約3.0倍、Honoは約27.5倍になる。 しかし基準値が極端に小さい比較では、倍率より絶対差を見た方が実装判断につながる。
itty-routerの追加量はgzip後567 bytesだった。 route定義とparameter抽出を導入しても、この四経路では1KB未満の増加に収まった。
Honoはraw比で7,524 bytes増えた。 これは今回の最小APIに含めていないcontextやmiddlewareを含むframework側コードもbundleへ入るためで、四経路だけならrawやitty-routerより大きい。
Worker bundleはブラウザへ配信するJavaScriptではない
7,808 bytesという数字を、Webページのclient JavaScriptと同じ意味で扱うのは誤りである。 Cloudflare Workersのコードはedge runtimeで実行され、通常のHTTPレスポンスごとにそのbundle全体が利用者へ送信されるわけではない。
今回のgzip値は三実装のコード量を同じ圧縮条件で比較するための指標である。 ページ転送量、Workerの起動時間、requestあたりCPU時間、Cloudflare内部での保存形式は測っていない。
したがって「Honoは7.5KB増えるから遅い」という結論はこの測定から出せない。 性能を判断するには、同じWorkerを実際にdeployしてCPU timeやlatencyを別に測る必要がある。
ルート数より抽象化を使う量で選ぶ
raw Workerは、経路が少なく共通処理も薄いAPIなら最小のまま保ちやすい。 今回のような四経路なら394 bytesの生成物で契約を満たせた。
itty-routerはroute DSLとparameter抽出が欲しい一方、framework全体の機能は要らない場合に中間案になる。 今回の追加コストはgzip後567 bytesで、raw handlerの手書き分岐を減らす対価として小さい。
Honoはmiddleware、context、validator integration、複数runtimeで共通するrouting modelまで使うときに比較対象になる。 Hono公式もCloudflare Workersでapplicationをそのままexportする構成を用意しており、単なるpath matcherより広いframeworkとして設計されている。
その機能を使わない二、三個のendpointだけなら、今回の7,524 bytesは不要な抽象化になり得る。 一方でAPIが増えて独自router、middleware chain、error handlingを自前で育て始めるなら、raw 394 bytesとの比較だけでは保守コストを数え落とす。
このサイトで将来Cloudflare Worker APIが必要になった場合は、単純なendpointならraw handlerかitty-routerから始める。 Hono固有の機能を二つ以上使う設計になった時点でHonoへ切り替え、そこで実際のWorker bundleとCPU timeをもう一度測るのが妥当である。