插件
插件
¥Plugins
Fastify 允许用户通过插件扩展其功能。插件可以是一组路由、服务器 decorator 或其他任何东西。你需要使用一个或多个插件的 API 是 register
。
¥Fastify allows the user to extend its functionalities with plugins. A plugin can
be a set of routes, a server decorator, or whatever. The API
that you will need to use one or more plugins, is register
.
默认情况下,register
会创建一个新范围,这意味着如果你对 Fastify 实例进行一些更改(通过 decorate
),此更改将不会反映在当前上下文祖级中,而只会反映在其后代中。这个特性允许我们实现插件的封装和继承,这样我们就创建了一个有向无环图(DAG),并且不会出现交叉依赖带来的问题。
¥By default, register
creates a new scope, this means that if you make some
changes to the Fastify instance (via decorate
), this change will not be
reflected by the current context ancestors, but only by its descendants. This
feature allows us to achieve plugin encapsulation and inheritance, in this
way we create a directed acyclic graph (DAG) and we will not have issues
caused by cross dependencies.
你可能已经在 入门 指南中看到了使用此 API 是多么容易:
¥You may have already seen in the Getting Started guide how easy it is to use this API:
fastify.register(plugin, [options])
插件选项
¥Plugin Options
fastify.register
的可选 options
参数支持一组预定义的选项,Fastify 本身将使用这些选项,除非插件已用 fastify-plugin 封装。无论插件是否已封装,此选项对象也将在调用时传递给插件。当前支持的 Fastify 特定选项列表是:
¥The optional options
parameter for fastify.register
supports a predefined
set of options that Fastify itself will use, except when the plugin has been
wrapped with fastify-plugin. This
options object will also be passed to the plugin upon invocation, regardless of
whether or not the plugin has been wrapped. The currently supported list of
Fastify specific options is:
注意:与 fastify-plugin 一起使用时,这些选项将被忽略
¥Note: Those options will be ignored when used with fastify-plugin
Fastify 将来可能会直接支持其他选项。因此,为了避免冲突,插件应该考虑为其选项命名空间。例如,插件 foo
可能像这样注册:
¥It is possible that Fastify will directly support other options in the future.
Thus, to avoid collisions, a plugin should consider namespacing its options. For
example, a plugin foo
might be registered like so:
fastify.register(require('fastify-foo'), {
prefix: '/foo',
foo: {
fooOption1: 'value',
fooOption2: 'value'
}
})
如果不关心冲突,插件可以简单地按原样接受选项对象:
¥If collisions are not a concern, the plugin may simply accept the options object as-is:
fastify.register(require('fastify-foo'), {
prefix: '/foo',
fooOption1: 'value',
fooOption2: 'value'
})
options
参数也可以是 Function
,它将在插件注册时进行评估,同时通过第一个位置参数授予对 Fastify 实例的访问权限:
¥The options
parameter can also be a Function
that will be evaluated at the
time the plugin is registered while giving access to the Fastify instance via
the first positional argument:
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 实例所做的更改,即利用现有的数据库连接来环绕它,这非常有用。
¥The Fastify instance passed on to the function is the latest state of the
external Fastify instance the plugin was declared on, allowing access to
variables injected via decorate
by preceding plugins
according to the order of registration. This is useful in case a plugin
depends on changes made to the Fastify instance by a preceding plugin i.e.
utilizing an existing database connection to wrap around it.
请记住,传递给函数的 Fastify 实例与将传递给插件的 Fastify 实例相同,是外部 Fastify 实例的副本而不是引用。实例的任何使用行为都将与在插件函数中调用时的行为相同,即如果调用 decorate
,则修饰变量将在插件函数中可用,除非它被 fastify-plugin
封装。
¥Keep in mind that the Fastify instance passed on to the function is the same as
the one that will be passed into the plugin, a copy of the external Fastify
instance rather than a reference. Any usage of the instance will behave the same
as it would if called within the plugins function i.e. if decorate
is called,
the decorated variables will be available within the plugins function unless it
was wrapped with fastify-plugin
.
路由前缀选项
¥Route Prefixing option
如果你传递带有键 prefix
和 string
值的选项,Fastify 将使用它为注册内的所有路由添加前缀,有关更多信息,请查看 此处。
¥If you pass an option with the key prefix
with a string
value, Fastify will
use it to prefix all the routes inside the register, for more info check
here.
请注意,如果你用 fastify-plugin
封装你的路由,此选项将不起作用(有 workaround 可用)。
¥Be aware that if you wrap your routes with
fastify-plugin
, this option will
not work (there is a workaround available).
错误处理
¥Error handling
错误处理由 avvio 完成。
¥The error handling is done by avvio.
作为一般规则,强烈建议你在下一个 after
或 ready
块中处理错误,否则你将在 listen
回调中收到它们。
¥As a general rule, it is highly recommended that you handle your errors in the
next after
or ready
block, otherwise you will get them inside the listen
callback.
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
after
、ready
和 listen
支持 async/await,fastify
也是 Thenable。
¥async/await is supported by after
, ready
, and listen
, as well as
fastify
being a Thenable.
await fastify.register(require('my-plugin'))
await fastify.after()
await fastify.ready()
await fastify.listen({ port: 3000 })
注意:注册插件时使用 await
会加载插件和底层依赖树,"finalizing" 则进行封装过程。加载插件及其依赖后对插件的任何更改都不会反映在父实例中。
¥Note: Using await
when registering a plugin loads the plugin
and the underlying dependency tree, "finalizing" the encapsulation process.
Any mutations to the plugin after it and its dependencies have been
loaded will not be reflected in the parent instance.
无害化管理支持
¥ESM support
Node.js v13.3.0
及以上版本也支持 ESM!
¥ESM is supported as well from Node.js
v13.3.0
and above!
// 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
创建一个插件
¥Create a plugin
创建插件非常简单,只需创建一个接受三个参数的函数,即 fastify
实例、options
对象和 done
回调。
¥Creating a plugin is very easy, you just need to create a function that takes
three parameters, the fastify
instance, an options
object, and the done
callback.
示例:
¥Example:
module.exports = function (fastify, opts, done) {
fastify.decorate('utility', function () {})
fastify.get('/', handler)
done()
}
你还可以在另一个 register
中使用 register
:
¥You can also use register
inside another register
:
module.exports = function (fastify, opts, done) {
fastify.decorate('utility', function () {})
fastify.get('/', handler)
fastify.register(require('./other-plugin'))
done()
}
有时,你需要知道服务器何时即将关闭,例如,因为你必须关闭与数据库的连接。要知道何时会发生这种情况,你可以使用 'onClose'
钩子。
¥Sometimes, you will need to know when the server is about to close, for example,
because you must close a connection to a database. To know when this is going to
happen, you can use the 'onClose'
hook.
不要忘记 register
总是会创建一个新的 Fastify 作用域,如果你不需要,请阅读以下部分。
¥Do not forget that register
will always create a new Fastify scope, if you do
not need that, read the following section.
处理范围
¥Handle the scope
如果你仅使用 register
来使用 decorate
扩展服务器的功能,则你有责任告诉 Fastify 不要创建新的范围。否则,上层范围内的用户将无法访问你的更改。
¥If you are using register
only for extending the functionality of the server
with decorate
, it is your responsibility to tell Fastify
not to create a new scope. Otherwise, your changes will not be accessible by the
user in the upper scope.
你有两种方法告诉 Fastify 避免创建新上下文:
¥You have two ways to tell Fastify to avoid the creation of a new context:
使用
fastify-plugin
模块¥Use the
fastify-plugin
module使用
'skip-override'
隐藏属性¥Use the
'skip-override'
hidden property
我们建议使用 fastify-plugin
模块,因为它为你解决了这个问题,并且你可以将 Fastify 的版本范围作为你的插件将支持的参数传递。
¥We recommend using the fastify-plugin
module, because it solves this problem
for you, and you can pass a version range of Fastify as a parameter that your
plugin will support.
const fp = require('fastify-plugin')
module.exports = fp(function (fastify, opts, done) {
fastify.decorate('utility', function () {})
done()
}, '0.x')
查看 fastify-plugin
文档以了解有关如何使用此模块的更多信息。
¥Check the fastify-plugin
documentation to learn more about how to use this module.
如果你不使用 fastify-plugin
模块,则可以使用 'skip-override'
hidden 属性,但我们不建议这样做。如果将来 Fastify API 发生变化,你将有责任更新模块,而如果你使用 fastify-plugin
,则可以确保向后兼容。
¥If you do not use the fastify-plugin
module, you can use the 'skip-override'
hidden property, but we do not recommend it. If in the future the Fastify API
changes it will be your responsibility to update the module, while if you use
fastify-plugin
, you can be sure about backward compatibility.
function yourPlugin (fastify, opts, done) {
fastify.decorate('utility', function () {})
done()
}
yourPlugin[Symbol.for('skip-override')] = true
module.exports = yourPlugin