恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
NocoBase 服务端插件(Server Plugin)开发指南:Plugin 基类、生命周期钩子与 this.app 应用上下文
首页
资讯中心
/
NocoBase 服务端插件(Server Plugin)开发指南:Plugin 基类、生命周期钩子与 this.app 应用上下文
NocoBase 服务端插件(Server Plugin)开发指南:Plugin 基类、生命周期钩子与 this.app 应用上下文
发布时间:2026/9/17 4:54:02
NocoBase 服务端插件Server Plugin开发指南Plugin 基类、生命周期钩子与 this.app 应用上下文【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobaseNocoBase 采用微内核 插件化架构服务端插件Server Plugin是扩展服务端能力注册接口、监听数据库事件、定义权限、调度任务等的主要方式。本文以服务端插件入口文件src/server/plugin.ts为中心系统讲解Plugin基类结构、afterAdd/beforeLoad/load/install等生命周期钩子的执行时机与源码级调度原理并结合this.app上挂载的 logger、db、resourceManager、acl、pm 等成员说明插件如何与系统各模块协作。读完本文你将能独立编写一个结构规范、生命周期调用正确的 NocoBase 服务端插件。服务端插件的定位与文件约定在 NocoBase 中服务端插件是扩展服务端功能的主要方式。插件包的src/server/目录下约定存放服务端代码其中src/server/plugin.ts或src/server/index.ts—— 插件入口导出继承自nocobase/server的Plugin子类src/server/collections/—— 数据表定义目录插件加载时会通过db.import()自动导入见 插件类源码 中的loadCollections()src/server/migrations/—— 数据迁移脚本目录升级时自动加载见loadMigrations()plugin.ts。关于插件骨架的完整目录结构可以参考 编写第一个插件其中src/server/plugin.ts正是本节所述服务端插件入口。插件类基础结构一个最基本的服务端插件类如下摘自 关联文档import { Plugin } from nocobase/server; export class PluginHelloServer extends Plugin { async afterAdd() {} async beforeLoad() {} async load() {} async install() {} async afterEnable() {} async afterDisable() {} async remove() {} async handleSyncMessage(message: Recordstring, any) {} static async staticImport() {} } export default PluginHelloServer;从源码看Plugin是一个抽象基类packages/core/server/src/plugin.ts#L44它实现了PluginInterface包含beforeLoad、load()、getName()并内置了app、options等字段export interface PluginInterface { beforeLoad?: () void; load(); getName(): string; } export abstract class PluginO any implements PluginInterface { options: any; app: Application; ... }所有生命周期方法在基类中都有空实现如afterAdd() {}、async load() {}子类只需按需覆写无需调用super。此外基类还提供了若干非空实现的辅助能力详见下文「插件类的隐藏能力」一节。插件实例由PluginManager统一创建new P(createAppProxy(this.app), options)plugin-manager.ts#L358构造时会将应用实例代理和插件元信息name、packageName、version、enabled、installed、isPreset等注入this.app与this.options这也是插件内部可以直接使用this.app和this.name的原因。生命周期方法详解插件的生命周期方法按固定顺序执行每个方法都有明确的执行时机与用途生命周期方法执行时机说明staticImport()插件加载前类的静态方法在跟应用或插件状态无关的初始化阶段执行用于不依赖插件实例的初始化工作。afterAdd()插件被添加到 PluginManager 后立即执行此时插件实例已创建但并非所有插件都已初始化完成可以做一些基础的初始化。beforeLoad()在所有插件的load()之前执行此时已经能拿到所有已启用的插件实例。适合注册数据库模型、监听数据库事件、注册中间件等准备工作。load()插件加载时执行所有插件的beforeLoad()执行完毕后才会开始执行load()。适合注册资源、API 接口等核心业务逻辑——比如通过resourceManager注册自定义 REST API。注意load()阶段数据库还没有完成同步不能执行数据库查询或写入操作——数据库操作应放在install()或请求处理函数中。install()插件首次激活时执行只在插件第一次被启用时执行一次通常用于初始化数据库表结构、插入初始数据等安装逻辑。如果后续版本需要变更表结构或迁移数据应该用 Migration 升级脚本 来处理。afterEnable()插件被启用后执行每次插件被启用时都会执行可以用来启动定时任务、建立连接等。afterDisable()插件被禁用后执行可以用来清理资源、停止任务、关闭连接等。remove()插件被删除时执行用于编写卸载逻辑比如删除数据库表、清理文件等。handleSyncMessage(message)多节点部署时的消息同步应用运行在多节点模式下时用于处理从其他节点同步过来的消息。staticImport()与应用状态无关的静态初始化staticImport()是Plugin类上的静态方法不依赖插件实例。NocoBase 通过runPluginStaticImports()packages/core/server/src/run-plugin-static-imports.ts#L13在应用启动早期扫描所有插件包逐个调用const plugin await importModule(packageName); if (plugin plugin.staticImport) { await plugin.staticImport(); }从源码结构看它适合做环境探测、全局配置注入等不依赖应用上下文的工作且单个插件的失败不会阻断其他插件catch后continue。afterAdd()加入 PluginManager 后立即触发在 PluginManager.addOrThrow() 中插件实例创建后会立刻执行await instance.afterAdd()。注意此时应用尚未进入加载流程其他插件可能还未初始化因此这里只能做插件自身的轻量准备。beforeLoad() 与 load()应用启动时的两阶段加载PluginManager.load()plugin-manager.ts#L428-L511将加载拆成两个循环第一轮遍历所有已启用插件依次执行plugin.beforeLoad()第二轮再次遍历依次执行plugin.loadCollections()→plugin.loadAI()→plugin.load()并将plugin.state.loaded置为true同时向外广播beforeLoadPlugin/afterLoadPlugin应用事件。这意味着beforeLoad()阶段你拿到的所有已启用插件实例都处于可用状态可以安全地在beforeLoad()里读取其他插件实例如this.app.pm.get(xxx)而load()则专注于注册资源、接口等业务逻辑。文档明确提示load()阶段数据库尚未同步不要在此阶段执行数据库查询或写入这类操作应放到install()或请求处理函数中。install()仅首次激活执行PluginManager.install()plugin-manager.ts#L513-L554在插件启用流程中先执行await this.app.db.sync()完成数据库同步再对未安装的插件执行plugin.install(options)随后标记installed true并广播beforeInstallPlugin/afterInstallPlugin事件。源码中InstallOptions支持cliArgs、clean、force、sync等选项plugin-manager.ts#L57-L62。因此install()是初始化表结构、插入种子数据的正确位置表结构或数据的后续演进则交由 Migration 数据迁移 处理。afterEnable() / afterDisable() / remove()在PluginManager.enable()plugin-manager.ts#L556-L688中启用插件的完整链路为beforeLoad() → loadCollections() → loadAI() → load() → beforeEnable() → db.sync() → install()未安装时→ afterEnable()其中afterEnable()每次启用都会触发适合启动定时任务、建立外部连接同时基类还预留了beforeEnable()、beforeDisable()、afterDisable()、beforeRemove()、afterRemove()等对称钩子plugin.ts#L127-L139。disable()流程会先广播beforeDisablePlugin事件并执行plugin.beforeDisable()再执行plugin.afterDisable()清理资源remove()则负责卸载逻辑如删除数据表、清理文件底层通过applicationPlugins仓库记录删除实现plugin-manager.ts#L737-L772。handleSyncMessage()多节点消息同步基类提供了成对的方法plugin.ts#L141-L152handleSyncMessage(message)—— 接收并处理其他节点同步过来的消息sendSyncMessage(message, options?)—— 通过this.app.syncMessageManager.publish(this.name, message, options)将消息发布给其他节点。只有应用以多节点模式运行时才需要关注这两个方法。执行顺序说明结合上文生命周期方法的典型执行流程如下静态初始化阶段staticImport()应用启动阶段afterAdd()→beforeLoad()→load()插件首次启用阶段afterAdd()→beforeLoad()→load()→install()插件二次启用阶段afterAdd()→beforeLoad()→load()插件禁用阶段禁用插件时执行afterDisable()插件删除阶段删除插件时执行remove()需要补充说明的是启用/禁用流程中的beforeEnable()/beforeDisable()分别先于afterEnable()/afterDisable()执行源码见 plugin-manager.ts#L630-L632 与 plugin-manager.ts#L704-L706且启用流程会在install()之前调用db.sync()这也是install()中能安全建表的原因。此外多插件启用时PluginManager会依据各插件package.json的peerDependencies做拓扑排序保证依赖插件先加载plugin-manager.ts#L1191-L1203。app 及相关成员插件扩展能力的核心入口在插件开发中通过this.app可以访问应用实例提供的各种 API——这是插件扩展功能的核心入口。app对象包含了系统的各个功能模块你可以在插件的生命周期方法中使用它们。app 成员列表成员名称类型/模块主要用途loggerLogger记录系统日志支持 info、warn、error、debug 等级别。详见 Logger 日志dbDatabaseORM 层操作、模型注册、事件监听、事务控制等。详见 Database 数据库resourceManagerResourceManager注册和管理 REST API 资源与操作处理器。详见 ResourceManager 资源管理aclACL定义权限、角色和资源访问策略。详见 ACL 权限控制cacheManagerCacheManager管理系统级缓存支持 Redis、内存缓存等多种后端。详见 Cache 缓存cronJobManagerCronJobManager注册和管理定时任务支持 Cron 表达式。详见 CronJobManager 定时任务i18nI18n多语言翻译和本地化。详见 I18n 国际化cliCLI注册自定义命令扩展 NocoBase CLI。详见 Command 命令行dataSourceManagerDataSourceManager管理多个数据源实例及其连接。详见 DataSourceManager 数据源管理pmPluginManager动态加载、启用、禁用、删除插件管理插件间的依赖关系。:::tip 提示各个模块的详细用法请参考对应的文档章节。:::源码视角基类内置的快捷成员Plugin基类实际上已经为最常用的几个成员提供了只读 getterplugin.ts#L68-L109插件内可以直接使用而无需经this.app中转this.db—— 等价于this.app.db数据库访问入口this.pm—— 等价于this.app.pm插件管理器this.ai—— 等价于this.app.aiManagerAI 能力入口this.log—— 基于应用 logger 按当前插件名module: this.name派生的子 logger日志会自动带上插件标识this.name/this.enabled/this.installed/this.isPreset—— 分别对应插件名、启用状态、安装状态、是否预置。同时基类还提供createLogger(options)用于创建独立命名的 loggerplugin.ts#L115-L117以及t(key, options)方法它会以插件的packageName作为命名空间调用app.i18n.t便于插件做多语言文案plugin.ts#L272-L274。插件类的隐藏能力约定优于配置的自动加载除了生命周期钩子Plugin基类还内置了几个自动化能力理解它们能帮你写出更精简的插件loadCollections()plugin.ts#L196-L209插件加载时自动扫描server/collections目录通过this.db.import({ directory, from: packageName })导入数据表定义。也就是说用文件方式定义的数据表无需在代码里手动注册。loadMigrations()plugin.ts#L169-L183自动扫描server/migrations目录按beforeLoad/afterSync/afterLoad三个批次交给PluginManager汇总执行见 loadPresetMigrations 与 loadOtherMigrations。loadAI()plugin.ts#L214-L263自动扫描插件内的ai/目录加载 AI Tools、MCP Server、Skills 与 AI Employees——NocoBase 作为 AI 无代码平台插件可以直接通过目录约定暴露 AI 能力。upgrade()升级时执行与install()配合完成版本演进install()只做首次安装之后的表结构/数据变更请走 Migration 数据迁移。这些方法的典型调用时机可从 PluginManager.load() 中看到每个插件在load()前都会先执行loadCollections()与loadAI()。小结与进一步阅读服务端插件开发的核心可以概括为三件事在src/server/plugin.ts中继承nocobase/server的Plugin基类覆写生命周期钩子遵循各钩子的执行时机静态初始化用staticImport()加载阶段用beforeLoad()/load()数据初始化用install()启停清理用afterEnable()/afterDisable()卸载用remove()通过this.app或基类快捷成员this.db、this.pm、this.log等与系统各模块协作并在load()阶段完成资源、接口、权限的注册。建议进一步阅读以下文档继续深入服务端开发概述 — 服务端各模块的总览和导航Collections 数据表 — 用代码定义或扩展数据表结构Database 数据库 — CRUD、Repository、事务与数据库事件Migration 数据迁移 — 插件升级时的数据迁移脚本Event 事件 — 应用级和数据库级的事件监听与处理ResourceManager 资源管理 — 注册自定义 REST API 和操作编写第一个插件 — 从零开始创建一个完整的插件Logger 日志 — 记录系统日志ACL 权限控制 — 定义权限和访问策略Cache 缓存 — 管理系统级缓存CronJobManager 定时任务 — 注册和管理定时任务I18n 国际化 — 多语言翻译Command 命令行 — 注册自定义 CLI 命令DataSourceManager 数据源管理 — 管理多个数据源【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考