Hono vs Express:在 Cloudflare Workers 和 Node 上的性能基准

发布: (2026年4月21日 GMT+8 11:01)
5 分钟阅读
原文: Dev.to

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 412,40028 ms94 ms
Fastify 431,20011 ms38 ms
Hono 428,60012 ms41 ms
Hono 4 + Bun41,8008 ms27 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 显然是胜者。

0 浏览
Back to Blog

相关文章

阅读更多 »

NestJS 中的数据传输对象 (DTO)

什么是 Data Transfer Object DTO?Data Transfer Object DTO 是一种在 NestJS 中使用的设计模式,用于定义数据的结构以及在不同…之间的传输。