Hono vs Elysia — 次世代エッジ対応Webフレームワーク徹底比較
1. 結論
Cloudflare Workers・Deno・Vercel Edge Functionsなど多様なランタイムで動かしたいなら Hono、Bun に特化して最大限のパフォーマンスと型安全な開発体験を追求するなら Elysia を選んでください。どちらも軽量・高速で Express の後継として十分な実力を持ちますが、「どこで動かすか」と「どこまで型に頼りたいか」が選択の分岐点になります。
2. 比較表
| 観点 | Hono | Elysia |
|---|---|---|
| GitHub Stars(2025年6月時点) | ≈ 24k+ | ≈ 12k+ |
| 対応ランタイム | Bun, Deno, Cloudflare Workers, Vercel Edge, AWS Lambda, Node.js など | Bun 最優先(Node.js は互換レイヤー経由) |
| TypeScript 対応 | ◎(型推論付きルーティング) | ◎(End-to-End 型安全、型レベルバリデーション) |
| バリデーション | Zod / Valibot 等を Middleware で統合 | 組み込み(t スキーマ — TypeBox ベース) |
| バンドルサイズ(コア) | ≈ 14 KB (minified) | ≈ 30 KB (minified) |
| ベンチマーク(Bun 上) | 非常に高速 | Bun 最適化によりさらに高速 |
| ミドルウェアエコシステム | 公式 40+ 種(JWT, CORS, OpenAPI 等) | プラグインシステム(Eden, Swagger, GraphQL 等) |
| RPC / クライアント連携 | hono/client(型付き RPC) | Eden Treaty(型付き RPC) |
| OpenAPI / Swagger | @hono/zod-openapi | 組み込みプラグイン |
| 学習コスト | 低い(Express ライクな API) | やや高い(独自のデコレータ・ライフサイクル) |
| 本番採用実績 | Cloudflare 公式推奨、多数の企業採用 | Bun エコシステムで急成長中 |
3. それぞれの強み
Hono の強み
-
マルチランタイム対応が圧倒的 Cloudflare Workers、Deno Deploy、AWS Lambda、Vercel Edge Functions、Fastly Compute — 一つのコードベースでほぼすべてのエッジ環境に対応できます。Web Standards(
Request/Response)に忠実な設計がこれを可能にしています。 -
Express からの移行が容易
app.get()/app.post()/c.json()といった API は Express 経験者なら直感的に理解できます。 -
軽量なコアと豊富な公式ミドルウェア コア自体は極めて小さく、必要な機能だけをインポートする設計です。公式が提供するミドルウェアは 40 種以上あり、JWT 認証、CORS、ETag、キャッシュなど実務で必要なものが揃っています。
-
JSX / SSR サポート
hono/jsxにより React ライクな JSX をサーバーサイドで使えます。hono/htmlによるストリーミング SSR も可能で、フルスタック開発にも対応します。
Elysia の強み
-
End-to-End の型安全性 ルート定義 → バリデーション → レスポンス → クライアント(Eden Treaty)まで、すべてが TypeScript の型で繋がります。スキーマを一度書けば、型定義・バリデーション・OpenAPI ドキュメントが自動生成されます。
-
Bun 上での極限パフォーマンス Bun のネイティブ API を直接活用するため、Bun 環境では他のフレームワークを上回るスループットを記録します。
-
宣言的なプラグインシステム
.use()でプラグインをチェーンするだけで機能が追加され、プラグインが追加した型情報が自動的に伝播します。 -
組み込みバリデーションの一貫性 外部ライブラリに依存せず、
t.Object()/t.String()などの TypeBox ベースのスキーマで統一的にバリデーションを記述できます。
4. コード例で比較
お題:ユーザー作成 API(POST /users)
入力バリデーション付きで、型安全にリクエストを処理する例を示します。
Hono(Zod バリデーション + 型付き RPC)
// server.ts
import { Hono } from "hono";
import { zValidator } from "@hono/zod-validator";
import { z } from "zod";
const userSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
age: z.number().int().min(0).optional(),
});
const app = new Hono()
.post(
"/users",
zValidator("json", userSchema),
async (c) => {
// body は { name: string; email: string; age?: number } と推論される
const body = c.req.valid("json");
// DB 保存処理(省略)
const newUser = { id: crypto.randomUUID(), ...body };
return c.json({ user: newUser }, 201);
}
)
.get("/users/:id", async (c) => {
const id = c.req.param("id"); // string と推論
// DB 取得処理(省略)
return c.json({ user: { id, name: "Taro", email: "taro@example.com" } });
});
export type AppType = typeof app;
export default app;
// client.ts — 型付き RPC クライアント
import { hc } from "hono/client";
import type { AppType } from "./server";
const client = hc<AppType>("http://localhost:3000");
const res = await client.users.$post({
json: {
name: "Taro",
email: "taro@example.com",
age: 30,
},
});
const data = await res.json();
// data.user.id — 型が推論される
console.log(data.user.id);
Elysia(組み込みバリデーション + Eden Treaty)
// server.ts
import { Elysia, t } from "elysia";
const app = new Elysia()
.post(
"/users",
async ({ body }) => {
// body は { name: string; email: string; age?: number } と推論される
const newUser = { id: crypto.randomUUID(), ...body };
return { user: newUser };
},
{
body: t.Object({
name: t.String({ minLength: 1, maxLength: 100 }),
email: t.String({ format: "email" }),
age: t.Optional(t.Integer({ minimum: 0 })),
}),
response: {
201: t.Object({
user: t.Object({
id: t.String(),
name: t.String(),
email: t.String(),
age: t.Optional(t.Integer()),
}),
}),
},
}
)
.get(
"/users/:id",
async ({ params }) => {
// params.id — string と推論される
return {
user: { id: params.id, name: "Taro", email: "taro@example.com" },
};
},
{
params: t.Object({
id: t.String(),
}),
}
)
.listen(3000);
export type App = typeof app;
// client.ts — Eden Treaty クライアント
import { treaty } from "@elysiajs/eden";
import type { App } from "./server";
const client = treaty<App>("http://localhost:3000");
const { data, error } = await client.users.post({
name: "Taro",
email: "taro@example.com",
age: 30,
});
if (data) {
// data.user.id — 型が推論される
console.log(data.user.id);
}
コード比較のポイント
| 観点 | Hono | Elysia |
|---|---|---|
| バリデーション定義 | Zod スキーマを別途定義 → zValidator で接続 | ルート定義のオプションに直接記述 |
| レスポンス型定義 | 戻り値から自動推論 | response で明示的にスキーマ定義も可能 |
| クライアント RPC | hc() — fetch ベースの薄いラッパー | treaty() — { data, error } パターン |
| エラーハンドリング | HTTP Response をそのまま返す | 構造化された error オブジェクト |
5. どちらを選ぶべきか — ユースケース別推奨
✅ Hono を選ぶべきケース
| ユースケース | 理由 |
|---|---|
| Cloudflare Workers / Pages にデプロイ | 公式推奨フレームワーク。Wrangler との統合もスムーズ |
| マルチランタイム対応が必要 | 同一コードを Deno Deploy、AWS Lambda、Vercel Edge 等に展開可能 |
| Express からの段階的移行 | API が似ており、既存の Express ミドルウェアの知見が活かせる |
| SSR / フルスタック開発 | hono/jsx や HonoX によるサーバーサイドレンダリング対応 |
| チームに Bun 以外のランタイム経験者が多い | Node.js / Deno 経験者がすぐに馴染める |
✅ Elysia を選ぶべきケース
| ユースケース | 理由 |
|---|---|
| Bun で統一した開発環境 | Bun のネイティブ最適化を最大限に活用できる |
| End-to-End 型安全を最優先 | スキーマ定義一つで型・バリデーション・ドキュメントが完結 |
| tRPC 的な開発体験が欲しい | Eden Treaty による型付き RPC が非常に強力 |
| OpenAPI ドキュメント自動生成を重視 | スキーマ定義から Swagger UI を自動生成 |
| 小〜中規模の API サーバー | 宣言的な記述で少ないコード量で高品質な API を構築可能 |
⚠️ 判断に迷ったら
- ランタイムが決まっていない / 将来変わる可能性がある → Hono
- Bun 一択で、型安全性を極限まで追求したい → Elysia
- チームの TypeScript 習熟度が高くない → Hono(API がシンプル)
6. まとめ
Hono と Elysia はどちらも「Express の次」を担う次世代フレームワークですが、設計思想が明確に異なります。
Hono は「Web Standards に準拠し、どこでも動く」ことを最優先にしています。Cloudflare Workers の公式推奨という強力な後ろ盾もあり、エッジコンピューティング時代のデファクトスタンダードになりつつあります。マルチランタイム対応が必要なプロジェクトや、Express からの移行先として最も安全な選択肢です。
Elysia は「Bun 上での最高の開発体験」に全振りしています。TypeBox ベースの組み込みバリデーション、Eden Treaty による End-to-End 型安全、そして Bun ネイティブの圧倒的なパフォーマンスは、Bun エコシステムにコミットするチームにとって非常に魅力的です。
どちらも活発に開発が続いており、2025年現在のエッジ対応フレームワークとしてはトップクラスの完成度です。まずは自分のプロジェクトのデプロイ先ランタイムとチームが求める型安全性のレベルを明確にし、それに合った方を選んでみてください。