express vs koa vs hapi vs sails
Node.js Web 框架选型指南
expresskoahapisails类似的npm包:

Node.js Web 框架选型指南

expresshapikoasails 都是 Node.js 生态中成熟的 Web 服务器框架,但设计哲学差异巨大。express 是最流行的极简框架,依靠中间件构建功能;koa 由 Express 原班人马打造,主打异步编程体验;hapi 强调配置驱动和安全性,适合大型企业;sails 则是全能型 MVC 框架,内置 ORM 和自动生成 API 功能。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
express71,720,99068,88675.4 kB1914 个月前MIT
koa5,588,06835,74565 kB3321 天前MIT
hapi57,57414,783-587 年前BSD-3-Clause
sails27,09522,8433.27 MB5891 个月前MIT

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

对于前端架构师而言,选择 Node.js Web 框架不仅仅是选一个工具,而是选择一种开发模式和维护策略。expresshapikoasails 代表了四种不同的设计思路。我们将通过核心架构、异步处理、路由验证和维护状态四个维度进行深度剖析。

🏗️ 核心架构:中间件 vs 配置 vs MVC

express 采用线性中间件模型。

  • 请求通过一系列函数处理,开发者自由决定顺序。
  • 灵活性高,但缺乏强制结构,大型项目需自行规范。
// express: 中间件链
const express = require('express');
const app = express();

app.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});

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

hapi 采用配置驱动模型。

  • 逻辑通过配置对象定义,而非代码流程。
  • 强制分离关注点,适合大型团队协作。
// hapi: 配置路由
const Hapi = require('@hapi/hapi');

const init = async () => {
  const server = Hapi.server({ port: 3000 });
  
  server.route({
    method: 'GET',
    path: '/',
    handler: (request, h) => {
      return 'Hello World';
    }
  });
  
  await server.start();
};

koa 采用洋葱模型中间件。

  • 类似 Express,但通过 async/await 控制流程。
  • 上下文对象 ctx 封装了请求和响应,更简洁。
// koa: 洋葱模型
const Koa = require('koa');
const app = new Koa();

app.use(async (ctx, next) => {
  console.log('Time:', Date.now());
  await next();
});

app.use(async ctx => {
  ctx.body = 'Hello World';
});

sails 采用传统 MVC 架构。

  • 自动路由控制器,内置模型视图控制器结构。
  • 约定优于配置,适合快速生成 CRUD 接口。
// sails: 控制器动作
// api/controllers/HomeController.js
module.exports = {
  index: function (req, res) {
    return res.view('homepage', { message: 'Hello World' });
  }
};

⏳ 异步处理:回调 vs Async/Await

express 传统上基于回调,现在支持 Promise。

  • 中间件使用 next() 函数传递控制流。
  • 错误处理需显式调用 next(err)
// express: 回调风格
app.get('/user', (req, res, next) => {
  getUser(id, (err, user) => {
    if (err) return next(err);
    res.json(user);
  });
});

hapi 原生支持 Promise 和 async/await。

  • 处理函数直接返回 Promise 或值。
  • 错误通过抛出异常或返回 error 对象处理。
// hapi: Promise 风格
server.route({
  method: 'GET',
  path: '/user',
  handler: async (request, h) => {
    const user = await getUser(id);
    return user;
  }
});

koa 原生基于 async/await 设计。

  • 没有回调地狱,代码像同步一样书写。
  • 错误通过 try/catch 自动捕获。
// koa: Async/Await 风格
app.use(async ctx => {
  try {
    const user = await getUser(id);
    ctx.body = user;
  } catch (err) {
    ctx.status = 500;
  }
});

sails 混合支持回调和 Promise。

  • 底层基于 Express,但封装了异步逻辑。
  • 水线 ORM (Waterline) 支持 Promise 链式调用。
// sails: 混合风格
// api/controllers/UserController.js
module.exports = {
  find: async function (req, res) {
    try {
      const users = await User.find();
      return res.json(users);
    } catch (err) {
      return res.serverError(err);
    }
  }
};

🛡️ 路由与验证:自由 vs 严格

express 路由灵活,验证需第三方库。

  • 使用 express-router 或直接在 app 定义。
  • 验证通常结合 joiexpress-validator
// express: 灵活路由
app.use('/api', apiRouter);

// 验证需手动集成
app.post('/user', validateUser, (req, res) => {
  res.send('Created');
});

hapi 内置强大的验证系统。

  • 使用 joi 库定义输入输出规则。
  • 自动返回验证错误,减少样板代码。
// hapi: 内置验证
server.route({
  method: 'POST',
  path: '/user',
  options: {
    validate: {
      payload: {
        name: Joi.string().required()
      }
    }
  },
  handler: (request, h) => {
    return { id: 1, name: request.payload.name };
  }
});

koa 路由需中间件,验证需自行集成。

  • 核心不包含路由,常用 koa-router
  • 验证逻辑与 Express 类似,需手动组装。
// koa: 中间件路由
const router = require('koa-router')();

router.post('/user', async ctx => {
  // 验证需手动调用
  await validate(ctx.request.body);
  ctx.body = 'Created';
});

app.use(router.routes());

sails 自动基于控制器生成路由。

  • 约定式路由,无需手动映射每个 URL。
  • 内置蓝印 API (Blueprint API) 自动生成 CRUD。
// sails: 自动路由
// 配置 config/routes.js 或直接依赖约定
// GET /user/find 自动映射到 UserController.find

📉 维护状态与生态系统

express 生态最庞大,更新稳定。

  • 几乎所有 Node 库都支持 Express 中间件。
  • 社区活跃,遇到问题容易找到解决方案。
// express: 丰富的中间件生态
const cors = require('cors');
const helmet = require('helmet');
app.use(cors());
app.use(helmet());

hapi 企业级维护,更新节奏稳健。

  • 插件生态质量高,但数量少于 Express。
  • 适合长期稳定的大型系统,而非快速迭代原型。
// hapi: 插件注册
await server.register({
  plugin: require('@hapi/inert') // 静态文件服务
});

koa 社区活跃,核心精简。

  • 中间件质量高,但需自行筛选组合。
  • 适合喜欢定制技术栈的团队。
// koa: 组合中间件
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());

sails 更新频率较低,生态增长缓慢。

  • 适合维护旧项目或特定快速开发场景。
  • 新项目若需 MVC 结构,常转向 NestJS 等现代框架。
// sails: 内置功能无需额外包
// WebSocket 支持默认开启,无需额外配置 socket.io

📊 总结对比表

特性expresshapikoasails
架构模式中间件链配置驱动洋葱模型MVC 框架
异步风格回调/PromisePromise/AsyncAsync/Await混合
路由方式手动定义配置对象中间件自动约定
数据验证第三方库内置 (Joi)第三方库内置
学习曲线
适用场景通用 API/SSR大型企业服务高性能中间层快速原型/旧项目

💡 选型建议

express 是默认的安全选择 🛡️。如果你不确定选什么,或者需要最多的社区资源,选它。它就像瑞士军刀,虽然不专精某一项,但什么都能做。

hapi 是严谨的工程师之选 📐。如果你需要严格的输入验证和配置管理,且团队规模较大,它能减少人为错误。

koa 是现代开发者的偏好 🚀。如果你讨厌回调地狱,希望代码更干净,且愿意自己组装工具,它提供更好的开发体验。

sails 是特定场景的利器 🔨。如果你需要快速生成完整的 CRUD API 且不想配置 ORM,它很快。但在新项目中,请仔细评估其长期维护性。

最后建议:对于大多数前端团队构建 BFF (Backend For Frontend) 或 SSR 服务,expresskoa 通常是最优解。若涉及复杂的企业级业务逻辑且对安全性要求极高,hapi 值得考虑。避免在新的高并发核心业务中使用 sails,除非你有明确的遗留系统迁移需求。

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

  • express:

    选择 express 如果你需要最广泛的社区支持、丰富的中间件生态以及灵活的架构。它适合大多数 API 服务和 SSR 应用,尤其是团队希望快速上手且不受严格约束的场景。

  • koa:

    选择 koa 如果你希望拥有更现代的异步编程体验(async/await),且喜欢极简核心以便自行组装工具链。它适合追求代码简洁性和高性能的中间层服务。

  • hapi:

    选择 hapi 如果你正在构建大型企业级应用,需要严格的输入验证、内置缓存策略和配置驱动的开发模式。它适合对安全性和稳定性要求极高的金融或数据敏感型项目。

  • sails:

    选择 sails 如果你需要快速构建传统 MVC 结构的应用,且希望内置 ORM 和 WebSocket 支持而不想配置太多工具。但需注意其更新频率较低,适合维护旧项目或快速原型。

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