事件的起因
有一个线上的项目,是用Electron开发的一个客户端桌面应用,由于项目已经很长时间了,其中引用的部分包过时,最为显著的是Electron- Builder 版本过低,导致在Mac 系统升级到12.5.1 后,没有/usr/bin/python 命令而无法打包。 关于为什么要用python ,因为Electron 在Mac 环境打包dmg 格式的安装镜像时,Electron- Builder 底层调python 生成的dmg 包,而项目中使用了"vue-cli-plugin-electron-builder": "~1.4.0", 插件,没有直接引用Electron- Builder 。
ERROR Error: Exit code: ENOENT. spawn /usr/bin/python ENOENT
Error: Exit code: ENOENT. spawn /usr/bin/python ENOENT
at /Users/aaa/Documents/electron_pro/node_modules/builder-util/src/util.ts:125:16
at exithandler (node:child_process:406:5)
at ChildProcess.errorhandler (node:child_process:418:5)
at ChildProcess.emit (node:events:527:28)
at ChildProcess.emit (node:domain:475:12)
at Process.ChildProcess._handle.onexit (node:internal/child_process:289:12)
at onErrorNT (node:internal/child_process:478:16)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
折腾
升级
查询资料得知是Electron-Builder 的问题,首先尝试是的是升级相关依赖,上述插件中引用的Electron-Builder 的版本为21.2.0 。 查询相关资料,要解决该问题,需要升级到23.0.0 ,那么对应的vue-cli-plugin-electron-builder 版本就要由原来的1.4.0 升级到2.1.0 ,这种大版本升级,必然会导致很多兼容性的问题,并且之间差的版本太多。尝试升级解决,结果越解决问题越多,而且还不知道有没有暗病,只能换种思路去解决了。
修复python
既然报错中说找不到/usr/bin/python ,那为什么升级后就没有了呢,可不可以能过软链接的方式创建一个呢。查看升级说明,原来Mac OS 在新系统中移除了python2 ,旧系统中默认安装python2 ,所以/usr/bin/python 默认可以调用python2 ,而新系统中没有了,转而内置了/usr/bin/python3 ,并且/usr/bin/ 这个目录做了系统级的保护,你就算用root 用户也是无法修改该目录下的文件的。看来修复/usr/bin/python 这条路也走不通了。。。
npm-patch
既然升级依赖和修复python 这两条路都走不通,那只能给Electron-Builder 打补丁了。 首先要找到报错的位置,是在node_modules/builder-util/src/util.ts:125:16 ,找到该文件,发现实际的报错并不在这里。直接到electron-builder 中找找看,发现package.json 中引用了一个包"dmg-builder": "21.2.0" 猜想一下,我们打dmg的包,那这个dmg-builder 一定会用到了。去到包里面发现,有两个文件会有用到python 的可能 搜索发现 早期版本的Electron-Builder 使用的不是系统暴露出来的python 命令,而是在代码中写死使用/usr/bin/python 这个命令。。。看到这里,我只能说,坑爹呀!!!,感觉心里有千万只猛兽踏过。。
打补丁
安装python2
由于早期版本的Electron-Builder 中使用的是python2 ,python2 和3部分语法和包位置不能通用,所以,这里必须给电脑中安装python2 ,安装过程这里就不写了。请自行查阅资料。
给项目中安装patch-package 依赖
npm install patch-package postinstall -D
修改代码
将下图中的/usr/bin/python 修改你自己系统中的python2 的路径,只要能调用到python2 就可以,文中使用python2 的绝对路径
补丁生效
直接这样修改还不行,不能生效,必须执行patch-package 命令,使用patch-package + 修改的文件所在的包名 ,便可生成补丁。 patch成功后,会在项目根目录下生成patches目录,用来存放补丁文件 patch文件和git提交记录有点像,记录了文件地址和详细的修改明细
完成打包
至此,打补丁修复的过程已经完毕,已经可以正常打包。patches 下的文件需要提交至git 库,别的同事在拉取代码,安装依赖后,通过执行patch-package 即可应用patches下的补丁,不用再重复上面的步骤。为方便起见,也可以配置postinstall 命令,在执行npm install 后可自动运行postinstall 。 在package.json 中的scripts 中加入"postinstall": "patch-package"
后记
在我的环境上,已经可以正常打包,安装后打开,报错如下: 又是某个包版本引起的问题,主要原因Uncaught Exception: Error: Cannot find module 'fs/promises' ,通过排查,发现是electron-updater/out/AppUpdater.js 中的const promises_1 = require("fs/promises"); 报错,查阅资料发现,需要修改成const promises_1 = require("fs").promises 即可。那就继续使用补丁解决吧。
注:
npm-patch 方法虽然能够解决一些问题,但很显然不是个长久之法,像文中这种不影响业务代码的可以这样解决,但如果可能,请使用升级依赖的方式解决。如果在主要的业务代码中有需要修改的地方,请尽量提交issue , 待作者修复后,需要第一时间升级至新版本。
|