在后续维护electron项目中想到:每次客户端有更新(即使改动不大),都要重新打包后把客户端发给供应商用户,虽随着用户越来越多,更新也越来越麻烦,花在沟通上的成本更大,所以考虑使用自动更新,减少沟通成本,让用户在没有察觉的情况下就能更新到最新版。
官方支持的方法是利用内置的Squirrel框架和Electron的autoUpdater模块。
但因为之前适用electron-builder工具打包,且,其自带有更新功能,所以还是使用electron-builder的自动更新。
1、引入自动更新插件,在主进程中使用
1 | const { autoUpdater } = require('electron-updater') |
这将使用electron-updater的默认配置,自动下载并弹出提醒,但提示语固定且为英语,所以在查看了AppUpdater.js后,修改了更新的回调。
1 | autoUpdater.checkForUpdates().then(it => { |
checkForUpdates是electron-updater的内置方法,是一个promise,可以在成功回调里做特殊处理。参考checkForUpdatesAndNotify方法,在downloadPromise完成后弹窗提示:
1 | // AppUpdater.js |
如果需要更多定制,可以使用以下事件:
1 | autoUpdater.on('error', (ev, err) => { |
2、发布方式:
The publish key contains a set of options instructing electron-builder on how it should publish artifacts and build update info files for auto update.
String | Object | Array<Object | String>
whereObject
it is BintrayOptions, GenericServerOptions, GitHub, S3Options or SpacesOptions. Order is important — first item will be used as a default auto-update server. Can be specified in the top-level configuration or any platform- (mac, linux, win) or target- (e.g. nsis) specific configuration.If
GH_TOKEN
is defined — defaults to[{provider: "github"}]
.If
BT_TOKEN
is defined andGH_TOKEN
is not — defaults to[{provider: "bintray"}]
我们使用的是
1 | "publish": [ |
此时,重新打包会生成latest.yml:
1 | version: 1.0.2 |
这是程序判断有无更新的依据,url(http://localhost:8080/installer,假设起在本地,也可以换成线上的地址)上存放安装包和latest.yml文件,运行客户端时会访问url的latest.yml查询是否有版本更新。
遇到的坑:
electron provider url 测试为本地时,漏了个/,导致ERR_INVALID_URL
electron provider url 测试为线上时,当时线上安装包地址使用软连接,不是带版本号的文件名,而是直接erp.exe,但在测试自动更新时发现,无论如何更新安装包和latest.yml文件,都没有改变sha512,即使检测到了新版本,可是安装包的地址指向不对,一直是第一次上传的版本,因为这个url使用了cdn缓存,导致软连接一直指向了最开始上传的版本,即使刷新了cdn地址和预加载大文件都不可以,所以最后没有使用软连接,而是直接带上了版本号,这样就能正常更新。
在这次更新electron时,需要做到打开多个客户端,在修改代码后测试发现,第一个客户端中能正常获取localStorage,但之后的客户端都无法获取,查看issue后发现,这是因为两个浏览器进程使用的是相同路径的数据,一旦文件被一个进程读取(localStorage是以本地文件存储的方式),即被锁住,其他进程无法读取,除非把这些数据拷贝到另一个路径下。所以electron推荐使用单实例窗口,否则可能会出现无法获取到部分数据。
Running multiple instances of Electron is generally a bad idea and not really supported with the default configuration. Some renderer features don’t work in this scenario (localStorage, IndexedDb, persisted sessions?)
打开一个窗口会创建3个进程,这是由于Chromium的特征导致的:
Yes. When you run Electron it will run 3 processes. That’s because of Chromium’s multi-process architecture