アダプタとデプロイ
Hono のコアは Web 標準(Request/Response)。各ランタイムが少しずつ違うので、
その差を埋めるアダプタで繋ぐ。「コードはそのまま、デプロイ先だけ変える」が現実になる。
主なアダプタ一覧
| ランタイム | アダプタ | 備考 |
|---|---|---|
| Cloudflare Workers | 不要(Hono コア) | 標準対応 |
| Cloudflare Pages | 不要(_worker.js / Pages Functions) | 標準対応 |
| Bun | 不要(Bun.serve) | 標準対応 |
| Deno | 不要(Deno.serve) | 標準対応 |
| Node.js | @hono/node-server | fetch を Node に翻訳 |
| AWS Lambda | hono/aws-lambda | API Gateway / Function URL |
| Lambda@Edge | hono/lambda-edge | CloudFront |
| Vercel Edge | 不要(標準 Web Handler) | 標準対応 |
| Netlify | hono/netlify | Edge Functions |
| Fastly Compute | hono/fastly | |
| Service Worker | 不要 | ブラウザ内実行も可能 |
Cloudflare Workers
import { Hono } from "hono"
type Bindings = {
DB: D1Database
KV: KVNamespace
AI: Ai
}
const app = new Hono<{ Bindings: Bindings }>()
app.get("/", (c) => c.text("Hello from CF Workers"))
export default app
wrangler.toml
name = "my-hono-app"
main = "src/index.ts"
compatibility_date = "2026-05-01"
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "..."
[[kv_namespaces]]
binding = "KV"
id = "..."
[ai]
binding = "AI"
デプロイ
npm install -g wrangler
wrangler login
wrangler deploy
Cloudflare Pages(Functions)
既存の静的サイトに API を足したい時。functions/[[path]].ts でキャッチオール。
import { Hono } from "hono"
import { handle } from "hono/cloudflare-pages"
const app = new Hono().basePath("/api")
app.get("/hello", (c) => c.text("Hello"))
export const onRequest = handle(app)
Bun
import { Hono } from "hono"
const app = new Hono()
app.get("/", (c) => c.text("Bun + Hono"))
export default app
bun run --hot src/index.ts
Deno
import { Hono } from "npm:hono"
const app = new Hono()
app.get("/", (c) => c.text("Deno + Hono"))
Deno.serve(app.fetch)
deno run --allow-net main.ts
Deno Deploy
deno deploy CLI または Deno Deploy ダッシュボードで GitHub 連携。
Node.js
npm install hono @hono/node-server
import { serve } from "@hono/node-server"
import { Hono } from "hono"
const app = new Hono()
app.get("/", (c) => c.text("Node + Hono"))
serve({ fetch: app.fetch, port: 3000 }, (info) => {
console.log(`http://localhost:${info.port}`)
})
静的ファイル
import { serveStatic } from "@hono/node-server/serve-static"
app.use("/static/*", serveStatic({ root: "./public" }))
AWS Lambda
import { Hono } from "hono"
import { handle } from "hono/aws-lambda"
const app = new Hono()
app.get("/", (c) => c.text("Lambda + Hono"))
export const handler = handle(app)
SST / AWS CDK / Serverless Framework でデプロイ。Function URL(API Gateway 不要)でも動く。
Vercel
import { Hono } from "hono"
const app = new Hono().basePath("/api")
app.get("/hello", (c) => c.json({ ok: true }))
export const config = { runtime: "edge" } // Edge Runtime
export default app.fetch
Netlify
import { Hono } from "https://deno.land/x/hono/mod.ts"
import { handle } from "https://deno.land/x/hono/adapter/netlify/mod.ts"
const app = new Hono()
app.get("*", (c) => c.text("Netlify Edge"))
export default handle(app)
export const config = { path: "/api/*" }
環境変数の扱いの違い
| 環境 | アクセス |
|---|---|
| Cloudflare Workers | c.env.MY_VAR |
| Bun / Deno / Node | process.env / Bun.env / Deno.env.get(...) |
| Vercel | process.env |
| Lambda | process.env |
移植性のために、初期化時に環境変数を吸収するレイヤを作っておくと楽:
function getEnv(c: any, key: string) {
if (c.env && key in c.env) return c.env[key]
if (typeof process !== "undefined" && process.env[key]) return process.env[key]
return undefined
}
WebSocket
WebSocket 対応はランタイム依存:
- Cloudflare Workers:
WebSocketPairを使う(Durable Objects と組み合わせると強力) - Bun:
upgradeで対応 - Deno:
Deno.upgradeWebSocket - Node.js:
@hono/node-wsまたはwsライブラリ
テスト
import { describe, it, expect } from "vitest"
import app from "../src/index"
describe("API", () => {
it("GET /", async () => {
const res = await app.request("/")
expect(res.status).toBe(200)
expect(await res.text()).toBe("Hello")
})
it("POST /users", async () => {
const res = await app.request("/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "A", email: "a@b.c" }),
})
expect(res.status).toBe(201)
})
})
app.request() でランタイム不要のテストが可能。fetch を直接受ける形なので超簡単。
マルチランタイム同時対応
同じコードを複数ランタイムに出すパターン。エントリポイントだけ分ける:
src/
├── app.ts ← 共通の Hono アプリ
├── cloudflare.ts ← export default app
├── node.ts ← serve(app)
└── lambda.ts ← handle(app)
ローカル開発
- Cloudflare:
wrangler dev - Bun:
bun --hot run src/index.ts - Deno:
deno run --watch --allow-net main.ts - Node:
tsx watch src/index.ts
- サーバレスでフリーティアを最大化: Cloudflare Workers
- Bun のパフォーマンス: Bun + Fly.io / Railway
- 既存の Node エコシステム: Node + Render / Railway
- AWS が会社標準: Lambda + Function URL