更新应用
有多种方法可以为你的 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,你可以通过从带有 macUpdateManifestBaseUrl
的 ZIP Maker(macOS)和带有 remoteReleases
的 Squirrel.Windows Maker(Windows)发布元数据工件来设置静态文件存储更新。
¥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.
Manual publishing
在 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": "Theses 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": "Theses 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
使用元数据的最简单方法是安装 update-electron-app,这是一个嵌入式 Node.js 模块,用于设置自动更新程序并使用原生对话框提示用户。
¥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,这是一个免费的开源 Web 服务,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 上运行
¥App runs on macOS or Windows
-
应用有一个公共 GitHub 存储库
¥App has a public GitHub repository
-
版本发布到 GitHub 发布
¥Builds are published to GitHub Releases
-
构建为 code-signed(仅限 macOS)
¥Builds are code-signed (macOS only)
使用此服务的最简单方法是安装 update-electron-app,这是一个预先配置为与 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:
-
Hazel - 更新可在 Vercel 上免费部署的私有或开源应用的服务器。它源自 GitHub 发布 并利用 GitHub 的 CDN 的强大功能。
¥Hazel – Update server for private or open-source apps which can be deployed for free on Vercel. It pulls from GitHub Releases and leverages the power of GitHub's CDN.
-
坚果 - 也使用 GitHub 发布,但在磁盘上缓存应用更新并支持私有存储库。
¥Nuts – Also uses GitHub Releases, but caches app updates on disk and supports private repositories.
-
electron-release-server - 提供用于处理发布的仪表板,并且不需要发布源自 GitHub。
¥electron-release-server – Provides a dashboard for handling releases and does not require releases to originate on GitHub.
-
核 - 由 Atlassian 维护的 Electron 应用的完整更新服务器。支持多种应用和渠道;使用静态文件存储来降低服务器成本。
¥Nucleus – A complete update server for Electron apps maintained by Atlassian. Supports multiple applications and channels; uses a static file store to minify server cost.
部署更新服务器后,你可以检测应用代码以使用 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
首先,在主进程代码中导入所需的模块。以下代码可能因不同的服务器软件而异,但其工作原理与使用 Hazel 时所描述的相同。
¥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)
一旦你的应用达到 packaged,它将收到你发布的每个新 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
现在你已经为应用配置了基本更新机制,你需要确保用户在有更新时收到通知。这可以使用 自动更新 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.
例如,如果你的 feed 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": "Theses 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.