V3 迁移指南
本指南旨在帮助您从 Fastify v2 迁移到 v3。
在开始之前,请确保已修复 v2 中的所有弃用警告。所有 v2 弃用功能已移除,升级后将不再起作用。(#1750)
重大更改
更改中间件支持 (#2014)
从 Fastify v3 开始,框架本身不再自带中间件支持。
如果您在应用程序中使用 Express 中间件,请在执行此操作之前安装并注册 @fastify/express
或 @fastify/middie
插件。
v2
// Using the Express `cors` middleware in Fastify v2.
fastify.use(require('cors')());
v3
// Using the Express `cors` middleware in Fastify v3.
await fastify.register(require('@fastify/express'));
fastify.use(require('cors')());
更改日志序列化 (#2017)
日志 序列化程序 已更新,现在使用 Fastify Request
和 Reply
对象,而不是原生对象。
如果自定义序列化程序依赖于原生对象上存在但在 Fastify 对象上不存在的 request
或 reply
属性,则必须更新这些序列化程序。
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, // No change required
customProp: reply.raw.customProp // Log custom property from res object
};
}
}
}
});
更改模式替换 (#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)
setSchemaCompiler
和 setSchemaResolver
选项已被 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 开始,onRoute
和 onRegister
钩子的行为将略有更改,以支持钩子封装。
onRoute
- 该钩子将异步调用。在同一封装范围内注册新插件时,该钩子将被继承。因此,此钩子应在注册任何插件之前注册。onRegister
- 与 onRoute 钩子相同。唯一的区别是,现在第一次调用不再是框架本身,而是第一个注册的插件。
更改内容类型解析器语法 (#2286)
在 Fastify v3 中,内容类型解析器现在对解析器具有单个签名。
新的签名为 fn(request, payload, done)
或 async fn(request, payload)
。请注意,request
现在是 Fastify 请求,而不是 IncomingMessage
。有效负载默认情况下为流。如果在 addContentTypeParser
中使用了 parseAs
选项,则 payload
反映选项值(字符串或缓冲区)。
旧签名 fn(req, [done])
或 fn(req, payload, [done])
(其中 req
为 IncomingMessage
)仍然受支持,但已弃用。
更改 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); // This is of type `PingQuerystring`
console.log(request.params); // This is of type `PingParams`
console.log(request.headers); // This is of type `PingHeaders`
console.log(request.body); // This is of type `PingBody`
}
);
v3
server.get<{
Querystring: PingQuerystring;
Params: PingParams;
Headers: PingHeaders;
Body: PingBody;
}>('/ping/:bar', opts, async (request, reply) => {
console.log(request.query); // This is of type `PingQuerystring`
console.log(request.params); // This is of type `PingParams`
console.log(request.headers); // This is of type `PingHeaders`
console.log(request.body); // This is of type `PingBody`
});
管理未捕获异常 (#2073)
在同步路由处理程序中,如果抛出错误,服务器会根据设计崩溃,而不会调用已配置的 .setErrorHandler()
。这种情况已更改,现在所有同步和异步路由中的意外错误都将得到管理。
v2
fastify.setErrorHandler((error, request, reply) => {
// this is NOT called
reply.send(error)
})
fastify.get('/', (request, reply) => {
const maybeAnArray = request.body.something ? [] : 'I am a string'
maybeAnArray.substr() // Thrown: [].substr is not a function and crash the server
})
v3
fastify.setErrorHandler((error, request, reply) => {
// this IS called
reply.send(error)
})
fastify.get('/', (request, reply) => {
const maybeAnArray = request.body.something ? [] : 'I am a string'
maybeAnArray.substr() // Thrown: [].substr is not a function, but it is handled
})
其他新增功能和改进
- 无论钩子如何注册,钩子现在都具有一致的上下文 (#2005)
- 弃用
request.req
和reply.res
,改为使用request.raw
和reply.raw
(#2008) - 移除
modifyCoreObjects
选项 (#2015) - 添加
connectionTimeout
选项 (#2086) - 添加
keepAliveTimeout
选项 (#2086) - 为 插件 添加异步/等待支持 (#2093)
- 添加将对象作为错误抛出的功能 (#2134)