Plug-in Independent Dependency Management Document
Overview
The plug-in independent dependency management system solves the problem of dependency package pollution in the traditional plug-in system.package.jsonof the problem. Through dynamic loading, dependency injection and intelligent caching mechanism, completely independent dependency management of plug-ins is realized.
Core Features
✅Independent dependency management
- Plugins can define their own dependency packages without the need to configure them in the main project.
- Supports multiple dependency types: external dependencies, internal dependencies, peer-to-peer dependencies, and optional dependencies.
- Automatic dependency resolution and version management
✅Dynamic loading mechanism
- Dynamic loading of plug-in dependencies at runtime
- CDN external dependency automatic loading
- Local file internal dependency import on demand
- Intelligent cache to avoid repeated loading
✅Dependency Injection System
- Automatically inject dependencies during plug-in initialization
- Support dependency availability check
- Provides a dependency injector interface
✅Degradation and Fault Tolerance
- Optional Dependency Support Downgrade Scenario
- Dependency loading failure does not affect plug-in operation
- Detailed error logs and status reports
Dependency type description
1. Peer-to-peer dependence (Peer Dependencies)
Use the existing dependency packages of the main project to avoid repeated loading.
export const dependencies = {
'vue': '^2.6.0', // 简单字符串配置
'element-ui': '^2.15.0' // 使用主项目的 Element UI
}Features:
- No increase in package volume
- Version compatibility is controlled by the master project
- Fastest loading speed
2. External dependencies (External Dependencies)
Dynamically load third-party libraries from the CDN.
export const dependencies = {
'lodash': {
type: 'external',
version: '^4.17.21',
source: 'https://unpkg.com/lodash@4.17.21/lodash.min.js'
},
'moment': {
type: 'external',
version: '^2.29.4',
source: 'https://unpkg.com/moment@2.29.4/moment.min.js',
fallback: true // 支持降级方案
}
}Features:
- Load on demand to reduce initial package volume
- Support version control
- Network dependency, need to handle loading failure
3. Internal dependencies (Internal Dependencies)
Load the tool module inside the plug-in.
export const dependencies = {
'chart-utils': {
type: 'internal',
version: '^1.0.0',
path: './utils/chart-utils.js'
},
'api-client': {
type: 'internal',
version: '^1.0.0',
path: './services/api-client.js'
}
}Features:
- Plugin Private Tools Module
- Support modular development
- Fast loading speed
4. Optional Dependency (Optional Dependencies)
If not available, it will not affect the plug-in operation.
export const dependencies = {
'echarts': {
type: 'optional',
version: '^5.0.0',
fallback: true
},
'three': {
type: 'optional',
version: '^0.150.0',
fallback: true
}
}Features:
- Enhancements, not required
- Support for downgrading to simple implementation
- Improve plug-in compatibility
Method of use
1. Define plug-in dependencies
In the plug-in'sindex.jsDefine the dependency configuration in:
// 插件依赖配置
export const dependencies = {
// 对等依赖
'vue': '^2.6.0',
'element-ui': '^2.15.0',
// 外部依赖
'lodash': {
type: 'external',
version: '^4.17.21',
source: 'https://unpkg.com/lodash@4.17.21/lodash.min.js'
},
// 内部依赖
'utils': {
type: 'internal',
version: '^1.0.0',
path: './utils/index.js'
},
// 可选依赖
'chart': {
type: 'optional',
version: '^5.0.0',
fallback: true
}
}2. Use the dependency injector.
Receive the dependency injector in the plugin initialization function:
// 插件初始化函数
export async function init(dependencyInjector) {
console.log('插件初始化开始...')
// 获取依赖
const lodash = dependencyInjector.get('lodash')
const utils = dependencyInjector.get('utils')
const chart = dependencyInjector.get('chart')
// 检查依赖是否可用
if (dependencyInjector.has('lodash')) {
console.log('Lodash 可用:', lodash)
// 使用 lodash
window._ = lodash
}
if (dependencyInjector.has('utils')) {
console.log('Utils 可用:', utils)
// 使用内部工具
window.utils = utils
}
if (dependencyInjector.has('chart')) {
console.log('Chart 可用:', chart)
// 使用图表库
window.chart = chart
} else {
console.log('Chart 不可用,使用降级方案')
// 使用简单的 Canvas 替代
}
// 批量注入依赖
dependencyInjector.inject(window, ['lodash', 'utils'])
console.log('插件初始化完成')
}3. Uninstall the plug-in
Clean up dependencies in the plugin unload function:
'''javascript // Plug-in unload function export async function destroy(dependencyInjector) { console.log ('Plugin uninstall started... ')
// Clean up global variables delete window ._ delete window.utils delete window.chart
console.log ('Plugin Uninstall Completed') }
## API 参考
### PluginDependencyManager
#### `loadPluginDependencies(pluginName, dependencies)`
加载插件的所有依赖。
**参数:**
- `pluginName` (string): 插件名称
- `dependencies` (Object): 依赖配置
**返回:** Promise<Object> 加载结果
#### `getPluginDependencies(pluginName)`
获取插件的依赖信息。
**参数:**
- `pluginName` (string): 插件名称
**返回:** Object|null 依赖信息
#### `isDependencyLoaded(pluginName, depName)`
检查依赖是否已加载。
**参数:**
- `pluginName` (string): 插件名称
- `depName` (string): 依赖名称
**返回:** boolean 是否已加载
### PluginDependencyLoader
#### `loadPluginDependencies(pluginName, pluginConfig)`
加载插件依赖并处理结果。
**参数:**
- `pluginName` (string): 插件名称
- `pluginConfig` (Object): 插件配置
**返回:** Promise<Object> 处理结果
#### `createDependencyInjector(pluginName)`
创建依赖注入器。
**参数:**
- `pluginName` (string): 插件名称
**返回:** Object 依赖注入器
### DependencyInjector
#### `get(depName)`
获取指定依赖。
**参数:**
- `depName` (string): 依赖名称
**返回:** any 依赖模块
#### `has(depName)`
检查依赖是否可用。
**参数:**
- `depName` (string): 依赖名称
**返回:** boolean 是否可用
#### `inject(target, depNames)`
批量注入依赖到目标对象。
**参数:**
- `target` (Object): 目标对象
- `depNames` (Array): 依赖名称数组
**返回:** Object 目标对象
## 最佳实践
### 1. 依赖类型选择
```javascript
//✅Recommendation: Use peer dependencies first
export const dependencies = {
'vue': '^ 2.6.0', // peer dependency
element-ui ': '^ 2.15.0 '// peer dependency
}
//✅Recommendation: Large libraries use external dependencies
export const dependencies = {
'lodash ': {
type: 'external ',
version: '^4.17.21 ',
source: 'https://unpkg.com/lodash@4.17.21/lodash.min.js'
}
}
//✅Recommendation: Tool functions use internal dependencies
export const dependencies = {
'utils ': {
type: 'internal ',
version: '^1.0.0 ',
path: './utils/index.js'
}
}
//✅Recommendation: Enhancement using optional dependencies
export const dependencies = {
'chart ': {
type: 'optional ',
version: '^5.0.0 ',
fallback: true
}
}2. 错误处理
export async function init(dependencyInjector) {
try {
// Check key dependencies
if (! dependencyInjector.has('vue')) {
throw new Error('Vue Dependency Unavailable')
}
// Handle optional dependencies
if (dependencyInjector.has('chart')) {
// Use the chart library
this.initChart()
} else {
// Use the downgrade scheme
this.initSimpleChart()
}
} catch (error) {
console.error ('plugin initialization failed: ', error)
// graceful degradation
this.initFallbackMode()
}
}3. 性能优化
//✅Recommendation: Preload common dependencies
await pluginDependencyLoader.preloadCommonDependencies ([
'lodash ',
'Moment ',
'axios'
])
//✅Recommended: Use the cache
const cacheKey =`${pluginName}:${JSON.stringify(dependencies)}`
if (dependencyCache.has(cacheKey)) {
return dependencyCache.get(cacheKey)
}
//✅Recommended: Avoid duplicate loading
if (this.loadingPromises.has(cacheKey)) {
return this.loadingPromises.get(cacheKey)
}故障排除
常见问题
1. 外部依赖加载失败
问题: CDN 依赖无法加载
解决方案:
// Use multiple CDN sources
'lodash ': {
type: 'external ',
version: '^4.17.21 ',
source: 'https://unpkg.com/lodash@4.17.21/lodash.min.js ',
fallback: 'https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js'
}2. 内部依赖路径错误
问题: 内部依赖文件找不到
解决方案:
// Use relative path
'utils ': {
type: 'internal ',
version: '^1.0.0 ',
path: './utils/index.js' // relative to the plug-in root
}3. 对等依赖版本冲突
问题: 插件需要的版本与主项目不兼容
解决方案:
// Use a compatible version range
'vue': '^ 2.6.0', // compatible with version 2.6.x调试技巧
// 1. Check the dependency loading status
console.log ('dependent state: ', pluginDependencyManager.getDependencyStats())
// 2. Check specific plug-in dependencies
console.log ('plugin dependency: ', pluginDependencyLoader.getPluginDependencies (my-plugin))
// 3. Check the dependency injector
const injector = pluginDependencyLoader.createDependencyInjector('my-plugin')
console.log ('Available dependencies: ', Object.keys(injector.getAll()))总结
插件独立依赖管理系统提供了:
- 完全独立:插件依赖不再污染主项目
- 灵活配置:支持多种依赖类型和加载方式
- 智能管理:自动处理依赖解析、加载和缓存
- 容错机制:支持降级方案和错误恢复
- 性能优化:按需加载和智能缓存
通过这个系统,你可以:
- ✅ 开发完全独立的插件
- ✅ 避免依赖包污染主项目
- ✅ 支持插件间的依赖隔离
- ✅ 实现插件的热插拔和动态加载
- ✅ 提供更好的用户体验和开发体验
开始使用插件独立依赖管理,让你的插件系统更加模块化和可扩展!