開發者指南 外掛開發與深度定製
快速掌握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外掛市場註冊賬號,按照指引提交外掛。需要提供外掛的名稱、描述、版本資訊和構建產物。