Fastify 允許用戶通過(guò)插件的方式擴(kuò)展自身的功能。 一個(gè)插件可以是一組路由,一個(gè)服務(wù)器裝飾器或者其他任意的東西。 在使用一個(gè)或者許多插件時(shí),只需要一個(gè) API register。
默認(rèn), register 會(huì)創(chuàng)建一個(gè) 新的作用域( Scope ), 這意味著你能夠改變 Fastify 實(shí)例(通過(guò)decorate), 這個(gè)改變不會(huì)反映到當(dāng)前作用域, 只會(huì)影響到子作用域。 這樣可以做到插件的封裝和繼承, 我們創(chuàng)建了一個(gè)無(wú)回路有向圖(DAG), 因此不會(huì)有交叉依賴的問(wèn)題。
你已經(jīng)在起步部分很直觀的看到了怎么使用這個(gè) API。
fastify.register(plugin, [options])
fastify.register 可選參數(shù)列表支持一組預(yù)定義的 Fastify 可用的參數(shù), 除了當(dāng)插件使用了 fastify-plugin。 選項(xiàng)對(duì)象會(huì)在插件被調(diào)用傳遞進(jìn)去, 無(wú)論這個(gè)插件是否用了 fastify-plugin。 當(dāng)前支持的選項(xiàng)有:
注意:當(dāng)使用 fastify-plugin 時(shí),這些選項(xiàng)會(huì)被忽略
Fastify 有可能在將來(lái)會(huì)直接支持其他的選項(xiàng)。 因此為了避免沖突, 插件應(yīng)該考慮給選項(xiàng)加入命名空間。 舉個(gè)例子, 插件 foo 可以像以下代碼一樣注冊(cè):
fastify.register(require('fastify-foo'), {
prefix: '/foo',
foo: {
fooOption1: 'value',
fooOption2: 'value'
}
})
如果不考慮沖突, 插件可以簡(jiǎn)化成直接接收對(duì)象參數(shù):
fastify.register(require('fastify-foo'), {
prefix: '/foo',
fooOption1: 'value',
fooOption2: 'value'
})
options 參數(shù)還可以是一個(gè)在插件注冊(cè)時(shí)確定的 函數(shù),這個(gè)函數(shù)的第一位參數(shù)是 fastify 實(shí)例:
const fp = require('fastify-plugin')
fastify.register(fp((fastify, opts, done) => {
fastify.decorate('foo_bar', { hello: 'world' })
done()
}))
// fastify-foo 的 options 參數(shù)會(huì)是 { hello: 'world' }
fastify.register(require('fastify-foo'), parent => parent.foo_bar)
傳給函數(shù)的 fastify 實(shí)例是插件聲明時(shí)外部 fastify 實(shí)例的最新?tīng)顟B(tài),允許你訪問(wèn)注冊(cè)順序在前的插件通過(guò) decorate 注入的變量。這在需要依賴前置插件對(duì)于 Fastify 實(shí)例的改動(dòng)時(shí)派得上用場(chǎng),比如,使用已存在的數(shù)據(jù)庫(kù)連接來(lái)包裝你的插件。
請(qǐng)記住,傳給函數(shù)的 fastify 實(shí)例和傳給插件的實(shí)例是一樣的,不是外部 fastify 實(shí)例的引用,而是拷貝。任何對(duì)函數(shù)的實(shí)例參數(shù)的操作結(jié)果,都會(huì)和在插件函數(shù)中操作的結(jié)果一致。也就是說(shuō),如果調(diào)用了 decorate,被注入的變量在插件函數(shù)中也是可用的,除非你使用 fastify-plugin 包裝了這個(gè)插件。
如果你傳入以 prefix為 key , string 為值的選項(xiàng), Fastify 會(huì)自動(dòng)為這個(gè)插件下所有的路由添加這個(gè)前綴, 更多信息可以查詢 這里.注意如果使用了 fastify-plugin 這個(gè)選項(xiàng)不會(huì)起作用。
錯(cuò)誤處理是由 avvio 解決的。一個(gè)通用的原則, 我們建議在下一個(gè) after 或 ready 代碼塊中處理錯(cuò)誤, 否則錯(cuò)誤將出現(xiàn)在 listen 回調(diào)里。
fastify.register(require('my-plugin'))
// `after` 將在上一個(gè) `register` 結(jié)束后執(zhí)行
fastify.after(err => console.log(err))
// `ready` 將在所有 `register` 結(jié)束后執(zhí)行
fastify.ready(err => console.log(err))
// `listen` 是一個(gè)特殊的 `ready`,
// 因此它的執(zhí)行時(shí)機(jī)與 `ready` 一致
fastify.listen(3000, (err, address) => {
if (err) console.log(err)
})
async-await 只被 ready 與 listen 支持。
fastify.register(require('my-plugin'))
await fastify.ready()
await fastify.listen(3000)
自 Node.js v13.3.0 開(kāi)始, ESM 也被支持了!
// main.mjs
import Fastify from 'fastify'
const fastify = Fastify()
fastify.register(import('./plugin.mjs'))
fastify.listen(3000, console.log)
// plugin.mjs
async function plugin (fastify, opts) {
fastify.get('/', async (req, reply) => {
return { hello: 'world' }
})
}
export default plugin
創(chuàng)建插件非常簡(jiǎn)單, 你只需要?jiǎng)?chuàng)建一個(gè)方法, 這個(gè)方法接收三個(gè)參數(shù): fastify 實(shí)例、options 選項(xiàng)和 done 回調(diào)。例子:
module.exports = function (fastify, opts, done) {
fastify.decorate('utility', () => {})
fastify.get('/', handler)
done()
}
你也可以在一個(gè) register 內(nèi)部添加其他 register:
module.exports = function (fastify, opts, done) {
fastify.decorate('utility', () => {})
fastify.get('/', handler)
fastify.register(require('./other-plugin'))
done()
}
有時(shí)候, 你需要知道這個(gè)服務(wù)器何時(shí)即將關(guān)閉, 例如在你必須關(guān)閉數(shù)據(jù)庫(kù)連接的時(shí)候。 要知道什么時(shí)候發(fā)生這種情況, 你可以用 'onClose' 鉤子。
別忘了 register 會(huì)創(chuàng)建一個(gè)新的 Fastify 作用域, 如果你不需要, 閱讀下面的章節(jié)。
如果你使用 register 僅僅是為了通過(guò)decorate擴(kuò)展服務(wù)器的功能, 你需要告訴 Fastify 不要?jiǎng)?chuàng)建新的上下文, 不然你的改動(dòng)不會(huì)影響其他作用域中的用戶。
你有兩種方式告訴 Fastify 避免創(chuàng)建新的上下文:
我們建議使用 fastify-plugin 模塊, 因?yàn)樗菍iT(mén)用來(lái)為你解決這個(gè)問(wèn)題, 并且你可以傳一個(gè)能夠支持的 Fastify 版本范圍的參數(shù)。
const fp = require('fastify-plugin')
module.exports = fp(function (fastify, opts, done) {
fastify.decorate('utility', () => {})
done()
}, '0.x')
參考 fastify-plugin 文檔了解更多這個(gè)模塊。
如果你不用 fastify-plugin 模塊, 可以使用 'skip-override' 隱藏屬性, 但我們不推薦這么做。 如果將來(lái) Fastify API 改變了, 你需要去更新你的模塊, 如果使用 fastify-plugin, 你可以對(duì)向后兼容放心。
function yourPlugin (fastify, opts, done) {
fastify.decorate('utility', () => {})
done()
}
yourPlugin[Symbol.for('skip-override')] = true
module.exports = yourPlugin
更多建議: