前端

Electron - 自动升级实战

2021-07-01  本文已影响0人  红薯爱帅

1. 概述

本文讲解内容:

2. 功能介绍

2.1. 强制升级

    autoUpdater.on('update-downloaded', (info) => {
        log.info(info)
        if (info.minVersionSupported == undefined ||
            semver.lt(app.getVersion(), info.minVersionSupported)) {
            autoUpdater.quitAndInstall(true, true)
            return
        }
        dialog.showMessageBox({
            type: 'info',
            title: '软件升级',
            message: '发现新版本,是否立即升级?',
            buttons: ['是的', '稍后']
        }).then((resp) => {
            if (resp.response === 0) {
                log.info('begin to install new version ...')
                autoUpdater.quitAndInstall(true, true)
            }
        })
    })

2.2. 灰度发布

计划用grayReleased: 100实现,仔细想了一下,如果客户端每次随机一个数字,启动多次之后,可能都更新到最新版本了,所以,并没有真正灰度发布。

如果要保存随机数字与Version的对应关系,倒是可以解决这个问题,只是稍麻烦了点,回头再说吧。

3. Electron应用的开发测试方法

3.1. 修改development模式下的代码

在开发时,如果不禁用autoupdate,每次reload都会收到一个报错:

[error] Error: Error: ENOENT: no such file or directory, open 'D:\code\im\desktop-client\dist\main\dev-app-update.yml'

简单的办法,在development模式下,禁用autoupdate,但是,后续如果要做autoupdate窗口,总不能每次都build,然后执行uppacked文件吧,会很花时间。

所以,一劳永逸的做法,修改代码,以支持development模式下的正常开发。

provider: s3
bucket: public
endpoint: http://10.211.28.93:9999
channel: latest
path: /im/artifact/lastest/win
updaterCacheDirName: foxchat-updater
const isDev = process.env.environment == 'development'
if (isDev) {
    autoUpdater.updateConfigPath = path.join(__dirname, '../../dev-app-update.yml')
}

3.2. 开发测试

如果不开发autoupdate功能

如果开发autoupdate功能

4. Electron应用的发布流程

关键点是如何在publish时候修改latest.ymlelectron-builder也不支持
甚至如何只publish,也不支持,issue-4535

所以,只能自己开发脚本,完成latest.yml的修改,并上传MinIO
在build之后,测试OK了,和publish脚本一起执行即可

const Minio = require('minio')
const shell = require('shelljs')
const fs = require('fs')
import chalk from 'chalk'
import { version } from '../package.json'

const minioClient = new Minio.Client({
    endPoint: '10.211.28.93',
    port: 9999,
    useSSL: false,
    accessKey: 'xxx',
    secretKey: 'EXAMPLEKEY'
})

const TAG = '[script/build.ts]'
const extraFile = './script/publish-extra-info.yml'
const latestFile = `./release/${version}/s3/latest.yml`

function isExists(filepath: string) {
    if (!fs.existsSync(filepath)) {
        console.log(TAG, `File ${filepath} not exists.`)
    }
    return true
}

// TODO: 该脚本被执行多次时,会累加内容到latest.yml,可能会引起自动升级功能失效。因此,不能被执行多次
if (!isExists(extraFile) || !isExists(latestFile) || shell.exec(`cat ${extraFile} >> ${latestFile}`).code !== 0) {
    console.log(TAG, chalk.green(`Append failed from ${extraFile} to ${latestFile}.`))
    shell.exit(1)
}
console.log(TAG, chalk.green(`Append successed from ${extraFile} to ${latestFile}.`))

minioClient.fPutObject('public', 'im/artifact/lastest/win/latest.yml', latestFile, (err: any, objInfo: string) => {
    if(err) {
        return console.log(TAG, err)
    }
    console.log(TAG, chalk.green(`Upload to MinIO successed, object id: ${objInfo}.`))
})

5. 后记

在线升级功能,必须要有,几乎标配。否则,只能仰仗用户手动升级,体验很差。
但是,功能一定要稳定健壮,可以不炫,可以不酷,朴实可靠即可。
另外,随着项目上线,对MinIO的权限管理需要加强,包含bucket和key等。

上一篇 下一篇

猜你喜欢

热点阅读