Wiki.js扩展开发:自定义模块与插件开发指南
概述
Wiki.js作为现代化的开源Wiki平台,提供了强大的扩展开发能力。通过自定义模块和插件,开发者可以深度定制Wiki.js的功能,满足特定业务需求。本文将详细介绍Wiki.js的扩展开发体系,涵盖认证、存储、编辑器、搜索等各类模块的开发方法。
扩展架构解析
模块类型体系
Wiki.js采用模块化架构,支持多种类型的扩展模块:
模块文件结构
每个模块都遵循标准的文件结构:
模块目录/
├── definition.yml # 模块定义文件
├── module.js # 模块主逻辑
├── config.yml # 配置模板(可选)
└── assets/ # 静态资源(可选)
模块开发实战
1. 认证模块开发
认证模块负责用户身份验证,支持多种认证策略:
// server/modules/authentication/custom/authentication.js
const CustomStrategy = require('passport-custom').Strategy
module.exports = {
init(passport, conf) {
passport.use('custom',
new CustomStrategy(async (req, done) => {
try {
// 自定义认证逻辑
const userData = await authenticateUser(req.body)
if (userData) {
const user = await WIKI.models.users.query().findOne({
email: userData.email,
providerKey: 'custom'
})
if (user) {
done(null, user)
} else {
// 创建新用户
const newUser = await WIKI.models.users.createUser({
email: userData.email,
name: userData.name,
provider: 'custom',
providerKey: 'custom'
})
done(null, newUser)
}
} else {
done(new WIKI.Error.AuthLoginFailed(), null)
}
} catch (err) {
done(err, null)
}
})
)
}
}
对应的模块定义文件:
# definition.yml
key: custom
title: 自定义认证
description: 通过自定义API进行用户认证
author: your-company
logo: /assets/logo.png
color: blue
website: https://your-company.com
isAvailable: true
useForm: true
usernameType: email
props:
apiUrl:
type: string
title: API端点
description: 认证API的URL地址
required: true
apiKey:
type: string
title: API密钥
description: 用于认证的API密钥
required: true
2. 存储模块开发
存储模块用于管理文件存储,支持本地和云存储:
// server/modules/storage/custom/storage.js
const { Writable } = require('stream')
module.exports = {
async activated() {
// 初始化存储客户端
this.client = new CustomStorageClient(this.config)
},
async disabled() {
// 清理资源
await this.client.disconnect()
},
async delete(file) {
await this.client.deleteFile(file.path)
},
async upload(targetPath, file, options = {}) {
const uploadStream = this.client.createWriteStream(targetPath)
const fileStream = fs.createReadStream(file.path)
return new Promise((resolve, reject) => {
fileStream.pipe(uploadStream)
.on('finish', resolve)
.on('error', reject)
})
},
download(file) {
return this.client.createReadStream(file.path)
}
}
3. 编辑器模块开发
编辑器模块提供内容编辑功能:
// server/modules/editor/custom/editor.js
module.exports = {
async render(content) {
// 自定义渲染逻辑
return await this.customRenderer.render(content)
},
async parse(content) {
// 自定义解析逻辑
return await this.customParser.parse(content)
},
getAssets() {
return [
{ type: 'js', src: '/assets/editor.js' },
{ type: 'css', src: '/assets/editor.css' }
]
}
}
扩展模块开发
扩展模块提供通用功能扩展:
// server/modules/extensions/custom/ext.js
module.exports = {
async activated() {
// 注册自定义路由
WIKI.app.get('/api/custom', async (req, res) => {
res.json({ message: '自定义扩展API' })
})
// 注册事件监听器
WIKI.events.on('pageCreated', async (page) => {
await this.handlePageCreation(page)
})
},
async disabled() {
// 清理事件监听器
WIKI.events.removeAllListeners('pageCreated')
},
async handlePageCreation(page) {
// 自定义页面创建处理逻辑
console.log(`新页面创建: ${page.title}`)
}
}
配置管理
模块配置定义
# config.yml
fields:
- key: apiEndpoint
type: string
title: API端点
description: 外部服务的API地址
required: true
- key: apiKey
type: string
title: API密钥
description: 用于认证的API密钥
required: true
encrypted: true
- key: timeout
type: number
title: 超时时间
description: 请求超时时间(毫秒)
default: 5000
min: 1000
max: 30000
环境配置处理
module.exports = {
async activated() {
// 获取配置
this.config = await WIKI.config.getModule('custom')
// 环境变量覆盖
if (process.env.CUSTOM_API_KEY) {
this.config.apiKey = process.env.CUSTOM_API_KEY
}
}
}
错误处理与日志
统一错误处理
module.exports = {
async upload(targetPath, file) {
try {
await this.client.upload(targetPath, file)
} catch (err) {
WIKI.logger.error(`文件上传失败: ${err.message}`, {
module: 'custom-storage',
path: targetPath
})
throw new WIKI.Error.StorageUploadFailed()
}
}
}
自定义日志记录
const { createLogger, format, transports } = require('winston')
module.exports = {
async activated() {
this.logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp(),
format.json()
),
transports: [
new transports.File({
filename: 'logs/custom-module.log'
})
]
})
}
}
性能优化
缓存策略
module.exports = {
constructor() {
this.cache = new Map()
this.cacheTimeout = 300000 // 5分钟
},
async getData(key) {
if (this.cache.has(key)) {
const cached = this.cache.get(key)
if (Date.now() - cached.timestamp < this.cacheTimeout) {
return cached.data
}
}
const data = await this.fetchData(key)
this.cache.set(key, {
data,
timestamp: Date.now()
})
return data
}
}
批量处理
module.exports = {
async processBatch(items) {
const batchSize = 10
const results = []
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize)
const batchResults = await Promise.all(
batch.map(item => this.processItem(item))
)
results.push(...batchResults)
// 添加延迟避免速率限制
await this.delay(100)
}
return results
}
}
测试与调试
单元测试示例
const CustomModule = require('./custom-module')
describe('Custom Module', () => {
let module
beforeEach(() => {
module = new CustomModule()
})
test('should initialize correctly', async () => {
await module.activated()
expect(module.client).toBeDefined()
})
test('should handle upload errors', async () => {
await expect(module.upload('/test', null))
.rejects
.toThrow('Upload failed')
})
})
调试技巧
module.exports = {
async debugMethod() {
// 使用DEBUG环境变量控制调试输出
if (process.env.DEBUG === 'custom-module') {
console.log('调试信息:', this.internalState)
}
// 性能监控
const startTime = Date.now()
await this.expensiveOperation()
const duration = Date.now() - startTime
WIKI.logger.debug(`操作耗时: ${duration}ms`)
}
}
部署与发布
模块打包
创建标准的模块包结构:
custom-module/
├── package.json
├── definition.yml
├── module.js
├── config.yml
├── assets/
│ ├── logo.png
│ └── styles.css
└── README.md
版本管理
{
"name": "wiki-custom-module",
"version": "1.0.0",
"description": "自定义Wiki.js模块",
"wiki": {
"module": "authentication",
"compatibility": "^2.5.0"
},
"dependencies": {
"custom-sdk": "^1.2.0"
}
}
最佳实践
安全性考虑
module.exports = {
async handleRequest(req, res) {
// 输入验证
if (!this.validateInput(req.body)) {
throw new WIKI.Error.ValidationFailed()
}
// SQL注入防护
const safeQuery = this.sanitizeQuery(req.query.search)
// XSS防护
const safeContent = this.sanitizeHtml(req.body.content)
},
sanitizeHtml(html) {
return html.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
}
}
兼容性处理
module.exports = {
constructor() {
this.supportedVersions = ['2.5.0', '2.6.0', '3.0.0']
},
async activated() {
const wikiVersion = WIKI.version
if (!this.supportedVersions.some(v => wikiVersion.startsWith(v))) {
throw new Error(`不支持的Wiki.js版本: ${wikiVersion}`)
}
// 版本特定逻辑
if (wikiVersion.startsWith('3.')) {
this.useNewAPI()
} else {
this.useLegacyAPI()
}
}
}
总结
Wiki.js的扩展开发提供了强大的定制能力,通过模块化架构可以轻松实现各种功能扩展。开发时需要注意:
- 遵循模块规范:严格按照文件结构和接口定义开发
- 错误处理:实现完整的错误处理和日志记录
- 性能优化:合理使用缓存和批量处理
- 安全性:重视输入验证和数据防护
- 兼容性:考虑不同版本的兼容性处理
通过本文的指南,您可以快速上手Wiki.js的扩展开发,构建出功能强大、稳定可靠的自定义模块。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



