@ fastify/ 自动载入
Fastify的方便插件,可以加载目录中找到的所有插件并自动配置匹配文件夹结构的路由.
安装
npm i @fastify/autoload
兼容性
| 插件版本 | 快速化版本 |
|---|---|
>=6.x | ^5.x |
^5.x | ^4.x |
>=2.x <5.x | ^3.x |
^1.x | ^2.x |
^1.x | ^1.x |
请注意,如果一个快取版本没有支持,那么该插件的相应版本也一样 上表列出. 见 快速化 LTS 政策 更多细节.
示例
将自动加载到全部插件的服务器加速 plugins 目录 :
const fastify = require('fastify')
const autoload = require('@fastify/autoload')
const app = fastify()
app.register(autoload, {
dir: path.join(__dirname, 'plugins')
})
app.listen({ port: 3000 })
或采用无害环境管理语法:
import autoLoad from '@fastify/autoload'
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
import fastify from 'fastify'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const app = fastify()
app.register(autoLoad, {
dir: join(__dirname, 'plugins')
})
app.listen({ port: 3000 })
文件夹结构 :
├── plugins
│ ├── hooked-plugin
│ │ ├── autohooks.mjs
│ │ ├── routes.js
│ │ └── children
│ │ ├── commonjs.cjs
│ │ ├── module.mjs
│ │ └── typescript.ts
│ ├── single-plugin
│ │ ├── index.js
│ │ └── utils.js
│ ├── more-plugins
│ │ ├── commonjs.cjs
│ │ ├── module.mjs
│ │ └── typescript.ts
│ └── another-plugin.js
├── package.json
└── app.js
全局配置
自动加载可以使用下列选项进行定制:
dir (必须)
包含要加载插件的基础目录 .
一个目录中的每个脚本文件都作为插件处理,除非目录包含索引文件(例如. index.js) (中文(简体) ). 在这种情况下,只有索引文件(和潜在的子目录)才会被加载.
支持以下脚本类型:
.js(通用JS或ES模块取决于type父领域package.json(中文(简体) ).cjs(共同JS) (中文(简体) ).mjs(ES模块).ts(编)
dirNameRoutePrefix (可选) - 默认 : true
确定路径是否在自动加载目录中与子目录名称自动前缀。 它可以是必须返回用作前缀的字符串的同步函数,也可以是必须返回的 false 以跳过目录的前缀.
fastify.register(autoLoad, {
dir: path.join(__dirname, 'routes'),
dirNameRoutePrefix: false // lack of prefix will mean no prefix, instead of directory name
})
fastify.register(autoLoad, {
dir: path.join(__dirname, 'routes'),
dirNameRoutePrefix: function rewrite (folderParent, folderName) {
if (folderName === 'YELLOW') {
return 'yellow-submarine'
}
if (folderName === 'FoOoO-BaAaR') {
return false
}
return folderName
}
})
appendAutoPrefix (可选) - 默认 : false
如何控制 autoPrefix 从插件文件与目录产生的前缀合并.
false(默认) :autoPrefix替换该插件的目录前缀.true: 保留目录衍生的前缀,以及autoPrefix之后附上.
示例目录:
routes/
children/
new-routes.js // exports autoPrefix = '/batch'
默认行为( A)appendAutoPrefix: false),该路径被加载为:
/your-parent-prefix/batch/entity
与 appendAutoPrefix: true,该路线的加载方式为:
/your-parent-prefix/children/batch/entity
fastify.register(autoLoad, {
dir: path.join(__dirname, 'routes'),
appendAutoPrefix: true
})
matchFilter (可选)
过滤匹配任何要加载的路径 。 可以是 RegExp,字符串,也可以是返回布尔函数的函数.
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
matchFilter: (path) => path.split("/").at(-2) === "handlers"
})
ignoreFilter (可选)
过滤匹配任何不应加载的路径 。 可以是 RegExp,字符串,也可以是函数返回布尔.
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
ignoreFilter: (path) => path.endsWith('.spec.js')
})
ignorePattern (可选)
RegExp 匹配任何不应加载的文件或文件夹 .
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
ignorePattern: /^.*(?:test|spec).js$/
})
scriptPattern (可选)
覆盖默认接受的脚本文件的 Regex 。 您只应该使用此选项 定制钩子供应商,例如 ts-node。否则,在此扩大接受扩展将导致错误.
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
scriptPattern: /(?<!\.d)\.(ts|tsx)$/
})
indexPattern (可选)
覆盖此程序的正则x index.js 命名大会.
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
indexPattern: /^.*routes(?:\.ts|\.js|\.cjs|\.mjs)$/
})
maxDepth (可选)
限制嵌入插件加载的深度 .
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
maxDepth: 2 // files in `opts.dir` nested more than 2 directories deep will be ignored.
})
forceESM (可选)
如果设定为“ true” 它总是使用 await import 来装入插件或钩子.
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
forceESM: true
})
encapsulate (可选) - 默认 : true
如果设置为 false 每个装入的插件都用 粘贴- 插件。这允许您在需要时在插件和父上下文之间共享上下文。 例如,如果需要共享装饰器. 读取 这个 更多细节.
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
encapsulate: false
})
options (可选)
所有已注册插件所用的全局选项对象 .
这里指定的任何选项都会覆盖 plugin.autoConfig 选项.
当设置两者 options.prefix 财务报告和审定财务报表 plugin.autoPrefix 他们将蒙蔽.
默认, plugin.autoPrefix 替换目录产生的前缀。 设定 appendAutoPrefix: true 以保留目录前缀和附件 plugin.autoPrefix 跟着他们.
// index.js
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
options: { prefix: '/defaultPrefix' }
})
// /plugins/something.js
module.exports = function (fastify, opts, next) {
// your plugin
}
module.exports.autoPrefix = '/something'
// /plugins/something.mjs
export default function (f, opts, next) {
f.get('/', (request, reply) => {
reply.send({ something: 'else' })
})
next()
}
export const autoPrefix = '/prefixed'
// routes can now be added to /defaultPrefix/something
autoHooks (可选)
应用钩从 autohooks.js 文件到文件夹中的插件.
自动钩子从 autohooks 文件将用插件封装。 若为 false,所有数据 autohooks.js 文件将被忽略 .
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
autoHooks: true // apply hooks to routes in this level
})
若为 autoHooks 设置,文件夹中的所有插件都将是 封装
和装饰值 不导出 在文件夹外.
autoHooksPattern (可选)
覆盖此程序的正则x autohooks 命名大会.
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
autoHooks: true,
autoHooksPattern: /^[_.]?auto_?hooks(?:\.js|\.cjs|\.mjs)$/i
})
cascadeHooks (可选)
如果使用 autoHooks连锁钩给所有儿童 如果 autoHooks 实值 false。 。 。 .
默认行为 autoHooks 将钩子只应用到 autohooks.js 文件已经找到。 设置 cascadeHooks: true 将继续对孩子施用钩子.
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
autoHooks: true, // apply hooks to routes in this level,
cascadeHooks: true // continue applying hooks to children, starting at this level
})
overwriteHooks (可选)
如果使用 cascadeHooks,当新的 autohooks.js 遇到了文件。 如果 autoHooks 实值 false。 。 。 .
默认行为 cascadeHooks 将钩子积累为新 autohooks.js 档案被发现并级联到儿童身上。 设置 overwriteHooks: true 将启动新钩级联 autohooks.js 遇到了文件.
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
autoHooks: true, // apply hooks to routes in this level,
cascadeHooks: true, // continue applying hooks to children, starting at this level,
overwriteHooks: true // re-start hook cascade when a new `autohooks.js` file is found
})
routeParams (可选)
文件夹的前缀 _ 将变为动态路由参数。 如果您想要使用混合路由参数, 请使用双下划线 __。 。 。 .
/*
├── routes
├── __country-__language
│ │ └── actions.js
│ └── users
│ ├── _id
│ │ └── actions.js
│ ├── __country-__language
│ │ └── actions.js
│ └── index.js
└── app.js
*/
fastify.register(autoLoad, {
dir: path.join(__dirname, 'routes'),
routeParams: true
// routes/users/_id/actions.js will be loaded with prefix /users/:id
// routes/__country-__language/actions.js will be loaded with prefix /:country-:language
})
// curl http://localhost:3000/users/index
// { userIndex: [ { id: 7, username: 'example' } ] }
// curl http://localhost:3000/users/7/details
// { user: { id: 7, username: 'example' } }
// curl http://localhost:3000/be-nl
// { country: 'be', language: 'nl' }
使用环境变量覆盖类型Script检测
此插件使用 本地类型剥离 与节点23 及后.
使用该程序可自动检测TypeScript的运行时间 FASTIFY_AUTOLOAD_TYPESCRIPT 环境变量。 如果设定为真实值 .ts 文件,期望节点有 TypeScript 可装入器.
对于要使用自动加载来装入 TypeScript 文件但检测 TypeScript 加载器失败的情况, 这样做是有用的, 例如, 您正在使用自定义加载器 .
可以像这样使用:
FASTIFY_AUTOLOAD_TYPESCRIPT=1 node --loader=my-custom-loader index.ts
插件配置
每个插件都可以使用以下模块属性进行单独配置:
plugin.autoConfig
指定用作 opts 参数.
module.exports = function (fastify, opts, next) {
console.log(opts.foo) // 'bar'
next()
}
module.exports.autoConfig = { foo: 'bar' }
或采用无害环境管理的语法:
import plugin from '../lib-plugin.js'
export default async function myPlugin (app, options) {
app.get('/', async (request, reply) => {
return { hello: options.name }
})
}
export const autoConfig = { name: 'y' }
如果您需要访问父实例, 您也可以使用回调功能 :
export const autoConfig = (fastify) => {
return { name: 'y ' + fastify.rootName }
}
然而,注意到 prefix 选项应直接设置于 autoConfig 用于自动加载到预期工作:
export const autoConfig = (fastify) => {
return { name: 'y ' + fastify.rootName }
}
autoConfig.prefix = '/hello'
plugin.autoPrefix
设置插件的路由前缀 .
plugin.autoPrefix 默认覆盖目录产生的前缀。 使用全局 appendAutoPrefix 选项 plugin.autoPrefix 改为目录前缀.
module.exports = function (fastify, opts, next) {
fastify.get('/', (request, reply) => {
reply.send({ hello: 'world' })
})
next()
}
module.exports.autoPrefix = '/something'
// when loaded with autoload, this will be exposed as /something
或采用无害环境管理的语法:
export default async function (app, opts) {
app.get('/', (request, reply) => {
return { something: 'else' }
})
}
export const autoPrefix = '/prefixed'
plugin.prefixOverride
覆盖所有其他前缀选项.
// index.js
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
options: { prefix: '/defaultPrefix' }
})
// /foo/something.js
module.exports = function (fastify, opts, next) {
// your plugin
}
module.exports.prefixOverride = '/overriddenPrefix'
// this will be exposed as /overriddenPrefix
或采用无害环境管理的语法:
export default async function (app, opts) {
// your plugin
}
export const prefixOverride = '/overriddenPrefix'
如果您在文件夹中有一个插件, 您不需要应用任何前缀, 您可以设置 prefixOverride = ''数字 :
// index.js
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
options: { prefix: '/defaultPrefix' }
})
// /foo/something.js
module.exports = function (fastify, opts, next) {
// your plugin
}
// optional
module.exports.prefixOverride = ''
// routes can now be added without a prefix
plugin.autoload
切换插件是否应该装入 .
示例
module.exports = function (fastify, opts, next) {
// your plugin
}
// optional
module.exports.autoload = false
opts.name
设置插件的名称, 使其可以被引用为依赖 .
opts.dependencies
设置插件依赖性以确保正确的负载顺序 .
示例
// plugins/plugin-a.js
const fp = require('fastify-plugin')
function plugin (fastify, opts, next) {
// plugin a
}
module.exports = fp(plugin, {
name: 'plugin-a',
dependencies: ['plugin-b']
})
// plugins/plugin-b.js
function plugin (fastify, opts, next) {
// plugin b
}
module.exports = fp(plugin, {
name: 'plugin-b'
})
自动锁定 :
自动hooks功能为您在路径中自动添加钩子,装饰等提供了多个选项. CJS和无害环境管理 autohook 支持格式.
默认行为 autoHooks: true 即封装 autohooks.js 包含文件文件夹内容的插件 。 这个 cascadeHooks: true 选项以当前文件夹内容和所有后续子项封装钩子,并附加 autohooks.js 正在累积应用文件。 这个 overwriteHooks: true 选项将随时重新启动级联 autohooks.js 遇到了文件.
插件和钩子由文件夹封装并注册在 fastify 装入 @fastify/autoload 插件 。 关于封装如何在Fastify操作的更多信息,请参见: https://fastify.dev/docs/latest/Reference/Encapsulation/#封装
示例
├── plugins
│ ├── hooked-plugin
│ │ ├── autohooks.js // req.hookOne = 'yes' # CJS syntax
│ │ ├── routes.js
│ │ └── children
│ │ ├── old-routes.js
│ │ ├── new-routes.js
│ │ └── grandchildren
│ │ ├── autohooks.mjs // req.hookTwo = 'yes' # ESM syntax
│ │ └── routes.mjs
│ └── standard-plugin
│ └── routes.js
└── app.js
// hooked-plugin/autohooks.js
module.exports = async function (app, opts) {
app.addHook('onRequest', async (req, reply) => {
req.hookOne = yes;
});
}
// hooked-plugin/children/grandchildren/autohooks.mjs
export default async function (app, opts) {
app.addHook('onRequest', async (req, reply) => {
req.hookTwo = yes
})
}
# app.js { autoHooks: true }
$ curl http://localhost:3000/standard-plugin/
{} # no hooks in this folder, so behavior is unchanged
$ curl http://localhost:3000/hooked-plugin/
{ hookOne: 'yes' }
$ curl http://localhost:3000/hooked-plugin/children/old
{}
$ curl http://localhost:3000/hooked-plugin/children/new
{}
$ curl http://localhost:3000/hooked-plugin/children/grandchildren/
{ hookTwo: 'yes' }
# app.js { autoHooks: true, cascadeHooks: true }
$ curl http://localhost:3000/hooked-plugin/
{ hookOne: 'yes' }
$ curl http://localhost:3000/hooked-plugin/children/old
{ hookOne: 'yes' }
$ curl http://localhost:3000/hooked-plugin/children/new
{ hookOne: 'yes' }
$ curl http://localhost:3000/hooked-plugin/children/grandchildren/
{ hookOne: 'yes', hookTwo: 'yes' } # hooks are accumulated and applied in ascending order
# app.js { autoHooks: true, cascadeHooks: true, overwriteHooks: true }
$ curl http://localhost:3000/hooked-plugin/
{ hookOne: 'yes' }
$ curl http://localhost:3000/hooked-plugin/children/old
{ hookOne: 'yes' }
$ curl http://localhost:3000/hooked-plugin/children/new
{ hookOne: 'yes' }
$ curl http://localhost:3000/hooked-plugin/children/grandchildren/
{ hookTwo: 'yes' } # new autohooks.js takes over
许可证
许可证根据 麻省理工学院。 。 。 .