插件扩展
🌐 Plugins extension
Page summary:
现有插件可以通过将代码放置在
/src/extensions或使用全局register/bootstrap钩子来覆盖。本手册中的说明涵盖了重塑插件内容类型模式或服务器逻辑 —— 尽管上游更新可能会破坏扩展。
Strapi 带有可以从 Marketplace 安装的插件,也可以作为 npm 包安装。你 也可以创建自己的插件(参见 插件开发)或扩展现有插件。
🌐 Strapi comes with plugins that can be installed from the Marketplace or as npm packages. You can also create your own plugins (see plugins development) or extend the existing ones.
- 任何插件更新都可能会破坏该插件的扩展。
- 当需要时,Strapi 的新版本将会发布迁移指南,但这些指南从不涵盖插件扩展。如果需要进行大量自定义,请考虑分叉插件。
- 目前,插件的管理面板部分只能使用 patch-package进行扩展,但请注意,这样做可能会在未来的 Strapi 版本中破坏你的插件。
插件扩展代码位于 ./src/extensions 文件夹(参见 项目结构)。一些插件会自动在该处创建文件,准备进行修改。
🌐 Plugin extensions code is located in the ./src/extensions folder (see project structure). Some plugins automatically create files there, ready to be modified.
扩展文件夹结构示例
/extensions
/some-plugin-to-extend
strapi-server.js|ts
/content-types
/some-content-type-to-extend
schema.json
/another-content-type-to-extend
schema.json
/another-plugin-to-extend
strapi-server.js|ts
插件可以通过两种方式扩展:
🌐 Plugins can be extended in 2 ways:
扩展插件的内容类型
🌐 Extending a plugin's content-types
插件的内容类型可以通过两种方式扩展:使用 strapi-server.js|ts 中的编程接口,以及通过重写内容类型的架构。
🌐 A plugin's Content-Types can be extended in 2 ways: using the programmatic interface within strapi-server.js|ts and by overriding the content-types schemas.
内容类型的最终架构取决于以下加载顺序:
🌐 The final schema of the content-types depends on the following loading order:
- 原始插件的内容类型,
./src/extensions/plugin-name/content-types/content-type-name/schema.json中定义的 schema 中声明所覆盖的内容类型strapi-server.js|ts导出的contentTypes中的内容类型声明- Strapi 应用中
register()函数 的内容类型声明
要覆盖插件的 content-types:
🌐 To overwrite a plugin's content-types:
- (可选) 如果
./src/extensions文件夹尚不存在,请在应用根目录下创建该文件夹。 - 创建一个与要扩展的插件同名的子文件夹。
- 创建一个
content-types子文件夹。 - 在
content-types子文件夹内,创建另一个与要覆盖的内容类型相同 singularName 的子文件夹。 - 在这个
content-types/name-of-content-type子文件夹中,在一个schema.json文件中定义该内容类型的新架构(参见 schema 文档)。 - (可选) 对每种内容类型重复步骤 4 和 5 以进行覆盖。
扩展插件的界面
🌐 Extending a plugin's interface
当 Strapi 应用初始化时,插件、扩展和全局生命周期函数事件按以下顺序发生:
🌐 When a Strapi application is initializing, plugins, extensions and global lifecycle functions events happen in the following order:
- 插件已加载并公开其接口。
./src/extensions中的文件已加载。./src/index.js|ts中的register()和bootstrap()函数被调用。
插件的接口可以在步骤 2(即在 ./src/extensions 内)或步骤 3(即在 ./src/index.js|ts 内)进行扩展。
🌐 A plugin's interface can be extended at step 2 (i.e. within ./src/extensions) or step 3 (i.e. inside ./src/index.js|ts).
如果你的 Strapi 项目是基于 TypeScript 的,请确保 index 文件具有 TypeScript 扩展名(即 src/index.ts),否则它将无法被编译。
🌐 If your Strapi project is TypeScript-based, please ensure that the index file has a TypeScript extension (i.e., src/index.ts) otherwise it will not be compiled.
在扩展文件夹内
🌐 Within the extensions folder
要使用 ./src/extensions 文件夹扩展插件的服务器接口:
🌐 To extend a plugin's server interface using the ./src/extensions folder:
- (可选) 如果
./src/extensions文件夹尚不存在,请在应用根目录下创建该文件夹。 - 创建一个与要扩展的插件同名的子文件夹。
- 创建一个
strapi-server.js|ts文件,以使用 Server API 扩展插件的后端。 - 在此文件中,定义并导出一个函数。该函数接收
plugin接口作为参数,以便可以扩展它。
后端扩展示例
module.exports = (plugin) => {
plugin.controllers.controllerA.find = (ctx) => {};
plugin.policies[newPolicy] = (ctx) => {};
plugin.routes['content-api'].routes.push({
method: 'GET',
path: '/route-path',
handler: 'controller.action',
});
return plugin;
};
strapi-server.js|ts 文件也是你可以通过替换上传插件的 generateFileName() 函数来覆盖图片功能的地方,从而生成自定义图片名称。
🌐 The strapi-server.js|ts file is also where you can override the image function, by replacing the Upload plugin's generateFileName() function so that it generates custom image names.
自定义文件命名逻辑示例
module.exports = (plugin) => {
plugin.services['image-manipulation'].generateFileName = (file) => {
// Example: prefix a timestamp before the generated base name
return `${Date.now()}_${name}`;
};
return plugin;
};
generateFileName() 属于上传插件的 image-manipulation 服务,并期望一个单一的 name: string 参数。
此自定义依赖于内部上传插件服务(image-manipulation)。内部扩展点不是 Strapi 稳定的公共 API 的一部分,可能会在不同版本之间发生变化。
🌐 This customization relies on an internal Upload plugin service (image-manipulation). Internal extension points are not part of Strapi's stable public API and can change between versions.
在注册和引导函数中
🌐 Within the register and bootstrap functions
要在 ./src/index.js|ts 中扩展插件的接口,请使用整个项目的 bootstrap() 和 register() 函数,并通过 getter 以编程方式访问接口。
🌐 To extend a plugin's interface within ./src/index.js|ts, use the bootstrap() and register() functions of the whole project, and access the interface programmatically with getters.
在 ./src/index.js|ts 中扩展插 件内容类型的示例
module.exports = {
register({ strapi }) {
const contentTypeName = strapi.contentType('plugin::my-plugin.content-type-name')
contentTypeName.attributes = {
// Spread previous defined attributes
...contentTypeName.attributes,
// Add new, or override attributes
'toto': {
type: 'string',
}
}
},
bootstrap({ strapi }) {},
};