插件
插件
¥Plugins
Fastify 可以通过插件进行扩展,插件可以是一组路由、服务器 decorator 或其他功能。使用 register
API 添加一个或多个插件。
¥Fastify can be extended with plugins, which can be a set of routes, a server
decorator, or other functionality. Use the register
API to
add one or more plugins.
默认情况下,register
会创建一个新范围,这意味着对 Fastify 实例的更改(通过 decorate
)不会影响当前上下文祖级,只会影响其后代。此功能支持插件封装和继承,创建有向无环图 (DAG) 并避免交叉依赖问题。
¥By default, register
creates a new scope, meaning changes to the Fastify
instance (via decorate
) will not affect the current context ancestors, only
its descendants. This feature enables plugin encapsulation and inheritance,
creating a directed acyclic graph (DAG) and avoiding cross-dependency issues.
入门 指南包含使用此 API 的示例:
¥The Getting Started guide includes an example of using 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 一起使用时,这些选项将被忽略。
¥These options will be ignored when used with fastify-plugin.
为避免冲突,插件应考虑命名空间其选项。例如,插件 foo
可能像这样注册:
¥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 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
evaluated at plugin registration,
providing access to the Fastify instance via the first 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 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 if a plugin depends on changes made to
the Fastify instance by a preceding plugin, such as utilizing an existing database
connection.
请记住,传递给函数的 Fastify 实例与传递给插件的实例相同,是外部 Fastify 实例的副本而不是引用。实例的任何使用都将表现得与在插件函数内调用时相同。例如,如果调用 decorate
,则除非使用 fastify-plugin
封装,否则修饰变量将在插件函数中可用。
¥Keep in mind that the Fastify instance passed to the function is the same as the
one 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 plugin's function. For example, if decorate
is called, the decorated
variables will be available within the plugin's function unless it was wrapped
with fastify-plugin
.
路由前缀选项
¥Route Prefixing option
如果传递了带有键 prefix
和 string
值的选项,Fastify 将使用它作为注册内所有路由的前缀。有关更多信息,请查看 此处。
¥If an option with the key prefix
and a string
value is passed, Fastify will
use it to prefix all the routes inside the register. For more info, check
here.
请注意,如果路由用 fastify-plugin
封装,则此选项将不起作用(请参阅 workaround)。
¥Be aware that if routes are wrapped with
fastify-plugin
, this option will
not work (see the workaround).
错误处理
¥Error handling
错误处理由 avvio 完成。
¥Error handling is done by avvio.
作为一般规则,在下一个 after
或 ready
块中处理错误,否则它们将被捕获在 listen
回调中。
¥As a general rule, handle errors in the next after
or ready
block, otherwise
they will be caught 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" 是封装过程。加载插件及其依赖后对插件的任何更改都不会反映在父实例中。
¥Using await
when registering a plugin loads the plugin and its dependencies,
"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
ESM 从 Node.js v13.3.0
及以上版本开始受支持。
¥ESM is supported 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 easy. 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
中使用:
¥register
can also be used inside another register
:
module.exports = function (fastify, opts, done) {
fastify.decorate('utility', function () {})
fastify.get('/', handler)
fastify.register(require('./other-plugin'))
done()
}
请记住,register
始终会创建一个新的 Fastify 范围。如果不需要,请阅读以下部分。
¥Remember, register
always creates a new Fastify scope. If this is not needed,
read the following section.
处理范围
¥Handle the scope
如果 register
仅用于通过 decorate
扩展服务器功能,请告诉 Fastify 不要创建新的作用域。否则,更改将无法在上层范围内访问。
¥If register
is used only to extend server functionality with
decorate
, tell Fastify not to create a new scope. Otherwise,
changes will not be accessible in the upper scope.
有两种方法可以避免创建新上下文:
¥There are two ways to avoid creating a new context:
-
使用
fastify-plugin
模块¥Use the
fastify-plugin
module -
使用
'skip-override'
隐藏属性¥Use the
'skip-override'
hidden property
建议使用 fastify-plugin
模块,因为它解决了这个问题并允许传递插件将支持的 Fastify 版本范围:
¥Using the fastify-plugin
module is recommended, as it solves this problem and
allows passing a version range of Fastify that the 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'
隐藏属性,但不建议这样做。未来的 Fastify API 更改将由你负责更新,而 fastify-plugin
确保向后兼容。
¥If not using fastify-plugin
, the 'skip-override'
hidden property can be used,
but it is not recommended. Future Fastify API changes will be your responsibility
to update, whilst fastify-plugin
ensures backward compatibility.
function yourPlugin (fastify, opts, done) {
fastify.decorate('utility', function () {})
done()
}
yourPlugin[Symbol.for('skip-override')] = true
module.exports = yourPlugin