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 結構描述規格的 $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)
);
變更的 preParsing 鉤子行為 (#2286)
從 Fastify v3 開始,preParsing
鉤子的行為會稍微變更,以支援請求負載操作。
鉤子現在會採用額外引數 payload
,因此新的鉤子簽章為 fn(request, reply, payload, done)
或 async fn(request, reply, payload)
。
鉤子可以選擇性地透過 done(null, stream)
或在 async 函式的情況下傳回資料流,來傳回新的資料流。
如果鉤子傳回新的資料流,則後續鉤子將會使用該資料流,而不是原始資料流。此項的範例用例是處理壓縮請求。
新的資料流應該將 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.raw
和reply.raw
的request.req
和reply.res
(#2008) - 已移除
modifyCoreObjects
選項 (#2015) - 已新增
connectionTimeout
選項 (#2086) - 已新增
keepAliveTimeout
選項 (#2086) - 新增對 外掛程式 的 async-await 支援 (#2093)
- 已新增將物件當作錯誤擲出的功能 (#2134)