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
相关文章
相关标签/搜索