在本指南中,我们将比较用Node.js构建Web应用程序的最常用框架之一Express.js和其最流行的替代品之一tinyhttp。
以下是我们要介绍的内容。
什么是 tinyhttp?
tinyhttp是一个类似于 Express.js 的现代网络框架,是用 TypeScript 编写的。与 Express.js 相比,它使用了非常少的依赖性,这使得它的速度超快。
tinyhttp 提供了路由、req/res 扩展等功能,同时只依赖于六个模块,其中四个是 tinyhttp 自己的。
所有为 Express.js 创建的中间件都能与 tinyhttp 顺利地工作。请看这个tinyhttp + Express/GraphQL集成的例子,了解如何用 tinyhttp 使用 Express.js 中间件。
tinyhttp 还支持路由的 async/await,这在 Express.js 中是不存在的。tinyhttp 内部有适当的类型和一个函数检查器,可以解决异步函数。换句话说,同步和异步在 tinyhttp 中都能正常工作。看看这些async和MongoDB的例子,看看如何制作 async 处理程序。
根据官方文档,下面是 tinyhttp 最重要的功能的简短列表。
- 比 Express 快 2.5 倍
- 完整的Express中间件支持
- 支持异步中间件
- 本地ESM和CommonJS支持
- 没有遗留的依赖,只有 JavaScript 本身
- 开箱即用的类型
- 没有内置的中间件支持
什么是Express.js?
Express.js是一个灵活的Node.js框架,为Web和移动应用程序提供了一套强大的功能。创建强大的API非常容易,因为Express.js带有很多中间件和其他内置的支持。
Express.js并没有配备数据库,这要由第三方模块来完成,这使得你可以与几乎所有的数据库对接。Express.js支持无数的模板引擎,与(path, locals, callback) 签名。
这个框架的构建方式是,它作为一个最小和灵活的Node.js网络应用程序框架,为构建单页、多页和混合网络应用程序提供了一套强大的功能。
Express.js的一些特点。
- 开源社区支持
- 快速的应用开发
- 易于学习
- 支持模板引擎
- I/O处理
- 内置的中间件支持
tinyhttp vs. Express.js:一个基本的比较
对于 tinyhttp 和 Express v4 的高层次比较,让我们看看支持的最小 Node.js 版本、ECMAScript 版本、测试覆盖率等。
| 标准 | tinyhttp | Express v4 |
|---|---|---|
| 最低支持的 Node.js 版本 | 12.4.0 | 0.10.0 |
| 最低支持的ECMAScript版本 | ES2019 | ES5 (?) |
req /res 扩展 | ![]() | ![]() |
| 测试覆盖率 | 92% | 100% |
| 编译为本地ESM | ![]() | ![]() |
| 支持TypeScript | ![]() | ![]() |
| 软件包大小(仅核心部分 | 35.2 kB | 208 kB |
| 内置中间件 | ![]() | ![]() |
关于上表的一些说明。
- tinyhttp工作所需的最低Node.js版本是12.4.0,而在Express v4中,我们甚至可以从Node.js 0.10.0开始工作。
- tinyhttp的最低支持版本是ES2019(ES10),而在Express v4中,我们需要ES5。
req是一个包含引发事件的 HTTP 请求信息的对象。在对req的响应中,你使用res来发回所需的 HTTP 响应。tinyhttp 和 express v4 都支持req/res扩展。- 对于 tinyhttp 来说,代码库的测试覆盖率是 92%,对于 Express.js v4 来说是 100%。
- 与ES6(或ES2015)规范一起引入的ESM(EcmaScript Modules)规范描述了如何在JavaScript中导入和导出模块。我们可以在 tinyhttp 中使用 ESM,但我们需要外部支持,比如Babel,用于 Express.js。
- 与Express.js不同,tinyhttp带有TypeScript支持。
- tinyhttp 的核心包大小为 35.2kB,而 Express.js 为 208kB。
- tinyhttp没有内置的中间件。Express.js 则有内置的中间件。
性能标杆
说完了基本情况,让我们看看使用fastify 基准测试工具的性能报告。在这里,我们使用req/s、transfer/s和latency等参数来衡量两个框架的性能。
下面是关于这个基准测试所使用的硬件、系统和条件的一些说明。
- 硬件。
- 小米Pro 2019版(笔记本电脑
- CPU。英特尔酷睿i7-8550U
- 内存:16GB
- 系统。
- 内核:5.7.19-2
- 节点。15.5
- 条件。
- 100个连接
- 10条管道
- 40s持续时间
| 框架 | req/s | 传输/秒 | 延迟 |
|---|---|---|---|
| @tinyhttp/app (w/o exts) | 24575 | 3.81 MB | 3.37毫秒 |
| @tinyhttp/app (esm) | 22820 | 3.54 MB | 4.04 ms |
| @tinyhttp/app (cjs) | 22637 | 3.51 MB | 4.08 ms |
| express@4.17.1 | 12986 | 2 MB | 7.11 ms |
req/s 是指每秒的请求数。Latency 是指用户的行动和网络应用程序对该行动的响应之间的延迟,也被称为总的往返时间。
从上表中,我们可以看到,tinyhttp能够以更低的延迟在每秒进行更多的传输,而不是Express.js v4
注意:基准测试并不完全准确,在每次运行和每台机器上都可能有所不同。关键是要比较比例而不是绝对值。
总结我们的性能基准,tinyhttp(没有额外的req/res 扩展)比 Express.js 快了 ~1.9 倍。
tinyhttp 和 Express.js 在运行。一个简单的例子
现在是时候建立一个简单的应用实例了,这样我们就可以看到 tinyhttp 和 Express.js 并肩作战的情况。
你可以使用任何软件包管理器来安装 tinyhttp 和 Express。我将使用npm来演示。
要安装 tinyhttp。
npm i @tinyhttp/app
安装 Express.js。
npm install express
'Hello World
Express.js 和 tinyhttp 应用程序的结构非常相似。如果你知道 Express.js,那么你也知道 tinyhttp。
tinyhttp。
import { App } from '@tinyhttp/app'
const app = new App()
const PORT = 3000
app
.get('/', (_, res) => void res.send('<h1>Hello World</h1>'))
.listen(PORT, () => console.log(`Started on http://localhost:${PORT}!`))
Express.js。
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello world');
});
app.listen(3000, () => console.log('listening on port 3000'));
你可能注意到,我们没有使用require ,而是使用了 ESM 的导入。tinyhttp 被设计为与Native ESM 一起使用。与 Express 不同,tinyhttp 被编译为 ESM 和 CommonJS 的模块系统。同时,不知为何,它仍然比 Express.js 小得多。
你可以用它在 Node.js 中使用import/export 语法。要设置一个Node ESM包,把"type": "module" 放在package.json 文件中,像这样。
{
"type": "module"
}
另一个选择是使用.mjs 扩展。这样,你就不需要把那个"type" 字段放在package.json 。欲了解更多信息,请查看ECMAScript Modules Node.js文档。
因为最流行的 Express.js 中间件也使用了过时的模块,所以 tinyhttp 提供了一套它对流行的物品的重写/重制,比如logger,session, 等等。
路由
现在让我们来看看如何在 tinyhttp 和 Express.js 中处理一些基本的路由。Express.js 在他们的req 和res 对象中包含了很多辅助函数。tinyhttp 使用诸如res.send,res.download,res.redirect 等方法完全实现了 Express.js 的 APIs。
tinyhttp。
import { App } from '@tinyhttp/app'
import { once } from 'events'
const app = new App()
const PORT = 3000
app.get('/', (req, res) => {
res.send('Sent a GET!')
})
app.post('/', async (req, res) => {
// Nothing complex here, we just listen to 'data' event and return the data as a promise to a `data` variable
const data = await once(req, 'data').then(d => d.toString())
// And then we send it
res.end(`Sent some data: ${data}`)
})
app.listen(PORT, () => console.log(`Started on http://localhost:${PORT}!`))
Express.js
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.send("Send a GET!");
});
app.post('/', function(req, res){
res.send("hello'!\n");
});
app.listen(3000);
结论
tinyhttp 既快又轻,你今天就可以开始在后端应用中使用它。tinyhttp存储库包含了很多例子,包括MongoDB和GraphQL的集成。当你需要用最少的代码快速入门时,我会推荐使用 tinyhttp。
也就是说,Express.js仍然很受欢迎,并将继续在主要项目和行业中使用,因为它有广泛的开源社区支持和简单的学习曲线。
tinyhttp vs. Express.js一文。对比Node.js框架,首先出现在LogRocket博客上。

