更新应用
有几种方式可以为你的 Electron 应用提供自动更新。最简单且官方支持的方法是利用内置的 Squirrel 框架和 Electron 的 autoUpdater 模块。
🌐 There are several ways to provide automatic updates to your Electron application. The easiest and officially supported one is taking advantage of the built-in Squirrel framework and Electron's autoUpdater module.
使用云对象存储(无服务器)
🌐 Using cloud object storage (serverless)
对于一个简单的无服务器更新进程,Electron 的 autoUpdater 模块可以通过指向包含最新版本元数据的静态存储 URL 来检查是否有可用更新。
🌐 For a simple serverless update flow, Electron's autoUpdater module can check if updates are available by pointing to a static storage URL containing latest release metadata.
当有新版本可用时,这些元数据需要与版本本身一起发布到云存储中。macOS 和 Windows 的元数据格式不同。
🌐 When a new release is available, this metadata needs to be published to cloud storage alongside the release itself. The metadata format is different for macOS and Windows.
发布版本元数据
🌐 Publishing release metadata
使用 Electron Forge,你可以通过从 ZIP Maker(macOS)使用 macUpdateManifestBaseUrl 和 Squirrel.Windows Maker(Windows)使用 remoteReleases 发布元数据工件来设置静态文件存储的更新。
🌐 With Electron Forge, you can set up static file storage updates by publishing
metadata artifacts from the ZIP Maker (macOS) with macUpdateManifestBaseUrl
and the Squirrel.Windows Maker (Windows) with remoteReleases.
请参阅 Forge 的从 S3 自动更新指南,了解完整示例。
🌐 See Forge's Auto updating from S3 guide for an end-to-end example.
手动发布
在 macOS 上,Squirrel.Mac 可以通过读取具有以下 JSON 格式的 releases.json 文件来接收更新:
🌐 On macOS, Squirrel.Mac can receive updates by reading a releases.json file with the
following JSON format:
{
"currentRelease": "1.2.3",
"releases": [
{
"version": "1.2.1",
"updateTo": {
"version": "1.2.1",
"pub_date": "2023-09-18T12:29:53+01:00",
"notes": "These are some release notes innit",
"name": "1.2.1",
"url": "https://mycompany.example.com/myapp/releases/myrelease"
}
},
{
"version": "1.2.3",
"updateTo": {
"version": "1.2.3",
"pub_date": "2024-09-18T12:29:53+01:00",
"notes": "These are some more release notes innit",
"name": "1.2.3",
"url": "https://mycompany.example.com/myapp/releases/myrelease3"
}
}
]
}
在 Windows 上,Squirrel.Windows 可以通过读取在构建进程中生成的 RELEASES 文件来接收更新。该文件详细说明了用于更新到 .nupkg 的增量包。
🌐 On Windows, Squirrel.Windows can receive updates by reading from the RELEASES
file generated during the build process. This file details the .nupkg delta
package to update to.
B0892F3C7AC91D72A6271FF36905FEF8FE993520 electron-fiddle-0.36.3-full.nupkg 103298365
这些文件应该与你的发布版本位于同一目录下,并放在一个了解你应用平台和架构的文件夹结构中。
🌐 These files should live in the same directory as your release, under a folder structure that is aware of your app's platform and architecture.
例如:
🌐 For example:
my-app-updates/
├─ darwin/
│ ├─ x64/
│ │ ├─ my-app-1.0.0-darwin-x64.zip
│ │ ├─ my-app-1.1.0-darwin-x64.zip
│ │ ├─ RELEASES.json
│ ├─ arm64/
│ │ ├─ my-app-1.0.0-darwin-arm64.zip
│ │ ├─ my-app-1.1.0-darwin-arm64.zip
│ │ ├─ RELEASES.json
├─ win32/
│ ├─ x64/
│ │ ├─ my-app-1.0.0-win32-x64.exe
│ │ ├─ my-app-1.0.0-win32-x64.nupkg
│ │ ├─ my-app-1.1.0-win32-x64.exe
│ │ ├─ my-app-1.1.0-win32-x64.nupkg
│ │ ├─ RELEASES
读取发布元数据
🌐 Reading release metadata
使用元数据最简单的方法是安装 更新电子应用,这是一个即插即用的 Node.js 模块,它可以设置 autoUpdater 并通过原生对话框提示用户。
🌐 The easiest way to consume metadata is by installing update-electron-app, a drop-in Node.js module that sets up autoUpdater and prompts the user with a native dialog.
对于静态存储更新,将 updateSource.baseUrl 参数指向包含发布元数据文件的目录。
🌐 For static storage updates, point the updateSource.baseUrl parameter to
the directory containing your release metadata files.
const { updateElectronApp, UpdateSourceType } = require('update-electron-app')
updateElectronApp({
updateSource: {
type: UpdateSourceType.StaticStorage,
baseUrl: `https://my-bucket.s3.amazonaws.com/my-app-updates/${process.platform}/${process.arch}`
}
})
使用 update. Electronjs.org
🌐 Using update.electronjs.org
Electron 团队维护着 update.electronjs.org,这是一个免费开源的网络服务,Electron 应用可以使用它进行自我更新。该服务面向符合以下条件的 Electron 应用设计:
🌐 The Electron team maintains update.electronjs.org, a free and open-source webservice that Electron apps can use to self-update. The service is designed for Electron apps that meet the following criteria:
- 应用在 macOS 或 Windows 上运行
- 应用有一个公共 GitHub 存储库
- 构建已发布到 GitHub 发行版
- 构建版本已代码签名 (仅限 macOS)
使用此服务的最简单方法是安装 更新电子应用,这是一个为 update.electronjs.org 使用预配置的 Node.js 模块。
🌐 The easiest way to use this service is by installing update-electron-app, a Node.js module preconfigured for use with update.electronjs.org.
使用你选择的 Node.js 包管理器安装模块:
🌐 Install the module using your Node.js package manager of choice:
- npm
- Yarn
npm install update-electron-app
yarn add update-electron-app
然后,从应用的主进程文件调用更新程序:
🌐 Then, invoke the updater from your app's main process file:
require('update-electron-app')()
默认情况下,该模块将在应用启动时检查更新,然后每十分钟检查一次。当发现更新时,它将自动在后台下载。下载完成后,会显示一个对话框,允许用户重新启动应用。
🌐 By default, this module will check for updates at app startup, then every ten minutes. When an update is found, it will automatically be downloaded in the background. When the download completes, a dialog is displayed allowing the user to restart the app.
如果你需要自定义你的配置,你可以 传递选项给 update-electron-app 或 直接使用更新服务。
🌐 If you need to customize your configuration, you can pass options to update-electron-app or use the update service directly.
使用其他更新服务
🌐 Using other update services
如果你正在开发一个私有的 Electron 应用,或者你没有将版本发布到 GitHub Releases,那么可能需要运行你自己的更新服务器。
🌐 If you're developing a private Electron application, or if you're not publishing releases to GitHub Releases, it may be necessary to run your own update server.
步骤1:部署更新服务器
🌐 Step 1: Deploying an update server
根据你的需要,你可以选择以下之一:
🌐 Depending on your needs, you can choose from one of these:
- 榛子 – 为私有或开源应用更新服务器,可免费部署在 Vercel 上。它从 GitHub 发行版 获取内容,并利用 GitHub CDN 的强大功能。
- 坚果 – 也使用 GitHub 发行版,但将应用更新缓存到磁盘并支持私有仓库。
- 电子发布服务器 – 提供了一个用于管理版本的仪表板,并且不要求版本必须源自 GitHub。
- 细胞核 – Atlassian 维护的 Electron 应用完整更新服务器。支持多个应用和渠道;使用静态文件存储以降低服务器成本。
一旦你部署了更新服务器,就可以在应用代码中使用 Electron 的 autoUpdater 模块来接收和应用更新。
🌐 Once you've deployed your update server, you can instrument your app code to receive and apply the updates with Electron's autoUpdater module.
步骤 2:在你的应用中接收更新
🌐 Step 2: Receiving updates in your app
首先,在你的主进程代码中导入所需的模块。以下代码可能因不同的服务器软件而有所不同,但在使用 榛子 时,它的工作方式如上述所示。
🌐 First, import the required modules in your main process code. The following code might vary for different server software, but it works like described when using Hazel.
请确保下面的代码仅在已打包的应用中执行,而不是在开发环境中执行。你可以使用 app.isPackaged API 来检查环境。
🌐 Please ensure that the code below will only be executed in your packaged app, and not in development. You can use the app.isPackaged API to check the environment.
const { app, autoUpdater, dialog } = require('electron')
接下来,构建更新服务器源的 URL,并将其告知 autoUpdater:
🌐 Next, construct the URL of the update server feed and tell autoUpdater about it:
const server = 'https://your-deployment-url.com'
const url = `${server}/update/${process.platform}/${app.getVersion()}`
autoUpdater.setFeedURL({ url })
作为最后一步,检查更新。下面的示例将每分钟检查一次:
🌐 As the final step, check for updates. The example below will check every minute:
setInterval(() => {
autoUpdater.checkForUpdates()
}, 60000)
一旦你的应用被打包,每次你发布新的 GitHub 发行版 时,它都将收到更新。
🌐 Once your application is packaged, it will receive an update for each new GitHub Release that you publish.
步骤3:在有更新时通知用户
🌐 Step 3: Notifying users when updates are available
现在你已经为你的应用配置了基本的更新机制,你需要确保当有更新时用户会收到通知。这可以通过使用 autoUpdater API 事件 来实现:
🌐 Now that you've configured the basic update mechanism for your application, you need to ensure that the user will get notified when there's an update. This can be achieved using the autoUpdater API events:
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Restart', 'Later'],
title: 'Application Update',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail:
'A new version has been downloaded. Restart the application to apply the updates.'
}
dialog.showMessageBox(dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall()
})
})
还要确保错误得到了处理。下面是一个将它们记录到 stderr 的示例:
🌐 Also make sure that errors are
being handled. Here's an example
for logging them to stderr:
autoUpdater.on('error', (message) => {
console.error('There was a problem updating the application')
console.error(message)
})
由于 autoUpdate 发出的请求不在你的直接控制范围内,你可能会遇到一些难以处理的情况(例如更新服务器需要身份验证)。url 字段支持 file:// 协议,这意味着通过一些努力,你可以通过从本地目录加载更新来绕过服务器通信部分的进程。这里是一个可能的实现示例。
🌐 Because the requests made by autoUpdate aren't under your direct control, you may find situations
that are difficult to handle (such as if the update server is behind authentication). The url
field supports the file:// protocol, which means that with some effort, you can sidestep the
server-communication aspect of the process by loading your update from a local directory.
Here's an example of how this could work.
更新服务器规范
🌐 Update server specification
对于高级部署需求,你还可以部署自己的兼容 Squirrel 的更新服务器。例如,你可能希望基于百分比进行发布,通过不同的发布渠道分发应用,或将更新服务器设置为需要身份验证才能访问。
🌐 For advanced deployment needs, you can also roll out your own Squirrel-compatible update server. For example, you may want to have percentage-based rollouts, distribute your app through separate release channels, or put your update server behind an authentication check.
Squirrel.Windows 和 Squirrel.Mac 客户端需要不同的响应格式,但你可以通过根据 process.platform 的值将请求发送到不同的端点,从而使用同一个服务器来支持两个平台。
🌐 Squirrel.Windows and Squirrel.Mac clients require different response formats,
but you can use a single server for both platforms by sending requests to
different endpoints depending on the value of process.platform.
const { app, autoUpdater } = require('electron')
const server = 'https://your-deployment-url.com'
// e.g. for Windows and app version 1.2.3
// https://your-deployment-url.com/update/win32/1.2.3
const url = `${server}/update/${process.platform}/${app.getVersion()}`
autoUpdater.setFeedURL({ url })
Windows
Squirrel.Windows 客户端期望更新服务器在你端点的 /RELEASES 子路径下返回最新可用版本的 RELEASES 构件。
🌐 A Squirrel.Windows client expects the update server to return the RELEASES artifact
of the latest available build at the /RELEASES subpath of your endpoint.
例如,如果你的订阅源 URL 是 https://your-deployment-url.com/update/win32/1.2.3,那么 https://your-deployment-url.com/update/win32/1.2.3/RELEASES 端点应该返回你想提供的版本的 RELEASES 工件的内容。
🌐 For example, if your feed URL is https://your-deployment-url.com/update/win32/1.2.3,
then the https://your-deployment-url.com/update/win32/1.2.3/RELEASES endpoint
should return the contents of the RELEASES artifact of the version you want to serve.
B0892F3C7AC91D72A6271FF36905FEF8FE993520 https://your-static.storage/your-app-1.2.3-full.nupkg 103298365
Squirrel.Windows 会进行比较检查,以确定当前应用是否应该更新到 RELEASES 中返回的版本,因此即使没有可用更新,也应该返回响应。
🌐 Squirrel.Windows does the comparison check to see if the current app should update to
the version returned in RELEASES, so you should return a response even when no update
is available.
macOS
当有更新可用时,Squirrel.Mac 客户端会在 feed URL 的端点处期待一个 JSON 响应。该对象有一个必需的 url 属性,它对应于应用更新的 ZIP 压缩包。对象中的其他所有属性都是可选的。
🌐 When an update is available, the Squirrel.Mac client expects a JSON response at the feed URL's endpoint.
This object has a mandatory url property that maps to a ZIP archive of the
app update. All other properties in the object are optional.
{
"url": "https://your-static.storage/your-app-1.2.3-darwin.zip",
"name": "1.2.3",
"notes": "These are some release notes innit",
"pub_date": "2024-09-18T12:29:53+01:00"
}
如果没有可用更新,服务器应返回204 No Content HTTP 响应。
🌐 If no update is available, the server should return a 204 No Content
HTTP response.