項目現狀:每次有新版本發佈時,須要用戶本身去手動點擊下載,而後手動一步步操做安裝,每次都要去從新選擇安裝目錄等,過程較爲耗時,也須要用戶去手動操做,用戶體驗不佳。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(),會退出當前的應用而且安裝剛剛下載好的新版本