自动更新 #
一、自动更新概述 #
1.1 更新流程 #
text
┌─────────────────────────────────────────────────────────────┐
│ 自动更新流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ 应用启动 │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 检查更新 │◄─────────────────────┐ │
│ └──────┬──────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────┐ 无更新 │ │
│ │ 有新版本? │─────────────────────┤ │
│ └──────┬──────┘ │ │
│ │ 有更新 │ │
│ ▼ │ │
│ ┌─────────────┐ │ │
│ │ 下载更新 │ │ │
│ └──────┬──────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────┐ │ │
│ │ 安装更新 │ │ │
│ └──────┬──────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────┐ │ │
│ │ 重启应用 │──────────────────────┘ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
1.2 更新方式 #
| 方式 | 说明 | 适用场景 |
|---|---|---|
| 全量更新 | 下载完整安装包 | 大版本更新 |
| 增量更新 | 只下载差异文件 | 小版本更新 |
| 热更新 | 只更新渲染进程 | Web 资源更新 |
二、electron-updater #
2.1 安装 #
bash
npm install electron-updater
2.2 基本配置 #
json
// package.json
{
"build": {
"publish": {
"provider": "github",
"owner": "your-username",
"repo": "your-repo"
}
}
}
2.3 主进程更新逻辑 #
javascript
// electron/main/updater.js
const { autoUpdater } = require('electron-updater');
const { dialog, BrowserWindow } = require('electron');
let mainWindow;
function setupAutoUpdater(window) {
mainWindow = window;
// 设置更新服务器
autoUpdater.setFeedURL({
provider: 'github',
owner: 'your-username',
repo: 'your-repo'
});
// 检查更新失败
autoUpdater.on('error', (error) => {
console.error('更新检查失败:', error);
dialog.showErrorBox('更新错误', error.message);
});
// 检查更新中
autoUpdater.on('checking-for-update', () => {
console.log('正在检查更新...');
});
// 发现新版本
autoUpdater.on('update-available', (info) => {
console.log('发现新版本:', info.version);
dialog.showMessageBox(mainWindow, {
type: 'info',
title: '发现新版本',
message: `发现新版本 ${info.version},是否立即下载?`,
buttons: ['下载', '稍后提醒']
}).then((result) => {
if (result.response === 0) {
autoUpdater.downloadUpdate();
}
});
});
// 没有新版本
autoUpdater.on('update-not-available', (info) => {
console.log('当前已是最新版本');
});
// 下载进度
autoUpdater.on('download-progress', (progress) => {
const percent = progress.percent.toFixed(1);
const transferred = (progress.transferred / 1024 / 1024).toFixed(1);
const total = (progress.total / 1024 / 1024).toFixed(1);
console.log(`下载进度: ${percent}% (${transferred}MB / ${total}MB)`);
// 发送进度到渲染进程
mainWindow?.webContents.send('update-progress', {
percent,
transferred,
total
});
});
// 下载完成
autoUpdater.on('update-downloaded', (info) => {
console.log('更新下载完成');
dialog.showMessageBox(mainWindow, {
type: 'info',
title: '更新就绪',
message: '新版本已下载完成,是否立即安装?',
buttons: ['立即安装', '稍后安装']
}).then((result) => {
if (result.response === 0) {
autoUpdater.quitAndInstall();
}
});
});
}
// 检查更新
function checkForUpdates() {
autoUpdater.checkForUpdates();
}
// 手动检查更新
function checkForUpdatesAndNotify() {
autoUpdater.checkForUpdatesAndNotify();
}
module.exports = {
setupAutoUpdater,
checkForUpdates,
checkForUpdatesAndNotify
};
2.4 初始化更新 #
javascript
// electron/main/index.js
const { app, BrowserWindow } = require('electron');
const { setupAutoUpdater, checkForUpdates } = require('./updater');
let mainWindow;
app.whenReady().then(() => {
mainWindow = new BrowserWindow({...});
// 设置自动更新
setupAutoUpdater(mainWindow);
// 启动时检查更新
if (!isDev) {
checkForUpdates();
}
});
三、更新通知 #
3.1 渲染进程通知 #
javascript
// preload.js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
onUpdateProgress: (callback) => {
ipcRenderer.on('update-progress', (event, progress) => {
callback(progress);
});
},
checkForUpdates: () => {
ipcRenderer.invoke('check-for-updates');
}
});
javascript
// renderer.js
// 监听更新进度
window.electronAPI.onUpdateProgress((progress) => {
console.log(`下载进度: ${progress.percent}%`);
updateProgressBar(progress.percent);
});
// 手动检查更新
document.getElementById('check-update').addEventListener('click', () => {
window.electronAPI.checkForUpdates();
});
3.2 自定义更新 UI #
javascript
// electron/main/updater.js
class UpdateManager {
constructor(mainWindow) {
this.mainWindow = mainWindow;
this.updateInfo = null;
}
showUpdateNotification(info) {
this.mainWindow.webContents.send('update-available', info);
}
showDownloadProgress(progress) {
this.mainWindow.webContents.send('download-progress', progress);
}
showUpdateReady(info) {
this.mainWindow.webContents.send('update-ready', info);
}
}
四、更新服务器 #
4.1 GitHub Releases #
json
// package.json
{
"build": {
"publish": {
"provider": "github",
"owner": "your-username",
"repo": "your-repo",
"releaseType": "release"
}
}
}
4.2 私有服务器 #
json
{
"build": {
"publish": {
"provider": "generic",
"url": "https://updates.example.com/"
}
}
}
javascript
// 服务器目录结构
// https://updates.example.com/
// ├── latest.yml (Windows)
// ├── latest-mac.yml (macOS)
// ├── latest-linux.yml (Linux)
// ├── my-app-1.0.0.exe
// ├── my-app-1.0.0.dmg
// └── my-app-1.0.0.AppImage
4.3 S3/CDN #
json
{
"build": {
"publish": {
"provider": "s3",
"bucket": "my-app-updates",
"region": "us-east-1",
"path": "updates/"
}
}
}
五、更新配置 #
5.1 自动下载配置 #
javascript
// electron-builder.yml
publish:
provider: github
owner: your-username
repo: your-repo
# 自动下载更新
autoUpdater:
autoDownload: false # 不自动下载
autoInstallOnAppQuit: true # 退出时自动安装
javascript
// main.js
autoUpdater.autoDownload = false; // 手动控制下载
autoUpdater.autoInstallOnAppQuit = true; // 退出时安装
5.2 更新频率 #
javascript
// 定时检查更新
function scheduleUpdateCheck() {
// 每小时检查一次
setInterval(() => {
autoUpdater.checkForUpdates();
}, 60 * 60 * 1000);
// 或每天检查一次
const checkTime = new Date();
checkTime.setHours(10, 0, 0, 0); // 每天 10:00
const delay = checkTime - Date.now();
setTimeout(() => {
autoUpdater.checkForUpdates();
scheduleUpdateCheck();
}, delay);
}
5.3 增量更新 #
yaml
# electron-builder.yml
nsis:
differentialPackage: true
六、更新日志 #
6.1 显示更新日志 #
javascript
// electron/main/updater.js
autoUpdater.on('update-available', async (info) => {
// 获取更新日志
const releaseNotes = info.releaseNotes;
mainWindow.webContents.send('update-available', {
version: info.version,
releaseDate: info.releaseDate,
releaseNotes: releaseNotes
});
});
javascript
// renderer.js
window.electronAPI.onUpdateAvailable((info) => {
showUpdateDialog({
version: info.version,
changes: info.releaseNotes
});
});
6.2 CHANGELOG 格式 #
markdown
## [1.1.0] - 2024-01-15
### Added
- 新功能 A
- 新功能 B
### Changed
- 改进 C
### Fixed
- 修复 D
七、回滚机制 #
7.1 版本回滚 #
javascript
// 存储上一版本信息
const Store = require('electron-store');
const store = new Store({ name: 'app-state' });
// 检测是否回滚
function checkRollback() {
const lastVersion = store.get('lastVersion');
const currentVersion = app.getVersion();
if (lastVersion && lastVersion !== currentVersion) {
// 版本变化
const versionCompare = compareVersions(currentVersion, lastVersion);
if (versionCompare < 0) {
// 版本回滚
console.log('检测到版本回滚');
}
}
store.set('lastVersion', currentVersion);
}
7.2 更新失败处理 #
javascript
autoUpdater.on('error', (error) => {
console.error('更新失败:', error);
// 记录失败信息
const failedUpdates = store.get('failedUpdates', []);
failedUpdates.push({
version: autoUpdater.currentVersion,
error: error.message,
timestamp: new Date().toISOString()
});
store.set('failedUpdates', failedUpdates);
// 提示用户手动下载
dialog.showMessageBox(mainWindow, {
type: 'error',
title: '更新失败',
message: '自动更新失败,请手动下载最新版本',
buttons: ['前往下载', '取消']
}).then((result) => {
if (result.response === 0) {
shell.openExternal('https://github.com/user/repo/releases');
}
});
});
八、最佳实践 #
8.1 更新检查清单 #
markdown
- [ ] 配置更新服务器
- [ ] 实现更新检查逻辑
- [ ] 添加下载进度显示
- [ ] 实现安装提示
- [ ] 处理更新错误
- [ ] 测试更新流程
8.2 更新测试 #
javascript
// 开发环境测试更新
if (isDev) {
autoUpdater.updateConfigPath = path.join(__dirname, 'dev-app-update.yml');
}
// dev-app-update.yml
owner: your-username
repo: your-repo
provider: github
九、总结 #
9.1 核心要点 #
| 要点 | 说明 |
|---|---|
| electron-updater | 推荐的更新库 |
| 更新服务器 | GitHub/私有服务器 |
| 更新流程 | 检查→下载→安装→重启 |
| 进度通知 | 通知渲染进程 |
| 错误处理 | 处理更新失败 |
9.2 下一步 #
现在你已经掌握了自动更新机制,接下来让我们学习 代码签名,深入了解各平台的代码签名流程!
最后更新:2026-03-28