前言
公众号:【可乐前端】,分享前端面试与web实战知识
在前面已经实现了我们自己的Markdown编辑软件,首次安装肯定是要手动下载安装的,但是在后续的迭代更新中,如果还需要一次次的去手动下载安装替换的话,那么体验肯定是不太好的。
本文介绍了如何在 Electron
中自动发布到 GitHub
以及自动更新的实现方案,话不多说,让我们立刻开始。
自动发布
我们可以依托 GitHub
作为安装包的托管平台,对于每一次的版本发布,都可以在对应的仓库里新建一个 release
,并把对应的安装包资源传输到 release
中。
打包的时候可以使用 electron-builder
这个库,在根目录下创建 electron-builder.yml
配置文件。写入如下配置:
publish: provider: github owner: '你的账户名' repo: '你的仓库名' token: '你的token' releaseType: 'release'
如何生成 GitHub Token
已经在上一期文章中介绍过,感兴趣的同学可以在上面链接中点开查看。然后修改打包的命令如下:
"build:mac": "npm run build && electron-builder --mac --config --publish always"
这样在我们在我们执行完打包命令之后,会自动把产物推送到 GitHub
对应的 release
中。这里需要注意的一点是,版本号都是基于 package.json
的 version
字段,所以在每一次打包发布之前记得先修改这里的值。
可以看到在打包完成之后,会自动把产物推送到 GitHub
中,我们可以在 GitHub
对应的发布分支上看到对应的内容。
publish
中 provider
的可选值
在 electron-builder
中,publish
部分的 provider
字段用于指定发布提供者。以下是一些常见的 provider
取值:
GitHub (github
):
使用 GitHub
来发布应用程序。设置 provider: github
时,需要提供 GitHub
仓库的相关信息,例如 repo
、owner
和 GitHub Personal Access Token
。
publish: provider: github repo: owner/repo owner: owner token: $GITHUB_TOKEN
Generic (generic
):
使用通用的发布提供者,这通常用于自定义或私有的发布流程。需要指定发布的目标地址、协议等信息。
publish: provider: generic url: "https://your-custom-publish-server.com" channel: "latest"
当使用通用发布模式时(例如 https://your-custom-publish-server.com
),那么这个自定义服务器应该支持以下几个路由:
/update/${platform}/${arch}/${version}
:
${platform}
: 平台,例如win
,mac
, 或linux
。${arch}
: 架构,例如x64
或arm64
。${version}
: 版本号,例如1.0.0
。
- 该路由用于获取应用程序更新信息,返回一个
JSON
对象,其中包含更新的版本号、下载地址等信息。
示例响应:
{ "name": "YourApp", "notes": "Release notes for version 1.1.0", "pub_date": "2024-02-25T12:00:00Z", "url": "https://your-custom-publish-server.com/downloads/YourApp-1.1.0.zip", "version": "1.1.0" }
/download/${version}/${filename}
:
${version}
: 版本号,例如1.0.0
。${filename}
: 文件名,例如YourApp-1.0.0.zip
。
- 该路由用于提供应用程序的下载文件,返回文件的二进制内容。
/latest
:
该路由用于获取最新版本的应用程序信息,返回一个JSON
对象,其中包含最新版本的版本号、下载地址等信息。
示例响应:
{ "name": "YourApp", "notes": "Release notes for latest version", "pub_date": "2024-02-25T12:00:00Z", "url": "https://your-custom-publish-server.com/downloads/YourApp-latest.zip", "version": "latest" }
Bintray (bintray
):
使用 Bintray
提供者,这通常用于发布到 JCenter
仓库。需要提供 Bintray
仓库的相关信息,例如 owner
、package
、repo
等。
publish: provider: bintray owner: bintray-owner package: bintray-package repo: bintray-repo user: bintray-username token: $BINTRAY_API_KEY
S3 (s3
):
使用 Amazon S3
提供者,用于将应用程序发布到 Amazon S3
存储桶。需要提供 S3
存储桶的相关信息。
publish: provider: s3 bucket: your-s3-bucket acl: public-read
自动更新
自动发布处理完之后,接下来介绍自动更新。自动更新可以使用electron-updater这个库。首先在应用初始化的时候,需要查看当前应用是否有新版本可用,即是否需要自动更新;如果当前有新版本可用,则下载新版本的资源,下载完之后就可以重启应用了。
介绍一下用到electron-updater中的API:
- checkForUpdates:检查是否有新更新可用
- downloadUpdate:下载更新
- quitAndInstall:安装更新
- on:监听事件
- checking-for-update:检查更新中
- update-available:有新版本可用
- update-not-available:没有新版本可用
- error:错误事件
- update-downloaded:更新下载完毕
- download-progress:下载事件,其中包括总下载量、已下载量等属性
- total:下载的文件的总字节数
- delta: 表示自上次进度事件以来已下载的字节数
- transferred: 表示自下载开始以来已经传输的字节数
- percent: 表示下载完成的百分比
- bytesPerSecond: 表示当前下载速度,即每秒传输的字节数
了解了上面的知识之后,可以实现一个监听更新的函数listenAutoUpdate,在app ready时调用。
import { autoUpdater } from 'electron-updater' import { COMMON_ERROR_LOG } from '../event' import { app, dialog } from 'electron' export default (mainWindow) => { const sendStatusToWindow = (text) => { mainWindow.webContents.send(COMMON_ERROR_LOG, `update msg:${text}`) } autoUpdater.checkForUpdates() autoUpdater.autoDownload = false autoUpdater.autoInstallOnAppQuit = true autoUpdater.on('checking-for-update', () => { sendStatusToWindow('Checking for update...') }) autoUpdater.on('update-available', (info) => { // 当有新版本可用时,弹窗提示用户 dialog .showMessageBox({ type: 'info', title: '新版本可用', message: '有一个可用的新版本,要更新吗', buttons: ['是', '否'] }) .then((result) => { if (result.response === 0) { // 用户选择更新,触发下载和安装 autoUpdater.downloadUpdate() } }) }) autoUpdater.on('update-not-available', (info) => { sendStatusToWindow('Update not available.') }) autoUpdater.on('error', (err) => { sendStatusToWindow(err) }) autoUpdater.on('update-downloaded', () => { // 处理下载完成的情况 dialog .showMessageBox({ type: 'info', title: '更新下载完成', message: '点击确定重启获取最新内容', buttons: ['确定'] }) .then(() => { // 调用 quitAndInstall 来安装更新 autoUpdater.quitAndInstall() }) }) autoUpdater.on('download-progress', (progressObj) => { sendStatusToWindow(JSON.stringify(progressObj)) }) }
上面的代码主要做了如下的事情:
- 检查是否有更新。
- 监听自动更新的不同阶段的事件,包括检查更新、更新可用、更新未可用、下载进度以及下载完成。
- 根据不同事件的触发,执行相应的操作,例如弹出提示用户更新的对话框、显示下载进度等。
在 Mac
中需要注意的坑:
- 在一些脚手架生成的代码中会有这么一段代码:
app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } })
这样资源占用导致自动更新失败,需要把这个 if
去掉
- 在
macOS
上,应用程序必须得到签名后才能自动更新。 这是Squirrel.Mac
的要求。
最后
以上就是本文的所有内容,介绍了 Electron
中自动发布与更新的一些方法。如果你觉得有意思的话,点点关注点点赞吧~