Fastify 是一个 web 开发框架,其设计灵感来自 Hapi 和 Express,致力于以最少的开销和强大的插件结构提供最佳的开发体验。Fastify 是这个领域里速度最快的 web 框架之一。
近日 Fastify 官方宣布发布 Fastify v4 的第一个 RC 版本。此版本包含对开发体验的各种改进及少量的重大更改,并进行部分错误修复,例如异步函数返回 undefined 错误等。
如果你想测试该版本,可以通过下面指令进行升级
npm i fastify@next
更新亮点
避免使用 undefined 来解决问题
Fastify 设计之初使用基于回调的 API (reply.send({ hello: 'world' })
)和基于 Promise 的 API(return { hello: 'world' }
)的结合。但是这种结合使用引起了很多混乱,例如 FST_ERR_PROMISE_NOT_FULFILLED 问题。而且大多数人并不知道如何解决这些问题,因此从 v4 开始,Fastify 强制要求有返回值。
import Fastify from 'fastify'
const app = Fastify({ logger: true })
app.get('/', async (request, reply) => {
setImmediate(() => {
reply.send({ hello: 'world' })
})
// return reply is needed to tell Fastify we will call
// reply.send() in the future.
return reply
})
await app.listen({ port: 3000 })
新的错误处理组合
在 Fastify v4 之前,有多种错误处理的方式,而且每种处理方式都是独立的。Fastify v4 将自定义错误处理程序进行封装,如果自错误在插件内部抛出,父级将捕获该错误并处理它。
import Fastify from "fastify";
const fastify = Fastify();
fastify.register(async (fastify) => {
fastify.setErrorHandler(async (err) => {
console.log(err.message); // 'kaboom'
throw new Error("caught");
});
fastify.get("/encapsulated", async () => {
throw new Error("kaboom");
});
});
fastify.setErrorHandler(async (err) => {
console.log(err.message); // 'caught'
throw new Error("wrapped");
});
const res = await fastify.inject("/encapsulated");
console.log(res.json().message); // 'wrapped
Pino 升级至 V7 版本
Fastify 中 Pino 已经升级至 V7,该版本的 Pino 可以利用工作线程,不再需要存在单独的进程中,这将极大的改善开发者的体验并简化配置。
import Fastify from 'fastify'
const fastify = Fastify({
logger: {
transport: {
target: 'pino-pretty',
options: { destination: 1 }
}
}
})
冷启动更快
Fastify 在后台使用 AJV 进行请求验证和响应序列化。冷启动慢的原因主要在于 uri-js 的使用,因此 Fastify 团队开发了一个更轻量级的替代方案:https ://github.com/fastify/fast-uri
新的 Pino 类型
Pino@7 附带自己的类型。因此,你现在可以直接从 Fastify 中指定 Pino 的所有选项,而无需安装任何其他类型。
开箱即用的类型提供程序
Type Providers 是 TypeScript 独有的特性,它允许 Fastify 能够直接从内联 JSON Schema 静态推断类型信息。
import Fastify from 'fastify'
import { TypeBoxTypeProvider, Type } from 'fastify-type-provider-typebox'
const fastify = Fastify({
ajv: {
customOptions: {
strict: 'log',
keywords: ['kind', 'modifier']
}
}
}).withTypeProvider<TypeBoxTypeProvider>()
fastify.route({
method: 'GET',
path: '/route',
schema: {
querystring: Type.Object({
foo: Type.Number(),
bar: Type.String()
})
},
handler: (request, reply) => {
// type Query = { foo: number, bar: string }
const { foo, bar } = request.query // type safe!
}
})
弃用 .listen 可变参数
当前版本中,Fastify 官方不止改进了用户的体验,同样改进了贡献者的使用体验。
当前版本弃用了 fastify.listen 方法的可变参数,v4 版本之前,下列调用都是有效的:
- fastify.listen(8000)
- fastify.listen(8000, '127.0.0.1')
- fastify.listen(8000, '127.0.0.1', 511)
- fastify.listen(8000, (err) => { if (err) throw err })
- fastify.listen({ port: 8000, host: '127.0.0.1' }, (err) => { if (err) throw err })
- 和许多其他排列
但从 v4 版本开始,.listen 方法接收一个 option 对象和一个可选的回调 callback。这些简化使用更容易创建 IPv4 和 IPv6 的减铜,并且维护 Typescript 类型变得更简单。
因此,对于 Fastify v4 ,下面的调用是有效的:
- fastify.listen()
- fastify.listen({ port: 8000 }) // 返回一个 Promise
- fastify.listen({ port: 8000 }, (err) => { if (err) throw err })
find-my-way 升级到 v5 版本
find-my-way 是 Fastify 的路由器,在 V5 版本中,修复了很多问题:
- 改进的 URL 解码
- 添加了 decodedUriParameters 选项
- 优化查找方法
- 修复双冒号和参数节点冲突
- 修复参数解析
- 优化约束策略
Ajv v8
Fastify v4 包含Ajv v8,你可以在ajv.js.org/v6-to-v8-mi… 阅读如何进行模式迁移
放弃对旧 Node.js 版本的支持
Fastify v4 版本,将放弃对 Node.js v10 和 v12 的支持,仅支持 v14、v16 和 v18 版本。
如果你想了解更多讯息,请参考: medium.com/@fastifyjs/…