Fastify v4 发布候选版本

1,897 阅读3分钟

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/…