前言
用过 Node.js 开发过的同学肯定都上手过 koa,因为他简单优雅的写法,再加上丰富的社区生态,而且现存的许多 Node.js 框架都是基于 koa 进行二次封装的。但是说到性能,就不得不提到一个知名框架: fastify
,听名字就知道它的特性就是快,官方给出的Benchmarks甚至比 Node.js 原生的 http.Server
还要快。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JalnOzRs-1611196695413)(https://file.shenfq.com/pic/20201213162826.png)]
性能提升的关键
我们先看看 fastify
是如何启动一个服务的。
# 安装 fastify
npm i -S fastify@3.9.1
// 创建服务实例
const fastify = require('fastify')()
app.get('/', {
schema: {
response: {
// key 为响应状态码
'200': {
type: 'object',
properties: {
hello: {
type: 'string' }
}
}
}
}
}, async () => {
return {
hello: 'world' }
})
// 启动服务
;(async () => {
try {
const port = 3001 // 监听端口
await app.listen(port)
console.info(`server listening on ${
port}`)
} catch (err) {
console.error(err)
process.exit(1)
}
})()
从上面代码可以看出,fastify
对请求的响应体定义了一个 schema
,fastify
除了可以定义响应体的 schema
,还支持对如下数据定义 schema
:
body
:当为 POST 或 PUT 方法时,校验请求主体;query
:校验 url 的 查询参数;params
:校验 url 参数;response
:过滤并生成用于响应体的schema
。
app.post('/user/:id', {
schema: {
params: {
type: 'object',
properties: {
id: {
type: 'number' }
}
},
response: {
// 2xx 表示 200~299 的状态都适用此 schema
'2xx': {
type: 'object',
properties: {
id: {
type: 'number' },
name: {
type: 'string' }
}
}
}
}
}, async (req) => {
const id = req.params.id
const userInfo = await User.findById(id)
// Content-Type 默认为 application/json
return userInfo
})
让 fastify
性能提升的的秘诀在于,其返回 application/json
类型数据的时候,并没有使用原生的 JSON.stringify
,而是自己内部重新实现了一套 JSON 序列化的方法,这个 schema
就是 JSON 序列化性能翻倍的关键。
如何对 JSON 序列化
在探索 fastify
如何对 JSON 数据序列化之前,我们先看看 JSON.stringify
需要经过多么繁琐的步骤,这里我们参考 Douglas Crockford (JSON 格式的创建者)开源的 JSON-js
中实现的 stringify
方法。
JSON-js:https://github.com/douglascrockford/JSON-js/blob/master/json2.js
// 只展示 JSON.stringify 核