---
title: "ElysiaJS と Hono のコアな選択、月とスッポン？ いいえ、双璧です"
description: "serverless でバックエンドを書いている人なら、Hono というフレームワークはきっとよく使っているはず。でも、それが唯一の答えとは限りません。いい匂いのする ElysiaJS も、ぜひ一度味見してみてください。"
author: "kidneyweakx"
published: 2025-10-10T00:00:00.000Z
updated: 2026-10-29T11:23:42.393Z
lang: ja
tags: ["serverless", "typescript", "elysia", "hono"]
canonical: https://kidneyweakx.com/blog/elysiajs-and-hono-core-choice?lang=ja
alternate_zh_tw: https://kidneyweakx.com/blog/elysiajs-and-hono-core-choice.md
alternate_en: https://kidneyweakx.com/blog/elysiajs-and-hono-core-choice.md?lang=en
---

# ElysiaJS と Hono のコアな選択、月とスッポン？ いいえ、双璧です

> serverless でバックエンドを書いている人なら、Hono というフレームワークはきっとよく使っているはず。でも、それが唯一の答えとは限りません。いい匂いのする ElysiaJS も、ぜひ一度味見してみてください。

ちょうど手元で両方とも使っています。Solid(ar)ity のバックエンドは **Hono + zod-openapi**、このブログの CMS は **Elysia** で、どちらも Cloudflare Workers 上で動いています。しばらく使ってみて気づいたのは、この 2 つのフレームワークは見た目こそよく似ているものの、コアの取捨選択がまったく違うということ。この記事では benchmark は比べません。比べるのは「**それぞれが何を最優先にしているか**」です。

<br />

## ひとことで言うと

* **Hono：Web 標準ファースト。** コアは `Request` が入って `Response` が出るだけなので、Workers、Deno、Bun、Node とどこでも動く
* **Elysia：型ファースト。** コアは schema から handler、フロントエンドの client まで、型を一本につなげること。Bun がホームグラウンド

どちらも速くて小さい。違いは、その優先順位のために何を犠牲にできるか、です。

## Hono：Workers ではネイティブそのもの

Hono を Workers で使っていて一番快適なのは、**binding が context に直接乗っている**ことです。

```ts
app.get('/posts', async (c) => {
  const index = await c.env.R2.get('index.json')
  return c.json(await index?.json())
})
```

`c.env` はその request の env そのもので、魔法は何もありません。Workers はもともと「binding は request と一緒に動く」という設計で、Hono はちょうどそのモデルどおりに作られているので、プラットフォームとケンカしません。

バリデーションを厳密にしたければ、`@hono/zod-openapi` を足せば OK。schema を 1 回書くだけで、バリデーションと OpenAPI ドキュメントが一緒に出てきます。Solid(ar)ity のバックエンドは外部から連携してもらう前提なので、自動生成される API ドキュメントがあるのはとても重要で、これが当初 Hono を選んだ理由でもあります。

## Elysia：型がフロントエンドまでつながる

Elysia の売りは end-to-end type safety です。TypeBox で schema を書けば、handler の引数や戻り値、さらにはフロントエンドから Eden で API を呼ぶときの型まで、すべて自動で推論されます。**フロントとバックのどちらかを変えると、もう片方が即座に赤線になります。**

フロントもバックも自分で書く小さなプロジェクトなら、この体験は本当に気持ちいいです。フルスタック的には最高。このブログの管理画面も、Svelte のフロントエンドが同じ repo の Elysia API を直接叩いていて、フィールドをひとつ変えると、どこが追従できていないかを TypeScript がすぐに教えてくれます。

<br />

ただし、Elysia を Workers に載せるには、2 か所で妥協が必要です。

**1. AOT をオフにする**

Elysia は速さのために、デフォルトで起動時にコードを動的生成します（AOT compile）。でも Workers は `new Function` / `eval` のような動的コードを禁止しているので、必ずこうします。

```ts
new Elysia({ aot: false })
```

この 1 行がないと、デプロイした瞬間にエラーになります。AOT をオフにすると、Workers 上の Elysia は Bun 上ほど速くはなくなりますが、管理画面ならまったく体感できません。

**2. env は自分で渡す**

Elysia には `c.env` のようなものがありません。私は Worker の `fetch` エントリで、`AsyncLocalStorage` を使って env を包んでいます。

```ts
export default {
  fetch(request, env) {
    return runWithEnv(env, () => app.handle(request))
  },
}
```

handler の中では `useEnv()` で取り出します。これには `nodejs_compat` を有効にして `node:async_hooks` を使えるようにする必要があります。動くことは動くのですが、自前で発明したレイヤーが 1 枚増えるわけで、**こういう接着剤を書きすぎると、それが将来の技術的負債になります**。バックエンドは軽ければ軽いほど、あとでパッチ対応などでアップグレードするときに困ることが少なくて済みます。

## で、どう選ぶ？

私の選び方はシンプルです。

| 状況 | 選ぶもの |
| --- | --- |
| 主に Workers / 複数の runtime で動かす | Hono |
| API を外部に連携してもらう、OpenAPI ドキュメントが必要 | Hono + zod-openapi |
| フロントもバックも自分で書く、同じ repo、主に Bun で動かす | Elysia |
| フロントから API を呼ぶときの型をとても重視する | Elysia + Eden |

<br />

結局のところ、**Hono はプラットフォームに沿って育ったフレームワーク、Elysia は開発体験に沿って育ったフレームワーク**です。Workers 上ではプラットフォームに沿ったほうが摩擦がずっと少なく、Bun 上では Elysia の型体験はなかなか代わりがききません。

もし今ブログの管理画面を書き直すなら、たぶん Hono を選んで、AOT と AsyncLocalStorage という 2 つの接着剤をなくすと思います。とはいえ、当時 Elysia を選んだことも後悔していません。フロントとバックが一緒に赤線になるあの快感は、小さなツールを書くときには本当にたまらないんですよね。
