服务器 API:生命周期
🌐 Server API: Lifecycle
Page summary:
服务器 API 有 3 个生命周期函数。在应用完全初始化之前,使用
register()声明功能;初始化 Strapi 后,使用bootstrap()运行逻辑;关闭时,使用destroy()清理资源。每个函数都接收{ strapi }作为其 参数。
生命周期函数控制插件的服务器端逻辑在 Strapi 应用启动和关闭过程中何时运行。它们与路由、控制器、服务和其他服务器模块一起从服务器入口文件导出。
🌐 Lifecycle functions control when your plugin's server-side logic runs during the Strapi application startup and shutdown sequence. They are exported from the server entry file alongside routes, controllers, services, and other server blocks.
在深入了解本页的概念之前,请确保你已经:
🌐 Before diving deeper into the concepts on this page, please ensure you have:
- 创建了一个 Strapi 插件,
- 已阅读并理解了服务器 API的基础知识
启动序列
🌐 Startup sequence
了解每个生命周期何时运行可以帮助你把正确的代码放在正确的位置:
🌐 Understanding when each lifecycle runs helps you put the right code in the right place:
| 阶段 | 插件中可用的内容 || --- | --- || 2. 注册 | strapi 对象可用,但数据库尚未初始化,路由尚未初始化 || 4. 引导 | 完整运行时:数据库已初始化,路由已初始化,服务和内容类型已加载,其他插件可用 || 5. 关闭 | 正在关闭;在 Strapi 完成停止之前使用此钩子释 放资源 |
每个生命周期函数在每个插件实例上只会被调用一次。如果在同一个插件实例上第二次调用生命周期(例如在自定义测试中),Strapi 会抛出错误。在正常操作下不会发生这种情况。
🌐 Each lifecycle function is called once per plugin instance. If a lifecycle is called a second time on the same plugin instance (for example in custom tests), Strapi throws an error. This does not occur under normal operation.
register()
类型: Function
register() 在启动早期运行,位于数据库初始化和路由初始化之前。
使用 register() 来:
🌐 Use register() to:
- 注册 自定义字段 的服务器端
- 注册数据库迁移
- 在 Strapi HTTP 服务器上注册服务器中间件(例如
strapi.server.use(...)) - 在引导之前扩展另一个插件的内容类型或接口
- JavaScript
- TypeScript
'use strict';
module.exports = ({ strapi }) => {
// Register a server-level middleware early in startup
strapi.server.use(async (ctx, next) => {
ctx.set('X-Plugin-Version', '1.0.0');
await next();
});
};
import type { Core } from '@strapi/strapi';
export default ({ strapi }: { strapi: Core.Strapi }) => {
// Register a server-level middleware early in startup
strapi.server.use(async (ctx: any, next: () => Promise<void>) => {
ctx.set('X-Plugin-Version', '1.0.0');
await next();
});
};
bootstrap()
类型: Function
bootstrap() 在模块生命周期注册(插件/API)、数据库初始化、路由初始化和内容 API 操作注册之后运行。
使用 bootstrap() 来:
🌐 Use bootstrap() to:
- 用初始数据填充数据库
- 使用
strapi.service('admin::permission').actionProvider.registerMany(...)注册管理员 RBAC 操作 - 注册 cron 任务
- 订阅数据库生命周期事件
- 从你的插件或其他插件调用服务
- 设置需要先注册其他插件的跨插件集成
- JavaScript
- TypeScript
'use strict';
module.exports = async ({ strapi }) => {
// Register admin RBAC actions for this plugin
await strapi.service('admin::permission').actionProvider.registerMany([
{
section: 'plugins',
displayName: 'Read',
uid: 'read',
pluginName: 'my-plugin',
},
{
section: 'plugins',
displayName: 'Settings',
uid: 'settings',
pluginName: 'my-plugin',
},
]);
};
import type { Core } from '@strapi/strapi';
export default async ({ strapi }: { strapi: Core.Strapi }) => {
// Register admin RBAC actions for this plugin
await strapi.service('admin::permission').actionProvider.registerMany([
{
section: 'plugins',
displayName: 'Read',
uid: 'read',
pluginName: 'my-plugin',
},
{
section: 'plugins',
displayName: 'Settings',
uid: 'settings',
pluginName: 'my-plugin',
},
]);
};
destroy()
类型: Function
destroy() 在 Strapi 实例关闭时调用。这是可选的。只有在你的插件持有需要显式清理的资源时才实现它。
使用 destroy() 来:
🌐 Use destroy() to:
- 关闭外部连接(数据库、消息队列、WebSocket 服务器)
- 在
bootstrap()中清除间隔或超时 - 移除在插件生命周期内注册的事件监听器
- JavaScript
- TypeScript
'use strict';
module.exports = ({ strapi }) => {
// Close an external connection opened in bootstrap()
strapi.plugin('my-plugin').service('queue').disconnect();
};
import type { Core } from '@strapi/strapi';
export default ({ strapi }: { strapi: Core.Strapi }) => {
// Close an external connection opened in bootstrap()
strapi.plugin('my-plugin').service('queue').disconnect();
};
最佳实践
🌐 Best practices
- 保持
register()轻量化。 它在完全初始化之前运行。 - 使用
bootstrap()进行数据库读写。 数据库在引导阶段初始化,而不是在注册阶段。任何对strapi.documents()的调用或查询数据库的服务都应放在bootstrap()中。 - 在
bootstrap()中注册管理员 RBAC 操作。 在bootstrap()中使用strapi.service('admin::permission').actionProvider.registerMany(...)。这是在权限服务可用时。内容 API 操作在同一阶段由 Strapi 自动注册。 - 始终将资源创建与
destroy()配对。 如果你的插件在bootstrap()中打开连接、注册全局定时器或附加进程监听器,请实现destroy()来清理这些资源。这可以防止在测试和优雅重启期间发生资源泄漏。 - 避免
register()中插件之间的强依赖。 在注册时,其他插件的注册顺序无法保证。依赖于另一个插件已初始化的跨插件调用应放在bootstrap()中。 - 优先使用服务而非内联逻辑。 将非平凡的启动逻辑移入专用的服务方法(例如
strapi.plugin('my-plugin').service('setup').initialize())。这样可以保持生命周期文件的可读性,同时使逻辑易于测试。