AI辅助编程之NocoBase插件编写:高效实现自定义功能
本文介绍了如何利用AI辅助快速开发NocoBase插件,实现自动隐藏菜单功能。通过官方CLI工具创建标准化插件结构,结合环境检测(URL参数和微前端环境)、样式控制和路由监听等核心模块开发,在不深入掌握系统架构的情况下高效完成定制功能。文章重点展示了插件骨架搭建、环境检测逻辑实现等关键步骤,体现了AI在复杂系统开发中的辅助价值,帮助开发者绕过源码阅读和架构理解的门槛,快速产出符合规范的插件方案。
AI辅助编程之NocoBase插件编写:高效实现自定义功能
在开源软件开发中,开发者常陷入一个困境:想给复杂系统定制功能,却对其架构和源码一知半解。按传统方式,啃文档、扒源码、摸架构一套流程下来,动辄耗时数周甚至数月,效率极低。而借助AI辅助开发,这个难题有了高效解法。本文就以NocoBase的plugin-auto-hide-menu插件开发为例,分享如何在不深钻系统架构的前提下,快速打造高质量自定义插件。
一、项目背景
1.1 NocoBase 简介
NocoBase 是一款基于 Node.js + React 开发的开源无代码/低代码平台,最加分的就是它的插件化架构。简单说,我们想扩展功能不用动核心源码,搞个独立插件就行,既灵活又好维护,不少企业做低代码项目都会优先选它。
1.2 需求场景
这次我们要做的是一个自动隐藏菜单的插件,核心需求很明确,就是在特定场景下把导航元素“藏起来”,具体要满足这几点:
-
嵌入模式适配:只要页面带
?embed=true参数访问,左侧菜单和顶部导航就自动隐身; -
微前端兼容:如果在 wujie 微前端环境里运行,菜单也得乖乖隐藏;
-
实时响应能力:路由切换的时候,能自动检测场景并调整菜单显示状态,体验不脱节;
-
边缘场景处理:打开 Modal 或 Drawer 弹框时,菜单得保持隐藏,不能突然冒出来搞破坏。
1.3 开发挑战
说实话,这次开发的坑还不少,也更能体现传统开发模式的憋屈:
-
NocoBase 2.0 作为企业级系统,光源码文件就有几百个,复杂度拉满;
-
官方文档更偏向基础使用,想搞点高级定制,能参考的内容少得可怜;
-
得同时搞定 React、Ant Design Pro、插件系统好几套技术栈,知识跨度有点大;
-
项目赶时间,根本没功夫逐行啃源码、慢慢摸透逻辑。
1.4 依托源码信息,提升开发精准度
项目中nocobase-src/目录下的NocoBase源码,是提升开发精准度的关键。它能自动定位并匹配相关源码片段,无需手动截取投喂,相当于有了一套完整的“系统知识库”,确保开发方案贴合NocoBase原生架构,而非依赖通用技术常识拼凑。
-
精准匹配核心源码:涉及插件基类、布局控制等需求时,能自动查找官方实现(如插件生命周期、Ant Design Pro布局组件),推导适配方案,避免代码与系统架构冲突;
-
自动对齐类型规范:读取源码中的TypeScript类型声明文件,生成代码时自动贴合类型要求,省去手动核对类型的繁琐工作;
-
适配官方目录规则:通过源码分析NocoBase核心包、官方插件的目录布局,让自定义插件结构贴合官方规范,后续集成更顺畅;
-
借鉴官方开发思路:遇到功能卡点时,自动参考功能相近的官方插件源码,提炼适配NocoBase生态的最佳实践。
小提醒:源码仅用于理解系统逻辑、推导开发方案,所有自定义功能必须放在独立插件目录,严禁修改核心源码,否则会引发版本升级后的兼容性问题。
二、完整开发流程
2.1 第一步:明确需求与目标,转化技术方案
明确需求是高效开发的前提,需求描述越清晰,开发方向越精准,避免模糊表述导致方案偏差。把功能点、适配场景讲透,能快速梳理出对应的技术思路,大幅减少试错成本。
向 AI 提问示例:
我需要开发一个 NocoBase 插件,实现以下功能:
1. 检测 URL 参数 embed=true
2. 检测 wujie 微前端环境
3. 自动隐藏左侧菜单和顶部导航
4. 支持路由变化时实时响应
核心价值:快速将业务需求拆解为环境检测、样式控制、路由监听三大技术模块,提前锁定开发方向,无需反复琢磨整体架构。
2.2 第二步:使用官方工具创建插件,筑牢基础
这一步全程由全局规则驱动,依托官方工具完成,无任何自主发挥空间。提前配置开发规则,约束仅调用NocoBase官方CLI工具创建插件,目录结构完全由CLI自动生成,既杜绝手动搭建的不规范问题,又保证插件结构合规可控。
核心前提:配置全局规则:
# 全局开发规则核心条款(写入项目根目录的 plugin-dev-rule.md)
1. 创建NocoBase插件时,必须调用官方CLI工具,由CLI自动生成目录结构,禁止自主设计、生成目录,禁止手动创建目录结构
2. 插件名固定为@my-project/plugin-auto-hide-menu,严格遵循NocoBase 2.x规范,仅执行CLI调用,不修改插件命名及目录规则
3. CLI命令需适配项目目录,自动指定路径为packages/plugins/@my-project/下,目录生成完全依赖CLI输出
执行逻辑与结果:读取全局开发规则后,仅触发官方CLI工具的调用指令,不参与目录设计、结构规划等操作。插件目录、配置文件均由CLI按NocoBase官方规范生成,全程严格遵循规则执行。
✅ 推荐做法 - 官方 CLI 命令:
# 使用 NocoBase CLI 创建插件
yarn nocobase create-plugin @my-project/plugin-auto-hide-menu
# 或指定完整路径(适配自定义目录结构)
yarn nocobase create-plugin @my-project/plugin-auto-hide-menu \
--path=packages/plugins/@my-project/plugin-auto-hide-menu
❌ 禁止做法 - 手动创建/跳过CLI:
# 避免手动创建目录
mkdir -p packages/plugins/@my-project/plugin-auto-hide-menu
# 禁止跳过CLI工具,直接手动搭建插件结构
官方 CLI 的核心优势:
-
生成的目录结构完全符合 NocoBase 规范,系统能稳稳识别插件;
-
自动配置好 package.json 和构建脚本,不用自己费劲适配;
-
自带 TypeScript 类型声明,不用额外写类型文件;
-
客户端、服务端入口文件一键生成,完美对齐插件生命周期;
-
和当前 NocoBase 版本自动兼容,省了很多适配时间。
官方CLI生成的标准结构:以下目录结构完全由NocoBase官方CLI输出,无任何人工或自主设计干预,确保与官方规范完全一致。
packages/plugins/@my-project/plugin-auto-hide-menu/
├── src/
│ ├── client/
│ │ └── index.tsx # 客户端入口(自动生成)
│ └── server/
│ └── index.ts # 服务端入口(自动生成)
├── package.json # 插件配置(自动生成)
├── client.d.ts # 客户端类型定义(自动生成)
├── client.js # 客户端构建入口(自动生成)
├── server.d.ts # 服务端类型定义(自动生成)
├── server.js # 服务端构建入口(自动生成)
└── README.md # 插件说明(自动生成)
核心原则:提前配置全局规则,AI仅按规则调用官方CLI,目录及文件结构完全由CLI生成,AI不自主发挥、不设计目录,全程依托官方工具保障规范性。
2.3 第三步:核心功能开发
3.1 客户端插件骨架搭建
基于CLI生成的入口文件,搭建插件基础骨架,精准对齐NocoBase插件生命周期规范,避免因对生命周期不熟悉导致功能异常。
import { Plugin } from '@nocobase/client';
export class PluginAutoHideMenuClient extends Plugin {
async afterAdd() {
console.log('🚀 自动隐藏菜单插件已添加');
}
async load() {
console.log('✅ 自动隐藏菜单插件加载中...');
// 核心逻辑入口
this.applyCSSHideStyles(); // CSS样式注入
this.setupRouteListener(); // 路由监听
this.setupModalListener(); // 弹框监听
console.log('✅ 自动隐藏菜单插件加载完成');
}
}
核心价值:精准给出 NocoBase 插件的基类继承方式,理清 afterAdd、load 等生命周期方法的用法,同时预留核心逻辑入口,避免因不懂生命周期导致功能失效。
3.2 环境检测逻辑实现
针对“检测embed参数”和“识别wujie环境”两大需求,可快速生成靠谱的检测逻辑,无需手动查资料、试错验证。
向 AI 提问示例:
如何检测页面是否在 wujie 微前端环境中运行?
如何安全获取 URL 查询参数,适配浏览器兼容性?
AI 生成的检测逻辑:
// 检查 wujie 微前端环境
private checkWujieEnvironment(): boolean {
try {
const checks = {
windowExists: typeof window !== 'undefined',
wujieExists: window?.$wujie !== undefined,
wujieId: window?.['__WUJIE_ID__'],
wujieMount: window?.['__WUJIE_MOUNT__'],
};
console.log('🔍 wujie 环境检测详情:', checks);
// 多维度验证,提升检测可靠性
return checks.wujieExists ||
checks.wujieId !== undefined ||
checks.wujieMount !== undefined;
} catch (error) {
console.warn('⚠️ 检测 wujie 环境时出错:', error);
return false;
}
}
// 检查 URL 中的 embed 参数
private checkEmbedParam(): boolean {
if (typeof window === 'undefined') return false;
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get('embed') === 'true';
}
核心优势:提供多维度检测方案,避免单一条件判断的不稳定性;自带错误捕获机制,就算检测出问题也不会影响整体功能;同时适配SSR场景,防止客户端渲染报错,考虑周全。
3.3 CSS 样式注入:隐藏导航元素
针对NocoBase基于Ant Design Pro的布局特性,可推导精准的CSS选择器与样式方案,确保菜单隐藏效果达标且适配多场景。
向 AI 提问示例:
NocoBase 基于 Ant Design Pro 布局,如何通过 CSS 隐藏左侧菜单和顶部导航?
需确保样式优先级足够,且适配不同布局模式(折叠/展开)。
AI 生成的 CSS 注入逻辑:
private applyCSSHideStyles() {
const style = document.createElement('style');
style.setAttribute('data-auto-hide-menu-styles', 'true');
style.textContent = `
/* 通过 body 自定义属性控制样式切换 */
body[data-menu-hidden="true"] .ant-pro-sider,
body[data-menu-hidden="true"] .ant-layout-sider,
body[data-menu-hidden="true"] aside.ant-layout-sider {
display: none !important;
visibility: hidden !important;
opacity: 0 !important;
z-index: -9999 !important;
position: absolute !important;
left: -9999px !important;
top: -9999px !important;
}
/* 隐藏侧边栏折叠按钮 */
body[data-menu-hidden="true"] .ant-pro-sider-collapsed-button {
display: none !important;
}
/* 隐藏顶部导航栏 */
body[data-menu-hidden="true"] .ant-pro-layout-header,
body[data-menu-hidden="true"] .ant-layout-header {
display: none !important;
height: 0 !important;
}
/* 调整内容区域布局,避免留白 */
body[data-menu-hidden="true"] .ant-layout-content {
margin-left: 0 !important;
margin-top: 0 !important;
width: 100% !important;
}
`;
document.head.appendChild(style);
}
核心优势:覆盖 Ant Design Pro 布局的核心选择器,确保菜单隐藏彻底;通过 body 自定义属性控制样式切换,逻辑清晰且易扩展;叠加多种隐藏方式和 !important 优先级,轻松覆盖系统默认样式。
3.4 路由监听:实时响应 URL 变化
NocoBase作为SPA应用,路由切换不刷新页面,需监听路由变化以重新触发环境检测。可快速生成适配多场景的路由监听方案,省去自主研究的时间。
向 AI 提问示例:
如何在 React SPA 应用中监听路由变化?
需兼容浏览器前进/后退、手动跳转等多种场景,避免漏监。
AI 生成的路由监听逻辑:
private setupRouteListener() {
// 核心:更新 body 自定义属性,控制样式
const updateBodyAttribute = () => {
const hasEmbedParam = this.checkEmbedParam();
const isWujieEnv = this.checkWujieEnvironment();
const shouldHide = hasEmbedParam || isWujieEnv;
if (shouldHide) {
document.body.setAttribute('data-menu-hidden', 'true');
console.log('🎨 菜单已隐藏');
} else {
document.body.removeAttribute('data-menu-hidden');
console.log('🎨 菜单已显示');
}
};
// 初始化时执行一次
updateBodyAttribute();
// 监听浏览器前进/后退事件
window.addEventListener('popstate', () => {
setTimeout(updateBodyAttribute, 100); // 延迟执行,避免路由切换时序问题
});
// 监听 SPA 路由变化(适配 React Router 隐式跳转)
let lastUrl = window.location.href;
const checkUrlChange = () => {
if (lastUrl !== window.location.href) {
lastUrl = window.location.href;
setTimeout(updateBodyAttribute, 100);
}
};
// 通过 MutationObserver 监听 DOM 变化,间接捕获路由切换
const observer = new MutationObserver(checkUrlChange);
observer.observe(document.body, {
childList: true,
subtree: true
});
}
核心优势:提供多重监听方案,兼顾浏览器前进后退、SPA内部路由跳转等场景,无漏监问题;100毫秒延迟设计,完美规避路由切换与样式更新的时序冲突;用 MutationObserver 兜底,保障功能稳定性。
2.4 第四步:边缘情况处理——弹框样式兼容
开发完成后测试发现,打开Ant Design的Modal或Drawer弹框时,系统会调整DOM结构与样式层级,导致已隐藏的菜单重新显示。针对这一边缘问题,可快速定位原因并生成解决方案。
向 AI 提问示例:
在 Ant Design 中,打开 Modal 或 Drawer 后,之前通过 CSS 隐藏的菜单会重新显示,如何解决?
需确保弹框打开期间,菜单始终保持隐藏状态。
问题 分析与解决方案:
问题根源很明确——Modal/Drawer 会给 body 追加样式,还会调整 DOM 层级,导致之前的隐藏样式被覆盖。解决方案简单有效:用 MutationObserver 监听弹框变化,一旦检测到弹框打开/关闭,重新应用一次隐藏样式即可。
private setupModalListener() {
const modalObserver = new MutationObserver((mutations) => {
let hasModalChange = false;
mutations.forEach((mutation) => {
// 检测弹框遮罩层添加/移除
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
const element = node as Element;
if (element.classList.contains('ant-modal-mask') ||
element.classList.contains('ant-drawer-mask')) {
hasModalChange = true;
}
}
});
}
// 检测 body 样式变化(Drawer 会设置 overflow: hidden)
if (mutation.attributeName === 'style' && mutation.target === document.body) {
hasModalChange = true;
}
});
if (hasModalChange) {
console.log('🔍 检测到弹框变化,重新应用隐藏样式');
setTimeout(() => this.reapplyHideStyles(), 100);
}
});
// 监听 body 及其子元素的变化
modalObserver.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['class', 'style']
});
}
// 重新应用隐藏样式,覆盖弹框带来的样式变更
private reapplyHideStyles() {
const shouldHide = this.checkEmbedParam() || this.checkWujieEnvironment();
if (shouldHide) {
document.body.setAttribute('data-menu-hidden', 'true');
// 直接操作 DOM 元素,强制隐藏
const elementsToHide = document.querySelectorAll(`
.ant-pro-sider,
.ant-layout-sider,
.ant-pro-sider-collapsed-button
`);
elementsToHide.forEach((element) => {
const htmlElement = element as HTMLElement;
htmlElement.style.setProperty('display', 'none', 'important');
htmlElement.style.setProperty('visibility', 'hidden', 'important');
});
}
}
2.5 第五步:服务端插件实现
本次插件核心逻辑虽在客户端,但NocoBase要求插件必须配套服务端入口文件才能正常加载。可生成极简版本的服务端代码,满足官方规范的同时,预留后续扩展空间。
import { Plugin } from '@nocobase/server';
export class PluginAutoHideMenuServer extends Plugin {
async afterAdd() {
console.log('🚀 自动隐藏菜单插件服务端已添加');
}
async load() {
console.log('✅ 自动隐藏菜单插件服务端加载完成');
// 预留扩展入口,以后想加配置管理、权限控制等服务端逻辑都能在这加
}
}
export default PluginAutoHideMenuServer;
2.6 第六步:配置与文档补全
功能开发完成后,同步完善配置文件与说明文档,无需手动逐行整理,兼顾规范性与易用性。
AI 生成的 package.json 关键配置:
{
"name": "@my-project/plugin-auto-hide-menu",
"version": "0.8.0",
"main": "dist/server/index.js",
"peerDependencies": {
"@nocobase/client": "2.x",
"@nocobase/server": "2.x"
}
}
同时可生成完整的 README.md,包含功能说明、使用方法、注意事项,后续交接给同事或者自己复盘时,都能快速理清插件逻辑,降低维护成本。
三、高效开发的优势与关键技巧
3.1 核心优势
-
效率直接拉满:不用逐行啃源码、死磕文档,可快速对齐规范、生成代码、排查问题,原本要几周的开发活,1天就能搞定;
-
补全知识盲区:不管是 NocoBase 插件生命周期,还是 MutationObserver 用法,都能快速掌握实现逻辑与原理,边开发边积累经验;
-
自带最佳实践:生成的代码天然包含类型安全、错误处理、日志输出等细节,比手动编写更规范,后续维护成本更低;
-
排障快人一步:遇到弹框样式冲突这种边缘问题,能快速定位原因并给出解决方案,不用反复调试、盲目试错。
3.2 关键技巧
1. 提前定好开发规则,规避偏差
核心是在项目根目录的plugin-dev-rule.md文件中,划定明确的开发边界与约束,比如仅允许调用官方CLI创建插件、目录结构完全由工具生成,从根源上避免开发偏差。
# NocoBase 插件开发规则
## 核心要求
1. 必须用官方 CLI 创建插件,目录及文件结构完全由CLI自动生成,仅调用CLI,禁止自主设计、生成目录,禁止手动创建目录结构
2. 禁止修改 nocobase-src 核心源码,所有功能放独立插件目录(目录由CLI生成)
3. 代码需兼容 TypeScript 5.1、React 18,对齐 NocoBase 2.x 规范,按规范生成代码,不自主变更规则
## 源码使用边界
1. 可读取 nocobase-src 目录下源码,用于推导代码实现方案,但禁止生成修改核心源码的代码
2. 仅执行规则内指令(如调用CLI、生成业务代码),不做任何超出规则的自主发挥(含目录设计、规范变更等)
2. 提问要精准,别让 AI 猜
模糊描述只会导致方案偏差,一定要说清技术栈、版本和具体需求,才能得到直达痛点的方案。
❌ 不好的提问:“帮我隐藏菜单”
✅ 好的提问:“基于 NocoBase 2.0 + React 18,开发插件实现:URL 带 ?embed=true 或在 wujie 环境中时,自动隐藏左侧菜单和顶部导航,路由切换时要实时响应。”
3. 迭代优化,别追求“一步到位”
不用追求一步生成完美代码,分轮次优化更高效:先实现基础功能,测试后反馈问题(比如弹框冲突),再针对性修复,逐步打磨细节。
4. 代码要验证,别直接复制粘贴
生成的代码虽靠谱,但也要结合实际场景测试,比如在不同浏览器、不同路由场景下验证,确保功能稳定,必要时根据测试结果微调代码。
四、实际效果与经验总结
4.1 最终实现效果
这款插件最终完美落地了所有需求,不管是 embed 参数模式、wujie 微前端环境,都能精准隐藏菜单;路由切换、弹框打开时,菜单状态也能稳定保持,没有出现样式错乱、响应延迟的问题。而且代码类型安全、结构清晰,后续想加新规则(比如按角色隐藏菜单)也很容易扩展。
4.2 经验总结
这次开发最大的感受是:高效工具能帮我们“减负”,把啃源码、查文档、写样板代码这些繁琐活包揽下来,让我们聚焦在需求理解、方案决策、功能验证等核心工作上。
但也要认清工具的局限性:它对项目专属规范、版本差异的敏感度不足,复杂业务逻辑仍需人工设计。因此最佳模式是“工具做执行,人做决策”,用规则约束执行过程,用测试验证最终结果,最大化提升开发效率。基于本次经验,后续同类NocoBase插件开发,均可沿用这套“定规则、靠工具、重验证”的思路,形成可复用的开发范式。
五、附录:完整代码结构
5.1 插件目录结构
packages/plugins/@my-project/plugin-auto-hide-menu/
├── src/
│ ├── client/
│ │ └── plugin.tsx # 客户端核心实现
│ ├── server/
│ │ └── plugin.ts # 服务端实现
│ └── locale/ # 多语言支持
│ ├── zh-CN.json
│ └── en-US.json
├── package.json # 插件配置
├── README.md # 使用文档
└── FEATURES.md # 功能说明
5.2 项目整体结构
my-nocobase-app/
├── nocobase-src/ # NocoBase 源码(可读取用于推导方案)
│ └── nocobase-2.0.0-alpha.56/
│ ├── packages/core/ # 核心包
│ └── packages/plugins/@nocobase/ # 官方插件
├── packages/plugins/@my-project/ # 自定义插件目录
│ └── plugin-auto-hide-menu/ # 本文插件
├── plugin-dev-rule.md # 开发规则约束文件
└── 项目配置文件...
总的来说,借助高效开发方式实现NocoBase插件,不仅快速落地了需求,还摸清了插件开发的核心逻辑、沉淀了可复用的思路。希望本文能帮到更多想快速上手开源系统定制开发的同学,用好工具、定好规则,少走弯路、高效产出高质量插件。
更多推荐


所有评论(0)