@ldesign/dynamic-import
v0.0.5
Published
一个功能强大的Node.js动态包管理工具,支持运行时动态导入npm包、自动依赖安装、批量导入、版本控制等功能
Readme
🚀 Dynamic Import Manager
一个功能强大的Node.js动态包管理工具,让你在运行时轻松导入npm包!
✨ 特性亮点
🎯 动态加载 - 运行时动态导入任意npm包,无需预先安装⚡ 自动安装 - 智能检测并自动安装缺失的依赖包 🔄 批量导入 - 支持同时导入多个包,提升效率 📦 版本控制 - 精确控制包版本,避免版本冲突 🎨 导出灵活 - 支持default、named、namespace多种导出方式🛡️ 类型安全 - 完整的TypeScript支持,开发更安心🚀 高性能 - 智能缓存机制,避免重复导入 🔧 易配置 - 支持多种包管理器(默认pnpm)🗂️ 临时安装 - 支持临时安装,自动清理package.json ⚙️ 灵活依赖 - 支持安装到devDependencies或dependencies
📦 安装
# 使用 npm
npm install @ldesign/dynamic-import
# 使用 yarn
yarn add @ldesign/dynamic-import
# 使用 pnpm (推荐)
pnpm add @ldesign/dynamic-import🎯 快速开始
基础用法
import { dynamicImport } from '@ldesign/dynamic-import'
// 动态导入lodash包(默认临时安装到devDependencies)
const { module: lodash } = await dynamicImport('lodash')
console.log(lodash.chunk([1, 2, 3, 4], 2)) // [[1, 2], [3, 4]]
// 指定版本导入,安装到dependencies
const { module: axios } = await dynamicImport('axios', {
version: '1.6.0',
exportType: 'default',
isTemporary: false, // 保留在package.json中
installType: 'prod', // 安装到dependencies
})
const response = await axios.get('https://api.github.com')
// 临时安装(不保留在package.json中)
const { module: chalk } = await dynamicImport('chalk', {
isTemporary: true, // 默认值,安装后自动清理
installType: 'dev', // 默认值,安装到devDependencies
})
console.log(chalk.blue('Hello World!'))高级用法
import { DynamicPackageManager } from '@ldesign/dynamic-import'
// 创建管理器实例
const manager = await DynamicPackageManager.create()
// 批量导入多个包
const result = await manager.importBatch({
packages: [
{ packageName: 'lodash', exportType: 'default' },
{ packageName: 'dayjs', version: '1.11.0' },
{
packageName: 'chalk',
exportType: 'named',
namedExports: ['red', 'blue'],
},
],
parallel: true,
maxConcurrency: 3,
})
console.log(`成功导入 ${result.successful.length} 个包`)
console.log(`失败 ${result.failed.length} 个包`)📚 API 文档
便捷函数
dynamicImport(packageName, options?)
动态导入单个包的便捷函数。
const result = await dynamicImport('package-name', {
version: '1.0.0', // 指定版本
exportType: 'default', // 导出类型: 'default' | 'named' | 'namespace'
namedExports: ['func1'], // 具名导出列表(exportType为'named'时使用)
forceReinstall: false, // 是否强制重新安装
isTemporary: true, // 是否临时安装(默认true,安装后从package.json删除)
installType: 'dev', // 安装类型: 'dev' | 'prod'(默认'dev')
})importFromSpec(packageSpec, exportType?)
从包规范字符串导入包。
// 基础用法
const result = await importFromSpec('[email protected]')
// 作用域包
const result = await importFromSpec('@types/[email protected]', 'namespace')batchImport(packages, options?)
批量导入多个包。
const result = await batchImport(
[
{ packageName: 'lodash', exportType: 'default' },
{ packageName: 'axios', version: '1.6.0' },
],
{
parallel: true, // 是否并行导入
maxConcurrency: 3, // 最大并发数
continueOnError: true, // 出错时是否继续
}
)核心类
DynamicPackageManager
主要的包管理器类,提供完整的动态导入功能。
// 创建实例
const manager = await DynamicPackageManager.create()
const manager = new DynamicPackageManager('pnpm', '/custom/path')
// 导入包
const result = await manager.import({
packageName: 'package-name',
version: '1.0.0',
exportType: 'default'
})
// 批量导入
const batchResult = await manager.importBatch({
packages: [...],
parallel: true
})
// 包管理
await manager.installPackage('package-name', '1.0.0')
await manager.uninstallPackage('package-name')
// 缓存管理
manager.clearAllCaches()
const cacheInfo = manager.getCacheInfo()🎨 使用示例
示例1:动态加载工具库
import { dynamicImport } from '@ldesign/dynamic-import'
async function processData(data: any[]) {
// 动态加载lodash进行数据处理
const { module: _ } = await dynamicImport('lodash')
return _(data)
.filter(item => item.active)
.groupBy('category')
.mapValues(group => group.length)
.value()
}示例2:条件导入不同的包
import { dynamicImport } from '@ldesign/dynamic-import'
async function createLogger(type: 'simple' | 'advanced') {
if (type === 'simple') {
const { module: chalk } = await dynamicImport('chalk', {
exportType: 'named',
namedExports: ['red', 'green', 'blue'],
})
return {
info: (msg: string) => console.log(chalk.blue(msg)),
error: (msg: string) => console.log(chalk.red(msg)),
}
} else {
const { module: winston } = await dynamicImport('winston')
return winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [new winston.transports.Console()],
})
}
}示例3:插件系统
import { DynamicPackageManager } from '@ldesign/dynamic-import'
class PluginSystem {
private manager = await DynamicPackageManager.create()
private plugins = new Map()
async loadPlugin(pluginName: string, version?: string) {
try {
const result = await this.manager.import({
packageName: pluginName,
version,
exportType: 'default',
})
this.plugins.set(pluginName, result.module)
console.log(`✅ 插件 ${pluginName} 加载成功`)
return result.module
} catch (error) {
console.error(`❌ 插件 ${pluginName} 加载失败:`, error.message)
throw error
}
}
async loadPlugins(pluginConfigs: Array<{ name: string; version?: string }>) {
const packages = pluginConfigs.map(config => ({
packageName: config.name,
version: config.version,
exportType: 'default' as const,
}))
const result = await this.manager.importBatch({
packages,
parallel: true,
continueOnError: true,
})
result.successful.forEach(plugin => {
this.plugins.set(plugin.packageName, plugin.module)
})
return {
loaded: result.successful.length,
failed: result.failed.length,
plugins: this.plugins,
}
}
}⚙️ 配置选项
DynamicImportOptions
interface DynamicImportOptions {
packageName: string // 包名
version?: string // 指定版本
exportType?: ExportType // 导出类型
namedExports?: string[] // 具名导出列表
forceReinstall?: boolean // 强制重新安装
installDir?: string // 自定义安装目录
packageManager?: PackageManager // 包管理器类型
}BatchImportOptions
interface BatchImportOptions {
packages: DynamicImportOptions[] // 包配置列表
parallel?: boolean // 是否并行安装
maxConcurrency?: number // 最大并发数
continueOnError?: boolean // 失败时是否继续
}导出类型
'default'- 默认导出(推荐)'named'- 具名导出,需要指定namedExports'namespace'- 命名空间导出,导入整个模块
包管理器支持
'pnpm'- 高性能的npm替代品(默认和推荐)'yarn'- Yarn Package Manager'npm'- Node Package Manager
🔧 高级用法
自定义包管理器
import { DynamicPackageManager } from '@ldesign/dynamic-import'
// 使用特定的包管理器和目录
const manager = new DynamicPackageManager('yarn', '/custom/project/path')
// 或者自动检测(默认优先使用pnpm)
const autoManager = await DynamicPackageManager.create('/custom/path')缓存管理
// 获取缓存信息
const cacheInfo = manager.getCacheInfo()
console.log(`缓存大小: ${cacheInfo.size}`)
console.log(`缓存的包: ${cacheInfo.packages.join(', ')}`)
// 清除特定包的缓存
manager.clearCache('package-name')
// 清除所有缓存
manager.clearAllCaches()
// 预加载包(不导入)
await manager.preloadPackages([
{ name: 'lodash', version: '4.17.21' },
{ name: 'axios', version: '1.6.0' },
])错误处理
import {
DynamicImportError,
PackageInstallError,
ModuleImportError,
} from '@ldesign/dynamic-import'
try {
const result = await dynamicImport('non-existent-package')
} catch (error) {
if (error instanceof PackageInstallError) {
console.error('包安装失败:', error.message)
console.error('包名:', error.packageName)
console.error('退出码:', error.exitCode)
} else if (error instanceof ModuleImportError) {
console.error('模块导入失败:', error.message)
console.error('包名:', error.packageName)
} else if (error instanceof DynamicImportError) {
console.error('动态导入错误:', error.message)
}
}版本控制
// 精确版本
await dynamicImport('lodash', { version: '4.17.21' })
// 版本范围(使用semver)
await dynamicImport('lodash', { version: '^4.17.0' })
await dynamicImport('lodash', { version: '~4.17.20' })
// 最新版本(默认)
await dynamicImport('lodash')
// 强制重新安装特定版本
await dynamicImport('lodash', {
version: '4.17.21',
forceReinstall: true,
})💡 最佳实践
1. 错误处理
始终使用try-catch包装动态导入操作:
async function safeImport(packageName: string) {
try {
return await dynamicImport(packageName)
} catch (error) {
console.error(`导入 ${packageName} 失败:`, error.message)
return null
}
}2. 性能优化
利用缓存机制避免重复导入:
const manager = await DynamicPackageManager.create()
// 第一次导入会安装和缓存
const lodash1 = await manager.import({ packageName: 'lodash' })
// 第二次导入直接使用缓存,速度更快
const lodash2 = await manager.import({ packageName: 'lodash' })3. 批量操作
对于多个包的导入,使用批量操作提升效率:
// ✅ 推荐:批量导入
const result = await batchImport(
[
{ packageName: 'lodash' },
{ packageName: 'axios' },
{ packageName: 'dayjs' },
],
{ parallel: true }
)
// ❌ 不推荐:逐个导入
const lodash = await dynamicImport('lodash')
const axios = await dynamicImport('axios')
const dayjs = await dynamicImport('dayjs')4. 类型安全
充分利用TypeScript类型定义:
import type { DynamicImportResult } from '@ldesign/dynamic-import'
// 指定返回类型
const result: DynamicImportResult<typeof import('lodash')> =
await dynamicImport('lodash')
// 使用泛型
const { module } = await dynamicImport<typeof import('axios')>('axios')❓ 常见问题
Q: 支持哪些Node.js版本?
A: 支持Node.js 16.0.0及以上版本。
Q: 可以在浏览器中使用吗?
A: 不可以,这是一个专为Node.js环境设计的工具,依赖于文件系统和包管理器。
Q: 如何处理包的依赖冲突?
A: 工具会使用指定的包管理器来解决依赖冲突。建议使用pnpm以获得更好的依赖管理。
Q: 导入的包会被永久安装吗?
A: 是的,包会被安装到项目的node_modules目录中。如需清理,可以手动删除或使用包管理器的清理命令。
Q: 支持私有npm仓库吗?
A: 支持,工具会使用当前环境配置的npm registry设置。
Q: 如何调试导入失败的问题?
A: 可以通过捕获错误对象来获取详细的错误信息,包括包名、错误类型和原始错误。
🤝 贡献指南
我们欢迎所有形式的贡献!
开发环境设置
# 克隆仓库
git clone https://github.com/your-username/dynamic-import-manager.git
cd dynamic-import-manager
# 安装依赖
pnpm install
# 运行测试
pnpm test
# 构建项目
pnpm build
# 检查代码质量
pnpm lint提交规范
- 🐛
fix:修复bug - ✨
feat:新功能 - 📝
docs:文档更新 - 🎨
style:代码格式化 - ♻️
refactor:代码重构 - ⚡
perf:性能优化 - ✅
test:测试相关
📄 许可证
本项目采用 MIT 许可证。
🙏 致谢
感谢所有为这个项目做出贡献的开发者!
如果这个项目对你有帮助,请给它一个 ⭐️!
