Hono vs Express:在 Cloudflare Workers 和 Node 上的性能基准
Source: Dev.to
(请提供需要翻译的正文内容,我才能为您完成简体中文的翻译。)
基准概览
所有测试均使用 wrk(12 线程,400 连接,30 秒时长)在相同硬件(M3 Pro,36 GB RAM)上运行,使用共享的 Postgres 连接池(pg,10 连接)并在每个请求中执行一次按主键的 SELECT。
测试路由
GET /users/:id – 验证 UUID 参数,执行一次按主键的 SELECT,返回 JSON。
结果
| 框架 | 请求/秒 | p50 延迟 | p99 延迟 |
|---|---|---|---|
| Express 4 | 12,400 | 28 ms | 94 ms |
| Fastify 4 | 31,200 | 11 ms | 38 ms |
| Hono 4 | 28,600 | 12 ms | 41 ms |
| Hono 4 + Bun | 41,800 | 8 ms | 27 ms |
注意: Express 无法在 Cloudflare Workers 上运行(没有 Node.js 运行时)。Hono 是为该环境设计的。
Workers 与 Node
配置与冷启动
| 环境 | 模拟请求/秒 | 冷启动延迟 |
|---|---|---|
| Hono 在 Workers 上 | ~45,000 | 见下例 |
// Example cold‑start handler (Express‑style)
const { id } = req.params;
if (!isValidUUID(id)) {
return res.status(400).json({ error: 'Invalid ID' });
}
const user = await db.users.findById(id);
if (!user) return res.status(404).json({ error: 'Not found' });
res.json(user);
});
app.listen(3000);
Hono(TypeScript)
import { Hono } from 'hono';
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';
const app = new Hono();
app.get(
'/users/:id',
zValidator('param', z.object({ id: z.string().uuid() })),
async (c) => {
const { id } = c.req.valid('param'); // typed & validated
const user = await db.users.findById(id);
if (!user) return c.json({ error: 'Not found' }, 404);
return c.json(user);
}
);
export default app; // Works on Workers, Bun, Node, Deno
关键区别
c.req.valid('param')返回 已类型化、已验证的数据。- 在 Express 中,
req.params仅是Record;必须手动进行验证。
这种模式类似于 tRPC 的类型安全,但适用于传统的 REST 接口。
中间件概览
| 功能 | Hono(官方) | Express(npm 生态系统) |
|---|---|---|
| CORS、压缩、日志、JWT 认证、速率限制、缓存头 | ✅ | ✅(通过第三方) |
| Zod / TypeBox 验证器 | ✅ | ✅(通过第三方) |
| 静态文件服务 | ✅ | ✅ |
| OpenAPI 规范生成 | ✅ | ✅(通过 swagger-ui-express 等) |
| Passport.js | ❌(暂无干净的移植) | ✅ |
express-session | ❌(使用 Workers KV / Durable Objects) | ✅ |
| 专用 OAuth 中间件 | ❌(部分缺失) | ✅ |
对于全新项目,Hono 官方中间件覆盖了约 90 % 的典型使用场景。迁移一个严重依赖 passport.js 或其他小众中间件的现有 Express 应用时,需要考虑迁移成本。
可移植性示例
// src/app.ts – write once
import { Hono } from 'hono';
export const app = new Hono();
app.get('/health', (c) => c.json({ ok: true }));
export default app;
Cloudflare Workers
# wrangler.toml
# point `main` to src/app.ts
// Workers entry (no extra code needed)
export default app;
Node.js
import { serve } from '@hono/node-server';
import { app } from './app';
serve({ fetch: app.fetch, port: 3000 });
Bun
import { app } from './app';
Bun.serve({ fetch: app.fetch, port: 3000 });
相同的代码库既可以在边缘运行时(Workers、Pages Functions)上运行,也可以在传统服务器上运行,从而简化了部署流水线。
决策指南
- 已有使用大量中间件的 Express 应用 → 迁移成本可能超过性能收益。
- 团队不熟悉 Web Request/Response API(Hono 的
c.req/c.res) → 需要考虑培训开销。 - 需要 Passport.js 或其他 Express‑特定插件 → 继续使用 Express,或寻找替代方案。
- 全新 TypeScript API → 采用 Hono。
- 部署目标为 Cloudflare Workers、Pages Functions 或其他边缘运行时 → Hono 是自然的选择。
- 希望在不全面采用 tRPC 的情况下实现端到端类型安全 → 使用 Hono + Zod 验证器。
- Bun 运行时 → 在我们的测试中,Hono + Bun 目前提供最快的性能。
Performance Considerations
Hono 与 Express 在 Node 上的性能差距仅在 high concurrency 时才重要。在典型的生产负载 ≈ 100 req/sec 下,面向用户的延迟差异可以忽略不计。选择 Hono 应基于其更佳的开发者体验和类型安全,而不是原始的基准数字。
Hono vs. Fastify
Fastify 在纯 Node 环境下略快于 Hono,但 不支持在 Workers 上运行,且插件系统更复杂。当 多运行时可移植性(Workers ↔ Node ↔ Bun)是优先考虑时,Hono 显然是胜者。