自动更新概述:让应用自己升级
本教程共 45 篇 · 第 29 篇 · 更新于 2026-08-03
29. 自动更新概述:让应用自己升级
本节目标
- 理解为什么桌面应用需要自动更新能力。
- 了解
autoUpdater背后的 Squirrel 机制。 - 弄清更新服务器与更新源(feed)的角色。
- 掌握「检查→下载→安装」的整体更新流程。
- 知道 macOS / Windows / Linux 在自动更新上的差异。
1-1 为什么需要自动更新
网页应用天然随时是最新版,因为每次访问都拉取服务器资源。桌面应用却不同:用户安装的是一份本地副本,不重装就不会变。
如果你的应用有 bug 需要修,或者有新功能要上线,却只能靠用户手动去官网下载新版,那升级率会很低,旧版本会长期滞留。自动更新就是让应用「自己发现新版本并装上」的能力。
它带来的好处很直接:安全补丁能快速触达用户,新功能无需用户干预即可生效,也减轻了你维护多个旧版本的负担。
1-2 autoUpdater 是什么
Electron 内置的 autoUpdater 模块,负责「向更新服务器询问是否有新版本,有则下载并安装」。它在主进程运行,本质是一个 EventEmitter,通过事件把更新状态告诉你的代码。
注意它只管「更新」这一件事,不负责「打包」和「发布」。打包由 Electron Forge 等工具完成,发布是把产物传到 GitHub Releases 或自有服务器,更新则是 autoUpdater 在已安装的应用里完成的最后一步。
// 主进程 main.js(仅示意结构,细节见下一章)
const { autoUpdater } = require('electron/main')
autoUpdater.on('update-available', () => {
console.log('发现新版本,开始下载')
})
1-3 底层的 Squirrel 机制
autoUpdater 并非自己发明了一套更新协议,而是建立在 Squirrel 这套成熟的桌面更新框架之上。不同平台选用不同的实现:
- macOS:基于 Squirrel.Mac。应用必须是「签名过的普通
.app」,更新时把新版本换进应用目录。 - Windows:根据打包格式自动选择。用 Squirrel.Windows 安装器打包的,走 Squirrel.Windows;用 MSIX 打包的,走 MSIX 更新机制。Electron 会自动识别,无需你手动配置。
Squirrel 的核心思路是「原子替换」:下载新版本到临时位置,校验无误后再切换,避免更新中途断电导致应用无法启动。这也是为什么 macOS 上自动更新强制要求代码签名——Squirrel.Mac 的更新过程依赖签名来保证来源可信。
1-4 更新服务器与更新源
autoUpdater 不会凭空知道有没有新版本,它需要指向一个「更新服务器」,从那里拉取更新源(feed)。feed 本质上是一个描述「最新版本号、下载地址」的数据。
官方维护了一个免费服务 update.electronjs.org,专门给开源、公开仓库、发布在 GitHub Releases 上的 macOS / Windows 应用使用。它的要求是:
- 应用运行在 macOS 或 Windows。
- 拥有公开的 GitHub 仓库。
- 构建产物发布到 GitHub Releases。
- 构建经过代码签名(macOS 必需)。
如果你用的是私有仓库,或需要自建服务,Electron 官方文档也提供「搭建自有更新服务器」的分步指南。无论哪种,最终都是把 feed 地址告诉 autoUpdater。
1-5 整体更新流程
一次完整的自动更新,可以拆成三个清晰阶段:
第一步,检查。应用启动后(或你定时触发)调用 checkForUpdates(),向 feed 询问当前版本是否落后于最新版。
第二步,下载。若服务器返回「有更新」,autoUpdater 自动开始下载新版本安装包。这一步无需你手动干预,下载进度通过事件反馈。
第三步,安装。下载完成后,你可以提示用户「重启以更新」,调用 quitAndInstall() 重启并装上新版。即便不主动调用,下次应用正常启动时也会自动应用已下载的更新。
启动应用
→ checkForUpdates() 询问 feed
→ 有更新:自动下载(update-available)
→ 下载完成(update-downloaded)
→ 提示用户重启 / 下次启动自动生效
1-6 平台差异与限制
自动更新不是在所有平台都开箱即用,必须心中有数:
- macOS:支持良好,但应用必须签名,且走 Squirrel.Mac 的更新机制。
- Windows:支持良好,更新方式随打包格式(Squirrel.Windows / MSIX)自动切换。
- Linux:内置
autoUpdater不支持自动更新。官方建议直接用各发行版的包管理器(apt、dnf、pacman 等)来更新,或自行提供更新逻辑。
此外,Windows 的 Squirrel.Windows 安装后会在首次运行时短暂占用文件锁,头几秒内 checkForUpdates() 会失败。实践中可在首次启动时跳过检查,或给检查加超时与重试。
1-7 feed 长什么样
理解 feed 有助于排查更新为何「检测不到」。以 update.electronjs.org 为例,它会根据你仓库的 GitHub Releases 自动生成对应地址,形如 https://update.electronjs.org/所有者/仓库名/平台/当前版本。
服务器收到请求后,比对当前版本与最新 Release 的版本号。若最新版本更高,就返回新版的下载信息与签名;若相等或更低,则返回「无更新」。所以发布前务必先提升 package.json 的 version,否则服务器始终认为你已是最新。
这也是为什么第 30 章会反复强调「先升版本再打包」。版本号是更新的唯一判断依据,任何疏漏都会让更新链路静默失效。
从用户信任的角度看,自动更新也是一把双刃剑。做得好,bug 当天就能止住;做得差,错误的更新可能把用户的应用弄坏。因此更新必须可回退、可校验,下载环节要验证签名,安装环节要保留旧版以便失败回滚。把这些可靠性放进设计,自动更新才是真正省心的能力。
常见误区
不要把自动更新和「热更新网页」混为一谈。Electron 更新的是整个应用二进制,不是远程加载的页面,不能靠改服务器就改变已安装客户端的逻辑。
不要以为 Linux 也能用 autoUpdater。内置模块在 Linux 上无自动更新能力,需要走系统包管理器,规划跨平台更新策略时要单独处理。
不要跳过代码签名。尤其 macOS,未签名的 .app 不仅会被系统拦截,连 Squirrel.Mac 的自动更新也无法进行,签名是更新的前置条件。