共计 2853 个字符,预计需要花费 8 分钟才能阅读完成。
在公司开发的下载器过程中,遇到的一些坑点
electron 中弹窗的确认取消以及系统自带的叉号之间的关系
场景:在用户退出 app 时,需要提示用户是否确认退出,此时弹窗出现,如果点击确认就继续退出,执行回调,否则的话,不退出
问题:点击叉号的时候,回调中返回的值是 0,由于代码中写的 buttons 顺序为 [‘ 确认 ’, ‘ 取消 ’],点击“确认”的时候对应的 response 也是 0,就导致了点击“确认”和点击叉号的行为一致,这样的话是不正确的,点击叉号应该等同于取消退出。
// 问题代码,点击确认按钮会退出,点击右上角叉号也会退出
dialog.showMessageBox(mainWindow, { buttons: ['确认', '取消'] }, (response) => {if (reponse === 0) {// 执行退出操作}
});
// 修改后代码,点击确认退出,点击右上角叉号不退出
dialog.showMessageBox(mainWindow, { buttons: ['取消', '确认'] }, (response) => {if (response === 1) {// 执行确认退出操作}
});
打包后子进程中的代码没有执行的问题
场景:在本地开发过程中,使用子进程去下载资源,能够正常的下载,但是打包之后,发现下载不了,子进程中的事件没有执行。导致下载流程受阻
问题:electron 中使用到子进程的时候,是把子进程当作一个外部依赖来做的,打包后并不会将子进程的代码打进到包中,需要额外进行配置。
解决方式:对子进程文件进行额外配置注:本项目脚手架基于 electron-vue,配置文件和 electron-vue 保持相同
-
打包配置:asarUnpack 这个配置是用来将子进程中用的一些第三方包进行整理,否则子进程找不到这些包,就跑不起来。子进程中用的第三方包都需要在 asarUnpack 中进行配置。
extraResources 这个配置用来将我们的代码子进程文件所在目录,打包出来放在一个指定的地方,在代码中有需要引用子进程文件的地方,就用这个地址去找对应的 js 文件,因为开发和打包后的路径是不一样的,具体 package.json 配置如下"mac": { "icon": "build/icons/icon.icns", "extendInfo": { "CFBundleURLSchemes": ["link"] }, "asarUnpack": [ "**/node_modules/electron-log/**/*", "**/node_modules/unzipper/**/*", "**/node_modules/axios/**/*", "**/node_modules/archiver/**/*" ], "extraResources": [ { "from": "src/main", "to": "app.asar.unpacked/download" } ] }, "win": { "icon": "build/icons/icon.ico", "asarUnpack": [ "**/node_modules/electron-log/**/*", "**/node_modules/unzipper/**/*", "**/node_modules/axios/**/*", "**/node_modules/archiver/**/*" ], "extraResources": [ { "from": "src/main", "to": "app.asar.unpacked/download" } ], "target": [ { "target": "nsis", "arch": ["x64"] } ] }
-
子进程 fork 路径:electron 中开发和打包后子进程的 fork 路径并不相同,开发时候,可以直接使用当前路径进行引用,但是打包后子进程 js 文件直接通过相对路径就获取不到了。所以 fork 子进程的时候路径需要如下配置,
process.resoucesPath
: electron 中定义的资源目录的路径,在打包后子进程 js 所在的路径。let isDev = process.env.NODE_ENV !== 'production'; let scriptPath = isDev ? path.join(__dirname, 'child_download_serial.js') : path.join(process.resourcesPath, 'app.asar.unpacked/download/child_download_serial.js');
上面两步做完了,打包完毕后可以在安装后的安装包下看到自己子进程的代码目录,此时说明配置成功,并且子进程和主进程能够正常通信了。
以上方案在 windows 下和 mac 下都适用
子进程中的 log 输出不了
场景:想看一下子进程中输出的 log,查看子进程的执行情况
问题:子进程的 console 在控制台中看不到,因为子进程和父进程是分开的,我们只能看到父进程的输出
解决方式:拿到子进程后,在父进程中监听子进程的 stdout.on(‘data’) 事件,这样在子进程中的所有 console.log 在父亲进程中都会触发 data 事件,父进程可以输出子进程的 console 内容。注意 fork 的时候需要给一个 silent:true 的配置,如果为 true,则子进程的 stdin、stdout 和 stderr 将会被输送到父进程,否则它们将会继承自父进程。同理,也可以监听子进程的 stderr 的 data 事件,可以捕获到子进程的错误
childDownload = fork(scriptPath, [], {silent: true});
childDownload.stdout.on('data', data => {console.log('子进程的 console', data.toString());
});
electron 闪退的问题
场景:在退出软件的时候,由于代码原因报了一个错误,然后软件成功关闭,但是当再次手动打开软件时,出现闪退情况
问题:主进程出错后,没有对错误进行捕获,导致再次打开软件依然有这个错误存在,软件打不开
解决方式:全局进行一个错误捕获,避免某些情况下的错误未捕获导致闪退打不开软件的问题
// 必要的全局错误捕获
process.on('uncaughtException', error => {log.error(error.stack || JSON.stringify(error));
app.exit();});
web 端唤醒客户端覆盖问题
场景:错题本下载器安装后,再安装错题本 logger 工具,此时再 web 中点击唤醒下载工具,唤醒的是错题本 logger 工具
问题:再两者打包的时候,对应的 appId 都是相同的,导致后安装的软件将前安装的软件给顶替了,当再网页中唤醒的时候,就将替换后的软件唤醒了
解决方式:package.json 中的 appId 保证唯一性
原文链接:https://github.com/chaijinson… 持续更新