Skip to Content

V4 迁移指南

本指南旨在帮助从 Fastify v3 迁移到 v4。

在迁移到 v4 之前,请确保已修复所有来自 v3 的弃用警告。v3 中的所有弃用警告已被删除,升级后将不再工作。

代码转换工具

Fastify v4 代码转换工具

为了帮助您进行升级,我们与 Codemod  团队合作发布了代码转换工具,这些工具可以自动更新您的代码以适应 Fastify v4 中的许多新 API 和模式。

运行以下迁移配方 migration recipe  来自动将您的代码更新为 Fastify v4:

npx codemod@latest fastify/4/migration-recipe

这将执行以下代码转换工具:

每个这些代码转换工具都会自动化 v4 迁移指南中列出的更改。有关可用的 Fastify 代码转换工具和更多详细信息,请参阅 Codemod 注册表 

重大变更

错误处理组合 (#3261 )

当在异步错误处理函数中抛出一个错误时,如果设置了上一级的错误处理器,则会执行该处理器。如果没有设置上一级的错误处理器,默认的错误处理器将被执行:

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'

根级别的错误处理器是 Fastify 的通用错误处理器。 如果错误对象中存在头部信息和状态码,该错误处理器将使用这些信息。如果提供了自定义的错误处理器,则不会自动设置头部信息和状态码

移除 app.use() (#3506 )

在 Fastify v4 中,app.use() 已被移除,并且中间件的使用不再受支持。

如果你需要使用中间件,请使用 @fastify/middie@fastify/express,这些库将继续得到维护。 然而,强烈建议你迁移到 Fastify 的 钩子

注意:使用以下命令移除 app.use()

npx codemod@latest fastify/4/remove-app-use
### 将 `reply.res` 移动到 `reply.raw` 如果你之前使用 `reply.res` 属性来访问底层的请求对象,现在需要使用 `reply.raw`。 > **注意**:将 `reply.res` 替换为 `reply.raw`: > > ```bash > npx codemod@latest fastify/4/reply-raw-access >

需要 return reply 以指示 Promise 链的“分支”

在某些情况下,例如当响应异步发送或您没有显式返回响应时,现在需要从路由处理程序中返回 reply 参数。

exposeHeadRoutes 默认为 true

从 v4 版本开始,默认情况下每个 GET 路由都会创建一个同名的 HEAD 路由。可以通过在服务器选项中设置 exposeHeadRoutes: false 来恢复之前的默认行为。

同步路由定义 (#2954 )

为了改进路由定义中的错误报告,现在路由注册是同步的。 因此,如果你在插件中指定了 onRoute 回调钩子,则应该:

  • 将你的路由包裹在一个插件里(推荐)

    例如,重构以下代码:

    fastify.register((instance, opts, done) => { instance.addHook('onRoute', (routeOptions) => { const { path, method } = routeOptions; console.log({ path, method }); done(); }); }); fastify.get('/', (request, reply) => { reply.send('hello') });
改为: ```js fastify.register((instance, opts, done) => { instance.addHook('onRoute', (routeOptions) => { const { path, method } = routeOptions; console.log({ path, method }); done(); }); }); fastify.register((instance, opts, done) => { instance.get('/', (request, reply) => { reply.send('hello') }); done(); });

注意:使用以下命令进行代码转换:

npx codemod@latest fastify/4/wrap-routes-plugin
* 使用 `await register(...)` 例如,重构以下代码: ```js fastify.register((instance, opts, done) => { instance.addHook('onRoute', (routeOptions) => { const { path, method } = routeOptions; console.log({ path, method }); }); done(); });

改为:

await fastify.register((instance, opts, done) => { instance.addHook('onRoute', (routeOptions) => { const { path, method } = routeOptions; console.log({ path, method }); }); done(); });

注意:使用以下命令进行代码转换:

npx codemod@latest fastify/4/await-register-calls
### 可选的URL参数 如果您已经使用了任何隐式可选参数,尝试访问该路由时将收到404错误。现在您需要显式声明这些可选参数。 例如,如果您有一个用于列出和显示帖子的相同路由,请重构以下代码: ```js fastify.get('/posts/:id', (request, reply) => { const { id } = request.params; });

改为如下形式:

fastify.get('/posts/:id?', (request, reply) => { const { id } = request.params; });

不破坏性更改

.listen() 可变参数签名弃用

fastify.listen() 方法的 可变参数签名  现已弃用。

在此次发布之前,以下方法调用是有效的:

  • 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 }, (err) => { if (err) throw err })

在 Fastify v4 中,仅以下调用是有效的:

  • fastify.listen()
  • fastify.listen({ port: 8000 })
  • fastify.listen({ port: 8000 }, (err) => { if (err) throw err })

多类型模式的 schema 更改

Fastify v4 升级了 Ajv 到 v8 版本,这意味着 “type” 关键字中除了 “null” 之外的多类型 现在被禁止 

您可能会遇到类似以下的控制台警告:

严格模式:使用 allowUnionTypes 允许联合类型关键字在 "#/properties/image"(strictTypes)

因此,如下所示的 schema 需要更改为:

{ type: 'object', properties: { api_key: { type: 'string' }, image: { type: ['object', 'array'] } } }

变为:

{ type: 'object', properties: { api_key: { type: 'string' }, image: { anyOf: [ { type: 'array' }, { type: 'object' } ] } } }

添加 reply.trailers 方法(#3794 

Fastify 现在支持 [HTTP Trailer] 响应头。