Skip to Content

V3 迁移指南

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

开始之前,请确保修复所有来自 v2 的弃用警告。 所有 v2 弃用已删除,升级后将不再工作。 (#1750 )

不兼容变化

更改中间件支持 (#2014 )

从 Fastify v3 开始,框架本身不再默认提供中间件支持。

如果您在应用程序中使用 Express 中间件,请在使用之前安装并注册 @fastify/express@fastify/middie 插件。

v2:

// 在 Fastify v2 中使用 Express 的 `cors` 中间件。 fastify.use(require('cors')());

v3:

// 在 Fastify v3 中使用 Express 的 `cors` 中间件。 await fastify.register(require('@fastify/express')); fastify.use(require('cors')());

更改日志序列化 (#2017 )

日志 序列化器 已更新为使用 Fastify RequestReply 对象,而不是原生对象。

任何依赖于 requestreply 属性的自定义序列化器必须进行更新, 这些属性在原生对象中存在但在 Fastify 对象中不存在。

v2:

const fastify = require('fastify')({ logger: { serializers: { res(res) { return { statusCode: res.statusCode, customProp: res.customProp }; } } } });

v3:

const fastify = require('fastify')({ logger: { serializers: { res(reply) { return { statusCode: reply.statusCode, // 不需要更改 customProp: reply.raw.customProp // 记录来自 res 对象的自定义属性 }; } } } });

替换模式更改 (#2023 )

非标准的 replace-way 共享模式支持已被移除。此功能已由符合 JSON Schema 规范的 $ref 基础替换。为了更好地理解这一变化,请阅读 Fastify v3 中的验证和序列化 

v2:

const schema = { body: 'schemaId#' }; fastify.route({ method, url, schema, handler });

v3:

const schema = { body: { $ref: 'schemaId#' } }; fastify.route({ method, url, schema, handler });

更改模式验证选项 (#2023 )

setSchemaCompilersetSchemaResolver 选项已被替换为 setValidatorCompiler,以支持未来的工具改进。为了更好地理解这一变化,请阅读 Fastify v3 中的验证和序列化 

v2:

const fastify = Fastify(); const ajv = new AJV(); ajv.addSchema(schemaA); ajv.addSchema(schemaB); fastify.setSchemaCompiler(schema => ajv.compile(schema)); fastify.setSchemaResolver(ref => ajv.getSchema(ref).schema);

v3:

const fastify = Fastify(); const ajv = new AJV(); ajv.addSchema(schemaA); ajv.addSchema(schemaB); fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => ajv.compile(schema) );

修改了预解析钩子行为 (#2286 )

从 Fastify v3 开始,preParsing 钩子的行为将稍作调整以支持请求负载的修改。

该钩子现在接受一个额外的参数 payload,因此新的钩子签名是 fn(request, reply, payload, done) 或者 async fn(request, reply, payload)

该钩子可以选择通过 done(null, stream) 返回一个新的流或者在异步函数中直接返回流。

如果钩子返回了一个新流,则后续的钩子将使用这个新的流而不是原来的流。一个典型的用例是处理压缩请求。

新的流应该添加一个名为 receivedEncodedLength 的属性,该属性应反映从客户端接收的实际数据大小。例如,在压缩请求的情况下,它应该是压缩负载的大小。此属性可以在 data 事件期间动态更新。

Fastify v2 中没有负载的老语法仍然支持但已弃用。

修改了钩子行为 (#2004 )

从 Fastify v3 开始,onRouteonRegister 钩子的行为将稍作调整以支持钩子封装。

  • onRoute - 该钩子将异步调用。现在当在相同的封装作用域内注册新插件时,此钩子会被继承。因此,这个钩子应该在注册任何插件之前进行注册。
  • onRegister - 与 onRoute 钩子相同。唯一的区别是,第一次调用不再是框架本身,而是第一个已注册的插件。

修改了内容类型解析器语法 (#2286 )

在 Fastify v3 中,内容类型解析器现在具有单一的签名格式。

新的签名格式为 fn(request, payload, done) 或者 async fn(request, payload)。请注意,request 现在是一个 Fastify 请求对象,而不是一个 IncomingMessage 对象。默认情况下,payload 是一个流。如果在调用 addContentTypeParser 时使用了 parseAs 选项,则 payload 反映该选项的值(字符串或缓冲区)。

旧的签名格式 fn(req, [done]) 或者 fn(req, payload, [done]) (其中 reqIncomingMessage 对象)仍然受支持,但已弃用。

修改了 TypeScript 支持

Fastify 版本 3 中更改了类型系统。新的类型系统引入了泛型约束和默认值,并且提供了一种定义模式类型的全新方式,例如请求体、查询字符串等!

v2:

interface PingQuerystring { foo?: number; } interface PingParams { bar?: string; } interface PingHeaders { a?: string; } interface PingBody { baz?: string; } server.get<PingQuerystring, PingParams, PingHeaders, PingBody>( '/ping/:bar', opts, (request, reply) => { console.log(request.query); // 类型为 `PingQuerystring` console.log(request.params); // 类型为 `PingParams` console.log(request.headers); // 类型为 `PingHeaders` console.log(request.body); // 类型为 `PingBody` } );

v3:

server.get<{ Querystring: PingQuerystring; Params: PingParams; Headers: PingHeaders; Body: PingBody; }>('/ping/:bar', opts, async (request, reply) => { console.log(request.query); // 类型为 `PingQuerystring` console.log(request.params); // 类型为 `PingParams` console.log(request.headers); // 类型为 `PingHeaders` console.log(request.body); // 类型为 `PingBody` });

管理未捕获的异常 (#2073 )

在同步路由处理程序中,如果抛出了错误,则服务器会按设计崩溃,并且不会调用配置的 .setErrorHandler()。这种情况已更改,现在所有同步和异步路由中的意外错误都会被管理。

v2:

fastify.setErrorHandler((error, request, reply) => { // 这里 不会被 调用 reply.send(error) }) fastify.get('/', (request, reply) => { const maybeAnArray = request.body.something ? [] : 'I am a string' maybeAnArray.substr() // 抛出错误: [].substr is not a function 并导致服务器崩溃 })

v3:

fastify.setErrorHandler((error, request, reply) => { // 这里 会被 调用 reply.send(error) }) fastify.get('/', (request, reply) => { const maybeAnArray = request.body.something ? [] : 'I am a string' maybeAnArray.substr() // 抛出错误: [].substr is not a function,但会得到处理 })

进一步的添加和改进