hono vs elysia 徹底比較

hono の詳細elysia の詳細
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

Hono vs Elysia — 次世代エッジ対応Webフレームワーク徹底比較

1. 結論

Cloudflare Workers・Deno・Vercel Edge Functionsなど多様なランタイムで動かしたいなら Hono、Bun に特化して最大限のパフォーマンスと型安全な開発体験を追求するなら Elysia を選んでください。どちらも軽量・高速で Express の後継として十分な実力を持ちますが、「どこで動かすか」と「どこまで型に頼りたいか」が選択の分岐点になります。


2. 比較表

観点HonoElysia
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);
}

コード比較のポイント

観点HonoElysia
バリデーション定義Zod スキーマを別途定義 → zValidator で接続ルート定義のオプションに直接記述
レスポンス型定義戻り値から自動推論response で明示的にスキーマ定義も可能
クライアント RPChc() — 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年現在のエッジ対応フレームワークとしてはトップクラスの完成度です。まずは自分のプロジェクトのデプロイ先ランタイムチームが求める型安全性のレベルを明確にし、それに合った方を選んでみてください。