Electron 自动更新完整实现(全量更新 vs 增量更新)
本篇文章基于 electron-vite-vue
脚手架,完整展示 Electron 自动更新的两种实现方案:
- ✅ 方案一:全量更新(默认,适合首次发布或大版本)
- ✅ 方案二:增量更新(基于
.blockmap
,适合小版本快速发布)
每种方案将从构建配置、更新流程、代码实现三个维度细化讲解。
🧱 统一前置依赖安装
npm install electron-updater electron-log
📁 目录结构推荐
electron-vite-vue/
├── electron/
│ ├── main/
│ │ └── updater.ts
│ └── preload/
│ └── index.ts
├── src/
│ ├── App.vue
├── package.json
✅ 方案一:全量更新(默认)
📦 构建配置(package.json)
"build": {
"appId": "com.example.myapp",
"productName": "MyApp",
"win": {
"target": "nsis"
},
"publish": {
"provider": "github",
"owner": "your-github",
"repo": "your-repo"
}
}
🛠 发布文件(上传到 GitHub Releases)
MyApp Setup 1.0.0.exe
latest.yml
🔧 主进程更新逻辑(updater.ts)
import { autoUpdater } from 'electron-updater'
import { BrowserWindow, ipcMain } from 'electron'
import log from 'electron-log'
export function setupAutoUpdater(win: BrowserWindow) {
autoUpdater.logger = log
log.transports.file.level = 'info'
autoUpdater.autoDownload = false
autoUpdater.on('update-available', () => {
win.webContents.send('update-available')
})
autoUpdater.on('update-downloaded', () => {
win.webContents.send('update-downloaded')
})
ipcMain.on('check-for-updates', () => {
autoUpdater.checkForUpdates()
})
ipcMain.on('download-update', () => {
autoUpdater.downloadUpdate()
})
ipcMain.on('install-update', () => {
autoUpdater.quitAndInstall()
})
}
⚡ 方案二:增量更新(使用 .blockmap)
📦 构建配置(package.json)
"build": {
"appId": "com.example.myapp",
"productName": "MyApp",
"win": {
"target": "nsis"
},
"nsis": {
"differentialPackage": true
},
"publish": {
"provider": "github",
"owner": "your-github",
"repo": "your-repo"
}
}
🛠 发布文件(上传到 GitHub Releases)
MyApp Setup 1.0.1.exe
MyApp Setup 1.0.1.exe.blockmap
latest.yml
✅ 必须上传
.blockmap
才能启用增量下载。
📌 自动启用增量的前提:
- 上个版本的
.exe
文件完整可读取 - blockmap 文件无误
- 下载流程未被中断
🖥️ 通用渲染进程代码(App.vue)
<template>
<div>
<button @click="check">检查更新</button>
<button v-if="canDownload" @click="download">下载更新</button>
<button v-if="canInstall" @click="install">立即安装并重启</button>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const canDownload = ref(false)
const canInstall = ref(false)
function check() {
window.electronAPI.checkForUpdates()
}
function download() {
window.electronAPI.downloadUpdate()
}
function install() {
window.electronAPI.installUpdate()
}
onMounted(() => {
window.electronAPI.onUpdateAvailable(() => (canDownload.value = true))
window.electronAPI.onUpdateDownloaded(() => (canInstall.value = true))
})
</script>
🛡️ 通用 Preload 脚本(preload/index.ts)
import { contextBridge, ipcRenderer } from 'electron'
contextBridge.exposeInMainWorld('electronAPI', {
checkForUpdates: () => ipcRenderer.send('check-for-updates'),
downloadUpdate: () => ipcRenderer.send('download-update'),
installUpdate: () => ipcRenderer.send('install-update'),
onUpdateAvailable: (cb: () => void) => ipcRenderer.on('update-available', cb),
onUpdateDownloaded: (cb: () => void) => ipcRenderer.on('update-downloaded', cb)
})
📊 方案比较总结
对比维度 | 全量更新 | 增量更新(blockmap) |
---|---|---|
下载内容 | 整包 .exe | 差异块(基于 blockmap) |
更新包大小 | 大(几十~百 MB) | 小(几 MB) |
下载速度 | 较慢 | 更快 |
网络负载 | 高 | 低 |
容错性 | 高 | 中等(依赖历史版本) |
发布要求 | .exe + .yml | .exe + .blockmap + .yml |
适用场景 | 初次发布、大改动 | 小版本热更、频繁更新 |
✅ 推荐使用建议
使用场景 | 推荐方案 |
---|---|
第一次发布 | ✅ 全量 |
结构或模块变动大 | ✅ 全量 |
频繁发布小优化 | ✅ 增量 |
低带宽用户环境 | ✅ 增量 |
无法保证用户版本稳定 | ✅ 全量 |