使用electron-update实现electron应用的自动更新
因为我也是从零开始接触electron,所以许多不足之处可以提出来多多交流,如有补充万分感谢。一、项目环境我这边的框架使用的是electron和vue,因为vue的脚手架插件时有electron编译的,所以不需要自己去写build,非常方便,随便说一句希望以后这种官方合作越来越多。我这里使用的electron版本是13.0.1,vue的版本还是2.6.11,electron-update的版本是4
因为我也是从零开始接触electron,所以许多不足之处可以提出来多多交流,如有补充万分感谢。
一、项目环境
我这边的框架使用的是electron和vue,因为vue的脚手架插件时有electron编译的,所以不需要自己去写build,非常方便,随便说一句希望以后这种官方合作越来越多。
我这里使用的electron版本是13.0.1,vue的版本还是2.6.11,electron-update的版本是4.3.9
$ npm i electron
$ npm i electron-updater
二、设置配置项
之前我说过了,我使用的是vue脚手架的插件来进行编译的,所以没有build配置项,本步骤中的配置项都是放在build配置项中的,不过在我这个项目中没有build配置项所以我放在vue.config.js
文件中。在vue.config.js
文件中的electronBuilder
对象中添加一个builderOptions
编译选项对象,配置如下
builderOptions: {
nsis: {
oneClick: false,
perMachine: true,
allowElevation: true,
allowToChangeInstallationDirectory: true,
createDesktopShortcut: true,
runAfterFinish: true,
installerIcon: "./build/favicon.ico",
uninstallerIcon: "./build/favicon.ico"
},
publish: [{
provider: "generic",
url: "http://192.168.37.112:8888/uma-unimax-web/ext/download/"
}],
mac: {
icon: "./build/aaaaa.ico"
},
win: {
icon: "./build/aaaaa.ico"
},
linux: {
icon: "./build/aaaaa.ico"
}
}
这里解释一下各个参数的含义,其中publish
是最为关键的,该配置会在打包项目时生成一个latest.yml
文件,该文件是实现更新的关键。publish中的url一定要是服务器的地址同时还需要和主进程中的配置一致,这个会在后面说到。nsis
是应用相关的配置,这里随便说两个,例如allowToChangeInstallationDirectory
是否允许用户自定义安装目录,createDesktopShortcut
是否生成桌面快捷方式,installerIcon
安装包的图标。。。最后就是mac、win、linux中的icon就是各个环境下的应用图标样式。
三、在主进程中设置自动更新设置
我这里的主进程文件是background.ts
,大伙应该都是main.js,没啥区别。
- 首先在主进程中拿到
autoUpdater
对象
import { autoUpdater } from "electron-updater";
- 在创建窗口的方法中新建一个名为
handleUpdate
的方法,这个方法名可以自己取,这个方法主要是用来处理更新的。 - 在
handleUpdate
方法中设置应用更新下载的地址
autoUpdater.setFeedURL(
"http://61.183.71.118:8888/uma-unimax-web/ext/download"
);
其中ip地址就是之前在vue.config.js
文件中设置的ip地址,这里有域名也可以用域名会更方便。后面的路径就是专门用于存放之前说过的两个文件的地方(latest.yml以及最新的应用安装程序)。
四、建立更新事件的监听
首先定义一个消息对象,后面可以根据不同的状态发送不同的消息
const returnData = {
error: { status: -1, msg: "检测更新异常" },
checking: { status: 0, msg: "正在检查应用程序更新" },
updateAva: { status: 1, msg: "检测到新版本,正在下载,请稍后" },
updateNotAva: { status: -1, msg: "您现在使用的版本为最新版本,无需更新!" }
};
接下来就是一系列的事件监听
//更新错误
autoUpdater.on("error", function (error) {
sendUpdateMessage(returnData.error);
});
//检查中
autoUpdater.on("checking-for-update", function () {
sendUpdateMessage(returnData.checking);
});
//发现新版本
//当发现一个可用更新的时候,更新包下载会自动开始
autoUpdater.on("update-available", function (info) {
sendUpdateMessage(JSON.stringify(info) + '___' + JSON.stringify(returnData.updateAva));
});
//当前版本为最新版本
autoUpdater.on("update-not-available", function (info) {
setTimeout(function () {
sendUpdateMessage(returnData.updateNotAva);
}, 1000);
});
// 更新下载进度事件
autoUpdater.on("download-progress", function (progressObj) {
sendUpdateMessage("正在下载");
if (win) {
win.webContents.send("downloadProgress", progressObj);
}
});
autoUpdater.on("update-downloaded", function (
event,
releaseNotes,
releaseName,
releaseDate,
updateUrl,
quitAndUpdate
) {
sendUpdateMessage("更新完毕");
// 退出并安装
autoUpdater.quitAndInstall()
});
都有注释我就不多解释了,反正基本上拿去就能用,知道他是干啥的就行。
在这些事件监听都写了以后可以直接调用方法开启监听,如果你想手动开启监听也行,需要你自己设置一个主进程事件监听,然后在渲染进程触发,过程有点类似下面的触发更新操作。
五、消息处理
在主进程设置了更新事件后还需要定义一个方法去发送消息给渲染进程
// 通过main进程发送事件给renderer进程,提示更新信息
function sendUpdateMessage(text) {
if (win) {
win.webContents.send("message", text);
}
}
可以看到,之前事件监听中发送消息就是使用的该方法。
六、监听自动更新事件
// 检查更新
ipcMain.on("checkForUpdate", (event, data) => {
console.log("执行自动更新检查!!!");
autoUpdater.checkForUpdates();
});
这个事件是自定义的,用于触发自动更新,一般来说触发自动更新都是由渲染进程来触发的,下面会说如何触发
七、触发更新
在渲染进程中获取package.json
文件中的版本信息,然后在通过接口获取到服务器所存放的最新安装包的版本进行比对,如果不是最新版则提示用户执行更新。如果需要开始更新这个时候只需要在渲染进程中触发第六步设立的事件监听即可
ipcRenderer.send("checkForUpdate");
这个时候会触发更新事件,更新开始。
在事件触发后,autoUpdater
会自动触发第四步中的一系列监听,首先会开启checking-for-update
事件,确认需要更新后会执行update-available
事件开始下载,下载时会触发download-progress
事件,我们可以在该事件的回调中拿到下载进度等一系列参数。在下载完毕后会执行update-downloaded
事件,然后退出当前应用并自动安装新版本。
八、更新包存放地址
我尝试过更改更新包存放地址,但是好像无能为力,而且存放的地址我不知道为啥,很多人都不相同,我这里是C:\Users\用户\AppData\Local\项目名
路径下。
结语
这次自动更新我踩了不少雷花了不少时间,其实操作起来不难,主要是我自己太蠢经验太少,所以写一篇笔记来帮助自己记下来,毕竟也是一个不错的功能。其实这里只是最基本的更新要求,中断更新进程等操作我也没有完成,如果有大神告知不胜感激,后期如果做出来了我会更新的。
最后最后,为了防止有的同学因为我的文笔而看不懂,特展示代码
主进程
//处理更新操作
function handleUpdate() {
const returnData = {
error: { status: -1, msg: "检测更新异常" },
checking: { status: 0, msg: "正在检查应用程序更新" },
updateAva: { status: 1, msg: "检测到新版本,正在下载,请稍后" },
updateNotAva: { status: -1, msg: "您现在使用的版本为最新版本,无需更新!" }
};
//vue.config.json配置的一样
autoUpdater.setFeedURL(
"http://127.0.0.1:8888/download"
);//地址我就不写了,上面有说
//更新错误
autoUpdater.on("error", function (error) {
sendUpdateMessage(returnData.error);
});
//检查中
autoUpdater.on("checking-for-update", function () {
sendUpdateMessage(returnData.checking);
});
//发现新版本
//当发现一个可用更新的时候,更新包下载会自动开始
autoUpdater.on("update-available", function (info) {
sendUpdateMessage(JSON.stringify(info) + '___' + JSON.stringify(returnData.updateAva));
});
//当前版本为最新版本
autoUpdater.on("update-not-available", function (info) {
setTimeout(function () {
sendUpdateMessage(returnData.updateNotAva);
}, 1000);
});
// 更新下载进度事件
autoUpdater.on("download-progress", function (progressObj) {
sendUpdateMessage("正在下载");
if (win) {
win.webContents.send("downloadProgress", progressObj);
}
});
autoUpdater.on("update-downloaded", function (
event,
releaseNotes,
releaseName,
releaseDate,
updateUrl,
quitAndUpdate
) {
sendUpdateMessage("更新完毕");
// 退出并安装
autoUpdater.quitAndInstall()
});
//执行自动更新检查
// autoUpdater.checkForUpdates();
}
// 通过main进程发送事件给renderer进程,提示更新信息
function sendUpdateMessage(text) {
if (win) {
win.webContents.send("message", text);
}
}
// 检查更新
ipcMain.on("checkForUpdate", (event, data) => {
console.log("执行自动更新检查!!!");
autoUpdater.checkForUpdates();
});
handleUpdate()
渲染进程
ipcRenderer.send("checkForUpdate");
// 主进程返回的检测状态
ipcRenderer.on("message", (event, data) => {
// this.tips = text;
console.log(data);
if (data.status == -1) {
this.$toast.error({
message: data.msg,
position: "top-end",
});
}
});
//注意:“downloadProgress”事件可能存在无法触发的问题,只需要限制一下下载网速就好了
ipcRenderer.on("downloadProgress", (event, progressObj) => {
if (progressObj.percent) {
this.updateProgress = progressObj.percent;
if (progressObj.percent == 100) {
this.$toast.info({
message: "下载完成!",
position: "top-end",
});
}
}
// this.downloadPercent = progressObj.percent || 0;
});
更多推荐
所有评论(0)