Skip to main content

V4 迁移指南

¥V4 Migration Guide

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

¥This guide is intended to help with migration from Fastify v3 to v4.

在迁移到 v4 之前,请确保你已修复 v3 中的所有弃用警告。所有 v3 弃用内容均已删除,升级后它们将不再起作用。

¥Before migrating to v4, please ensure that you have fixed all deprecation warnings from v3. All v3 deprecations have been removed and they will no longer work after upgrading.

Codemods

Fastify v4 Codemods

为了帮助升级,我们与 Codemod 团队合作发布了代码修改,这些代码修改将自动将你的代码更新为 Fastify v4 中的许多新 API 和模式。

¥To help with the upgrade, we’ve worked with the team at Codemod to publish codemods that will automatically update your code to many of the new APIs and patterns in Fastify v4.

运行以下 迁移秘诀 以自动将你的代码更新到 Fastify v4:

¥Run the following migration recipe to automatically update your code to Fastify v4:

npx codemod@latest fastify/4/migration-recipe

这将运行以下代码修改:

¥This will run the following codemods:

这些 codemod 中的每一个都会自动执行 v4 迁移指南中列出的更改。有关可用 Fastify codemod 的完整列表和更多详细信息,请参阅 Codemod 注册表

¥Each of these codemods automates the changes listed in the v4 migration guide. For a complete list of available Fastify codemods and further details, see Codemod Registry.

重大变更

¥Breaking Changes

错误处理组合 ( #3261)

¥Error handling composition (

当异步错误处理函数中抛出错误时,如果设置了上层错误处理程序,则执行上层错误处理程序。如果没有上层错误处理程序,则默认将像以前一样执行:

¥When an error is thrown in an async error handler function, the upper-level error handler is executed if set. If there is no upper-level error handler, the default will be executed as it was previously:

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 的通用错误处理程序。此错误处理程序将使用 Error 对象中的标头和状态代码(如果存在)。如果提供了自定义错误处理程序,则不会自动设置标头和状态代码。

¥The root error handler is Fastify’s generic error handler. This error handler will use the headers and status code in the Error object, if they exist. The headers and status code will not be automatically set if a custom error handler is provided.

已删除 app.use()#3506)

¥Removed app.use() (

在 Fastify v4 中,app.use() 已被删除,不再支持使用中间件。

¥With v4 of Fastify, app.use() has been removed and the use of middleware is no longer supported.

如果你需要使用中间件,请使用 @fastify/middie@fastify/express,它们将继续得到维护。但是,强烈建议你迁移到 Fastify 的 hooks

¥If you need to use middleware, use @fastify/middie or @fastify/express, which will continue to be maintained. However, it is strongly recommended that you migrate to Fastify's hooks.

注意:Codemod 删除 app.use() 包含:

¥Note: Codemod remove app.use() with:

npx codemod@latest fastify/4/remove-app-use

reply.res 移至 reply.raw

¥reply.res moved to reply.raw

如果你以前使用 reply.res 属性访问底层 Request 对象,现在你将需要使用 reply.raw

¥If you previously used the reply.res attribute to access the underlying Request object you will now need to use reply.raw.

注意:Codemod reply.resreply.raw 具有:

¥Note: Codemod reply.res to reply.raw with:

npx codemod@latest fastify/4/reply-raw-access

需要 return reply 向 promise 链的 "fork" 发出信号

¥Need to return reply to signal a "fork" of the promise chain

在某些情况下,例如当异步发送响应或你未明确返回响应时,你现在需要从路由处理程序返回 reply 参数。

¥In some situations, like when a response is sent asynchronously or when you are not explicitly returning a response, you will now need to return the reply argument from your router handler.

exposeHeadRoutes 默认为真

¥exposeHeadRoutes true by default

从 v4 开始,每个 GET 路由都会创建一个同级 HEAD 路由。你可以通过在服务器选项中设置 exposeHeadRoutes: false 来恢复此行为。

¥Starting with v4, every GET route will create a sibling HEAD route. You can revert this behavior by setting exposeHeadRoutes: false in the server options.

同步路由定义( #2954)

¥Synchronous route definitions (

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

¥To improve error reporting in route definitions, route registration is now synchronous. As a result, if you specify an onRoute hook in a plugin you should now either:

  • 将你的路由封装在插件中(推荐)

    ¥wrap your routes in a plugin (recommended)

    例如,重构这个:

    ¥For example, refactor this:

    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') });

    进入这个:

    ¥Into this:

    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();
    });

注意:Codemod 同步路由定义具有:

¥Note: Codemod synchronous route definitions with:

npx codemod@latest fastify/4/wrap-routes-plugin
  • 使用 await register(...)

    ¥use await register(...)

    例如,重构这个:

    ¥For example, refactor this:

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

    进入这个:

    ¥Into this:

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

注意:Codemod 'await register(...)' 具有:

¥Note: Codemod 'await register(...)' with:

npx codemod@latest fastify/4/await-register-calls

可选的 URL 参数

¥Optional URL parameters

如果你已经使用了任何隐式可选参数,则在尝试访问路由时将收到 404 错误。你现在需要显式声明可选参数。

¥If you've already used any implicitly optional parameters, you'll get a 404 error when trying to access the route. You will now need to declare the optional parameters explicitly.

例如,如果你有相同的列出和显示帖子的路由,请重构:

¥For example, if you have the same route for listing and showing a post, refactor this:

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

进入这个:

¥Into this:

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

非重大变更

¥Non-Breaking Changes

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

¥Deprecation of variadic .listen() signature

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

¥The variadic signature of the fastify.listen() method is now deprecated.

在此版本之前,该方法的以下调用是有效的:

¥Prior to this release, the following invocations of this method were valid:

  • 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,只有以下调用有效:

¥With Fastify v4, only the following invocations are valid:

  • fastify.listen()

  • fastify.listen({ port: 8000 })

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

更改多种类型的架构

¥Change of schema for multiple types

Ajv 已在 Fastify v4 中升级到 v8,这意味着 "type" 关键字具有除 "null" 现在已被禁止 之外的多种类型。

¥Ajv has been upgraded to v8 in Fastify v4, meaning "type" keywords with multiple types other than "null" are now prohibited.

你可能会遇到控制台警告,例如:

¥You may encounter a console warning such as:

strict mode: use allowUnionTypes to allow union type keyword at "#/properties/image" (strictTypes)

因此,如下所示的模式需要更改:

¥As such, schemas like below will need to be changed from:

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

进入:

¥Into:

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

添加 reply.trailers 方法 ( #3794)

¥Add reply.trailers methods (

Fastify 现在支持 HTTP 预告片 响应标头。

¥Fastify now supports the HTTP Trailer response headers.