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
Request
和
Reply
对象,而不是原生对象。
任何依赖于 request
或 reply
属性的自定义序列化器必须进行更新,
这些属性在原生对象中存在但在 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 )
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
对象。默认情况下,payload
是一个流。如果在调用 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); // 类型为 `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,但会得到处理
})
进一步的添加和改进
- Hooks 现在无论以何种方式注册都具有一致的上下文环境 (#2005 )
- 废弃了
request.req
和reply.res
,改为使用request.raw
和reply.raw
(#2008 ) - 移除了
modifyCoreObjects
选项 (#2015 ) - 添加了
connectionTimeout
选项 (#2086 ) - 添加了
keepAliveTimeout
选项 (#2086 ) - 支持 插件 的 async-await (#2093 )
- 添加了抛出对象作为错误的功能 (#2134 )