跳至主要內容
版本:最新版 (v5.0.x)

外掛

外掛

Fastify 允許使用者使用外掛擴展其功能。外掛可以是一組路由、一個伺服器裝飾器,或任何其他東西。您需要使用一個或多個外掛的 API 是 register

預設情況下,register 會建立一個新的作用域,這表示如果您對 Fastify 實例進行一些變更(透過 decorate),此變更不會反映在目前內容的祖先中,而只會反映在其後代中。此功能允許我們實現外掛的封裝繼承,透過這種方式,我們建立一個有向無環圖 (DAG),並且不會有跨相依性造成的問題。

您可能已經在入門指南中看到使用此 API 是多麼容易

fastify.register(plugin, [options])

外掛選項

fastify.register 的可選 options 參數支援一組預定義的選項,Fastify 本身會使用這些選項,除非外掛已使用 fastify-plugin 包裝。這個選項物件也會在調用時傳遞給外掛,無論外掛是否已包裝。目前支援的 Fastify 特定選項清單如下

注意:當與 fastify-plugin 一起使用時,這些選項將被忽略

Fastify 未來可能會直接支援其他選項。因此,為了避免衝突,外掛應考慮對其選項進行命名空間。例如,外掛 foo 可以像這樣註冊

fastify.register(require('fastify-foo'), {
prefix: '/foo',
foo: {
fooOption1: 'value',
fooOption2: 'value'
}
})

如果不需要擔心衝突,外掛可以簡單地按原樣接受選項物件

fastify.register(require('fastify-foo'), {
prefix: '/foo',
fooOption1: 'value',
fooOption2: 'value'
})

options 參數也可以是一個 Function,它將在註冊外掛時進行評估,同時透過第一個位置引數存取 Fastify 實例

const fp = require('fastify-plugin')

fastify.register(fp((fastify, opts, done) => {
fastify.decorate('foo_bar', { hello: 'world' })

done()
}))

// The opts argument of fastify-foo will be { hello: 'world' }
fastify.register(require('fastify-foo'), parent => parent.foo_bar)

傳遞給函式的 Fastify 實例是宣告外掛的外部 Fastify 實例的最新狀態,允許存取透過decorate 依據註冊順序由先前的外掛注入的變數。如果外掛依賴於先前外掛對 Fastify 實例所做的變更(例如,利用現有的資料庫連線來包裝它),這非常有用。

請記住,傳遞給函式的 Fastify 實例與將傳遞給外掛的實例相同,是外部 Fastify 實例的副本,而不是參考。任何對實例的使用行為都與在外掛函式內部調用時相同,例如,如果調用 decorate,則裝飾的變數將在外掛函式內可用,除非它已使用 fastify-plugin 包裝。

路由前綴選項

如果您傳遞一個鍵為 prefix 且值為 string 的選項,Fastify 將使用它來為註冊內的所有路由加上前綴,有關更多資訊,請參閱此處

請注意,如果您使用 fastify-plugin 包裝您的路由,則此選項將不起作用(有一個變通方法可用)。

錯誤處理

錯誤處理由 avvio 完成。

作為一般規則,強烈建議您在下一個 afterready 區塊中處理錯誤,否則您會在 listen 回調中取得這些錯誤。

fastify.register(require('my-plugin'))

// `after` will be executed once
// the previous declared `register` has finished
fastify.after(err => console.log(err))

// `ready` will be executed once all the registers declared
// have finished their execution
fastify.ready(err => console.log(err))

// `listen` is a special ready,
// so it behaves in the same way
fastify.listen({ port: 3000 }, (err, address) => {
if (err) console.log(err)
})

async/await

afterreadylisten 支援async/await,而且 fastify 也是一個 Thenable。

await fastify.register(require('my-plugin'))

await fastify.after()

await fastify.ready()

await fastify.listen({ port: 3000 })

注意:在註冊外掛時使用 await 會載入外掛和底層相依性樹狀結構,從而「最終確定」封裝過程。在載入外掛及其相依性之後對外掛進行的任何變更都不會反映在父實例中。

ESM 支援

Node.js v13.3.0 及更高版本也支援 ESM!

// main.mjs
import Fastify from 'fastify'
const fastify = Fastify()

fastify.register(import('./plugin.mjs'))

fastify.listen({ port: 3000 }, console.log)


// plugin.mjs
async function plugin (fastify, opts) {
fastify.get('/', async (req, reply) => {
return { hello: 'world' }
})
}

export default plugin

建立外掛

建立外掛非常容易,您只需要建立一個接收三個參數的函式,即 fastify 實例、一個 options 物件和 done 回調。

範例

module.exports = function (fastify, opts, done) {
fastify.decorate('utility', function () {})

fastify.get('/', handler)

done()
}

您也可以在另一個 register 內部使用 register

module.exports = function (fastify, opts, done) {
fastify.decorate('utility', function () {})

fastify.get('/', handler)

fastify.register(require('./other-plugin'))

done()
}

有時,您需要知道伺服器何時即將關閉,例如,因為您必須關閉與資料庫的連線。若要知道何時會發生這種情況,您可以使用 'onClose' 鉤子。

別忘了 register 永遠會建立新的 Fastify 作用域,如果您不需要這樣做,請閱讀以下章節。

處理作用域

如果您使用 register 僅是為了使用decorate擴展伺服器的功能,則您有責任告知 Fastify 不要建立新的作用域。否則,使用者將無法在上層作用域中存取您的變更。

您有兩種方法可以告知 Fastify 避免建立新的內容

我們建議使用 fastify-plugin 模組,因為它可以為您解決此問題,而且您可以傳遞外掛將支援的 Fastify 版本範圍作為參數。

const fp = require('fastify-plugin')

module.exports = fp(function (fastify, opts, done) {
fastify.decorate('utility', function () {})
done()
}, '0.x')

請查看 fastify-plugin 文件,以了解更多關於如何使用此模組的資訊。

如果您不使用 fastify-plugin 模組,則可以使用 'skip-override' 隱藏屬性,但我們不建議這樣做。如果未來 Fastify API 發生變更,您有責任更新模組,而如果您使用 fastify-plugin,您可以確保向後相容性。

function yourPlugin (fastify, opts, done) {
fastify.decorate('utility', function () {})
done()
}
yourPlugin[Symbol.for('skip-override')] = true
module.exports = yourPlugin