跳至主要内容
版本: 最新版本 (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包装。

路由前缀选项

如果您使用键prefixstring值传递选项,Fastify 将使用它作为 register 内所有路由的前缀,有关更多信息,请查看此处

请注意,如果您使用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以及fastify作为Thenable都支持async/await

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