nodejs框架应该选哪一个好:express,koa,还是Hapi?

本文是翻译文章,原文请看Choosing the right Node.js Framework: Express, Koa, or Hapi?

nodejs已经发布十多年了。在这十多年中,它已经成为地球上发展最快的开源项目,在github上获得的超过59000的赞(注:作者是用的是2019年的统计,截止翻译时已经是89000多了)和上亿次的下载。

nodejs能够快速发展的原因之一是它允许开发者在服务端和客户端同时使用javaScript来开发。

nodejs是一个开源,跨平台的服务端运行环境,被设计来构建服务端可扩展的应用。因为nodejs广受欢迎,在以指数级的速度快速增长,它催生了一大批框架来提高构建应用的能力和速度。以追求在各种库,模版和组件的帮助下实现自动化。

在这篇文章中,我们会探索nodejs服务端三大框架express,Koa和Hapi的异同点。在将来的文章中,我们还会探索Next,Nuxt和Nest。

  • 将以下面几项作为对比的基础:
    • 受欢迎程度(github上的star和npm的下载量)
    • 安装
    • 基础的Hello World 应用
    • 优点
    • 不足
    • 性能
    • 安全
    • 社区活跃度

Express

GitHub Stars: 43,000+(注:截止翻译时已经+57,000了)

最新每周下载量800万+(注:最新数据时2546万+)

Express是一个小而灵活的node.js web应用框架,它提供了一系列强大的功能来构建web或者手机端应用,就像一个中间件一样帮助用户管理服务和路由。

安装Express

要安装Express,得确保已经安装了node.js。如果你想将Express安装到制定的目录,而且将它保存到依赖列表中,你应该使用下面的命令

1
$ npm install express --save

如果你只是临时下载,并不想添加到依赖列表中,可以使用下面的命令

1
$ npm install express --no-save

hello World应用

下面代码是用Express创建应用最简单的例子,它创建了一个服务,监听3000端口,当用户访问http://localhost:3000/时会返回“Hello World!”

1
2
3
4
5
6
7
8
const express = require('express')
const app = express()
const port = 3000

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

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

如果访问其它地址,将返回“404 not fund”。

优势

  • 基本上时nodejs中间件的标准
  • 简单,灵活可扩展
  • 开发速度快
  • 可定制
  • 学习曲线低
  • 集合第三方组件和
  • 专注于浏览器,模版渲染开箱即用

劣势

虽然Express方便易用,它还是不可避免的有一些小缺陷会影响开发进程。

  • 代码组织需要非常清晰,以避免在维护时出现问题
  • 当你的代码量比较多时,重构变得非常困难
  • 有很多手动的活需要干,因为你需要创建所有节点

(注:受眼界限制,客人感觉这个劣势有种为赋新词强说愁的感觉)

性能

Express提供了很薄的一层web应用的功能,不会将原生nodejs的特征掩盖住。

提升Express性能的最佳实践包括:

  • 使用Gzip压缩
  • 不要使用同步函数
  • 正确的日志输出(比如debug时,使用一些特殊的模块像debug,应用活动选择winston或者bunyan来记录)
  • 正确处理异常,使用 try-catch或者promises
  • 使用一些进程管理工具确保你的应用可以重启,或者使用一些init系统像systemd 或者 upstart。
  • 在集群中使用应用程序,可以通过集群来提升node.js性能(集群运行应用程序的多个实例,在实例之间分配负载和任务)。
  • 缓存请求结果,让应用不会重复一些服务端的请求。
  • 使用负载均衡器来运行它的多个实例并分配流量,例如 Nginx 或 HAProxy。
  • 使用对请求执行支持操作的反向代理。 它可以处理错误页面、压缩、缓存、服务文件和负载平衡等。

下图是Express的helo world应用每秒请求的响应状况
Express应用每秒请求的性能状况

安全

在这个链接你可以发现一大堆安全更新。因为nodejs的缺陷会直接影响到Express,所以时刻关注node.js的缺陷且确保node.js处于最新版本。

社区活跃度

贡献者数量:200(注:截止作者写稿时,不是现在,可以点击链接去查看,我没搞明白)

关闭的Pull Requests:821(注:最近的的是1052)

Express社区定期开会,他们通过邮件列表,Gitter, IRC 频道,github的issues,还有Express的wiki来交流。

最后想说一下,Express是非常受欢迎的node.js框架,在Express的基础上又诞生了很多新的框架

Koa

Github Starts 25000+(注:截止翻译时已经是32.6k+)
npm 每周下载量 300k+(注,截止发稿时的数据是1,243,321)

Koa的开发者和Express是同一团队,在Express之外开发Koa的目标是为web应用开发和Api开发提供更小,更富表达力,而且更健壮的基础设施。Koa通过利用async函数,可以丢弃回调函数并且增强错误处理能力。Koa自身没有附带任何中间件,通过提供一个优雅的方法来让服务开发快速而快乐。

一个Koa的应用就是一个对象,包含了一个数组,数组中有很多中间件函数,这些函数以类似栈的形式来执行。

安装

Koa要求安装node并且node的版本要高于7.6来确保有async函数的支持。

你可以通过你喜欢的版本管理工具来安装支持的nodejs版本,比如nvm:

1
2
3
$ nvm install 7
$ npm i koa
$ node my-koa-app.js

hello World应用

下面例子是Koa最基础的”Hello World”示例,监听3000端口。

1
2
3
4
5
6
7
8
const Koa = require('koa');
const app = new Koa();

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

app.listen(3000);

现在访问http://localhost:3000,就可以看到`Hello World。对于其它路径,将返回404 not fund(注:可能是我理解有误,这个路径可能只端口,我试着访问其它路径也是看到Hello World`)。

优势

  • Koa提高了互操性、健壮性,并且使得编写中间件更享受(注:问号脸,感觉说了又没说)。
  • 有很多有用的方法但是占用的内存空间很小,而且没有绑定中间件。
  • Koa是非常轻量级的框架,仅仅只有550行代码。
  • 用户体验非常好
  • 通过使用try/catch来获取更好的用户体验
  • 基于生成的控制流
  • 没有回掉函数,使得流程控制更加便利
  • 干净,可读的同步代码

劣势

  • Koa的开源社区非常小
  • 没有兼容Express风格的中间件
  • Koa使用的generators没有适配其它node.js开源框架的中间件

性能

使用Koa.js可以创建性能非常好的应用。因为可以停止使用回调函数,快速的解决错误,而且Koa是一个非常轻量级的开源框架。而且Koa.js能够使得代码管理更加容易。

去考虑代码运行的最佳实践是非常重要的,比如必行运行时,代码中使用异步API,保持代码小而轻,,使用gzip压缩等。

下图是Koa的helo world应用每秒请求的响应状况
Koa的helo world应用每秒请求的性能状况

安全

这有非常多的中间件和Headers来提升安全性,你可以在这个链接中看到。

Koa安全示例

社区活跃度

  • 贡献者人数:169
  • 关闭的Pull Requests:577

你可以通过G+ koa 社区,邮件列表Koa’s repokoa slack参与贡献和讨论。

Hapi

Github Stars:+11,000(注:截止翻译时是13.8k+)
npm 每周下载量:250k+(注:最新的时578.576)

Hapi是一个构造应用和服务的丰富框架。他让开发集中精力开发可扩展的应用逻辑而不用花时间在写基础功能。

这是一种配置驱动的模式,用已经配置好的模型去驱动服务操作。Hapi特有的功能是可以在特有的ip上创建服务,使用onPreHandler功能,我们可以在请求之前截取并且做一些请求的前置流程。

安装

Hapi要求你提前安装好node.js,然后用下面方式安装

1
npm install hapi

或者安装并且方法哦依赖里

1
npm install hapi --save

Hello World 基础应用

下面是Hapi的hello world基础应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
'use strict';

const Hapi=require('hapi');

// Create a server with a host and port
const server=Hapi.server({
host:'localhost',
port:8000
});

// Add the route
server.route({
method:'GET',
path:'/hello',
handler:function(request,h) {

return'hello world';
}
});

// Start the server
const start = async function() {

try {
await server.start();
}
catch (err) {
console.log(err);
process.exit(1);
}

console.log('Server running at:', server.info.uri);
};

start();


然后使用npm start运行应用,然后在打开浏览器访问localhost:8000/hello

优势

  • 提供了健壮的插件系统让你能够以最快的速度修复bug,增加新功能
  • 允许构造可扩展的api
  • 对request请求深度控制
  • 是构建REST API极好的选择,因为他提供了路由,输入,输出认证和缓存。
  • 可以为单页应用,手机应用提供各种服务API
  • 详细的API文档生成功能
  • 可以和各种前端框架结合使用,比如用React,Angualar,Vue.js创建单页应用
  • 基于配置的中间件方法
  • 提供缓存,身份鉴定,输入验证的功能
  • 提供了基于扩展的插件架构
  • 提供了非常好的企业级插件比如:joi, yar, catbox, boom, tv, travelogue.

劣势

  • 开发者需要自己去配置代码结构
  • 限定开发者只能使用hapi相关的插件,而不和Express/Connect兼容
  • 必须手动创建端点和测试
  • 需要手动重构

性能

一个2017年的研究表明Hapi的性能明显低于其它框架
node 框架性能对比

下图是Koa的helo world应用每秒请求的响应状况

Koa的helo world应用每秒请求的响应状况

安全

Hapi 安全插件区中大量的插件来提升它的安全性,比如Crumb,Joi,Hapi-rbac,BlankieCryptiles等。

社区活跃度

  • 贡献者人数:182
  • 关闭的pull Request:1176

你可以加入slack channel:hapihour.slack.com/,访问社区页面社区官方页面,关注官方twiter来关注社区的最新消息。