V3 迁移指南
¥V3 Migration Guide
本指南旨在帮助从 Fastify v2 迁移到 v3。
¥This guide is intended to help with migration from Fastify v2 to v3.
开始之前,请确保 v2 中的所有弃用警告均已修复。所有 v2 弃用内容均已删除,升级后它们将不再起作用。(#1750)
¥Before beginning please ensure that any deprecation warnings from v2 are fixed. All v2 deprecations have been removed and they will no longer work after upgrading. (#1750)
重大变更
¥Breaking changes
更改了中间件支持 ( #2014)
¥Changed middleware support (
从 Fastify v3 开始,框架本身就不再提供开箱即用的中间件支持。
¥From Fastify v3, middleware support does not come out-of-the-box with the framework itself.
如果你在应用中使用 Express 中间件,请在执行此操作之前安装并注册 @fastify/express
或 @fastify/middie
插件。
¥If you use Express middleware in your application, please install and register
the @fastify/express
or
@fastify/middie
plugin before doing so.
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)
¥Changed logging serialization (
日志记录 Serializers 已更新为现在的 Fastify Request
和 Reply
对象,而不是原生对象。
¥The logging Serializers have been updated to now
Fastify Request
and
Reply
objects instead of native ones.
如果任何自定义序列化器依赖于原生对象上存在的 request
或 reply
属性,但不存在于 Fastify 对象上,则必须更新它们。
¥Any custom serializers must be updated if they rely upon request
or reply
properties that are present on the native objects but not the Fastify objects.
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)
¥Changed schema substitution (
非标准 replace-way
共享架构支持已被删除。此功能已被符合 JSON 架构规范的基于 $ref
的替换所取代。为帮助理解此更改,请阅读 Fastify v3 中的验证和序列化。
¥The non-standard replace-way
shared schema support has been removed. This
feature has been replaced with JSON Schema specification compliant $ref
based
substitution. To help understand this change read Validation and Serialization
in 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)
¥Changed schema validation options (
setSchemaCompiler
和 setSchemaResolver
选项已被 setValidatorCompiler
取代,以实现未来的工具改进。为帮助理解此更改,请阅读 Fastify v3 中的验证和序列化。
¥The setSchemaCompiler
and setSchemaResolver
options have been replaced with
the setValidatorCompiler
to enable future tooling improvements. To help
understand this change read Validation and Serialization in 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)
);
更改了 preParsing 钩子行为 ( #2286)
¥Changed preParsing hook behavior (
从 Fastify v3 开始,preParsing
钩子的行为将略有变化以支持请求负载操作。
¥From Fastify v3, the behavior of the preParsing
hook will change slightly
to support request payload manipulation.
钩子现在接受一个附加参数 payload
,因此新的钩子签名是 fn(request, reply, payload, done)
或 async fn(request, reply, payload)
。
¥The hook now takes an additional argument, payload
, and therefore the new hook
signature is fn(request, reply, payload, done)
or async fn(request, reply,
payload)
.
钩子可以选择通过 done(null, stream)
返回新流,或者在异步函数的情况下返回流。
¥The hook can optionally return a new stream via done(null, stream)
or
returning the stream in case of async functions.
如果钩子返回一个新流,则在后续钩子中将使用该新流代替原始流。一个示例用例是处理压缩请求。
¥If the hook returns a new stream, it will be used instead of the original one in subsequent hooks. A sample use case for this is handling compressed requests.
新流应将 receivedEncodedLength
属性添加到流中,该属性应反映从客户端收到的实际数据大小。例如,在压缩请求中,它应该是压缩有效负载的大小。此属性可以在 data
事件期间动态更新(并且应该)。
¥The new stream should add the receivedEncodedLength
property to the stream
that should reflect the actual data size received from the client. For instance,
in a compressed request it should be the size of the compressed payload. This
property can (and should) be dynamically updated during data
events.
支持不带负载的 Fastify v2 旧语法,但已弃用。
¥The old syntax of Fastify v2 without payload is supported but it is deprecated.
更改了钩子行为 ( #2004)
¥Changed hooks behavior (
从 Fastify v3 开始,onRoute
和 onRegister
钩子的行为将略有变化以支持钩子封装。
¥From Fastify v3, the behavior of onRoute
and onRegister
hooks will change
slightly to support hook encapsulation.
onRoute
- 钩子将被异步调用。现在,当在同一封装范围内注册新插件时,会继承该钩子。因此,应在注册任何插件之前注册此钩子。¥
onRoute
- The hook will be called asynchronously. The hook is now inherited when registering a new plugin within the same encapsulation scope. Thus, this hook should be registered before registering any plugins.onRegister
- 与 onRoute 钩子相同。唯一的区别是,现在第一个调用将不再是框架本身,而是第一个注册的插件。¥
onRegister
- Same as the onRoute hook. The only difference is that now the very first call will no longer be the framework itself, but the first registered plugin.
更改了内容类型解析器语法 ( #2286)
¥Changed Content Type Parser syntax (
在 Fastify v3 中,内容类型解析器现在具有解析器的单一签名。
¥In Fastify v3 the content type parsers now have a single signature for parsers.
新签名是 fn(request, payload, done)
或 async fn(request, payload)
。请注意,request
现在是 Fastify 请求,而不是 IncomingMessage
。默认情况下,有效负载是一个流。如果在 addContentTypeParser
中使用了 parseAs
选项,则 payload
会反映选项值(字符串或缓冲区)。
¥The new signatures are fn(request, payload, done)
or async fn(request,
payload)
. Note that request
is now a Fastify request, not an
IncomingMessage
. The payload is, by default, a stream. If the parseAs
option
is used in addContentTypeParser
, then payload
reflects the option value
(string or buffer).
旧签名 fn(req, [done])
或 fn(req, payload, [done])
(其中 req
是 IncomingMessage
)仍然受支持,但已被弃用。
¥The old signatures fn(req, [done])
or fn(req, payload, [done])
(where req
is IncomingMessage
) are still supported but are deprecated.
更改了 TypeScript 支持
¥Changed TypeScript support
Fastify 版本 3 中更改了类型系统。新的类型系统引入了通用约束和默认,以及定义模式类型(例如请求正文、查询字符串等)的新方法!
¥The type system was changed in Fastify version 3. The new type system introduces generic constraining and defaulting, plus a new way to define schema types such as a request body, querystring, and more!
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)
¥Manage uncaught exception (
在同步路由处理程序中,如果抛出错误,则服务器在设计上崩溃而不会调用配置的 .setErrorHandler()
。这已经改变,现在同步和异步路由中的所有意外错误都得到了管理。
¥In sync route handlers, if an error was thrown the server crashed by design
without calling the configured .setErrorHandler()
. This has changed and now
all unexpected errors in sync and async routes are managed.
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
})
进一步的补充和改进
¥Further additions and improvements
无论钩子如何注册(#2005),它们现在都具有一致的上下文
¥Hooks now have consistent context regardless of how they are registered (#2005)
已弃用
request.req
和reply.res
,用于request.raw
和reply.raw
(#2008)¥Deprecated
request.req
andreply.res
forrequest.raw
andreply.raw
(#2008)删除
modifyCoreObjects
选项 (#2015)¥Removed
modifyCoreObjects
option (#2015)添加了
connectionTimeout
选项 (#2086)¥Added
connectionTimeout
option (#2086)添加了
keepAliveTimeout
选项 (#2086)¥Added
keepAliveTimeout
option (#2086)添加了将对象作为错误抛出的功能 (#2134)
¥Added the feature to throw object as error (#2134)