服务端 API:生命周期(Lifecycle)
页面摘要: 服务端 API 包含 3 个生命周期函数。使用
register()在应用完全初始化之前声明能力,使用bootstrap()在 Strapi 初始化后运行逻辑,使用destroy()在关闭时清理资源。每个函数都接收{ strapi }作为参数。
生命周期函数控制插件服务端逻辑在 Strapi 应用启动和关闭序列中的运行时机。它们与路由、控制器、服务和其他服务端块一起从 服务端入口文件 导出。
在深入阅读本页概念之前,请确保你已经:
- 创建了一个 Strapi 插件,
- 阅读并理解了 Server API 的基础知识。
启动序列
了解每个生命周期的运行时机,有助于你将正确的代码放在正确的位置:

| Phase | What is available in your plugin |
|---|---|
| 2. Register | strapi 对象可用,但数据库尚未初始化,路由也尚未初始化 |
| 4. Bootstrap | 完整运行时:数据库已初始化、路由已初始化、服务与内容类型已加载、其他插件可用 |
| 5. Shutdown | 关闭正在进行中;在此 hook 中,在 Strapi 完成停止之前释放资源 |
每个生命周期函数对每个插件实例调用一次。如果同一插件实例的生命周期被第二次调用(例如在自定义测试中),Strapi 会抛出错误。这不会在正常操作中发生。
register() {#register}
类型: Function
register() 在启动早期运行,在数据库初始化之前,也在路由初始化之前。
使用 register() 来:
- 注册 自定义字段 的服务端部分
- 注册数据库迁移
- 在 Strapi HTTP 服务端上注册服务端中间件(例如
strapi.server.use(...)) - 在 bootstrap 之前扩展另一个插件的内容类型或接口
JavaScript
'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();
});
};
TypeScript
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)、数据库初始化、路由初始化以及 Content API 操作注册之后运行。
使用 bootstrap() 来:
- 用初始数据填充数据库
- 使用
strapi.service('admin::permission').actionProvider.registerMany(...)注册管理面板 RBAC 操作 - 注册定时任务(cron jobs)
- 订阅数据库生命周期事件
- 调用你的插件或其他插件的服务
- 设置需要先注册其他插件的跨插件集成
JavaScript
'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',
},
]);
};
TypeScript
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() 来:
- 关闭外部连接(数据库、消息队列、WebSocket 服务端)
- 清除在
bootstrap()中设置的 interval 或 timeout - 移除在插件生命周期内注册的事件监听器
JavaScript
'use strict';
module.exports = ({ strapi }) => {
// Close an external connection opened in bootstrap()
strapi.plugin('my-plugin').service('queue').disconnect();
};
TypeScript
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();
};
最佳实践
-
保持
register()轻量。 它在完整初始化之前运行。 -
将数据库读/写放在
bootstrap()中。 数据库在 bootstrap 阶段初始化,而不是在 register 期间。任何对strapi.documents()或查询数据库的服务的调用都应放在bootstrap()中。 -
在
bootstrap()中注册管理面板 RBAC 操作。 在该阶段使用strapi.service('admin::permission').actionProvider.registerMany(...)。此时权限服务可用。Content API 操作由 Strapi 在同一阶段自动注册。 -
始终将资源创建与
destroy()配对。 如果你的插件在bootstrap()中打开了连接、注册了全局 interval 或附加了进程监听器,请实现destroy()来清理这些资源。这可以防止在测试和优雅重启期间发生资源泄漏。 -
避免在
register()中建立插件之间的硬依赖。 在注册时,其他插件的注册顺序无法保证。依赖于另一个插件已初始化的跨插件调用应放在bootstrap()中。 -
优先使用服务而非内联逻辑。 将非平凡的 bootstrap 逻辑移入专用的服务方法中(例如
strapi.plugin('my-plugin').service('setup').initialize())。这使生命周期文件保持可读,且逻辑可测试。