一、引言
如果你要构建一个 Web API 服务器,你会选择哪个框架?Express 统治了 Node.js 的 Web 框架市场超过十年,但它的设计是基于 Node.js 的 http 模块,无法在 Cloudflare Workers、Deno 或 Bun 上运行。边缘计算时代,需要新的思路。
Hono------ 一个基于 Web 标准 API 的超轻量 Web 框架,由开发者 Yusuke Wada 创建。它用 14KB 的包大小替代了 Express 的 572KB,同一份代码可以运行在 Cloudflare Workers、Deno、Bun、Node.js 等所有主流运行时上。
二、Hono 开源项目介绍
2.1 项目背景
Hono 由 Yusuke Wada (@yusukebe)创建,2022 年首次发布,目前 GitHub 上拥有 30K+ stars,npm 月下载量超过 2 亿次。
核心特性:
| 特性 | 说明 |
|---|---|
| Ultrafast | RegExpRouter 路由器,基于正则表达式,不依赖线性循环 |
| Lightweight | hono/tiny 预设仅 14KB(minified),零依赖 |
| Multi-runtime | Cloudflare Workers、Deno、Bun、Node.js、AWS Lambda 等 |
| Web Standards | 仅使用 Request/Response/Fetch 等 Web 标准 API |
| TypeScript | 一等公民支持,完整的类型推导 |
2.2 多运行时架构
2.3 Hono vs Express
| 维度 | Hono | Express |
|---|---|---|
| 包大小 | ~14KB | ~572KB(40 倍) |
| 运行时 | Workers/Deno/Bun/Node | Node.js 仅 |
| TypeScript | 一等公民 | 外部类型定义 |
| 异步模型 | 原生 async/await | 回调为主 |
| 中间件 | 基于 Web 标准 | 基于 Node.js http |
| 路由速度 | 超快(RegExpRouter) | 中等(线性匹配) |
三、Hono 核心概念
3.1 路由与响应
import { Hono } from 'hono'
const app = new Hono()
// 基础路由
app.get('/', (c) => c.text('Hello Hono!'))
app.get('/api/hello', (c) => c.json({ message: 'Hello!' }))
// 路径参数
app.get('/posts/:id', (c) => {
const id = c.req.param('id')
const page = c.req.query('page')
return c.json({ id, page })
})
// POST/DELETE
app.post('/posts', async (c) => {
const body = await c.req.json()
return c.json(body, 201)
})
app.delete('/posts/:id', (c) => c.text(`Deleted ${c.req.param('id')}`))
3.2 中间件
import { cors } from 'hono/cors'
import { logger } from 'hono/logger'
const app = new Hono()
app.use('*', cors()) // 全局 CORS
app.use('*', logger()) // 全局日志
四、实战:构建 TODO REST API
4.1 项目初始化
npm create hono@latest hono-todo-api
# 选择 nodejs 模板
cd hono-todo-api
npm install
npm install @hono/zod-validator
4.2 完整代码
import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { logger } from 'hono/logger'
import { z } from 'zod'
import { zValidator } from '@hono/zod-validator'
interface Todo {
id: number
title: string
completed: boolean
createdAt: string
}
let todos: Todo[] = [
{ id: 1, title: '学习 Hono 基础知识', completed: true, createdAt: new Date().toISOString() },
{ id: 2, title: '理解多运行时概念', completed: false, createdAt: new Date().toISOString() },
{ id: 3, title: '构建一个 REST API', completed: false, createdAt: new Date().toISOString() },
]
let nextId = 4
const createTodoSchema = z.object({
title: z.string().min(1, '标题不能为空').max(100, '标题不能超过100字'),
})
const updateTodoSchema = z.object({
title: z.string().min(1).max(100).optional(),
completed: z.boolean().optional(),
})
const app = new Hono()
app.use('*', cors())
app.use('*', logger())
// GET /todos - 获取所有待办事项
app.get('/todos', (c) => c.json({ todos }))
// GET /todos/:id - 获取单个待办事项
app.get('/todos/:id', (c) => {
const id = Number(c.req.param('id'))
const todo = todos.find(t => t.id === id)
if (!todo) return c.json({ error: '待办事项不存在' }, 404)
return c.json({ todo })
})
// POST /todos - 创建待办事项
app.post('/todos', zValidator('json', createTodoSchema), async (c) => {
const { title } = await c.req.json()
const newTodo: Todo = { id: nextId++, title, completed: false, createdAt: new Date().toISOString() }
todos.push(newTodo)
return c.json({ todo: newTodo }, 201)
})
// PUT /todos/:id - 更新待办事项
app.put('/todos/:id', zValidator('json', updateTodoSchema), async (c) => {
const id = Number(c.req.param('id'))
const todoIndex = todos.findIndex(t => t.id === id)
if (todoIndex === -1) return c.json({ error: '待办事项不存在' }, 404)
const body = await c.req.json()
todos[todoIndex] = { ...todos[todoIndex], ...body }
return c.json({ todo: todos[todoIndex] })
})
// DELETE /todos/:id - 删除待办事项
app.delete('/todos/:id', (c) => {
const id = Number(c.req.param('id'))
const todoIndex = todos.findIndex(t => t.id === id)
if (todoIndex === -1) return c.json({ error: '待办事项不存在' }, 404)
todos.splice(todoIndex, 1)
return c.json({ message: `已删除 ID 为 ${id} 的待办事项` })
})
app.onError((err, c) => {
console.error(err)
return c.json({ error: '服务器内部错误' }, 500)
})
export default app
4.3 运行测试
npm run dev
# 访问 http://localhost:3000
4.4 API 结构

五、Hono vs Express 对比
| 维度 | Hono | Express |
|---|---|---|
| 包大小 | ~14KB | ~572KB(40x) |
| 运行时 | Workers/Deno/Bun/Node | Node.js 仅 |
| TypeScript | 一等公民 | 外部 @types |
| 异步模型 | 原生 async/await | 回调 |
| JSON 解析 | 内置 c.req.json() |
需 express.json() |
| CORS | 内置 cors() |
需 cors 包 |
六、结语
Hono 展示了 Web 框架设计的另一种可能------基于 Web 标准,而不是基于运行时。它的设计理念是:框架应该适配运行时,而不是运行时适配框架。
适用场景: Edge API、微服务、Serverless、多运行时兼容项目 学习建议: 有 Express 经验者上手极快,从构建一个 CRUD API 开始,尝试部署到 Cloudflare Workers
