express vs koa vs fastify vs hapi
Node.js 后端框架架构选型指南
expresskoafastifyhapi类似的npm包:

Node.js 后端框架架构选型指南

express, fastify, hapi, 和 koa 都是 Node.js 生态中成熟的后端 Web 框架,用于构建 API 服务器和 Web 应用。express 是最经典的选择,生态最丰富,适合快速原型和传统项目;fastify 主打高性能和内置 JSON Schema 验证,适合高并发 API;koa 由 Express 原班人马打造,核心更现代且轻量,完全基于 async/await;hapi(现主要为 @hapi/hapi)则侧重配置化和企业级插件系统,适合大型复杂架构。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
express80,169,21068,86475.4 kB1893 个月前MIT
koa6,640,10735,73765 kB267 天前MIT
fastify5,488,20835,7352.73 MB1191 个月前MIT
hapi56,17614,768-597 年前BSD-3-Clause

Node.js Web 框架深度对比:Express, Fastify, Hapi, Koa

在 Node.js 后端开发中,选择 Web 框架是架构决策的第一步。express, fastify, hapi, 和 koa 代表了四种不同的设计哲学。作为架构师,我们需要从核心机制、开发体验、性能和维护成本四个维度进行拆解。

🏗️ 核心架构:中间件 vs 上下文 vs 配置

框架的核心决定了代码的组织方式。

express 采用传统的中间件栈模式。

  • 请求经过一系列函数,每个函数接收 req, resnext
  • 必须手动调用 next() 传递控制权,否则请求会挂起。
// express: 中间件链
app.use((req, res, next) => {
  console.log('Time:', Date.now());
  next(); // 必须调用
});

koa 采用洋葱模型上下文模式。

  • 所有状态挂载在 ctx 上,没有 reqres 分离。
  • 基于 async/await,await next() 控制流程,更直观。
// koa: 上下文组合
app.use(async (ctx, next) => {
  console.log('Time:', Date.now());
  await next(); // 等待下游完成
});

fastify 采用封装钩子模式。

  • 核心是钩子(hooks)和装饰器(decorators)。
  • 插件作用域隔离,避免全局污染,性能优化更激进。
// fastify: 钩子与封装
fastify.addHook('onRequest', async (request, reply) => {
  console.log('Time:', Date.now());
  // 无需手动调用 next,钩子自动执行
});

hapi 采用配置驱动模式。

  • 逻辑通过配置对象定义,而非链式调用。
  • 扩展点(extensions)明确,强调不可变性和安全性。
// hapi: 扩展点配置
server.ext('onRequest', (request, h) => {
  console.log('Time:', Date.now());
  return h.continue; // 显式返回继续
});

🛣️ 路由系统:内置 vs 外挂

路由管理方式直接影响项目结构。

express 内置路由实例。

  • 直接在 app 或 router 实例上定义。
  • 简单直接,支持参数和正则。
// express: 内置路由
app.get('/users/:id', (req, res) => {
  res.send({ id: req.params.id });
});

koa 核心不包含路由。

  • 官方推荐配合 @koa/router 使用。
  • 增加了依赖,但保持了核心轻量。
// koa: 外挂路由
const router = require('@koa/router')();
router.get('/users/:id', ctx => {
  ctx.body = { id: ctx.params.id };
});

fastify 内置高性能路由。

  • 语法类似 Express,但底层基于 find-my-way。
  • 支持约束路由(如按 Host 或 Version)。
// fastify: 内置路由
fastify.get('/users/:id', (req, reply) => {
  reply.send({ id: req.params.id });
});

hapi 配置式路由。

  • 路由是服务器配置的一部分,包含 method, path, handler。
  • 结构清晰,适合大型路由表管理。
// hapi: 配置路由
server.route({
  method: 'GET',
  path: '/users/{id}',
  handler: (request, h) => ({ id: request.params.id })
});

🛡️ 验证与序列化:手动 vs 内置

API 的安全性和数据规范性至关重要。

express 完全手动或依赖中间件。

  • 需自行集成 joi, zodexpress-validator
  • 灵活但容易遗漏,样板代码多。
// express: 手动验证
app.post('/user', (req, res, next) => {
  if (!req.body.name) return res.status(400).send('Name required');
  next();
});

koa 完全手动或依赖中间件。

  • 类似 Express,需引入 koa-joi 等库。
  • ctx 上处理验证逻辑。
// koa: 手动验证
router.post('/user', async ctx => {
  if (!ctx.request.body.name) {
    ctx.status = 400;
    ctx.body = 'Name required';
    return;
  }
});

fastify 内置 JSON Schema 验证。

  • 定义 Schema 后自动验证请求和响应。
  • 自动序列化响应,性能极高。
// fastify: 内置 Schema
fastify.post('/user', {
  schema: {
    body: { type: 'object', required: ['name'], properties: { name: { type: 'string' } } }
  }
}, (req, reply) => {
  reply.send(req.body); // 自动序列化
});

hapi 内置验证(基于 Joi)。

  • 在路由配置中定义 validate 选项。
  • 强制性强,减少运行时错误。
// hapi: 内置验证
server.route({
  method: 'POST',
  path: '/user',
  options: {
    validate: {
      payload: { name: Joi.string().required() }
    }
  },
  handler: (request, h) => request.payload
});

⚠️ 错误处理:回调 vs 异步 vs 扩展

错误处理机制决定了系统的稳定性。

express 依赖错误处理中间件。

  • 需定义 4 个参数的中间件 (err, req, res, next)
  • 容易忘记捕获异步错误,导致进程崩溃。
// express: 错误中间件
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

koa 原生 try/catch 支持。

  • 中间件内直接用 try/catch 捕获异步错误。
  • 全局监听 app.on('error') 处理未捕获异常。
// koa: 异步捕获
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    ctx.status = err.status || 500;
    ctx.body = err.message;
  }
});

fastify 统一错误处理器。

  • 注册 setErrorHandler 集中处理。
  • 支持按错误代码分类处理。
// fastify: 统一处理
fastify.setErrorHandler((error, request, reply) => {
  reply.status(500).send({ error: error.message });
});

hapi 扩展点处理。

  • 使用 onPreResponse 扩展点拦截响应。
  • 可以修改错误响应格式。
// hapi: 响应扩展
server.ext('onPreResponse', (request, h) => {
  const response = request.response;
  if (response.isBoom) {
    return h.response({ message: response.message }).code(response.output.statusCode);
  }
  return h.continue;
});

📊 综合对比总结

特性expressfastifyhapikoa
核心风格中间件栈钩子与封装配置驱动上下文洋葱模型
异步模型回调/AsyncAsyncAsyncAsync/Await 原生
路由内置内置 (高性能)内置 (配置式)需外挂 (@koa/router)
验证手动/中间件内置 JSON Schema内置 (Joi)手动/中间件
性能中等极高中等偏低中等
生态规模⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
学习曲线

💡 架构师建议

express 是稳妥的默认选择 🛡️。如果团队没有特殊性能需求,或者需要快速利用海量现有中间件(如 Passport, Multer),Express 能最大程度降低开发阻力。但在新项目中,需注意异步错误捕获的规范。

fastify 是高性能 API 的首选 🚀。如果构建微服务、高并发网关,或对请求/响应格式有严格 Schema 要求,Fastify 的内置验证和序列化能节省大量代码并提升吞吐量。其插件封装机制也更适合大型团队协作。

hapi 适合企业级规范项目 🏢。如果项目规模巨大,需要严格的配置管理和插件隔离,且团队能接受较陡的学习曲线,Hapi 的架构约束能减少人为错误。注意需迁移至 @hapi 命名空间。

koa 适合现代极简主义 🍃。如果团队偏好函数式编程风格,希望核心轻量且完全掌控中间件组合,Koa 是最佳选择。它没有历史包袱,代码最干净,但需要自己维护路由和验证生态。

最终结论:对于大多数新启动的 Node.js API 项目,fastify 在性能与现代开发体验之间取得了最佳平衡。若追求极致生态兼容性,express 依然可靠。

如何选择: express vs koa vs fastify vs hapi

  • express:

    选择 express 如果你需要最丰富的中间件生态,或者团队熟悉传统的回调风格。它适合快速构建原型、中小型项目,以及需要大量现成社区支持的场景。由于其历史悠久,遇到问题时最容易找到解决方案。

  • koa:

    选择 koa 如果你喜欢 async/await 原生支持,想要一个极简的核心,自己组装路由和验证库。它适合希望摆脱回调地狱,追求代码简洁和现代 JavaScript 特性的团队。由于核心小,你需要自己挑选中间件。

  • fastify:

    选择 fastify 如果你关注极致的性能,或者希望框架内置请求验证和序列化功能。它适合高并发 API 服务,以及对类型安全和 Schema 驱动开发有要求的团队。其插件封装机制也适合大型模块化项目。

  • hapi:

    选择 hapi 如果你的项目是企业级大型应用,偏好配置优于代码的风格,且需要强大的插件隔离能力。注意需使用 @hapi/hapi 包。它适合对安全性和架构规范性有严格要求的场景,但学习曲线较陡。

express的README

Express Logo

Fast, unopinionated, minimalist web framework for Node.js.

This project has a Code of Conduct.

Table of contents

NPM Version NPM Downloads Linux Build Test Coverage OpenSSF Scorecard Badge

import express from 'express'

const app = express()

app.get('/', (req, res) => {
  res.send('Hello World')
})

app.listen(3000, () => {
  console.log('Server is running on http://localhost:3000')
})

Installation

This is a Node.js module available through the npm registry.

Before installing, download and install Node.js. Node.js 18 or higher is required.

If this is a brand new project, make sure to create a package.json first with the npm init command.

Installation is done using the npm install command:

npm install express

Follow our installing guide for more information.

Features

  • Robust routing
  • Focus on high performance
  • Super-high test coverage
  • HTTP helpers (redirection, caching, etc)
  • View system supporting 14+ template engines
  • Content negotiation
  • Executable for generating applications quickly

Docs & Community

PROTIP Be sure to read the migration guide to v5

Quick Start

The quickest way to get started with express is to utilize the executable express(1) to generate an application as shown below:

Install the executable. The executable's major version will match Express's:

npm install -g express-generator@4

Create the app:

express /tmp/foo && cd /tmp/foo

Install dependencies:

npm install

Start the server:

npm start

View the website at: http://localhost:3000

Philosophy

The Express philosophy is to provide small, robust tooling for HTTP servers, making it a great solution for single page applications, websites, hybrids, or public HTTP APIs.

Express does not force you to use any specific ORM or template engine. With support for over 14 template engines via @ladjs/consolidate, you can quickly craft your perfect framework.

Examples

To view the examples, clone the Express repository:

git clone https://github.com/expressjs/express.git --depth 1 && cd express

Then install the dependencies:

npm install

Then run whichever example you want:

node examples/content-negotiation

Contributing

The Express.js project welcomes all constructive contributions. Contributions take many forms, from code for bug fixes and enhancements, to additions and fixes to documentation, additional tests, triaging incoming pull requests and issues, and more!

See the Contributing Guide for more technical details on contributing.

Security Issues

If you discover a security vulnerability in Express, please see Security Policies and Procedures.

Running Tests

To run the test suite, first install the dependencies:

npm install

Then run npm test:

npm test

Current project team members

For information about the governance of the express.js project, see GOVERNANCE.md.

The original author of Express is TJ Holowaychuk

List of all contributors

TC (Technical Committee)

TC emeriti members

TC emeriti members

Triagers

Triagers emeriti members

Emeritus Triagers

License

MIT