【2026年版】Hono.js入門ガイド|Cloudflare Workers + TypeScript で超高速APIを作る
2026年3月23日 · TechTools Lab編集部
個人開発でバックエンドAPIを作るとき、何を使えばいいか迷ったことはありませんか?Express.jsはNode.jsに縛られ、Next.jsはフロントも込みで重い。「もっとシンプルに、もっと速く、どこでも動くものが欲しい」——そんな要求に応えるのが Hono.js です。
Hono(炎)は日本人開発者が作った超軽量Webフレームワーク。Cloudflare Workers・Bun・Deno・Node.js・AWS Lambdaなど複数のランタイムで動作し、TypeScriptファーストで設計されています。2026年現在、個人開発者の間で急速に普及しており、GitHubスターも2万を超えています。
本記事では、Hono + Cloudflare Workers + TypeScript の組み合わせで実践的なAPIを作る方法を、セットアップからデプロイまで丁寧に解説します。
Hono.jsとは? なぜ2026年に選ぶべきか
Honoの特徴を一言で表すなら「Web標準に従った、どこでも動く軽量フレームワーク」です。Node.js独自のAPIではなく、ブラウザでも使われる標準のWeb API(Request/Response/Headers)をベースに設計されているため、ランタイムを選びません。
主な特徴
- 超高速 — ベンチマークでExpress.jsの約10倍のスループット。Cloudflare Workersのエッジで動くとさらに有利
- 超軽量 — コアバンドルサイズは約14KB。Cloudflare Workers の1MBスクリプト制限にも余裕で収まる
- TypeScriptファースト — 型定義が充実しており、IDEの補完が効いて開発体験が良い
- マルチランタイム — Cloudflare Workers・Bun・Deno・Node.js・Fastly Compute@Edgeで動作
- 豊富なミドルウェア — CORS・認証・Zod バリデーション・JWT など公式ミドルウェアが揃っている
Express.js・Fastify との比較
| 項目 |
Hono |
Express |
Fastify |
| ランタイム |
マルチ(CF Workers含む) |
Node.jsのみ |
Node.jsのみ |
| TypeScript |
ネイティブ |
@types必要 |
対応 |
| バンドルサイズ |
〜14KB |
〜220KB |
〜400KB |
| Web標準API |
✅ 完全準拠 |
❌ 独自実装 |
△ 一部 |
個人開発でCloudflare Workersを使うなら、HonoはExpressより圧倒的に相性が良いです。
セットアップ:Cloudflare Workers + Hono プロジェクトを作る
前提として、Node.js 18以上とCloudflareアカウントが必要です。Cloudflareのアカウントは無料で作れます。
ステップ1:Wranglerをインストール
Cloudflare Workers の公式CLIである Wrangler をインストールします。
npm install -g wrangler
wrangler login
wrangler login でブラウザが開き、Cloudflareアカウントでログインします。
ステップ2:Honoプロジェクトを作成
Honoの公式CLIでプロジェクトを雛形から作れます。
npm create hono@latest my-api
# テンプレート選択: cloudflare-workers を選ぶ
cd my-api
npm install
生成されたファイル構成はこうなります:
my-api/
├── src/
│ └── index.ts # エントリーポイント
├── wrangler.toml # Workers設定
├── package.json
└── tsconfig.json
ステップ3:最初のHelloWorld
生成された src/index.ts を確認してみましょう。
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => {
return c.text('Hello Hono!')
})
export default app
たったこれだけです。cはコンテキストオブジェクトで、リクエスト・レスポンス・環境変数へのアクセスを統一的に提供します。ローカルで動かすには:
npm run dev
# http://localhost:8787 でアクセス可能
広告
ConoHa WING
初期費用無料の高速クラウドサーバー
最大3,500円還元
詳しく見る →
ルーティング:RESTful APIを設計する
HonoのルーティングはExpressによく似ていますが、TypeScriptの型推論が強力です。
基本的なHTTPメソッド
import { Hono } from 'hono'
const app = new Hono()
// GETリクエスト
app.get('/users', (c) => {
return c.json({ users: ['Alice', 'Bob'] })
})
// パスパラメータ
app.get('/users/:id', (c) => {
const id = c.req.param('id')
return c.json({ id, name: 'Alice' })
})
// POSTリクエスト(BodyはJSONで受け取る)
app.post('/users', async (c) => {
const body = await c.req.json()
return c.json({ created: body }, 201)
})
// PUTとDELETE
app.put('/users/:id', async (c) => { /* ... */ })
app.delete('/users/:id', (c) => { /* ... */ })
export default app
ルートグループ化でコードを整理
APIが大きくなってきたら、Honoインスタンスをルート別に分割してマウントできます。
// routes/users.ts
import { Hono } from 'hono'
const users = new Hono()
users.get('/', (c) => c.json({ users: [] }))
users.get('/:id', (c) => c.json({ id: c.req.param('id') }))
export default users
// src/index.ts
import { Hono } from 'hono'
import users from './routes/users'
const app = new Hono()
app.route('/users', users) // /users/* にマウント
export default app
ミドルウェア:CORS・認証・ロギングを追加
Honoには公式ミドルウェアが充実しています。hono/middlewareから必要なものをインポートするだけです。
CORSミドルウェア
フロントエンドからAPIを叩くときに必須のCORSを一行で追加できます。
import { cors } from 'hono/cors'
app.use('/api/*', cors({
origin: ['https://yourapp.pages.dev'],
allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
}))
// 全ルートに適用するなら
app.use('*', cors())
Bearer Token認証
import { bearerAuth } from 'hono/bearer-auth'
app.use('/admin/*', bearerAuth({
token: 'my-secret-token' // 実際はenv変数から取得
}))
カスタムミドルウェア(ロギング)
独自のミドルウェアも簡単に書けます。next()で次の処理に進む点はExpressと同じです。
app.use('*', async (c, next) => {
const start = Date.now()
await next()
const ms = Date.now() - start
console.log(`${c.req.method} ${c.req.url} - ${c.res.status} (${ms}ms)`)
})
バリデーション:Zodで型安全なリクエスト処理
リクエストボディのバリデーションにはZodとの組み合わせが定番です。@hono/zod-validatorを使うと、バリデーション失敗時に自動で400エラーを返してくれます。
npm install zod @hono/zod-validator
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
const createUserSchema = z.object({
name: z.string().min(1).max(50),
email: z.string().email(),
age: z.number().int().min(18).optional(),
})
app.post(
'/users',
zValidator('json', createUserSchema),
async (c) => {
// バリデーション済みの型安全
なデータ
const data = c.req.valid('json')
// data.name, data.email は型推論が効いている
return c.json({ created: data }, 201)
}
)
これでバリデーション漏れによるバグを型レベルで防げます。個人開発でも手抜きせずに入れておくべき仕組みです。
広告
ConoHa WING
初期費用無料の高速クラウドサーバー
最大3,500円還元
詳しく見る →
Cloudflare D1・KVとの連携
Cloudflare WorkersにはD1(SQLiteベースのDB)やKV(キー・バリューストア)が統合されています。Honoと組み合わせると、データベース付きAPIをサーバーレスで無料運用できます。
D1(SQLiteデータベース)を使う
まずwrangler.tomlにD1の設定を追加します。
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Honoのコンテキストから環境変数経由でD1にアクセスします。
type Bindings = {
DB: D1Database
}
const app = new Hono<{ Bindings: Bindings }>()
app.get('/users', async (c) => {
const db = c.env.DB
const { results } = await db
.prepare('SELECT * FROM users LIMIT 10')
.all()
return c.json(results)
})
app.post('/users', async (c) => {
const { name, email } = await c.req.json()
const db = c.env.DB
await db
.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
.bind(name, email)
.run()
return c.json({ message: 'Created' }, 201)
})
KV(キー・バリューストア)でキャッシュ
type Bindings = {
CACHE: KVNamespace
}
app.get('/config', async (c) => {
const cached = await c.env.CACHE.get('config')
if (cached) return c.json(JSON.parse(cached))
// DB等から取得してキャッシュ
const config = { theme: 'dark', lang: 'ja' }
await c.env.CACHE.put('config', JSON.stringify(config), {
expirationTtl: 3600 // 1時間
})
return c.json(config)
})
D1の無料枠は1日50,000回の読み込み・10万行のストレージまで無料です。個人開発の規模なら十分すぎるほどです。
エラーハンドリングとHTTP例外
Honoには組み込みのHTTP例外クラスがあります。Expressのようにres.status(404).json(...)と書く必要がなく、コードが簡潔になります。
import { HTTPException } from 'hono/http-exception'
app.get('/users/:id', async (c) => {
const id = c.req.param('id')
const user = await findUser(id)
if (!user) {
throw new HTTPException(404, { message: 'User not found' })
}
return c.json(user)
})
// グローバルエラーハンドラ
app.onError((err, c) => {
if (err instanceof HTTPException) {
return c.json({ error: err.message }, err.status)
}
console.error(err)
return c.json({ error: 'Internal server error' }, 500)
})
グローバルエラーハンドラを設定しておくことで、内部の詳細エラーをユーザーに見せずに済みます。セキュリティ面でも重要な実装です。
デプロイ:本番環境へ公開する
デプロイはコマンド一発です。
npm run deploy
# または
wrangler deploy<
/code>
デプロイが成功すると、https://my-api.your-account.workers.dev のようなURLが発行されます。カスタムドメインも無料で設定できます。
シークレットの管理
APIキーなどの機密情報はwrangler.tomlに書かず、wrangler secretコマンドで管理します。
# シークレットをセット(入力は非表示)
wrangler secret put API_KEY
# シークレット一覧を確認
wrangler secret list
コード内ではc.env.API_KEYでアクセスできます。Gitに機密情報を含めない運用ができます。
実践例:WebページのステータスチェックAPIを作る
最後に、実用的な例として「URLの死活監視APIエンドポイント」を作ってみましょう。ユーザーが登録したURLを定期チェックするAPI——これはまさに、当サイトで紹介している PagePulse(Webページ変更監視ツール)のようなサービスのバックエンドに使えるアーキテクチャです。
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'
import { cors } from 'hono/cors'
type Bindings = {
DB: D1Database
}
const app = new Hono<{ Bindings: Bindings }>()
app.use('*', cors({
origin: ['https://your-frontend.pages.dev'],
}))
// URL登録
const registerSchema = z.object({
url: z.string().url(),
label: z.string().max(100).optional(),
})
app.post('/monitors', zValidator('json', registerSchema), async (c) => {
const { url, label } = c.req.valid('json')
const db = c.env.DB
await db
.prepare('INSERT INTO monitors (url, label, status) VALUES (?, ?, ?)')
.bind(url, label ?? url, 'unknown')
.run()
return c.json({ message: 'Monitor registered', url }, 201)
})
// ステータス確認
app.get('/monitors/:id/check', async (c) => {
const id = c.req.param('id')
const db = c.env.DB
const monitor = await db
.prepare('SELECT * FROM monitors WHERE id = ?')
.bind(id)
.first()
if (!monitor) throw new HTTPException(404, { message: 'Monitor not found' })
const startTime = Date.now()
let status = 'down'
let statusCode: number | null = null
try {
const res = await fetch(monitor.url as string, {
method: 'HEAD',
signal: AbortSignal.timeout(5000)
})
statusCode = res.status
status = res.ok ? 'up' : 'down'
} catch {
status = 'down'
}
const responseTime = Date.now() - startTime
await db
.prepare('UPDATE monitors SET status = ?, last_checked = datetime("now") WHERE id = ?')
.bind(status, id)
.run()
return c.json({ id, status, statusCode, responseTimeMs: responseTime })
})
export default app
このコードはCloudflare Workersのエッジで動くため、世界中のどこからでも低レイテンシで監視できます。Honoの型安全なルーティングのおかげで、IDEの補完もバッチリ効きます。
広告
ConoHa WING
初期費用無料の高速クラウドサーバー
最大3,500円還元
詳しく見る →
まとめ:Honoが個人開発に最適な理由
Hono + Cloudflare Workers の組み合わせは、2026年現在の個人開発バックエンドとして最有力の選択肢の一つです。
- ✅ 無料でAPIサーバーを運用できる(Workers無料枠:1日10万リクエスト)
- ✅ TypeScriptで型安全に開発できる
- ✅ デプロイが一瞬(
wrangler deployで完了)
- ✅ D1・KV・R2などCloudflareのエコシステムと統合しやすい
- ✅ コードが簡潔(ボイラープレートが最小限)
複雑なインフラ管理なしに、コードを書いてデプロイするだけでAPIが動く。個人開発者にとって、これ以上ありがたい環境はないでしょう。
バックエンドが完成したら、フロントエンドのデプロイ先として Cloudflare Pages を使うのがおすすめです。APIとフロントを同じCloudflareエコシステムに揃えることで、レイテンシを最小化できます。
また、作ったサービスの稼働状況を外部に伝えたい場合は、ステータスページも用意しておきましょう。StatusCraftは個人開発者でも無料で使えるステータスページツールで、APIのダウン情報をリアルタイムに公開できます。
🔥 今日からHonoを試してみよう
Cloudflareアカウントは無料。npm create hono@latest を実行するだけで、5分後にはエッジAPIが動きます。
Hono公式ドキュメントを見る →
ウェブサービスを作ったら、外部からのアクセスが正常に続いているか確認する仕組みも大切です。PagePulseのような監視ツールを使えば、APIが落ちたときにすぐ気づけます。個人開発の信頼性向上に役立てましょう。
さらに、ChromeでAPIレスポンスを素早く確認したいときは、QuickSummary(AI要約Chrome拡張)も合わせてインストールしておくと、長いJSONレスポンスやドキュメントをAIで要約して確認できて便利です。