DevToolBox免费
博客

Hono vs Express.js:新型极简 Web 框架之争

9 分钟阅读作者 DevToolBox

Express.js十多年来一直主导着Node.js Web开发,但Hono作为专为边缘计算时代设计的现代替代品正在崛起。本全面比较考察性能、开发者体验、生态系统和真实用例,帮助你为下一个项目选择合适的框架。

TL;DR - 快速总结

Hono提供卓越的性能(快5倍以上),可在任何JavaScript运行时(Node.js、Deno、Bun、Cloudflare Workers)上运行,并具有现代的TypeScript优先设计。Express.js对于遗留项目和需要广泛中间件生态系统的团队仍然是安全的选择。对于2025年的新项目,推荐使用Hono。

核心要点

  • Hono比Express.js快5-10倍,内存使用量显著更低
  • Hono随处运行:Node.js、Deno、Bun、Cloudflare Workers、AWS Lambda
  • Express.js拥有最大的中间件生态系统,但许多已过时
  • Hono是TypeScript优先,开箱即用提供出色的类型推断
  • 两个框架有类似的API,使迁移相对容易
  • Hono的内置中间件涵盖大多数常见用例

什么是Hono?

Hono是一个轻量级、快速、可移植的Web框架,专为边缘计算设计。Hono(日语意为"火焰")由Yusuke Wada于2022年创建,优先考虑速度和可移植性。它使用Web标准Request/Response API,允许它在任何JavaScript运行时上无需修改即可运行。

什么是Express.js?

Express.js创建于2009年,是Node.js Web框架的事实标准。其极简、无倾向性的方法使其成为无数Web应用和API的基础。Express在npm上每周有超过3000万次下载,仍然是最广泛使用的Node.js框架。

架构对比

特性Express.jsHono
首次发布20092022
设计目标SimplicitySpeed + Portability
API标准Node.js req/resWeb Standards (Request/Response)
TypeScript支持需额外配置原生支持
运行时支持Node.js onlyNode.js, Deno, Bun, Workers
包大小~210KB~20KB
依赖数量30+0

性能对比

在AWS c6i.xlarge实例上使用wrk的性能基准测试:

Hello World 基准测试

使用100个并发连接进行简单JSON响应测试:

// Express Hello World
import express from 'express';
const app = express();

app.get('/', (req, res) => {
  res.json({ message: 'Hello World' });
});

app.listen(3000);

// Hono Hello World
import { Hono } from 'hono';
const app = new Hono();

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

export default app;
指标Express.jsHono提升
请求/秒~12,000~68,0005.7x
延迟 (p99)18ms3ms6x
内存使用 (启动)~45MB~8MB5.6x
内存使用 (负载下)~120MB~25MB4.8x

中间件性能

测试常用中间件(CORS、请求体解析、日志记录):

// Express with middleware
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';
import bodyParser from 'body-parser';

const app = express();
app.use(cors());
app.use(helmet());
app.use(morgan('tiny'));
app.use(bodyParser.json());

app.post('/api/users', (req, res) => {
  res.json({ created: req.body });
});

// Hono with middleware
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
import { bodyLimit } from 'hono/body-limit';

const app = new Hono();
app.use('*', cors());
app.use('*', logger());
app.use('*', bodyLimit({ maxSize: 1024 * 1024 })); // 1MB

app.post('/api/users', async (c) => {
  const body = await c.req.json();
  return c.json({ created: body });
});
配置Express.jsHono
CORS + Helmet + Logger + Body Parser~8,500 req/s~52,000 req/s
仅JSON响应~12,000 req/s~68,000 req/s

功能对比

比较内置功能和生态系统:

功能Express.jsHono
路由内置内置 (含模式匹配)
中间件需安装丰富的内置中间件
CORScors包hono/cors (内置)
Body解析body-parser包内置
JWT认证jsonwebtoken包hono/jwt (内置)
Cookie处理cookie-parser包hono/cookie (内置)
缓存需外部包hono/cache (内置)
HTML模板需选择模板引擎JSX支持内置
验证joi/yup/zod@hono/zod-validator
OpenAPI/Swagger需配置@hono/zod-openapi

代码示例

类似的API使迁移变得简单直接:

Express.js

// Express.js - Complete API example
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import jwt from 'jsonwebtoken';

const app = express();

// Middleware
app.use(helmet());
app.use(cors());
app.use(express.json());

// Authentication middleware
const authMiddleware = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'Unauthorized' });
  
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET!);
    req.user = decoded;
    next();
  } catch {
    res.status(401).json({ error: 'Invalid token' });
  }
};

// Routes
app.get('/api/users', async (req, res) => {
  try {
    const users = await db.query('SELECT id, email, name FROM users');
    res.json({ users });
  } catch (error) {
    res.status(500).json({ error: 'Database error' });
  }
});

app.post('/api/users', async (req, res) => {
  const { email, name } = req.body;
  
  try {
    const result = await db.query(
      'INSERT INTO users (email, name) VALUES ($1, $2) RETURNING *',
      [email, name]
    );
    res.status(201).json({ user: result[0] });
  } catch (error) {
    res.status(400).json({ error: 'Invalid data' });
  }
});

app.get('/api/users/:id', authMiddleware, async (req, res) => {
  const { id } = req.params;
  
  try {
    const user = await db.query('SELECT * FROM users WHERE id = $1', [id]);
    if (!user.length) return res.status(404).json({ error: 'Not found' });
    res.json({ user: user[0] });
  } catch (error) {
    res.status(500).json({ error: 'Database error' });
  }
});

// Error handling
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ error: 'Internal server error' });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Hono

// Hono - Complete API example
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
import { jwt } from 'hono/jwt';
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';

const app = new Hono();

// Global middleware
app.use('*', logger());
app.use('*', cors());

// Validation schemas
const userSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1),
});

// Public routes
app.get('/api/users', async (c) => {
  try {
    const users = await db.query('SELECT id, email, name FROM users');
    return c.json({ users });
  } catch {
    return c.json({ error: 'Database error' }, 500);
  }
});

app.post('/api/users', zValidator('json', userSchema), async (c) => {
  const { email, name } = c.req.valid('json');
  
  try {
    const result = await db.query(
      'INSERT INTO users (email, name) VALUES ($1, $2) RETURNING *',
      [email, name]
    );
    return c.json({ user: result[0] }, 201);
  } catch {
    return c.json({ error: 'Invalid data' }, 400);
  }
});

// Protected routes
app.use('/api/users/*', jwt({ secret: process.env.JWT_SECRET! }));

app.get('/api/users/:id', async (c) => {
  const id = c.req.param('id');
  const payload = c.get('jwtPayload');
  
  try {
    const user = await db.query('SELECT * FROM users WHERE id = $1', [id]);
    if (!user.length) return c.json({ error: 'Not found' }, 404);
    return c.json({ user: user[0] });
  } catch {
    return c.json({ error: 'Database error' }, 500);
  }
});

// Error handling
app.onError((err, c) => {
  console.error(`${err}`);
  return c.json({ error: 'Internal server error' }, 500);
});

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

export default app;

TypeScript体验

TypeScript支持对比:

Express.js

需要@types/express,类型定义有时过时。请求/响应对象的类型扩展需要额外配置。社区维护的类型可能滞后于新版本。

Hono

原生TypeScript编写,一流的类型支持。自动推断路径参数、查询参数和请求体类型。Context对象完全类型化,中间件可以修改类型上下文。

// Hono TypeScript - Type-safe routes
import { Hono } from 'hono';
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';

const app = new Hono();

// Types are automatically inferred
app.get('/api/users/:id', async (c) => {
  // id is typed as string
  const id = c.req.param('id');
  
  // query parameters are typed
  const page = c.req.query('page'); // string | undefined
  
  // Response is type-checked
  return c.json({ 
    id, 
    name: 'John',
    // TypeScript will error if you return wrong type
  });
});

// With Zod validation - types flow through
const schema = z.object({
  email: z.string().email(),
  age: z.number().min(0),
});

app.post('/api/users', zValidator('json', schema), async (c) => {
  // validated is typed as { email: string, age: number }
  const validated = c.req.valid('json');
  
  // TypeScript knows the exact shape
  console.log(validated.email); // ✓
  console.log(validated.name);  // ✗ TypeScript error!
  
  return c.json({ success: true });
});

部署选项

你可以在哪里部署每个框架?

平台Express.jsHono
Node.js✓ Native✓ Native
Deno需适配✓ Native
Bun✓ Compatible✓ Native
Cloudflare Workers需适配器✓ Native
Deno Deploy需适配器✓ Native
Vercel Edge需适配器✓ Native
AWS Lambda✓ serverless-http✓ @hono/aws-lambda
Fly.io✓ Docker✓ Docker / Native
Railway✓ Native✓ Native

从Express迁移到Hono

分步迁移指南:

// Migration: Express to Hono

// 1. Install dependencies
// npm uninstall express cors helmet morgan body-parser
// npm install hono @hono/node-server

// 2. Update imports
// Before:
import express from 'express';
import cors from 'cors';

// After:
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { serve } from '@hono/node-server';

// 3. Update app initialization
// Before:
const app = express();

// After:
const app = new Hono();

// 4. Update middleware
// Before:
app.use(cors());
app.use(express.json());

// After:
app.use('*', cors());
// JSON parsing is built-in, no middleware needed!

// 5. Update route handlers
// Before:
app.get('/users', (req, res) => {
  res.json({ users: [] });
});

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

// 6. Update error handling
// Before:
app.use((err, req, res, next) => {
  res.status(500).json({ error: err.message });
});

// After:
app.onError((err, c) => {
  return c.json({ error: err.message }, 500);
});

// 7. Start server (Node.js only)
// Before:
app.listen(3000);

// After:
serve({ fetch: app.fetch, port: 3000 });

何时使用每个框架

使用Hono的场景:

  • 新项目开发
  • 边缘计算/无服务器
  • 高性能API
  • Cloudflare Workers
  • TypeScript优先项目
  • 多运行时部署
  • 快速原型开发

使用Express的场景:

  • 遗留代码维护
  • 团队熟悉Express生态
  • 依赖特定中间件
  • Node.js专用部署
  • 企业级应用(已验证)
  • 需要丰富文档和教程

结论

在2025年,Hono代表着JavaScript Web框架的未来。其性能优势、运行时可移植性和现代设计使其成为新项目的理想选择。Express.js对于维护现有应用仍然是可靠的选择,但新开发应该认真考虑Hono。Web开发的未来是边缘优先、多运行时和TypeScript原生——这些都是Hono的优势。

试试我们的相关工具

JSON Formatter UUID Generator JWT Decoder

FAQ

Hono已经可以用于生产了吗?

是的,Hono已经可以用于生产,被Cloudflare、Deno等公司在生产环境中使用。它已达到4.x版本,API稳定,并积极维护,定期更新。

我可以在Hono中使用Express中间件吗?

不能直接,因为它们有不同的API。然而,Hono有大多数流行Express中间件的等效中间件,许多包可以两者通用。Hono生态系统包括CORS、请求体解析、认证和其他常见中间件。

Hono比Fastify快吗?

在大多数基准测试中,Hono和Fastify具有可比的性能,都比Express快得多。Hono的优势在于其跨运行时的可移植性,而Fastify专门为Node.js优化。

如何将Hono部署到Cloudflare Workers?

Hono无需任何适配器即可在Cloudflare Workers上原生工作。只需使用Web标准API并用wrangler部署。Hono使用Request/Response API使其成为边缘平台的理想选择。

Hono可以在现有项目中替代Express吗?

可以,但需要迁移你的中间件和路由处理器。API足够相似,路由逻辑容易转移。开始时可以一次迁移一个路由,或将Hono用于新的微服务。

Hono支持WebSocket吗?

Hono为Node.js和Deno提供内置WebSocket支持。对于Cloudflare Workers,你可以将Durable Objects与WebSockets一起使用。API简单且文档完善。

Hono适合构建REST API吗?

当然。Hono的内置验证、TypeScript支持和中间件使其非常适合REST API开发。它包括OpenAPI/Swagger集成等常见模式的辅助工具。

Hono中的文件上传呢?

Hono通过hono/multipart中间件内置支持multipart/form-data文件上传。它在所有支持的运行时上一致工作。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

{ }JSON Formatter🐳Docker Compose GeneratorNXNginx Config Generator

相关文章

Hono 完全指南:超快边缘计算 Web 框架

掌握 Hono 路由、中间件、Zod 验证、JWT 认证、CORS、OpenAPI、RPC 模式与多运行时支持。

Fastify 完全指南:高性能 Node.js Web 框架

掌握 Fastify 路由、Schema 验证、插件、钩子、序列化、日志、JWT 认证与数据库集成。

Express.js指南:路由、中间件、REST API和身份验证

掌握Express.js Node.js Web开发。涵盖路由、中间件、CRUD REST API构建、JWT身份验证、错误处理和Express vs Fastify vs Koa vs Hapi对比。