项目现状:每次有新版本发布时,须要用户本身去手动点击下载,而后手动一步步操做安装,每次都要去从新选择安装目录等,过程较为耗时,也须要用户去手动操做,用户体验不佳。javascript
electron 的打包能够采用electron-packager及electron-builder两种方式实现,通过对比以后发现electron-builder有比electron-packager有更丰富的的功能,支持更多的平台,同时也支持了自动更新。除了这几点以外,由electron-builder打出的包更为轻量,而且能够打包出不暴露源码的setup安装程序,因此将方案选为后者。java
A. 安装 electron-updater 包模块linux
npm install electron-updater --save
复制代码
B. 配置package.json文件里的buildweb
"build": { "productName": "uWorker", //项目名 这也是生成的exe文件的前缀名 "appId": "xxxx", //项目的appid "copyright": "xxx", //版权 信息 "directories": { "output": "dist" // 输出的文件夹 }, "publish": [ { "provider": "generic", //服务器提供商 也能够是GitHub等等 "url": "http://127.0.0.1/",//更新服务器地址,用本地服务作测试 } ], "dmg": { "background": "../build/body-background.jpg", "window": { "x": 400, "y": 100, "width": 1100, "height": 709 } } "mac": { "icon": "build/icons/icon.icns", // mac的图标路径 "artifactName": "${productName}_setup_${version}.${ext}" // 打出来的包所带的版本信息名 }, "win": { "icon": "build/icons/icon.ico", // windows的图标路径, // 打包出来以后的结果 "target": [ "nsis", "zip" ], "artifactName": "${productName}_setup_${version}.${ext}" // 打出来的包所带的版本信息名 }, "nsis": { "oneClick": false, // 一键安装 "perMachine": true, // 是否开启安装时权限限制(此电脑或当前用户) "allowElevation": true, // 容许请求提高。 若是为false,则用户必须使用提高的权限从新启动安装程序。 "allowToChangeInstallationDirectory": true, // 容许修改安装目录 "installerIcon": "../build/icons/icon.icns", // 安装图标 "uninstallerIcon": "../build/icons/icon.icns", //卸载图标 "installerHeaderIcon": "../build/icons/icon.icns", // 安装时头部图标 "createDesktopShortcut": true, // 建立桌面图标 "createStartMenuShortcut": true, // 建立开始菜单图标 } "linux": { "icon": "build/icons", "artifactName": "${productName}_setup_${version}.${ext}" } } "scripts": { "builder": "electron-builder" } 复制代码
注意: 配置了publish会生成latest.yml文件,用于自动更新的配置信息;不要本身轻易去修改该文件。若是文件有误,须要重打包获取新的latest.yml文件。npm
C. 打包操做json
npm run builder
复制代码
配置了publish以后在mac上会生成.dmg的包以及latest-mac.yml文件; 在windows上会生成.exe的包以及latest.yaml, 这是实现自动更新的关键。根据latest.yaml里的版本信息去判断是否有新版本,须要进行下载安装。windows
// windows 下的latest.yml version: 2.8.0 files: - url: 2.8.0.exe sha512: FmSi6nU1PJ1LRQIBjuvaw0TG32KHPM76FlGMRcWrSNOs7XGeaUALspgOKknTFYzuqmjEJk6JiHGNOm/UH+wDLw== size: 42463133 // 当target选择nsis和zip等时候,此时的files里会有多项,因此path是指定下载时候对于服务器上的下载文件地址,若是是mac的话指的的.zip. sha512参数是在下载时候作校验的,以确保下载的是正确的新版本 path: 2.8.0.exe sha512: FmSi6nU1PJ1LRQIBjuvaw0TG32KHPM76FlGMRcWrSNOs7XGeaUALspgOKknTFYzuqmjEJk6JiHGNOm/UH+wDLw== releaseDate: '2020-01-21T02:24:38.716Z' 复制代码
D. 配置主进程main.js文件,引入 electron-updater 文件,添加自动更新检测和事件监听(必定要是主进程main.js文件(或主进程main中的index.js文件),不然会报错)api
const {app, BrowserWindow,Menu,ipcMain} = require('electron') const path = require('path') const package = { version:"2.8.1", productEnv:"development",// development products feedUrl:"http://127.0.0.1/" }; // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let mainWindow; // ===============================================================更新区 // ===============================================================更新区 // ===============================================================更新区 const autoUpdater = require('electron-updater').autoUpdater; // 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操做自行编写 function updateHandle() { let message = { error: 'Check update is error.', checking: 'checking update now.', updateAva: 'has new packer is downing...', updateNotAva: 'is the lasted packer. do not to update !', }; const os = require('os'); autoUpdater.setFeedURL(package.feedUrl); autoUpdater.on('error', function (error) { console.log('出错了', error) sendUpdateMessage({cmd:'error',message:error}) }); autoUpdater.on('checking-for-update', function (message) { sendUpdateMessage({cmd:'checking-for-update',message:message}) }); autoUpdater.on('update-available', function (message) { sendUpdateMessage({cmd:'update-available',message:message}) }); autoUpdater.on('update-not-available', function (message) { sendUpdateMessage({cmd:'update-not-available',message:message}) }); // 更新下载进度事件 autoUpdater.on('download-progress', function (progressObj) { sendUpdateMessage({cmd:'download-progress',message:progressObj}) }) autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl) { sendUpdateMessage({cmd:'update-downloaded',message:{ releaseNotes, releaseName, releaseDate, updateUrl }}) }); ipcMain.on('isUpdateNow', (e, arg)=>{ // sendUpdateMessage({cmd:'isUpdateNow',message:arg}) //some code here to handle event autoUpdater.quitAndInstall(); }); ipcMain.on("checkForUpdate",(e, arg)=>{ //执行自动更新检查 // sendUpdateMessage({cmd:'checkForUpdate',message:arg}) autoUpdater.checkForUpdates(); }) } // 经过main进程发送事件给renderer进程,提示更新信息 function sendUpdateMessage(data) { mainWindow.webContents.send('message', data) } 复制代码
const ipcRenderer = require('electron').ipcRenderer; ipcRenderer.on("staticData",function(event,data){ // 获取配置项数据 console.log('获取配置项数据', data) if(data.version) { Upd_version.innerText = data.version; if(typeof window.updateVerson == 'function') _app.innerText = data.version } }) ipcRenderer.on('message',(event,data) => { // 初始化参数 data = data || {}; var message = data.message || {}; console.log(data) // 需更新 if(data.cmd == 'update-available'){ Upd_app.style.display = "block"; if(message.version) { console.log("正在更新到最新版本:v "+message.version); Upd_version.innerText = message.version; } } // 更新异常 if(data.cmd == 'error'){ console.log('error', data) Upd_lock = false; Upd_btn.innerText = "当即更新"; if(message.errno == -4058){ Upd_app.style.display = "none"; } } // 下载中 if(data.cmd == 'download-progress'){ Upd_progress.value = Number(message.percent); Upd_percent = Number(message.percent); } // 下载完成 if(data.cmd == 'update-downloaded'){ // 下载完成 开始安装 if(Upd_percent == 100){ Upd_btn.innerText = "安装重启中..."; ipcRenderer.send('isUpdateNow'); } } }); setTimeout(function(){ autoUpdate() },500); function autoUpdate(){ if(Upd_lock) return false; Upd_lock = true; Upd_btn.innerText = "版本更新中."; ipcRenderer.send('checkForUpdate'); } 复制代码
E. 如今能够去模拟测试了,以windows的为例,安装刚刚打包出来的2.8.0的应用,而后再将版本号改成2.8.1,而后进行打包,而且部署到publish里设置的url服务目录下(用了IIS开了本地服务,不过刚开始一直失败,原来是要为.yml添加MIME的扩展类型~)服务器
windows安装示例markdown
效果如上视频所示,autoUpdater会检测到有新版本而且进行下载,在下载完成后能够本身选择弹框询问用户是否当即更新,用户选择肯定以后,会去调用autoUpdater.quitAndInstall(),会退出当前的应用而且安装刚刚下载好的新版本