当前位置: 首页 > news >正文

Electron 内置 npm 方案:打造无需 Node.js 环境的插件安装器

介绍

Dubbo-Desktop-Manager (简称 ddm)是我开发的 app,最早是用来管理测试 dubbo 框架服务的,现在的方向是基于npm仓库的开放插件平台。

目前已经内置的 dubbo 插件能力
多注册中心:zookeeper、nacos、etcd、dubbo-admin、dubbo-admin相同协议的服务
服务管理:提供者列表、消费者列表、 服务启用、服务禁用、编辑配置
服务测试:服务测试(目前已支持Telnet、dubbo、http 等协议)、invoke命令生成、参数填充、响应对比

为什么要内置 npm

原来 ddm 是All in One软件包。哪怕只改一个小功能,用户也得重新下载完整安装包。
用户都是很“懒”的:旧版本能用,就不想重新下载安装。加上没“给果子交钱”,没有经过 Apple 签名和公证,macOS 安装时困难重重。

所以我把软件升级为插件模式:app 只提供稳定的宿主能力,Dubbo 等功能由插件实现。插件可以独立安装和升级,体积小,也不用每次更新功能都重新发布本体。

插件包使用 npm 分发很合适。它已经解决了发布、版本、依赖和镜像等问题,但新的问题也随之出现:怎样执行npm install安装插件呢?

从 PicGo 的spawn方案开始

做插件系统前,我先阅读了 PicGo 作者 MARKSZ 的 Electron 系列博客,之后又研究了 PicGo 和 PicGo Core 的源码。它们对我的插件系统帮助很大,在此特别感谢 PicGo 作者。

PicGo Core 使用cross-spawn启动系统 npm:

constnpm=spawn('npm',args,{cwd:pluginDirectory})

我最初也尝试了这种方式。它简单、完整,但依赖用户安装 Node.js/npm。

ddm的未来定位是任何人可用易用的插件工具平台,未必他们会正确的安装Node.js,所以这个方案不符合我们的要求。

尝试 npm 6 的编程接口

我后续又了解到,npm 6 可以作为项目依赖直接调用:

importnpmfrom'npm'npm.load(config,err=>{npm.commands[command](modules,callback)})

这种方案不依赖系统 npm,但只能配合很低版本的 npm 使用。低版本 npm 功能不足,部分插件安装后无法正常使用。

后来我看到 Rubick 在 de0e9ed8 中删除了同样的 npm 依赖调用,改为cross-spawn,让用户自行安装 Node.js。我和 Rubick 作者交流了一下,确认原因同样是低版本 npm 的限制:

阅读 npm 8 源码

既然npm6可用,那么npm8也应该是可以的,我开始查看npm@8.19.4的源码。

npm 8 直接执行require('npm')会进入根index.js,并抛出:

The programmatic API was removed in npm v8.0.0

但继续查看源码可以发现,npm CLI 仍然是运行在 Node.js 上的 JavaScript 程序,核心Npm类位于lib/npm.js

Electron 主进程就是 Node.js。因此我的最终方案是:把完整的 npm 8 打进应用,绕过根index.js,直接加载lib/npm.js,然后调用load()exec()

项目固定 npm 版本并通过 Electron Builder 复制完整目录:

{"dependencies":{"npm":"8.19.4"},"build":{"extraResources":["./node_modules/npm"]}}

NpmUtils 完整实现

NpmUtils负责加载内置 npm、指定安装目录、选择镜像并转发安装日志:

// 开发和生产环境使用不同的 npm 路径:constAPPLICATION_NPM_PATH_PREFIX=IS_DEVELOPMENT?path.join(process.cwd(),'node_modules/npm/'):path.join(process.resourcesPath,'node_modules/npm/')classNpmUtils{asyncexecCommand(command,args,where){if(!command){thrownewError('command is a must');}process.argv[0]=''process.argv[1]='dist_electron'process.argv[2]=commandfor(leti=0;i<args.length;i++){process.argv.push(args[i]);}constNpm=require(`${APPLICATION_NPM_PATH_PREFIX}/lib/npm.js`)classMyNpmextendsNpm{constructor(localPrefix){super()this.localPrefix=localPrefix;}/** 安装依赖时会修改title,可能会影响应用的title,所以重写忽略 */settitle(t){}}constnpm=newMyNpm(where)conststdoutWrite=process.stdout.write;conststderrWrite=process.stderr.write;try{process.stdout.write=(...msg)=>{npm.output(...msg)}process.stderr.write=(...msg)=>{npm.outputError(...msg)}awaitnpm.load()// 可以设置更快的仓库npm.config.set('registry','https://registry.npmmirror.com/')constcmd=npm.argv.shift()awaitnpm.exec(cmd,npm.argv)}finally{process.stdout.write=stdoutWrite;process.stderr.write=stderrWrite;}returnnpm.message;}}exportdefaultnewNpmUtils();

使用案例

安装插件:

awaitnpmUtils.execCommand('install',['ddm-plugin-dubbo-support@1.0.0','--loglevel','info'],pluginDirectory)

卸载插件:

awaitnpmUtils.execCommand('uninstall',['ddm-plugin-dubbo-support','--loglevel','info'],pluginDirectory)

真实代码参见:
PluginInstaller.js
NpmUtils.js

http://www.jsqmd.com/news/1252114/

相关文章:

  • 2026年7月广州别墅电梯/广州电梯实力厂家推荐几家_广州市永恒电梯有限公司 - 品牌宣传支持者
  • serpbase + Pinecone 向量数据库完整集成
  • Velprium时间工作空间:开发者时间管理与效率提升实战指南
  • Node.js与Vue.js实战:RSA非对称加密在登录场景下的应用与优化
  • 2026年7月外贸品牌出海/济南外贸培训咨询公司哪家靠谱_深圳德诺跨境贸易有限公司 - 行业平台推荐
  • 掌握一些底层的硬件知识,对于深层次理解 C++ 的运行机制(如指针、内存布局、多线程同步、性能优化等)有巨大的帮助
  • C++20四大核心特性深度解析:概念、范围、协程与模块实战指南
  • 2026株洲漏水检测维修本地口碑榜TOP5权威推荐-专业仪器精准测漏-正规防水补漏公司推荐:卫生间/厨房/屋顶/阳台/外墙渗漏水检测师傅上门 - 安佳防水
  • 株洲本地防水补漏精选TOP5推荐:正规漏水检测维修公司上门师傅推荐:厕所/棚顶/屋面/飘窗/阳台/地下室/厨房渗漏水精准测漏维修(2026最新) - 即刻修防水
  • 验证码识别技术:深度学习方案与工程实践
  • SLA稀疏线性注意力机制在视频生成中的高效应用
  • 制造业数字化转型:智慧工厂解决方案与实施策略
  • VC++绘图软件MyDraw:从GDI+到Direct2D的架构设计与性能优化
  • Unity RPG角色动画状态机:从原理到实战的Mecanim系统详解
  • 别急着把 PDF 交给 Agent:MCP 解析网关才是知识库上线前的胜负手
  • 基于YOLOv8的食品检测系统开发与优化实践
  • OmniTalker:阿里开源唇形同步技术解析与实践
  • 真力时中国售后服务中心|地址及售后热线权威信息声明(2026年7月最新) - 亨得利官方服务中心
  • 从芯片手册到真实性能:ADS8353/7853 ADC评估板硬件设计与软件实战指南
  • MSP432硬件开发工具选型与实战:调试适配器与目标板深度解析
  • 郑州民办高中怎么选?这份择校指南请收好 - 品牌排行榜
  • 计算机二级WPS演示文稿备考:从操作熟练到商务表达的高分策略
  • C# hash签名,哈希签名Sha256
  • 多模态RAG技术:让混合文档实现智能检索与生成
  • 移动平均和加权平均有什么区别?数据分析师必懂的平滑技术对比
  • bq40z50-R3 SBS命令与数据闪存配置实战指南
  • YOLOv11在课堂行为检测中的应用与实践
  • 企业AI架构:MCP+LLM+Agent技术融合实践
  • 为什么高性价比排污泵公司信息梳理?多家维度拆解
  • 腾讯WorkBuddy:免安装AI助手与多模型调度解析