Electron開發實戰之記帳軟件14——自動更新

代碼倉庫: https://github.com/hilanmiao/LanMiaoDesktopnode

官網介紹了多種更新方式,咱們使用的electron-builder的更新機制。 https://electronjs.org/docs/tutorial/updatesgit

安裝electron-updater模塊

npm install electron-updater

配置package.json

在build節點下添加以下內容github

"publish": {
      "provider": "github",
      "repo": "LanMiaoDesktop",
      "owner": "hilanmiao",
      "releaseType": "release"
    },

打包時就會生成latest.yml文件,這裏面記錄的是當前版本的信息,electron-updater會根據這個和最新版本比較,而後觸發相應事件。web

編寫主進程代碼

核心就是觸發「checkForUpdates、downloadUpdate」這兩個事件npm

import {autoUpdater} from 'electron-updater'

/**
 * 自動更新
 */
function autoUpdate() {
    // 經過main進程發送事件給renderer進程,提示更新信息
    function sendUpdateMessage(obj) {
        mainWindow.webContents.send('updateMessage', obj)
    }

    // 監測更新,在你想要檢查更新的時候執行,renderer事件觸發後的操做自行編寫
    const message = {
        error: '檢查更新出錯',
        checking: '正在檢查更新......',
        updateAva: '監測到新版本,正在下載......',
        updateNotAva: '如今使用的就是最新版本,不用下載'
    }

    // 當更新出現錯誤時觸發
    autoUpdater.on('error', (err) => {
        // sendUpdateMessage('error')
        sendUpdateMessage({action: 'error', errorInfo: err})
    })

    // 當開始檢查更新的時候觸發
    autoUpdater.on('checking-for-update', () => {
        // sendUpdateMessage('checking')
        sendUpdateMessage({action: 'checking'})
    })

    // 當發現一個可用更新的時候觸發,更新下載包會自動開始
    autoUpdater.autoDownload = false
    autoUpdater.on('update-available', (info) => {
        // sendUpdateMessage('updateAva')
        sendUpdateMessage({action: 'updateAva', updateInfo: info})
    })

    // 當沒有可用更新的時候觸發
    autoUpdater.on('update-not-available', (info) => {
        // sendUpdateMessage('updateNotAva')
        sendUpdateMessage({action: 'updateNotAva'})
    })

    // 更新下載進度事件
    autoUpdater.on('download-progress', (progressObj) => {
        mainWindow.webContents.send('downloadProgress', progressObj)
    })

    /**
     * event Event
     * releaseNotes String - 新版本更新公告
     * releaseName String - 新的版本號
     * releaseDate Date - 新版本發佈的日期
     * updateUrl String - 更新地址
     */
    autoUpdater.on('update-downloaded', (info) => {
        // 下載太快可能沒法觸發downloadProgress事件,因此手動通知一下
        mainWindow.webContents.send('downloadProgress', {percent: 100})
        // 能夠手動選擇是否當即退出並更新
        ipcMain.on('isUpdateNow', (e, arg) => {
            // some code here to handle event
            autoUpdater.quitAndInstall()
        })
    })

    ipcMain.on('checkForUpdate', () => {
        // 執行自動更新檢查
        autoUpdater.checkForUpdates()
    })

    ipcMain.on('downloadUpdate', () => {
        // 下載
        autoUpdater.downloadUpdate()
    })
}

下面這三個事件會返回給你一個info,裏面存了version、releaseNotes等信息,你能夠把這些信息保存下來備用。 json

須要注意的是若是下載的速度太快,可能沒法觸發downloadProgress(公司網速太快,一直觸發不了),因此須要本身手動觸發一次。服務器

編寫渲染進程代碼

主進程代碼已經寫好了,這裏無非就是通訊並接受返回值罷了。我是進入頁面就進行一次檢測,而後獲取releaseNotes並保存到localstorage裏了。核心就是觸發「checkForUpdates、downloadUpdate」這兩個事件。electron

downloadAndUpdate() {
    this.downloading = true

    // 開始下載
    ipcRenderer.send('downloadUpdate')
    ipcRenderer.on('downloadProgress', (event, progressObj) => {
        this.progress = JSON.stringify(progressObj)
        // console.log(progressObj)
        this.downloadPercent = progressObj.percent.toFixed(0) || 0
        // if(this.downloadPercent === 100) { // 這樣寫爲啥很差使呢?
        if(progressObj.percent === 100) {
            this.downloading = false
            // 詢問是否當即更新
            this.dialogUpdateNow = true
        }
    })
},
updateNow() {
   // 馬上退出並更新
   ipcRenderer.send('isUpdateNow')
},
checkForUpdate() {
    // 開始檢查
    ipcRenderer.send('checkForUpdate')
    // 添加自動更新事件的監聽
    ipcRenderer.on('updateMessage', (event, obj) => {
        if (obj.action === 'updateAva') {
            this.hasNewVersion = true
            this.saveVersionInfoList(obj.updateInfo)
            this.versionInfoList = this.getVersionInfoList()
        } else if (obj.action === 'error') {
            this.showError = true
            this.errorInfo = obj.errorInfo
        } else if(obj.action ==='updateNotAva') {
            this.noNewVersion = true
        } else {
            // console.log(text)
        }
    })
},

效果

確認更新後自動彈出安裝界面ide

說明

我是手動觸發的更新,圖省事的話能夠直接在渲染進程裏寫就ok了,可是不友好,假如用戶正在工做,這時候更新就不合適了,須要優化的地方還有不少,後面會持續優化,例如後臺更新這種常見需求。優化

electron-builder支持從github上更新。這是個開源項目,因此直接用github release 更新就行了,缺點是github可能比較慢,固然你也能夠換成本身的服務器或者放到別的地方,例如阿里的OSS,把你的安裝包放到某個目錄下,而後把生成的latest.放上,再改一下build的publish參數,以下,就能夠自動識別和下載了。

"publish": [
      {
        "provider": "generic",
        "url": "http://**.**.**.**:3002/download/"
      }
    ],

移除監聽事件

爲避免屢次切換頁面形成監聽的濫用,切換頁面前必須移除監聽事件。由於main.js中的事件多是共享給多個頁面的,因此這幾個頁面都會收到main.js發送的通知,這顯然是不對的。例如你debug的時候可能會看到這樣的消息。

(node:23006) Error: Possible EventEmitter memory leak detected. 11 conn-st listeners added. Use emitter.setMaxListeners() to increase limit
相關文章
相關標籤/搜索