Electron实现自定义全量更新的详细教程
作者:zooooooooy
1. 前言
本文主要介绍如何手动实现客户端应用的自动全量更新,通过改造electron-updater实现版本,系统等字段的动态判断更新。
实现后台配置不同设备,版本,系统的版本更新,可自行在后台配置定向更新,批量更新等。
2. 框架
采用electron-egg框架来进行的自动更新,一部分工作框架自带,只需要进行相应的自动更新修改即可。
3. 后台
3.1. 接口
匹配latest.yml的get请求,这个目前是必须的,具体的实现由后端代码自行处理。
/** * 适配Electron的更新,使用Get方式请求 */ @GetMapping("ee/latest.yml", produces = ["application/json"]) open fun eeLatest(appLatestRequest: AppLatestRequest): Any? { val appUpdate = appUpdateService.eeLatest(appLatestRequest) if(appUpdate == null) { return AppUpdateResponse(false) } else { return AppUpdateResponse(true, appUpdate.version, appUpdate.downloadUrl, appUpdate.sha512) } }
/** * APP更新接口 * 优先匹配单设备,在匹配全量的更新记录 */ fun check(appUpdateRequest: AppUpdateRequest): AppUpdate? { // 查找有没有直接设备匹配的更新记录,如果没有就查找所有 var appUpdates = appUpdateMapper.selectListByQuery( QueryWrapper.create() .ge(AppUpdate::version, appUpdateRequest.version) .eq(AppUpdate::deviceId, appUpdateRequest.deviceId) ) if(appUpdates.isEmpty()) { appUpdates = appUpdateMapper.selectListByQuery( QueryWrapper.create() .ge(AppUpdate::version, appUpdateRequest.version) .eq(AppUpdate::deviceId, "all") ) return appUpdates.filter { if(!it.checkRule.isNullOrEmpty()) { // 模板表达式匹配 return@filter AviatorEvaluator.compile(it.checkRule, true).execute( BeanUtil.beanToMap(appUpdateRequest) ) as Boolean } return@filter true }.firstOrNull() } else { return appUpdates.filter { if(!it.checkRule.isNullOrEmpty()) { // 模板表达式匹配 return@filter AviatorEvaluator.compile(it.checkRule, true).execute( BeanUtil.beanToMap(appUpdateRequest) ) as Boolean } return@filter true }.firstOrNull() } }
3.2. 规则
下发的规则字段匹配可能会非常多,经常变动。这个时候如果通过简单的字段来匹配的话,需要扩充很多字段,需要手动匹配逻辑(大于某个版本,小于某个版本)来进行处理。采用aviator表达式引擎来进行表达式计算,返回表达式是true或者false来决定是否适配这一条配置。
AviatorEvaluator.compile(it.checkRule, true).execute( BeanUtil.beanToMap(appUpdateRequest) )
通过配置的校验规则进行判断是否可以下发,参数来源于请求参数。
3.3. 返回JSON定义
class AppUpdateResponse( val canDownload: Boolean? = null, val version : String? = null, val path : String? = null, val sha512 : String? = null) { }
必须有version,path,sha512字段匹配,canDownload是后台增加用户判断是否需要下载的判断。
3.4. 更新表定义
-- auto-generated definition create table t_app_update ( id int auto_increment primary key, version varchar(16) null comment '版本号', device_id varchar(64) null comment '设备id', download_url varchar(255) null comment '下载地址', sha512 varchar(256) null comment '加签值', check_rule varchar(255) null comment '校验规则', platform varchar(20) null comment '平台 windows mac linux', open_flag tinyint default 1 null comment '开启标记 1- 开启 0 -关闭', tentant_code varchar(16) null comment '商户号', add_time datetime null, update_time datetime null ) engine = InnoDB charset = utf8mb4;
3.5. downloadUrl
download_url需要放置到外网一个可以访问的地址,用于后续进行下载。本项目采用minio对外提供文件下载地址。
4. 前台
4.1. 更新配置
核心是关闭自动更新,手动配置feedUrl,让请求到后台更新接口上,返回对应的json配置信息
4.1.1. 强制测试版本更新
// 强制测试版本更新 autoUpdater.forceDevUpdateConfig = true;
4.1.2. 关闭自动更新
autoUpdater.autoDownload = false;
4.1.3. 设置FeedUrl
const version = electronApp.getVersion(); Log.info('[addon:autoUpdater] current version: ', version); // 设置下载服务器地址 let server = cfg.options.url; let lastChar = server.substring(server.length - 1); server = lastChar === '/' ? server : server + "/" + "?version=" + version + "&platform=" + Os.platform(); Log.info('[addon:autoUpdater] server: ', server); cfg.options.url = server; try { autoUpdater.setFeedURL(cfg.options); } catch (error) { Log.error('[addon:autoUpdater] setFeedURL error : ', error); }
4.2. 更新监听
需要用到electron和web中的ipc通信,互相进行消息传递。
web | node | app.checkUpdate 自动或者手动触发更新 |
---|---|---|
node | checkUpdate 通过调用feedUrl,检查是否需要更新 | |
node | web | update-available 有可用更新,通过web弹窗提示 |
node | app.downloadUpdate 开始更新 | |
node | web | download-progress 更新进度,同步提示给web进行进度条展示 |
node | update-downloaded 下载完成,直接触发系统级别的安装 |
4.2.1. 更新状态值
const status = { error: -1, available: 1, noAvailable: 2, downloading: 3, downloaded: 4, }
4.3. 弹窗提示
需要监听是否有更新和更新进度两块,这两个合二为一。
ipc.on('app.updater', (event, info) => { const infoN = JSON.parse(info) console.log('app.updater', infoN) // 弹窗提示用户进行更新 if (infoN.status == 1) { // 改为确认框 ElMessageBox.confirm('发现新版本,是否立即更新?', '更新提示', { confirmButtonText: '更新', cancelButtonText: '稍后更新', type: 'warning' }).then((res) => { // 用户点击了更新按钮 console.log('用户点击了更新按钮', res) if (res === 'confirm') { ipc.invoke('app.downloadUpdate') openProgressDialog() } }).catch(() => { // 用户点击了稍后更新按钮 }); } else if(infoN.status == 3) { updateProgress(infoN.percentNumber) } }) <el-dialog v-model="showDialog" title="下载进度" :show-close="false" :close-on-click-modal="false" :close-on-press-escape="false" width="30%" > <el-progress :percentage="percentNumber" :stroke-width="18" :text-inside="true" /> </el-dialog>
5. 整体思路
5.1. 成果
更新为自动更新,通过ipc调用node,传递token过去
ipc.invoke('app.checkUpdate', userStore.getToken)
5.2. 结果
至此整个功能更新功能基本完成,后续需要开发一个更新页面,用来配置更新条目。适配不同版本,不同设备,不同平台的更新,相应的就可以做到定向更新,灰度更新等功能。
以上就是Electron实现自定义全量更新的详细教程的详细内容,更多关于Electron自定义全量更新的资料请关注脚本之家其它相关文章!