前端

Electron - 自动升级总结

2021-06-30  本文已影响0人  红薯爱帅

1. 概述

本文介绍electron应用的在线升级方案调研和开发。

2. 客户端升级方案探讨

客户端升级方案

如上图,通过三个方面讨论一下在线升级的几个概念

2.1. 带宽因素

带宽的大小,直接关系到安装包的下载时长。
带宽因素,其实也就是安装包的体积因素,所以,尽量生成高压缩比的安装包。
Electron应用的package.jsonbuild字段,可配置安装包的高压缩比:

{
  "build": {
    "asar": true,
    "compression": "maximum",
    ... 
  }
}

在安装包大小一定的情况下,在线升级分为全量更新增量更新

全量更新

下载NewVersion的Installer,并覆盖安装

增量更新

Electron应用如何支持增量更新

Electron-updater采用上述方法3,更新机制和详细日志可以参考附1的日志

2.2. 用户量

对于活跃用户量很大的应用,灰度发布很有必要,不论客户端还是服务端
如果是项目初期,用户量并不多,功能并不复杂,变动大,而且经常迭代更新,全量发布会减少项目的迭代负担,更早发现问题、解决问题
当然,前提是测试要充分,让用户发现问题是下下策

全量发布

针对所有用户发布

灰度发布

只针对部分用户发布,可以随机20%发布,也可以基于用户Tag发布(前提是有可用的用户Tag)

Electron应用如何支持灰度发布

Electron应用在electron-updater的基础上,也可以支持灰度发布,三个点:

2.3. 兼容性

强制更新

启动时,自动无感更新

这种情况,一般是服务端的升级已不再支持旧版本,Electron应用的实现机制

可选更新

启动时,自动可选更新

强制更新的最后一步,如果CurrentVersion >= minVersionSupported,用户可选择是否立即更新

启动后,手动检测更新

一般情况下,在客户端会提供一个Page,供用户手动查看当前版本、检测是否有新版本,以及执行立即更新

2.4. 其他问题

2.4.1. 新版本的变更内容

仿照灰度发布强制更新的做法,可以修改latest.yml来实现

Electron支持Github Release的Release-Notes,对其他server不支持,所以只能用上面workaround

2.4.2. 客户端安装失败后怎么办

这个问题很严重,主要是对终端的适配问题,于是,测试工作就显得尤为重要

如果真在用户端发生了,需要具体问题具体分析了

3. 构建与发布

3.1. 打包工具

Electron应用的打包和发布,主流工具有3个,可以参考官网介绍

经过各种对比,主要是易用性和生态完整性,决定采用electron-builder,官网:https://www.electron.build

3.2. 自动更新工具

Differences between electron-updater and built-in autoUpdater

import { autoUpdater } from "electron-updater"
autoUpdater.checkForUpdatesAndNotify()

Electron-updater的优缺点:

优点

缺点

3.3. Release Server

Electron的打包最终是为了发布,因此支持不同方式的Publish,Release Server有以下类型:

electron-release-server是一个完善的Generic Server,支持安装包的上传和下载,以及分类管理,自带Web。缺点是,还需要自己手动upload,不能自动publish。

本文采用MinIO(类S3的分布式对象存储服务)为例。

4. 打包开发与测试

4.1. 启动minio server

docker run -p 9999:9000 \
  --name minio --rm -d \
  -e "MINIO_ROOT_USER=xxx" \
  -e "MINIO_ROOT_PASSWORD=wJalrXUtnFENG/bxxR12CYxxxwwEXAMPLEKEY" \
  -v /home/xxx/soft/minio/data:/data \
  minio/minio server /data

通过浏览器打开MinIO Dashboard:http://10.211.28.93:9999
并创建一个prefix是*的readonly的bucket,名字是public,下面会用到

4.2. 自动打包发布

修改package.json,增加build字段如下,electron-builder会读这个字段

增加electron-builder.env文件,内容如下,存储MinIO的秘钥

# publish to minio witch is s3-likely storage server
AWS_ACCESS_KEY_ID=xxx
AWS_SECRET_ACCESS_KEY=wJalrXUtnFENG/bxxR12CYxxxwwEXAMPLEKEY

执行yarn electron-builder --publish always即可打包和发布

推荐采用MinIO作为release-server,可以自动publish,提高效率

{
  "build": {
    "appId": "com.foxchat.www",
    "asar": true,
    "compression": "maximum",
    "directories": {
      "output": "release/${version}"
    },
    "electronDownload": {
      "mirror": "https://npm.taobao.org/mirrors/electron/"
    },
    "files": [
      "!node_modules",
      "node_modules/@sentry/**/*",
      "dist/**"
    ],
    "mac": {
      "icon": "build/icons/icon.icns",
      "artifactName": "${productName}-${os}-${arch}-${version}-setup.${ext}",
      "target": [
        "dmg"
      ]
    },
    "win": {
      "icon": "build/icons/logo256.ico",
      "artifactName": "${productName}-${os}-${arch}-${version}-setup.${ext}",
      "target": [
        {
          "target": "nsis",
          "arch": [
            "x64"
          ]
        }
      ]
    },
    "linux": {
      "icon": "build/icons",
      "target": "deb"
    },
    "nsis": {
      "oneClick": false,
      "allowElevation": true,
      "perMachine": false,
      "allowToChangeInstallationDirectory": true,
      "installerIcon": "./build/icons/logo256.ico",
      "uninstallerIcon": "./build/icons/logo256.ico",
      "installerHeaderIcon": "./build/icons/logo256.ico",
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true,
      "shortcutName": "FoxChat",
      "deleteAppDataOnUninstall": false
    },
    "publish": [
      {
        "provider": "s3",
        "bucket": "public",
        "endpoint": "http://10.211.28.93:9999",
        "channel": "latest",
        "path": "/im/artifact/latest/${os}"
      },
      {
        "provider": "s3",
        "bucket": "public",
        "endpoint": "http://10.211.28.93:9999",
        "channel": "latest",
        "path": "/im/artifact/${version}/${os}"
      },
      {
        "provider": "generic",
        "url": "http://10.211.28.93:9797/artifact"
      }
    ]
  },
}

4.3. Tips

修改nsis脚本,可以自定义安装界面

参考:https://github.com/eyasliu/blog/issues/22

image image

5. 客户端自动更新开发

基于electron-updater完成开发,直接上代码

这里补充几点:

import { version } from '../../../package.json'
import { app } from 'electron'
app.getVersion = () => version
{
  version: '0.0.7',
  files: [
    {
      url: 'FoxChat-win-0.0.7-setup.exe',
      sha512: '795pdq9/Lt9MuANpM3tChxpCtzsqNe4v2wWyK41kUJ3PABHJns2xo5Jw46CWFOOCEVes57L5lmXV9v4NWNBeXg==',
      size: 62858586
    }
  ],
  path: 'FoxChat-win-0.0.7-setup.exe',
  sha512: '795pdq9/Lt9MuANpM3tChxpCtzsqNe4v2wWyK41kUJ3PABHJns2xo5Jw46CWFOOCEVes57L5lmXV9v4NWNBeXg==',
  releaseDate: '2021-06-29T10:09:27.716Z',
  releaseNotes: [ '增加在线升级功能', '登录功能优化' ],
  minVersionSupported: '0.1.0',
  grayReleased: 100,
  downloadedFile: 'C:\\Users\\Administrator\\AppData\\Local\\foxchat-updater\\pending\\FoxChat-win-0.0.7-setup.exe'
}
自动升级的安装包下载路径:
C:\Users\Administrator\AppData\Local\foxchat-updater

Electron-log的默认路径
C:\Users\Administrator\AppData\Roaming\FoxChat\logs
import { app, dialog } from 'electron'
import { autoUpdater } from "electron-updater"
import log from 'electron-log'

log.transports.file.level = "debug"
autoUpdater.logger = log

function updateHandle() {
    log.info('client version', app.getVersion())

    autoUpdater.autoDownload = false

    autoUpdater.on('error', (error) => {
        dialog.showErrorBox('Error: ', error == null ? "unknown" : (error.stack || error).toString())
    })
    
    autoUpdater.on('checking-for-update', () => {
        log.info('Checking for update')
    });

    autoUpdater.on('update-available', (info) => {
        log.info('Got a new client version, will auto download it', info)
        autoUpdater.downloadUpdate()  
    })

    autoUpdater.on('update-not-available', (info) => {
        log.info('Current version is up-to-date', info)
    })

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

    autoUpdater.on('download-progress', function (progressObj) {
        log.debug('download progress', progressObj)
    })

    autoUpdater.checkForUpdates()
}

updateHandle()

export {updateHandle}

附1,electron-updater的增量更新日志

增量更新的机制

效果

从下面的log可以,可以看到只下载了7%大小的文件内容,体积不到4MB:Full: 61,385.34 KB, To download: 4,103.49 KB (7%)

一次客户端升级的完整日志

[2021-06-30 15:27:03.799] [info]  client version 0.0.6
[2021-06-30 15:27:03.807] [info]  Checking for update
[2021-06-30 15:27:13.150] [info]  Found version 0.0.7 (url: FoxChat-win-0.0.7-setup.exe)
[2021-06-30 15:27:13.151] [info]  Got a new client version, will auto download it {
  version: '0.0.7',
  files: [
    {
      url: 'FoxChat-win-0.0.7-setup.exe',
      sha512: '795pdq9/Lt9MuANpM3tChxpCtzsqNe4v2wWyK41kUJ3PABHJns2xo5Jw46CWFOOCEVes57L5lmXV9v4NWNBeXg==',
      size: 62858586
    }
  ],
  path: 'FoxChat-win-0.0.7-setup.exe',
  sha512: '795pdq9/Lt9MuANpM3tChxpCtzsqNe4v2wWyK41kUJ3PABHJns2xo5Jw46CWFOOCEVes57L5lmXV9v4NWNBeXg==',
  releaseDate: '2021-06-29T10:09:27.716Z'
}
[2021-06-30 15:27:13.155] [info]  Downloading update from FoxChat-win-0.0.7-setup.exe
[2021-06-30 15:27:13.157] [debug] updater cache dir: C:\Users\Administrator\AppData\Local\foxchat-updater
[2021-06-30 15:27:13.164] [info]  Download block maps (old: "http://10.211.28.93:9999/public/im/artifact/latest/win/FoxChat-win-0.0.6-setup.exe.blockmap", new: http://10.211.28.93:9999/public/im/artifact/latest/win/FoxChat-win-0.0.7-setup.exe.blockmap)
[2021-06-30 15:27:13.202] [info]  File has 195 changed blocks
[2021-06-30 15:27:13.203] [debug] [
  {
    "kind": 0,
    "start": 0,
    "end": 350804
  },
  {
    "kind": 1,
    "start": 350804,
    "end": 430577
  },
  {
    "kind": 0,
    "start": 430577,
    "end": 463345
  },
  {
    "kind": 1,
    "start": 463345,
    "end": 490212
  },
  {
    "kind": 0,
    "start": 490212,
    "end": 10750880
  },
  {
    "kind": 1,
    "start": 10750880,
    "end": 14595768
  },
  {
    "kind": 0,
    "start": 14595640,
    "end": 54052515
  },
  {
    "kind": 1,
    "start": 54052643,
    "end": 54172009
  },
  {
    "kind": 0,
    "start": 54171859,
    "end": 62463158
  },
  {
    "kind": 1,
    "start": 62463308,
    "end": 62479157
  },
  {
    "kind": 0,
    "start": 62479006,
    "end": 62743206
  },
  {
    "kind": 1,
    "start": 62743357,
    "end": 62858586
  }
]
[2021-06-30 15:27:13.220] [info]  Full: 61,385.34 KB, To download: 4,103.49 KB (7%)
[2021-06-30 15:27:13.224] [info]  Differential download: http://10.211.28.93:9999/public/im/artifact/latest/win/FoxChat-win-0.0.7-setup.exe
[2021-06-30 15:27:13.249] [debug] download range: bytes=350804-430576
[2021-06-30 15:27:13.266] [debug] download progress {
  total: 4201972,
  delta: 79773,
  transferred: 79773,
  percent: 1.8984657679775117,
  bytesPerSecond: 1899357
}
[2021-06-30 15:27:13.268] [debug] download range: bytes=463345-490211
[2021-06-30 15:27:13.278] [debug] download progress {
  total: 4201972,
  delta: 106640,
  transferred: 106640,
  percent: 2.5378560352139425,
  bytesPerSecond: 1974815
}
[2021-06-30 15:27:13.388] [debug] download range: bytes=10750880-14595767
[2021-06-30 15:27:13.900] [debug] download progress {
  total: 4201972,
  delta: 3951528,
  transferred: 3951528,
  percent: 94.03984605323406,
  bytesPerSecond: 5845456
}
[2021-06-30 15:27:16.128] [debug] download range: bytes=54052643-54172008
[2021-06-30 15:27:16.138] [debug] download progress {
  total: 4201972,
  delta: 3964841,
  transferred: 3964841,
  percent: 94.3566734856872,
  bytesPerSecond: 1361085
}
[2021-06-30 15:27:16.156] [debug] download progress {
  total: 4201972,
  delta: 106053,
  transferred: 4070894,
  percent: 96.88055988949951,
  bytesPerSecond: 1388436
}
[2021-06-30 15:27:16.218] [debug] download range: bytes=62463308-62479156
[2021-06-30 15:27:16.236] [debug] download progress {
  total: 4201972,
  delta: 121902,
  transferred: 4086743,
  percent: 97.2577399373437,
  bytesPerSecond: 1356820
}
[2021-06-30 15:27:16.240] [debug] download range: bytes=62743357-62858585
[2021-06-30 15:27:16.263] [debug] download progress {
  total: 4201972,
  delta: 237131,
  transferred: 4201972,
  percent: 100,
  bytesPerSecond: 1382682
}
[2021-06-30 15:27:16.634] [info]  New version 0.0.7 has been downloaded to C:\Users\Administrator\AppData\Local\foxchat-updater\pending\FoxChat-win-0.0.7-setup.exe
[2021-06-30 15:27:32.884] [info]  begin to install new version ...
[2021-06-30 15:27:32.885] [info]  Install on explicit quitAndInstall
[2021-06-30 15:27:32.886] [info]  Install: isSilent: true, isForceRunAfter: true
[2021-06-30 15:27:33.149] [info]  Update installer has already been triggered. Quitting application.
[2021-06-30 15:27:43.027] [info]  client version 0.0.7
[2021-06-30 15:27:43.210] [info]  App starting... 0.0.7
上一篇 下一篇

猜你喜欢

热点阅读