hono-core について
Honoは、エッジ、サーバーレスなど複数のランタイムでAPIを構築する開発者向けのTypeScript中心のWebフレームワークです。Web標準APIを基盤とし、型付きルーティングとミドルウェアを提供します。
主な機能
- 01Web標準ベースのAPI
- 02マルチランタイム対応
- 03高速なRegExpRouterルーティング
- 04TypeScriptの型推論
- 05ミドルウェアエコシステム
活用シーン
- 01エッジ環境向けAPIの構築
- 02複数ランタイムで同じコードベースを実行
- 03型付きHTTPルートの作成
- 04CORS、認証、圧縮の追加
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ bobmatnyc/ claude-mpm-skills --skill hono-coreインストール後、Claude Code で/hono-coreを入力して読み込まれたか確認します。
同梱ファイルmetadata.json
詳細
Hono - 超高速 Web フレームワーク
概要
Hono は、Web 標準に基づいて構築された、小さくシンプルで超高速な Web フレームワークです。同じコードベースで Cloudflare Workers、Deno、Bun、Node.js などで動作します。名前は日本語で「炎」を意味します。
主な機能:
- Web 標準(Request/Response/fetch)に基づいて構築
- マルチランタイム:Cloudflare Workers、Deno、Bun、Node.js、Vercel、AWS Lambda
- RegExpRouter による超高速ルーティング
- TypeScript を第一級でサポート
- 軽量(圧縮後約 14KB)
- 豊富なミドルウェアエコシステム
インストール:
# Create new project (recommended)
npm create hono@latest my-app
# Or install in existing project
npm install hono
# Runtime-specific adapters
npm install @hono/node-server # Node.js
このスキルを使う場面
次のような場合に Hono を使用します:
- エッジ/サーバーレス環境(Cloudflare Workers、Vercel Edge)向けの API を構築する
- マルチランタイム間の移植性が必要(Bun、Deno、Node.js で同じコードを使用)
- 優れた型推論を備えた TypeScript 中心の開発を行いたい
- 軽量で高性能な API を構築する
- 一般的なパターン(CORS、認証、圧縮)に対応する組み込みミドルウェアが必要
Hono とその他のフレームワークの比較:
- Hono:マルチランタイム、Web 標準、超高速、エッジ向けに最適化
- Express:Node.js 専用、より大きなエコシステム、低速
- Fastify:Node.js 専用、スキーマベース、高いパフォーマンス
- Elysia:Bun 専用、優れたパフォーマンス、異なる API スタイル
コアコンセプト
アプリケーションの作成
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Hono!'))
export default app
TypeScript のジェネリクスを使用する場合(バインディング/変数用):
type Bindings = {
DATABASE_URL: string
API_KEY: string
}
type Variables = {
user: { id: string; name: string }
}
const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()
コンテキストオブジェクト(c)
コンテキスト c から、リクエストデータとレスポンスメソッドにアクセスできます:
app.get('/users/:id', async (c) => {
// Request data
const id = c.req.param('id') // Path parameter
const query = c.req.query('sort') // Query parameter ?sort=asc
const queries = c.req.queries('tags') // Multiple: ?tags=a&tags=b
const header = c.req.header('Authorization')
const body = await c.req.json() // JSON body
const form = await c.req.formData() // Form data
// Environment (Cloudflare Workers bindings)
const db = c.env.DATABASE_URL
// Custom variables (set by middleware)
const user = c.get('user')
// Response methods
return c.text('Plain text')
return c.json({ id, name: 'User' })
return c.html('<h1>Hello</h1>')
return c.redirect('/login')
return c.notFound()
})
レスポンスメソッド
// Text response
c.text('Hello', 200)
// JSON response
c.json({ message: 'Success' }, 201)
c.json({ error: 'Not found' }, 404)
// HTML response
c.html('<h1>Hello</h1>')
// Redirect
c.redirect('/login') // 302 default
c.redirect('/login', 301) // Permanent redirect
// Headers
c.header('X-Custom', 'value')
c.header('Cache-Control', 'max-age=3600')
// Streaming
c.streamText(async (stream) => {
await stream.write('Hello ')
await stream.write('World!')
})
// Raw Response
return new Response('Raw', { status: 200 })
ルーティングパターン
基本的なルーティング
const app = new Hono()
// HTTP methods
app.get('/users', getUsers)
app.post('/users', createUser)
app.put('/users/:id', updateUser)
app.delete('/users/:id', deleteUser)
app.patch('/users/:id', patchUser)
// All methods
app.all('/webhook', handleWebhook)
// Custom methods
app.on('PURGE', '/cache', purgeCache)
app.on(['GET', 'POST'], '/form', handleForm)
パスパラメーター
// Single parameter
app.get('/users/:id', (c) => {
const id = c.req.param('id')
return c.json({ id })
})
// Multiple parameters
app.get('/posts/:postId/comments/:commentId', (c) => {
const { postId, commentId } = c.req.param()
return c.json({ postId, commentId })
})
// Optional parameter
app.get('/api/animal/:type?', (c) => {
const type = c.req.param('type') || 'all'
return c.json({ type })
})
// Regex validation
app.get('/posts/:id{[0-9]+}', (c) => {
const id = c.req.param('id') // Only numeric IDs
return c.json({ id })
})
// Wildcards
app.get('/files/*', (c) => {
const path = c.req.param('*') // Everything after /files/
return c.text(`File: ${path}`)
})
ルートのグループ化
// Using app.route()
const api = new Hono()
api.get('/users', getUsers)
api.get('/posts', getPosts)
const app = new Hono()
app.route('/api/v1', api) // /api/v1/users, /api/v1/posts
// Using basePath()
const v2 = new Hono().basePath('/api/v2')
v2.get('/users', getUsers) // /api/v2/users
// Chaining
app
.get('/a', handlerA)
.post('/b', handlerB)
.delete('/c', handlerC)
ルートの整理(複数ファイル)
// routes/users.ts
import { Hono } from 'hono'
const users = new Hono()
users.get('/', async (c) => {
return c.json({ users: [] })
})
users.post('/', async (c) => {
const body = await c.req.json()
return c.json({ created: body }, 201)
})
users.get('/:id', async (c) => {
const id = c.req.param('id')
return c.json({ id })
})
export default users
// app.ts
import { Hono } from 'hono'
import users from './routes/users'
import posts from './routes/posts'
const app = new Hono()
app.route('/users', users)
app.route('/posts', posts)
export default app
ハンドラーパターン
インラインハンドラー
// Simple handler
app.get('/hello', (c) => c.text('Hello!'))
// Async handler
app.get('/users', async (c) => {
const users = await fetchUsers()
return c.json({ users })
})
// Multiple handlers (middleware chain)
app.get('/admin', authenticate, authorize, (c) => {
return c.json({ admin: true })
})
ファクトリーを使用した型安全なハンドラー
import { createFactory } from 'hono/factory'
const factory = createFactory<{ Bindings: Bindings }>()
// Create typed handler
const getUser = factory.createHandlers(async (c) => {
const id = c.req.param('id')
const db = c.env.DATABASE_URL // Typed!
return c.json({ id })
})
app.get('/users/:id', ...getUser)
エラー処理
組み込みのエラー処理
import { HTTPException } from 'hono/http-exception'
app.get('/users/:id', async (c) => {
const user = await findUser(c.req.param('id'))
if (!user) {
throw new HTTPException(404, { message: 'User not found' })
}
return c.json(user)
})
// Global error handler
app.onError((err, c) => {
console.error(`${err}`)
if (err instanceof HTTPException) {
return err.getResponse()
}
return c.json({ error: 'Internal Server Error' }, 500)
})
// Not found handler
app.notFound((c) => {
return c.json({ error: 'Route not found' }, 404)
})
カスタムエラークラス
class ValidationError extends HTTPException {
constructor(errors: string[]) {
super(400, {
message: 'Validation failed',
cause: errors
})
}
}
class AuthenticationError extends HTTPException {
constructor() {
super(401, { message: 'Authentication required' })
}
}
ランタイム固有のエクスポート
Cloudflare Workers
// src/index.ts
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Cloudflare!'))
export default app
Node.js
// src/index.ts
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Node!'))
serve({
fetch: app.fetch,
port: 3000
})
Bun
// src/index.ts
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Bun!'))
export default {
port: 3000,
fetch: app.fetch
}
Deno
// main.ts
import { Hono } from 'npm:hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Deno!'))
Deno.serve(app.fetch)
ベストプラクティス
ハンドラーはインラインで記述する(コントローラーは使わない)
// CORRECT: Inline handlers with proper type inference
app.get('/users/:id', async (c) => {
const id = c.req.param('id') // Type: string
return c.json({ id })
})
// AVOID: Controller-style (loses type inference)
class UserController {
getUser(c: Context) {
const id = c.req.param('id') // Type: string | undefined
return c.json({ id })
}
}
モジュール化されたルートを使用する
// CORRECT: Split routes by domain
// routes/users.ts
export const users = new Hono()
.get('/', listUsers)
.post('/', createUser)
.get('/:id', getUser)
// app.ts
app.route('/users', users)
すべてに型を付ける
// Define your environment bindings
type Bindings = {
DATABASE_URL: string
JWT_SECRET: string
MY_KV: KVNamespace
}
// Pass to Hono
const app = new Hono<{ Bindings: Bindings }>()
// Now c.env is fully typed
app.get('/', (c) => {
const url = c.env.DATABASE_URL // string
const kv = c.env.MY_KV // KVNamespace
})
クイックリファレンス
よく使うコンテキストメソッド
| メソッド | 説明 | 例 |
|---|---|---|
c.req.param(name) | パスパラメーターを取得 | c.req.param('id') |
c.req.query(name) | クエリパラメーターを取得 | c.req.query('page') |
c.req.header(name) | リクエストヘッダーを取得 | c.req.header('Authorization') |
c.req.json() | JSON ボディを解析 | await c.req.json() |
c.req.formData() | フォームデータを解析 | await c.req.formData() |
c.text(str, status) | テキストレスポンス | c.text('OK', 200) |
c.json(obj, status) | JSON レスポンス | c.json({}, 201) |
c.html(str) | HTML レスポンス | c.html('<h1>Hi</h1>') |
c.redirect(url) | リダイレクト | c.redirect('/login') |
c.header(k, v) | レスポンスヘッダーを設定 | c.header('X-Custom', 'val') |
c.set(key, val) | コンテキスト変数を設定 | c.set('user', user) |
c.get(key) | コンテキスト変数を取得 | c.get('user') |
c.env | 環境バインディング | c.env.API_KEY |
HTTP メソッド
app.get(path, ...handlers)
app.post(path, ...handlers)
app.put(path, ...handlers)
app.delete(path, ...handlers)
app.patch(path, ...handlers)
app.options(path, ...handlers)
app.head(path, ...handlers)
app.all(path, ...handlers)
app.on(method, path, ...handlers)
関連スキル
- hono-middleware - ミドルウェアのパターンと合成
- hono-validation - Zod によるリクエスト検証
- hono-rpc - 型安全な RPC クライアント
- hono-testing - テストのパターン
- hono-jsx - サーバーサイドの JSX レンダリング
- hono-cloudflare - Cloudflare Workers へのデプロイ
バージョン:Hono 4.x 最終更新日:2025年1月 ライセンス:MIT
コメント
Markdown 対応