开发者指南 插件开发与深度定制
快速掌握NocoBase插件开发和深度定制能力
核心架构:深入了解NocoBase架构设计
插件开发:完整的插件开发流程
深度定制:系统级定制与扩展
🏗️ 核心架构
深入了解NocoBase的架构设计,为插件开发和定制打下基础
架构概览
NocoBase采用模块化架构设计,主要由以下几个核心部分组成:
- 核心模块(Core):提供基础框架和核心功能,如用户认证、权限管理等
- 插件系统(Plugin System):支持通过插件扩展功能,是NocoBase的核心特性
- 数据库抽象层(Database Abstraction):支持多种数据库,提供统一的操作接口
- 前端框架(Frontend):基于React的前端实现,提供可视化配置界面
- API层(API Layer):提供RESTful API,支持前后端分离和第三方集成
插件系统
NocoBase的插件系统是其可扩展性的核心,主要特点包括:
- 模块化设计:每个插件都是一个独立的模块,可以单独安装和卸载
- 依赖管理:插件之间可以声明依赖关系,系统会自动处理加载顺序
- 钩子系统:提供丰富的钩子(hooks),允许插件在特定时机执行代码
- 配置管理:插件可以定义自己的配置项,通过系统界面进行管理
- 前端集成:插件可以同时包含后端逻辑和前端组件,实现完整功能
架构层次
层次结构
🔌 插件开发教程
完整的插件开发流程,从创建到发布
插件开发流程
创建插件
使用NocoBase提供的插件脚手架创建新插件
# 在NocoBase项目根目录执行
npm run create-plugin my-plugin
插件结构
了解插件的基本结构和配置文件
my-plugin/
├── package.json # 插件配置
├── src/
│ ├── server/ # 后端代码
│ ├── client/ # 前端代码
│ └── index.ts # 插件入口
└── README.md # 插件说明
实现后端功能
在server目录中实现后端逻辑
// src/server/index.ts
import { Plugin } from '@nocobase/server';
export class MyPlugin extends Plugin {
async load() {
// 注册API路由
this.app.router.get('/api/my-plugin/hello', async (ctx) => {
ctx.body = { message: 'Hello from my plugin!' };
});
// 注册钩子
this.app.on('beforeLoad', async () => {
// 插件加载前的逻辑
});
}
}
export default MyPlugin;
实现前端功能
在client目录中实现前端组件
// src/client/index.tsx
import React from 'react';
import { Plugin } from '@nocobase/client';
export class MyPluginClient extends Plugin {
async load() {
// 注册前端路由
this.app.router.add('my-plugin', {
path: '/my-plugin',
component: () => My Plugin Page
});
// 注册菜单
this.app.menu.add('my-plugin', {
name: 'My Plugin',
icon: 'Settings',
path: '/my-plugin'
});
}
}
export default MyPluginClient;
配置插件
在package.json中配置插件信息
// package.json
{
"name": "my-plugin",
"version": "1.0.0",
"description": "My NocoBase plugin",
"main": "lib/index.js",
"nocobase": {
"type": "plugin",
"name": "my-plugin",
"title": "My Plugin",
"description": "This is my plugin",
"icon": "Settings"
},
"dependencies": {
"@nocobase/server": "^1.0.0",
"@nocobase/client": "^1.0.0"
}
}
构建和安装
构建插件并安装到NocoBase中
# 构建插件
cd my-plugin
npm install
npm run build
# 安装到NocoBase
cd ..
npm install ./packages/plugins/my-plugin
# 启动NocoBase
npm run dev
🛠️ 深度定制
系统级定制与扩展,满足复杂业务需求
核心模块定制
修改核心功能
通过重写或扩展核心模块的方法,实现功能定制
钩子系统
使用系统提供的钩子,在特定时机执行自定义逻辑
数据库定制
扩展数据库模型,添加自定义字段和关系
前端定制
自定义组件
开发自定义前端组件,替换或扩展默认组件
主题定制
自定义系统主题,包括颜色、字体、布局等
路由定制
自定义前端路由,添加新页面和导航
定制示例
示例1:添加自定义API
// 在插件的server/index.ts中
import { Plugin } from '@nocobase/server';
export class MyPlugin extends Plugin {
async load() {
// 添加自定义API路由
this.app.router.get('/api/custom/hello', async (ctx) => {
// 实现自定义逻辑
const { name } = ctx.query;
ctx.body = {
message: `Hello, ${name || 'world'}!`,
timestamp: new Date().toISOString()
};
});
// 添加需要认证的API
this.app.router.post('/api/custom/protected', this.app.authMiddleware(), async (ctx) => {
// 只有认证用户才能访问
const user = ctx.state.currentUser;
ctx.body = {
message: 'This is a protected API',
user: {
id: user.id,
username: user.username
}
};
});
}
}
export default MyPlugin;
示例2:自定义前端组件
// 在插件的client/components/MyComponent.tsx中
import React from 'react';
import { Button, Card, Typography } from 'antd';
const { Title, Paragraph } = Typography;
export const MyComponent: React.FC = () => {
const [count, setCount] = React.useState(0);
return (
Counter
Current count: {count}
);
};
// 在插件的client/index.tsx中注册
import { Plugin } from '@nocobase/client';
import { MyComponent } from './components/MyComponent';
export class MyPluginClient extends Plugin {
async load() {
// 注册组件
this.app.components.register('MyComponent', MyComponent);
// 添加路由
this.app.router.add('my-plugin', {
path: '/my-plugin',
component: MyComponent
});
}
}
export default MyPluginClient;
📝 最佳实践
插件开发和定制的最佳实践,确保代码质量和可维护性
开发规范
代码规范
- 遵循ESLint和Prettier规范
- 使用TypeScript确保类型安全
- 编写清晰的注释和文档
插件设计
- 单一职责原则,每个插件只做一件事
- 提供合理的默认配置
- 考虑插件的可测试性
性能优化
前端优化
- 使用React.memo和useMemo优化渲染
- 合理使用useCallback缓存函数
- 优化组件结构,避免不必要的重渲染
后端优化
- 使用数据库索引优化查询
- 合理使用缓存减少数据库查询
- 优化API响应,避免返回过多数据
常见问题
Q: 插件开发时如何调试?
A: 使用NocoBase的开发模式,运行npm run dev启动开发服务器,支持热重载。前端可以使用Chrome DevTools调试,后端可以在VS Code中设置断点调试。
Q: 如何处理插件之间的依赖关系?
A: 在插件的package.json中通过dependencies声明依赖关系,NocoBase会自动处理插件的加载顺序。也可以在插件的load方法中检查其他插件是否已加载。
Q: 插件如何访问数据库?
A: 通过this.app.db访问数据库实例,可以使用Sequelize ORM进行数据库操作。例如:const User = this.app.db.getModel('users');
Q: 如何发布插件到插件市场?
A: 首先确保插件符合发布规范,然后在NocoBase插件市场注册账号,按照指引提交插件。需要提供插件的名称、描述、版本信息和构建产物。
开源低代码开发者 · 延伸路径
NocoBase 常与这些平台一起评估