hono-routing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Hono Routing & Middleware

Hono路由与中间件

Status: Production Ready ✅ Last Updated: 2025-10-22 Dependencies: None (framework-agnostic) Latest Versions: hono@4.10.2, zod@4.1.12, valibot@1.1.0, @hono/zod-validator@0.7.4, @hono/valibot-validator@0.5.3

状态:生产就绪 ✅ 最后更新:2025-10-22 依赖:无(与框架无关) 最新版本:hono@4.10.2, zod@4.1.12, valibot@1.1.0, @hono/zod-validator@0.7.4, @hono/valibot-validator@0.5.3

Quick Start (15 Minutes)

快速开始(15分钟)

1. Install Hono

1. 安装Hono

bash
npm install hono@4.10.2
Why Hono:
  • Fast: Built on Web Standards, runs on any JavaScript runtime
  • Lightweight: ~10KB, no dependencies
  • Type-safe: Full TypeScript support with type inference
  • Flexible: Works on Cloudflare Workers, Deno, Bun, Node.js, Vercel
bash
npm install hono@4.10.2
选择Hono的理由
  • 快速:基于Web标准构建,可在任意JavaScript运行时运行
  • 轻量:约10KB,无额外依赖
  • 类型安全:全面支持TypeScript类型推断
  • 灵活:可在Cloudflare Workers、Deno、Bun、Node.js、Vercel上运行

2. Create Basic App

2. 创建基础应用

typescript
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.json({ message: 'Hello Hono!' })
})

export default app
CRITICAL:
  • Use
    c.json()
    ,
    c.text()
    ,
    c.html()
    for responses
  • Return the response (don't use
    res.send()
    like Express)
  • Export app for runtime (Cloudflare Workers, Deno, Bun, Node.js)
typescript
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.json({ message: 'Hello Hono!' })
})

export default app
关键注意事项
  • 使用
    c.json()
    c.text()
    c.html()
    生成响应
  • 必须返回响应(不要像Express那样使用
    res.send()
  • 导出app以适配运行时(Cloudflare Workers、Deno、Bun、Node.js)

3. Add Request Validation

3. 添加请求验证

bash
npm install zod@4.1.12 @hono/zod-validator@0.7.4
typescript
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

const schema = z.object({
  name: z.string(),
  age: z.number(),
})

app.post('/user', zValidator('json', schema), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})
Why Validation:
  • Type-safe request data
  • Automatic error responses
  • Runtime validation, not just TypeScript

bash
npm install zod@4.1.12 @hono/zod-validator@0.7.4
typescript
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

const schema = z.object({
  name: z.string(),
  age: z.number(),
})

app.post('/user', zValidator('json', schema), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})
验证的作用
  • 确保请求数据类型安全
  • 自动返回错误响应
  • 不仅是TypeScript层面的类型检查,还包含运行时验证

The 6-Part Hono Mastery Guide

Hono精通指南(6部分)

Part 1: Routing Patterns

第1部分:路由模式

Basic Routes

基础路由

typescript
import { Hono } from 'hono'

const app = new Hono()

// GET request
app.get('/posts', (c) => c.json({ posts: [] }))

// POST request
app.post('/posts', (c) => c.json({ created: true }))

// PUT request
app.put('/posts/:id', (c) => c.json({ updated: true }))

// DELETE request
app.delete('/posts/:id', (c) => c.json({ deleted: true }))

// Multiple methods
app.on(['GET', 'POST'], '/multi', (c) => c.text('GET or POST'))

// All methods
app.all('/catch-all', (c) => c.text('Any method'))
Key Points:
  • Always return a Response (c.json, c.text, c.html, etc.)
  • Routes are matched in order (first match wins)
  • Use specific routes before wildcard routes
typescript
import { Hono } from 'hono'

const app = new Hono()

// GET请求
app.get('/posts', (c) => c.json({ posts: [] }))

// POST请求
app.post('/posts', (c) => c.json({ created: true }))

// PUT请求
app.put('/posts/:id', (c) => c.json({ updated: true }))

// DELETE请求
app.delete('/posts/:id', (c) => c.json({ deleted: true }))

// 多方法支持
app.on(['GET', 'POST'], '/multi', (c) => c.text('GET或POST请求'))

// 所有方法
app.all('/catch-all', (c) => c.text('任意请求方法'))
关键点
  • 必须返回Response对象(c.json、c.text、c.html等)
  • 路由按定义顺序匹配(先匹配的路由生效)
  • 通配符路由应放在具体路由之后

Route Parameters

路由参数

typescript
// Single parameter
app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ userId: id })
})

// Multiple parameters
app.get('/posts/:postId/comments/:commentId', (c) => {
  const { postId, commentId } = c.req.param()
  return c.json({ postId, commentId })
})

// Optional parameters (using wildcards)
app.get('/files/*', (c) => {
  const path = c.req.param('*')
  return c.json({ filePath: path })
})
CRITICAL:
  • c.req.param('name')
    returns single parameter
  • c.req.param()
    returns all parameters as object
  • Parameters are always strings (cast to number if needed)
typescript
// 单个参数
app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ userId: id })
})

// 多个参数
app.get('/posts/:postId/comments/:commentId', (c) => {
  const { postId, commentId } = c.req.param()
  return c.json({ postId, commentId })
})

// 可选参数(使用通配符)
app.get('/files/*', (c) => {
  const path = c.req.param('*')
  return c.json({ filePath: path })
})
关键注意事项
  • c.req.param('name')
    返回单个参数
  • c.req.param()
    返回所有参数组成的对象
  • 参数始终为字符串类型(如需数字需自行转换)

Query Parameters

查询参数

typescript
app.get('/search', (c) => {
  // Single query param
  const q = c.req.query('q')

  // Multiple query params
  const { page, limit } = c.req.query()

  // Query param array (e.g., ?tag=js&tag=ts)
  const tags = c.req.queries('tag')

  return c.json({ q, page, limit, tags })
})
Best Practice:
  • Use validation for query params (see Part 4)
  • Provide defaults for optional params
  • Parse numbers/booleans from query strings
typescript
app.get('/search', (c) => {
  // 单个查询参数
  const q = c.req.query('q')

  // 多个查询参数
  const { page, limit } = c.req.query()

  // 查询参数数组(例如:?tag=js&tag=ts)
  const tags = c.req.queries('tag')

  return c.json({ q, page, limit, tags })
})
最佳实践
  • 对查询参数使用验证(见第4部分)
  • 为可选参数提供默认值
  • 将查询字符串转换为数字/布尔值

Wildcard Routes

通配符路由

typescript
// Match any path after /api/
app.get('/api/*', (c) => {
  const path = c.req.param('*')
  return c.json({ catchAll: path })
})

// Named wildcard
app.get('/files/:filepath{.+}', (c) => {
  const filepath = c.req.param('filepath')
  return c.json({ file: filepath })
})
typescript
// 匹配/api/后的任意路径
app.get('/api/*', (c) => {
  const path = c.req.param('*')
  return c.json({ catchAll: path })
})

// 命名通配符
app.get('/files/:filepath{.+}', (c) => {
  const filepath = c.req.param('filepath')
  return c.json({ file: filepath })
})

Route Grouping (Sub-apps)

路由分组(子应用)

typescript
// Create sub-app
const api = new Hono()

api.get('/users', (c) => c.json({ users: [] }))
api.get('/posts', (c) => c.json({ posts: [] }))

// Mount sub-app
const app = new Hono()
app.route('/api', api)

// Result: /api/users, /api/posts
Why Group Routes:
  • Organize large applications
  • Share middleware for specific routes
  • Better code structure and maintainability

typescript
// 创建子应用
const api = new Hono()

api.get('/users', (c) => c.json({ users: [] }))
api.get('/posts', (c) => c.json({ posts: [] }))

// 挂载子应用
const app = new Hono()
app.route('/api', api)

// 结果:/api/users, /api/posts
路由分组的优势
  • 组织大型应用的路由结构
  • 为特定路由共享中间件
  • 提升代码结构的清晰度和可维护性

Part 2: Middleware Composition

第2部分:中间件组合

Middleware Flow

中间件流程

typescript
import { Hono } from 'hono'

const app = new Hono()

// Global middleware (runs for all routes)
app.use('*', async (c, next) => {
  console.log(`[${c.req.method}] ${c.req.url}`)
  await next() // CRITICAL: Must call next()
  console.log('Response sent')
})

// Route-specific middleware
app.use('/admin/*', async (c, next) => {
  // Auth check
  const token = c.req.header('Authorization')
  if (!token) {
    return c.json({ error: 'Unauthorized' }, 401)
  }
  await next()
})

app.get('/admin/dashboard', (c) => {
  return c.json({ message: 'Admin Dashboard' })
})
CRITICAL:
  • Always call
    await next()
    in middleware
  • Middleware runs BEFORE the handler
  • Return early to prevent handler execution
  • Check
    c.error
    AFTER
    next()
    for error handling
typescript
import { Hono } from 'hono'

const app = new Hono()

// 全局中间件(对所有路由生效)
app.use('*', async (c, next) => {
  console.log(`[${c.req.method}] ${c.req.url}`)
  await next() // 关键:必须调用next()
  console.log('响应已发送')
})

// 路由专属中间件
app.use('/admin/*', async (c, next) => {
  // 权限校验
  const token = c.req.header('Authorization')
  if (!token) {
    return c.json({ error: '未授权' }, 401)
  }
  await next()
})

app.get('/admin/dashboard', (c) => {
  return c.json({ message: '管理员控制台' })
})
关键注意事项
  • 中间件中必须调用
    await next()
  • 中间件在处理器之前执行
  • 可提前返回以阻止处理器执行
  • 调用
    next()
    后可通过
    c.error
    处理错误

Built-in Middleware

内置中间件

typescript
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { cors } from 'hono/cors'
import { prettyJSON } from 'hono/pretty-json'
import { compress } from 'hono/compress'
import { cache } from 'hono/cache'

const app = new Hono()

// Request logging
app.use('*', logger())

// CORS
app.use('/api/*', cors({
  origin: 'https://example.com',
  allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowHeaders: ['Content-Type', 'Authorization'],
}))

// Pretty JSON (dev only)
app.use('*', prettyJSON())

// Compression (gzip/deflate)
app.use('*', compress())

// Cache responses
app.use(
  '/static/*',
  cache({
    cacheName: 'my-app',
    cacheControl: 'max-age=3600',
  })
)
Built-in Middleware Reference: See
references/middleware-catalog.md
typescript
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { cors } from 'hono/cors'
import { prettyJSON } from 'hono/pretty-json'
import { compress } from 'hono/compress'
import { cache } from 'hono/cache'

const app = new Hono()

// 请求日志
app.use('*', logger())

// CORS配置
app.use('/api/*', cors({
  origin: 'https://example.com',
  allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowHeaders: ['Content-Type', 'Authorization'],
}))

// 美化JSON输出(仅开发环境使用)
app.use('*', prettyJSON())

// 压缩响应(gzip/deflate)
app.use('*', compress())

// 响应缓存
app.use(
  '/static/*',
  cache({
    cacheName: 'my-app',
    cacheControl: 'max-age=3600',
  })
)
内置中间件参考:详见
references/middleware-catalog.md

Middleware Chaining

中间件链式调用

typescript
// Multiple middleware in sequence
app.get(
  '/protected',
  authMiddleware,
  rateLimitMiddleware,
  (c) => {
    return c.json({ data: 'Protected data' })
  }
)

// Middleware factory pattern
const authMiddleware = async (c, next) => {
  const token = c.req.header('Authorization')
  if (!token) {
    throw new HTTPException(401, { message: 'Unauthorized' })
  }

  // Set user in context
  c.set('user', { id: 1, name: 'Alice' })

  await next()
}

const rateLimitMiddleware = async (c, next) => {
  // Rate limit logic
  await next()
}
Why Chain Middleware:
  • Separation of concerns
  • Reusable across routes
  • Clear execution order
typescript
// 按顺序调用多个中间件
app.get(
  '/protected',
  authMiddleware,
  rateLimitMiddleware,
  (c) => {
    return c.json({ data: '受保护数据' })
  }
)

// 中间件工厂模式
const authMiddleware = async (c, next) => {
  const token = c.req.header('Authorization')
  if (!token) {
    throw new HTTPException(401, { message: '未授权' })
  }

  // 将用户信息存入上下文
  c.set('user', { id: 1, name: 'Alice' })

  await next()
}

const rateLimitMiddleware = async (c, next) => {
  // 限流逻辑
  await next()
}
链式调用中间件的优势
  • 关注点分离
  • 可在多个路由间复用
  • 执行顺序清晰

Custom Middleware

自定义中间件

typescript
// Timing middleware
const timing = async (c, next) => {
  const start = Date.now()
  await next()
  const elapsed = Date.now() - start
  c.res.headers.set('X-Response-Time', `${elapsed}ms`)
}

// Request ID middleware
const requestId = async (c, next) => {
  const id = crypto.randomUUID()
  c.set('requestId', id)
  await next()
  c.res.headers.set('X-Request-ID', id)
}

// Error logging middleware
const errorLogger = async (c, next) => {
  await next()
  if (c.error) {
    console.error('Error:', c.error)
    // Send to error tracking service
  }
}

app.use('*', timing)
app.use('*', requestId)
app.use('*', errorLogger)
Best Practices:
  • Keep middleware focused (single responsibility)
  • Use
    c.set()
    to share data between middleware
  • Check
    c.error
    AFTER
    next()
    for error handling
  • Return early to short-circuit execution

typescript
// 响应计时中间件
const timing = async (c, next) => {
  const start = Date.now()
  await next()
  const elapsed = Date.now() - start
  c.res.headers.set('X-Response-Time', `${elapsed}ms`)
}

// 请求ID中间件
const requestId = async (c, next) => {
  const id = crypto.randomUUID()
  c.set('requestId', id)
  await next()
  c.res.headers.set('X-Request-ID', id)
}

// 错误日志中间件
const errorLogger = async (c, next) => {
  await next()
  if (c.error) {
    console.error('错误信息:', c.error)
    // 发送到错误追踪服务
  }
}

app.use('*', timing)
app.use('*', requestId)
app.use('*', errorLogger)
最佳实践
  • 中间件保持单一职责
  • 使用
    c.set()
    在中间件间共享数据
  • 调用
    next()
    后检查
    c.error
    处理错误
  • 可提前返回以中断执行链

Part 3: Type-Safe Context Extension

第3部分:类型安全的上下文扩展

Using c.set() and c.get()

使用c.set()和c.get()

typescript
import { Hono } from 'hono'

type Bindings = {
  DATABASE_URL: string
}

type Variables = {
  user: {
    id: number
    name: string
  }
  requestId: string
}

const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()

// Middleware sets variables
app.use('*', async (c, next) => {
  c.set('requestId', crypto.randomUUID())
  await next()
})

app.use('/api/*', async (c, next) => {
  c.set('user', { id: 1, name: 'Alice' })
  await next()
})

// Route accesses variables
app.get('/api/profile', (c) => {
  const user = c.get('user') // Type-safe!
  const requestId = c.get('requestId') // Type-safe!

  return c.json({ user, requestId })
})
CRITICAL:
  • Define
    Variables
    type for type-safe
    c.get()
  • Define
    Bindings
    type for environment variables (Cloudflare Workers)
  • c.set()
    in middleware,
    c.get()
    in handlers
typescript
import { Hono } from 'hono'

type Bindings = {
  DATABASE_URL: string
}

type Variables = {
  user: {
    id: number
    name: string
  }
  requestId: string
}

const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()

// 中间件设置变量
app.use('*', async (c, next) => {
  c.set('requestId', crypto.randomUUID())
  await next()
})

app.use('/api/*', async (c, next) => {
  c.set('user', { id: 1, name: 'Alice' })
  await next()
})

// 路由获取变量
app.get('/api/profile', (c) => {
  const user = c.get('user') // 类型安全!
  const requestId = c.get('requestId') // 类型安全!

  return c.json({ user, requestId })
})
关键注意事项
  • 定义
    Variables
    类型以实现
    c.get()
    的类型安全
  • 定义
    Bindings
    类型以适配环境变量(Cloudflare Workers)
  • 在中间件中使用
    c.set()
    ,在处理器中使用
    c.get()

Custom Context Extension

自定义上下文扩展

typescript
import { Hono } from 'hono'
import type { Context } from 'hono'

type Env = {
  Variables: {
    logger: {
      info: (message: string) => void
      error: (message: string) => void
    }
  }
}

const app = new Hono<Env>()

// Create logger middleware
app.use('*', async (c, next) => {
  const logger = {
    info: (msg: string) => console.log(`[INFO] ${msg}`),
    error: (msg: string) => console.error(`[ERROR] ${msg}`),
  }

  c.set('logger', logger)
  await next()
})

app.get('/', (c) => {
  const logger = c.get('logger')
  logger.info('Hello from route')

  return c.json({ message: 'Hello' })
})
Advanced Pattern: See
templates/context-extension.ts

typescript
import { Hono } from 'hono'
import type { Context } from 'hono'

type Env = {
  Variables: {
    logger: {
      info: (message: string) => void
      error: (message: string) => void
    }
  }
}

const app = new Hono<Env>()

// 创建日志中间件
app.use('*', async (c, next) => {
  const logger = {
    info: (msg: string) => console.log(`[INFO] ${msg}`),
    error: (msg: string) => console.error(`[ERROR] ${msg}`),
  }

  c.set('logger', logger)
  await next()
})

app.get('/', (c) => {
  const logger = c.get('logger')
  logger.info('来自路由的消息')

  return c.json({ message: 'Hello' })
})
高级模式:详见
templates/context-extension.ts

Part 4: Request Validation

第4部分:请求验证

Validation with Zod

使用Zod进行验证

bash
npm install zod@4.1.12 @hono/zod-validator@0.7.4
typescript
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

// Define schema
const userSchema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().min(18).optional(),
})

// Validate JSON body
app.post('/users', zValidator('json', userSchema), (c) => {
  const data = c.req.valid('json') // Type-safe!
  return c.json({ success: true, data })
})

// Validate query params
const searchSchema = z.object({
  q: z.string(),
  page: z.string().transform((val) => parseInt(val, 10)),
  limit: z.string().transform((val) => parseInt(val, 10)).optional(),
})

app.get('/search', zValidator('query', searchSchema), (c) => {
  const { q, page, limit } = c.req.valid('query')
  return c.json({ q, page, limit })
})

// Validate route params
const idSchema = z.object({
  id: z.string().uuid(),
})

app.get('/users/:id', zValidator('param', idSchema), (c) => {
  const { id } = c.req.valid('param')
  return c.json({ userId: id })
})

// Validate headers
const headerSchema = z.object({
  'authorization': z.string().startsWith('Bearer '),
  'content-type': z.string(),
})

app.post('/auth', zValidator('header', headerSchema), (c) => {
  const headers = c.req.valid('header')
  return c.json({ authenticated: true })
})
CRITICAL:
  • Always use
    c.req.valid()
    after validation (type-safe)
  • Validation targets:
    json
    ,
    query
    ,
    param
    ,
    header
    ,
    form
    ,
    cookie
  • Use
    z.transform()
    to convert strings to numbers/dates
  • Validation errors return 400 automatically
bash
npm install zod@4.1.12 @hono/zod-validator@0.7.4
typescript
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(18).optional(),
})

// 验证JSON请求体
app.post('/users', zValidator('json', userSchema), (c) => {
  const data = c.req.valid('json') // 类型安全!
  return c.json({ success: true, data })
})

// 验证查询参数
const searchSchema = z.object({
  q: z.string(),
  page: z.string().transform((val) => parseInt(val, 10)),
  limit: z.string().transform((val) => parseInt(val, 10)).optional(),
})

app.get('/search', zValidator('query', searchSchema), (c) => {
  const { q, page, limit } = c.req.valid('query')
  return c.json({ q, page, limit })
})

// 验证路由参数
const idSchema = z.object({
  id: z.string().uuid(),
})

app.get('/users/:id', zValidator('param', idSchema), (c) => {
  const { id } = c.req.valid('param')
  return c.json({ userId: id })
})

// 验证请求头
const headerSchema = z.object({
  'authorization': z.string().startsWith('Bearer '),
  'content-type': z.string(),
})

app.post('/auth', zValidator('header', headerSchema), (c) => {
  const headers = c.req.valid('header')
  return c.json({ authenticated: true })
})
关键注意事项
  • 验证后**必须使用
    c.req.valid()
    **获取数据(类型安全)
  • 验证目标包括:
    json
    query
    param
    header
    form
    cookie
  • 使用
    z.transform()
    将字符串转换为数字/日期
  • 验证失败时自动返回400错误

Custom Validation Hooks

自定义验证钩子

typescript
import { zValidator } from '@hono/zod-validator'
import { HTTPException } from 'hono/http-exception'

const schema = z.object({
  name: z.string(),
  age: z.number(),
})

// Custom error handler
app.post(
  '/users',
  zValidator('json', schema, (result, c) => {
    if (!result.success) {
      // Custom error response
      return c.json(
        {
          error: 'Validation failed',
          issues: result.error.issues,
        },
        400
      )
    }
  }),
  (c) => {
    const data = c.req.valid('json')
    return c.json({ success: true, data })
  }
)

// Throw HTTPException
app.post(
  '/users',
  zValidator('json', schema, (result, c) => {
    if (!result.success) {
      throw new HTTPException(400, { cause: result.error })
    }
  }),
  (c) => {
    const data = c.req.valid('json')
    return c.json({ success: true, data })
  }
)
typescript
import { zValidator } from '@hono/zod-validator'
import { HTTPException } from 'hono/http-exception'

const schema = z.object({
  name: z.string(),
  age: z.number(),
})

// 自定义错误处理器
app.post(
  '/users',
  zValidator('json', schema, (result, c) => {
    if (!result.success) {
      // 自定义错误响应
      return c.json(
        {
          error: '验证失败',
          issues: result.error.issues,
        },
        400
      )
    }
  }),
  (c) => {
    const data = c.req.valid('json')
    return c.json({ success: true, data })
  }
)

// 抛出HTTPException
app.post(
  '/users',
  zValidator('json', schema, (result, c) => {
    if (!result.success) {
      throw new HTTPException(400, { cause: result.error })
    }
  }),
  (c) => {
    const data = c.req.valid('json')
    return c.json({ success: true, data })
  }
)

Validation with Valibot

使用Valibot进行验证

bash
npm install valibot@1.1.0 @hono/valibot-validator@0.5.3
typescript
import { vValidator } from '@hono/valibot-validator'
import * as v from 'valibot'

const schema = v.object({
  name: v.string(),
  age: v.number(),
})

app.post('/users', vValidator('json', schema), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})
Zod vs Valibot: See
references/validation-libraries.md
bash
npm install valibot@1.1.0 @hono/valibot-validator@0.5.3
typescript
import { vValidator } from '@hono/valibot-validator'
import * as v from 'valibot'

const schema = v.object({
  name: v.string(),
  age: v.number(),
})

app.post('/users', vValidator('json', schema), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})
Zod vs Valibot:详见
references/validation-libraries.md

Validation with Typia

使用Typia进行验证

bash
npm install typia @hono/typia-validator@0.1.2
typescript
import { typiaValidator } from '@hono/typia-validator'
import typia from 'typia'

interface User {
  name: string
  age: number
}

const validate = typia.createValidate<User>()

app.post('/users', typiaValidator('json', validate), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})
Why Typia:
  • Fastest validation (compile-time)
  • No runtime schema definition
  • AOT (Ahead-of-Time) compilation
bash
npm install typia @hono/typia-validator@0.1.2
typescript
import { typiaValidator } from '@hono/typia-validator'
import typia from 'typia'

interface User {
  name: string
  age: number
}

const validate = typia.createValidate<User>()

app.post('/users', typiaValidator('json', validate), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})
选择Typia的理由
  • 最快的验证速度(编译时处理)
  • 无需在运行时定义校验规则
  • 支持AOT(提前编译)

Validation with ArkType

使用ArkType进行验证

bash
npm install arktype @hono/arktype-validator@2.0.1
typescript
import { arktypeValidator } from '@hono/arktype-validator'
import { type } from 'arktype'

const schema = type({
  name: 'string',
  age: 'number',
})

app.post('/users', arktypeValidator('json', schema), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})
Comparison: See
references/validation-libraries.md
for detailed comparison

bash
npm install arktype @hono/arktype-validator@2.0.1
typescript
import { arktypeValidator } from '@hono/arktype-validator'
import { type } from 'arktype'

const schema = type({
  name: 'string',
  age: 'number',
})

app.post('/users', arktypeValidator('json', schema), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})
对比分析:详见
references/validation-libraries.md
中的详细对比

Part 5: Typed Routes (RPC)

第5部分:类型化路由(RPC)

Why RPC?

为什么选择RPC?

Hono's RPC feature allows type-safe client/server communication without manual API type definitions. The client infers types directly from the server routes.
Hono的RPC功能支持类型安全的客户端/服务端通信,无需手动定义API类型。客户端可直接从服务端路由推断类型。

Server-Side Setup

服务端配置

typescript
// app.ts
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

const app = new Hono()

const schema = z.object({
  name: z.string(),
  age: z.number(),
})

// Define route and export type
const route = app.post(
  '/users',
  zValidator('json', schema),
  (c) => {
    const data = c.req.valid('json')
    return c.json({ success: true, data }, 201)
  }
)

// Export app type for RPC client
export type AppType = typeof route

// OR export entire app
// export type AppType = typeof app

export default app
CRITICAL:
  • Must use
    const route = app.get(...)
    for RPC type inference
  • Export
    typeof route
    or
    typeof app
  • Don't use anonymous route definitions
typescript
// app.ts
import { Hono } from 'hono'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

const app = new Hono()

const schema = z.object({
  name: z.string(),
  age: z.number(),
})

// 定义路由并导出类型
const route = app.post(
  '/users',
  zValidator('json', schema),
  (c) => {
    const data = c.req.valid('json')
    return c.json({ success: true, data }, 201)
  }
)

// 导出供RPC客户端使用的应用类型
export type AppType = typeof route

// 或者导出整个应用
// export type AppType = typeof app

export default app
关键注意事项
  • 必须使用
    const route = app.get(...)
    的形式才能支持RPC类型推断
  • 导出
    typeof route
    typeof app
  • 不要使用匿名路由定义

Client-Side Setup

客户端配置

typescript
// client.ts
import { hc } from 'hono/client'
import type { AppType } from './app'

const client = hc<AppType>('http://localhost:8787')

// Type-safe API call
const res = await client.users.$post({
  json: {
    name: 'Alice',
    age: 30,
  },
})

// Response is typed!
const data = await res.json() // { success: boolean, data: { name: string, age: number } }
Why RPC:
  • ✅ Full type inference (request + response)
  • ✅ No manual type definitions
  • ✅ Compile-time error checking
  • ✅ Auto-complete in IDE
typescript
// client.ts
import { hc } from 'hono/client'
import type { AppType } from './app'

const client = hc<AppType>('http://localhost:8787')

// 类型安全的API调用
const res = await client.users.$post({
  json: {
    name: 'Alice',
    age: 30,
  },
})

// 响应类型已推断!
const data = await res.json() // { success: boolean, data: { name: string, age: number } }
RPC的优势
  • ✅ 完整的类型推断(请求+响应)
  • ✅ 无需手动定义类型
  • ✅ 编译时错误检查
  • ✅ IDE自动补全

RPC with Multiple Routes

多路由RPC配置

typescript
// Server
const app = new Hono()

const getUsers = app.get('/users', (c) => {
  return c.json({ users: [] })
})

const createUser = app.post(
  '/users',
  zValidator('json', userSchema),
  (c) => {
    const data = c.req.valid('json')
    return c.json({ success: true, data }, 201)
  }
)

const getUser = app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ id, name: 'Alice' })
})

// Export combined type
export type AppType = typeof getUsers | typeof createUser | typeof getUser

// Client
const client = hc<AppType>('http://localhost:8787')

// GET /users
const usersRes = await client.users.$get()

// POST /users
const createRes = await client.users.$post({
  json: { name: 'Alice', age: 30 },
})

// GET /users/:id
const userRes = await client.users[':id'].$get({
  param: { id: '123' },
})
typescript
// 服务端
const app = new Hono()

const getUsers = app.get('/users', (c) => {
  return c.json({ users: [] })
})

const createUser = app.post(
  '/users',
  zValidator('json', userSchema),
  (c) => {
    const data = c.req.valid('json')
    return c.json({ success: true, data }, 201)
  }
)

const getUser = app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ id, name: 'Alice' })
})

// 导出组合后的类型
export type AppType = typeof getUsers | typeof createUser | typeof getUser

// 客户端
const client = hc<AppType>('http://localhost:8787')

// GET /users
const usersRes = await client.users.$get()

// POST /users
const createRes = await client.users.$post({
  json: { name: 'Alice', age: 30 },
})

// GET /users/:id
const userRes = await client.users[':id'].$get({
  param: { id: '123' },
})

RPC Performance Optimization

RPC性能优化

Problem: Large apps with many routes cause slow type inference
Solution: Export specific route groups instead of entire app
typescript
// ❌ Slow: Export entire app
export type AppType = typeof app

// ✅ Fast: Export specific routes
const userRoutes = app.get('/users', ...).post('/users', ...)
export type UserRoutes = typeof userRoutes

const postRoutes = app.get('/posts', ...).post('/posts', ...)
export type PostRoutes = typeof postRoutes

// Client imports specific routes
import type { UserRoutes } from './app'
const userClient = hc<UserRoutes>('http://localhost:8787')
Deep Dive: See
references/rpc-guide.md

问题:包含大量路由的大型应用会导致类型推断速度变慢
解决方案:导出特定的路由组而非整个应用
typescript
// ❌ 速度慢:导出整个应用
export type AppType = typeof app

// ✅ 速度快:导出特定路由组
const userRoutes = app.get('/users', ...).post('/users', ...)
export type UserRoutes = typeof userRoutes

const postRoutes = app.get('/posts', ...).post('/posts', ...)
export type PostRoutes = typeof postRoutes

// 客户端导入特定路由组
import type { UserRoutes } from './app'
const userClient = hc<UserRoutes>('http://localhost:8787')
深入探讨:详见
references/rpc-guide.md

Part 6: Error Handling

第6部分:错误处理

HTTPException

HTTPException

typescript
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'

const app = new Hono()

app.get('/users/:id', (c) => {
  const id = c.req.param('id')

  // Throw HTTPException for client errors
  if (!id) {
    throw new HTTPException(400, { message: 'ID is required' })
  }

  // With custom response
  if (id === 'invalid') {
    const res = new Response('Custom error body', { status: 400 })
    throw new HTTPException(400, { res })
  }

  return c.json({ id })
})
CRITICAL:
  • Use HTTPException for expected errors (400, 401, 403, 404)
  • Don't use for unexpected errors (500) - use
    onError
    instead
  • HTTPException stops execution immediately
typescript
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'

const app = new Hono()

app.get('/users/:id', (c) => {
  const id = c.req.param('id')

  // 针对客户端错误抛出HTTPException
  if (!id) {
    throw new HTTPException(400, { message: 'ID是必填项' })
  }

  // 自定义响应内容
  if (id === 'invalid') {
    const res = new Response('自定义错误内容', { status: 400 })
    throw new HTTPException(400, { res })
  }

  return c.json({ id })
})
关键注意事项
  • 针对预期错误使用HTTPException(400、401、403、404)
  • 不要针对意外错误使用(500)- 应使用
    onError
    处理
  • HTTPException会立即终止执行

Global Error Handler (onError)

全局错误处理器(onError)

typescript
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'

const app = new Hono()

// Custom error handler
app.onError((err, c) => {
  // Handle HTTPException
  if (err instanceof HTTPException) {
    return err.getResponse()
  }

  // Handle unexpected errors
  console.error('Unexpected error:', err)

  return c.json(
    {
      error: 'Internal Server Error',
      message: err.message,
    },
    500
  )
})

app.get('/error', (c) => {
  throw new Error('Something went wrong!')
})
Why onError:
  • Centralized error handling
  • Consistent error responses
  • Error logging and tracking
typescript
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'

const app = new Hono()

// 自定义错误处理器
app.onError((err, c) => {
  // 处理HTTPException
  if (err instanceof HTTPException) {
    return err.getResponse()
  }

  // 处理意外错误
  console.error('意外错误:', err)

  return c.json(
    {
      error: '内部服务器错误',
      message: err.message,
    },
    500
  )
})

app.get('/error', (c) => {
  throw new Error('发生了错误!')
})
onError的作用
  • 集中处理所有错误
  • 确保错误响应格式一致
  • 便于错误日志记录和追踪

Middleware Error Checking

中间件错误检查

typescript
app.use('*', async (c, next) => {
  await next()

  // Check for errors after handler
  if (c.error) {
    console.error('Error in route:', c.error)
    // Send to error tracking service
  }
})
typescript
app.use('*', async (c, next) => {
  await next()

  // 处理器执行后检查错误
  if (c.error) {
    console.error('路由错误:', c.error)
    // 发送到错误追踪服务
  }
})

Not Found Handler

404未找到处理器

typescript
app.notFound((c) => {
  return c.json({ error: 'Not Found' }, 404)
})
typescript
app.notFound((c) => {
  return c.json({ error: '未找到资源' }, 404)
})

Error Handling Best Practices

错误处理最佳实践

typescript
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'

const app = new Hono()

// Validation errors
app.post('/users', zValidator('json', schema), (c) => {
  // zValidator automatically returns 400 on validation failure
  const data = c.req.valid('json')
  return c.json({ data })
})

// Authorization errors
app.use('/admin/*', async (c, next) => {
  const token = c.req.header('Authorization')
  if (!token) {
    throw new HTTPException(401, { message: 'Unauthorized' })
  }
  await next()
})

// Not found errors
app.get('/users/:id', async (c) => {
  const id = c.req.param('id')
  const user = await db.getUser(id)

  if (!user) {
    throw new HTTPException(404, { message: 'User not found' })
  }

  return c.json({ user })
})

// Server errors
app.get('/data', async (c) => {
  try {
    const data = await fetchExternalAPI()
    return c.json({ data })
  } catch (error) {
    // Let onError handle it
    throw error
  }
})

// Global error handler
app.onError((err, c) => {
  if (err instanceof HTTPException) {
    return err.getResponse()
  }

  console.error('Unexpected error:', err)
  return c.json({ error: 'Internal Server Error' }, 500)
})

// 404 handler
app.notFound((c) => {
  return c.json({ error: 'Not Found' }, 404)
})

typescript
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'

const app = new Hono()

// 验证错误
app.post('/users', zValidator('json', schema), (c) => {
  // zValidator会在验证失败时自动返回400错误
  const data = c.req.valid('json')
  return c.json({ data })
})

// 授权错误
app.use('/admin/*', async (c, next) => {
  const token = c.req.header('Authorization')
  if (!token) {
    throw new HTTPException(401, { message: '未授权' })
  }
  await next()
})

// 资源未找到错误
app.get('/users/:id', async (c) => {
  const id = c.req.param('id')
  const user = await db.getUser(id)

  if (!user) {
    throw new HTTPException(404, { message: '用户不存在' })
  }

  return c.json({ user })
})

// 服务器错误
app.get('/data', async (c) => {
  try {
    const data = await fetchExternalAPI()
    return c.json({ data })
  } catch (error) {
    // 交给onError处理
    throw error
  }
})

// 全局错误处理器
app.onError((err, c) => {
  if (err instanceof HTTPException) {
    return err.getResponse()
  }

  console.error('意外错误:', err)
  return c.json({ error: '内部服务器错误' }, 500)
})

// 404处理器
app.notFound((c) => {
  return c.json({ error: '未找到资源' }, 404)
})

Critical Rules

关键规则

Always Do

必须遵守

Call
await next()
in middleware
- Required for middleware chain execution ✅ Return Response from handlers - Use
c.json()
,
c.text()
,
c.html()
Use
c.req.valid()
after validation
- Type-safe validated data ✅ Export route types for RPC -
export type AppType = typeof route
Throw HTTPException for client errors - 400, 401, 403, 404 errors ✅ Use
onError
for global error handling
- Centralized error responses ✅ Define Variables type for c.set/c.get - Type-safe context variables ✅ Use const route = app.get(...) - Required for RPC type inference
中间件中调用
await next()
- 中间件链执行的必要条件 ✅ 处理器返回Response对象 - 使用
c.json()
c.text()
c.html()
验证后使用
c.req.valid()
- 获取类型安全的验证后数据 ✅ 为RPC导出路由类型 -
export type AppType = typeof route
客户端错误抛出HTTPException - 400、401、403、404等错误 ✅ 使用
onError
进行全局错误处理
- 集中处理错误响应 ✅ 为c.set/c.get定义Variables类型 - 确保上下文变量类型安全 ✅ 使用const route = app.get(...)定义路由 - 支持RPC类型推断的必要条件

Never Do

禁止操作

Forget
await next()
in middleware
- Breaks middleware chain ❌ Use
res.send()
like Express
- Not compatible with Hono ❌ Access request data without validation - Use validators for type safety ❌ Export entire app for large RPC - Slow type inference, export specific routes ❌ Use plain throw new Error() - Use HTTPException instead ❌ Skip onError handler - Leads to inconsistent error responses ❌ Use c.set/c.get without Variables type - Loses type safety

中间件中忘记
await next()
- 会中断中间件链 ❌ 像Express那样使用
res.send()
- 与Hono不兼容 ❌ 未验证直接访问请求数据 - 使用验证器确保类型安全 ❌ 大型应用导出整个应用用于RPC - 类型推断速度慢,应导出特定路由组 ❌ 直接抛出new Error() - 应使用HTTPException替代 ❌ 跳过onError处理器 - 会导致错误响应格式不一致 ❌ 未定义Variables类型就使用c.set/c.get - 丢失类型安全

Known Issues Prevention

已知问题预防

This skill prevents 8 documented issues:
本技能可预防8个已记录的问题:

Issue #1: RPC Type Inference Slow

问题1:RPC类型推断速度慢

Error: IDE becomes slow with many routes Source: hono/docs/guides/rpc Why It Happens: Complex type instantiation from
typeof app
with many routes Prevention: Export specific route groups instead of entire app
typescript
// ❌ Slow
export type AppType = typeof app

// ✅ Fast
const userRoutes = app.get(...).post(...)
export type UserRoutes = typeof userRoutes
错误现象:包含大量路由时IDE运行缓慢 来源hono/docs/guides/rpc 原因
typeof app
会生成复杂的类型实例,导致类型推断缓慢 解决方法:导出特定的路由组而非整个应用
typescript
// ❌ 速度慢
export type AppType = typeof app

// ✅ 速度快
const userRoutes = app.get(...).post(...)
export type UserRoutes = typeof userRoutes

Issue #2: Middleware Response Not Typed in RPC

问题2:RPC客户端未推断中间件响应

Error: Middleware responses not inferred by RPC client Source: honojs/hono#2719 Why It Happens: RPC mode doesn't infer middleware responses by default Prevention: Export specific route types that include middleware
typescript
const route = app.get(
  '/data',
  myMiddleware,
  (c) => c.json({ data: 'value' })
)
export type AppType = typeof route
错误现象:中间件的响应未被RPC客户端推断 来源honojs/hono#2719 原因:RPC模式默认不会推断中间件的响应 解决方法:导出包含中间件的特定路由类型
typescript
const route = app.get(
  '/data',
  myMiddleware,
  (c) => c.json({ data: 'value' })
)
export type AppType = typeof route

Issue #3: Validation Hook Confusion

问题3:验证钩子混淆

Error: Different validator libraries have different hook patterns Source: Context7 research Why It Happens: Each validator (@hono/zod-validator, @hono/valibot-validator, etc.) has slightly different APIs Prevention: This skill provides consistent patterns for all validators
错误现象:不同验证库的钩子模式不一致 来源:Context7研究 原因:每个验证库(@hono/zod-validator、@hono/valibot-validator等)的API略有不同 解决方法:本技能提供了所有验证库的统一使用模式

Issue #4: HTTPException Misuse

问题4:HTTPException误用

Error: Throwing plain Error instead of HTTPException Source: Official docs Why It Happens: Developers familiar with Express use
throw new Error()
Prevention: Always use
HTTPException
for client errors (400-499)
typescript
// ❌ Wrong
throw new Error('Unauthorized')

// ✅ Correct
throw new HTTPException(401, { message: 'Unauthorized' })
错误现象:抛出普通Error而非HTTPException 来源:官方文档 原因:熟悉Express的开发者习惯使用
throw new Error()
解决方法:客户端错误(400-499)始终使用HTTPException
typescript
// ❌ 错误用法
throw new Error('未授权')

// ✅ 正确用法
throw new HTTPException(401, { message: '未授权' })

Issue #5: Context Type Safety Lost

问题5:上下文类型安全丢失

Error:
c.set()
and
c.get()
without type inference Source: Official docs Why It Happens: Not defining
Variables
type in Hono generic Prevention: Always define Variables type
typescript
type Variables = {
  user: { id: number; name: string }
}

const app = new Hono<{ Variables: Variables }>()
错误现象
c.set()
c.get()
无类型推断 来源:官方文档 原因:未在Hono泛型中定义
Variables
类型 解决方法:始终定义Variables类型
typescript
type Variables = {
  user: { id: number; name: string }
}

const app = new Hono<{ Variables: Variables }>()

Issue #6: Missing Error Check After Middleware

问题6:中间件执行后未检查错误

Error: Errors in handlers not caught Source: Official docs Why It Happens: Not checking
c.error
after
await next()
Prevention: Check
c.error
in middleware
typescript
app.use('*', async (c, next) => {
  await next()
  if (c.error) {
    console.error('Error:', c.error)
  }
})
错误现象:处理器中的错误未被捕获 来源:官方文档 原因:调用
await next()
后未检查
c.error
解决方法:在中间件中检查
c.error
typescript
app.use('*', async (c, next) => {
  await next()
  if (c.error) {
    console.error('错误信息:', c.error)
  }
})

Issue #7: Direct Request Access Without Validation

问题7:未验证直接访问请求数据

Error: Accessing
c.req.param()
or
c.req.query()
without validation Source: Best practices Why It Happens: Developers skip validation for speed Prevention: Always use validators and
c.req.valid()
typescript
// ❌ Wrong
const id = c.req.param('id') // string, no validation

// ✅ Correct
app.get('/users/:id', zValidator('param', idSchema), (c) => {
  const { id } = c.req.valid('param') // validated UUID
})
错误现象:未验证直接访问
c.req.param()
c.req.query()
来源:最佳实践 原因:开发者为了快速开发跳过验证 解决方法:始终使用验证器和
c.req.valid()
typescript
// ❌ 错误用法
const id = c.req.param('id') // 字符串,无验证

// ✅ 正确用法
app.get('/users/:id', zValidator('param', idSchema), (c) => {
  const { id } = c.req.valid('param') // 已验证的UUID
})

Issue #8: Incorrect Middleware Order

问题8:中间件顺序错误

Error: Middleware executing in wrong order Source: Official docs Why It Happens: Misunderstanding middleware chain execution Prevention: Remember middleware runs top-to-bottom,
await next()
runs handler, then bottom-to-top
typescript
app.use('*', async (c, next) => {
  console.log('1: Before handler')
  await next()
  console.log('4: After handler')
})

app.use('*', async (c, next) => {
  console.log('2: Before handler')
  await next()
  console.log('3: After handler')
})

app.get('/', (c) => {
  console.log('Handler')
  return c.json({})
})

// Output: 1, 2, Handler, 3, 4

错误现象:中间件执行顺序不符合预期 来源:官方文档 原因:对中间件链的执行顺序理解有误 解决方法:记住中间件从上到下执行,
await next()
执行处理器,然后从下到上执行后续逻辑
typescript
app.use('*', async (c, next) => {
  console.log('1: 处理器执行前')
  await next()
  console.log('4: 处理器执行后')
})

app.use('*', async (c, next) => {
  console.log('2: 处理器执行前')
  await next()
  console.log('3: 处理器执行后')
})

app.get('/', (c) => {
  console.log('处理器执行')
  return c.json({})
})

// 输出顺序:1, 2, 处理器执行, 3, 4

Configuration Files Reference

配置文件参考

package.json (Full Example)

package.json(完整示例)

json
{
  "name": "hono-app",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js"
  },
  "dependencies": {
    "hono": "^4.10.2"
  },
  "devDependencies": {
    "typescript": "^5.9.0",
    "tsx": "^4.19.0",
    "@types/node": "^22.10.0"
  }
}
json
{
  "name": "hono-app",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js"
  },
  "dependencies": {
    "hono": "^4.10.2"
  },
  "devDependencies": {
    "typescript": "^5.9.0",
    "tsx": "^4.19.0",
    "@types/node": "^22.10.0"
  }
}

package.json with Validation (Zod)

包含Zod验证的package.json

json
{
  "dependencies": {
    "hono": "^4.10.2",
    "zod": "^4.1.12",
    "@hono/zod-validator": "^0.7.4"
  }
}
json
{
  "dependencies": {
    "hono": "^4.10.2",
    "zod": "^4.1.12",
    "@hono/zod-validator": "^0.7.4"
  }
}

package.json with Validation (Valibot)

包含Valibot验证的package.json

json
{
  "dependencies": {
    "hono": "^4.10.2",
    "valibot": "^1.1.0",
    "@hono/valibot-validator": "^0.5.3"
  }
}
json
{
  "dependencies": {
    "hono": "^4.10.2",
    "valibot": "^1.1.0",
    "@hono/valibot-validator": "^0.5.3"
  }
}

package.json with All Validators

包含所有验证器的package.json

json
{
  "dependencies": {
    "hono": "^4.10.2",
    "zod": "^4.1.12",
    "valibot": "^1.1.0",
    "@hono/zod-validator": "^0.7.4",
    "@hono/valibot-validator": "^0.5.3",
    "@hono/typia-validator": "^0.1.2",
    "@hono/arktype-validator": "^2.0.1"
  }
}
json
{
  "dependencies": {
    "hono": "^4.10.2",
    "zod": "^4.1.12",
    "valibot": "^1.1.0",
    "@hono/zod-validator": "^0.7.4",
    "@hono/valibot-validator": "^0.5.3",
    "@hono/typia-validator": "^0.1.2",
    "@hono/arktype-validator": "^2.0.1"
  }
}

tsconfig.json

tsconfig.json

json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "lib": ["ES2022"],
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "allowJs": true,
    "checkJs": false,
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "outDir": "./dist"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "lib": ["ES2022"],
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "allowJs": true,
    "checkJs": false,
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "outDir": "./dist"
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

File Templates

文件模板

All templates are available in the
templates/
directory:
  • routing-patterns.ts - Route params, query params, wildcards, grouping
  • middleware-composition.ts - Middleware chaining, built-in middleware
  • validation-zod.ts - Zod validation with custom hooks
  • validation-valibot.ts - Valibot validation
  • rpc-pattern.ts - Type-safe RPC client/server
  • error-handling.ts - HTTPException, onError, custom errors
  • context-extension.ts - c.set/c.get, custom context types
  • package.json - All dependencies
Copy these files to your project and customize as needed.

所有模板文件均位于
templates/
目录下:
  • routing-patterns.ts - 路由参数、查询参数、通配符、路由分组
  • middleware-composition.ts - 中间件链式调用、内置中间件
  • validation-zod.ts - 带自定义钩子的Zod验证
  • validation-valibot.ts - Valibot验证
  • rpc-pattern.ts - 类型安全的RPC客户端/服务端
  • error-handling.ts - HTTPException、onError、自定义错误
  • context-extension.ts - c.set/c.get、自定义上下文类型
  • package.json - 所有依赖配置
可将这些文件复制到你的项目中并按需自定义。

Reference Documentation

参考文档

For deeper understanding, see:
  • middleware-catalog.md - Complete built-in Hono middleware reference
  • validation-libraries.md - Zod vs Valibot vs Typia vs ArkType comparison
  • rpc-guide.md - RPC pattern deep dive, performance optimization
  • top-errors.md - Common Hono errors with solutions

如需深入了解,请查看:
  • middleware-catalog.md - 完整的Hono内置中间件参考
  • validation-libraries.md - Zod、Valibot、Typia、ArkType的对比分析
  • rpc-guide.md - RPC模式深入解析、性能优化
  • top-errors.md - 常见Hono错误及解决方案

Official Documentation

官方文档



Dependencies (Latest Verified 2025-10-22)

依赖版本(2025-10-22最新验证)

json
{
  "dependencies": {
    "hono": "^4.10.2"
  },
  "optionalDependencies": {
    "zod": "^4.1.12",
    "valibot": "^1.1.0",
    "@hono/zod-validator": "^0.7.4",
    "@hono/valibot-validator": "^0.5.3",
    "@hono/typia-validator": "^0.1.2",
    "@hono/arktype-validator": "^2.0.1"
  },
  "devDependencies": {
    "typescript": "^5.9.0"
  }
}

json
{
  "dependencies": {
    "hono": "^4.10.2"
  },
  "optionalDependencies": {
    "zod": "^4.1.12",
    "valibot": "^1.1.0",
    "@hono/zod-validator": "^0.7.4",
    "@hono/valibot-validator": "^0.5.3",
    "@hono/typia-validator": "^0.1.2",
    "@hono/arktype-validator": "^2.0.1"
  },
  "devDependencies": {
    "typescript": "^5.9.0"
  }
}

Production Example

生产环境示例

This skill is validated across multiple runtime environments:
  • Cloudflare Workers: Routing, middleware, RPC patterns
  • Deno: All validation libraries tested
  • Bun: Performance benchmarks completed
  • Node.js: Full test suite passing
All patterns in this skill have been validated in production.

Questions? Issues?
  1. Check
    references/top-errors.md
    first
  2. Verify all steps in the setup process
  3. Ensure
    await next()
    is called in middleware
  4. Ensure RPC routes use
    const route = app.get(...)
    pattern
  5. Check official docs: https://hono.dev
本技能已在多个运行时环境中验证:
  • Cloudflare Workers:路由、中间件、RPC模式均验证通过
  • Deno:所有验证库测试通过
  • Bun:性能基准测试完成
  • Node.js:完整测试套件通过
本技能中的所有模式均已在生产环境中验证可行。

有疑问?遇到问题?
  1. 首先查看
    references/top-errors.md
  2. 验证设置过程中的所有步骤
  3. 确保中间件中调用了
    await next()
  4. 确保RPC路由使用
    const route = app.get(...)
    的定义方式
  5. 查看官方文档:https://hono.dev