Cloudflare Workerで数本のAPIを作るだけなら、標準のfetch() handlerだけでも実装できる。 それでもルートが増えると、path parameter、middleware、共通エラー処理のためにrouterやframeworkを置きたくなる。

ここでHonoを選ぶと、実際のworker bundleにはどれだけコードが増えるのだろうか。 package全体の展開サイズではなく、同じAPIをbundleした生成物で比べた。

比較対象はraw Workeritty-routerHonoの三つである。 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を使ったのは、三実装がRequestResponseURLなどの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をもう一度測るのが妥当である。