npm i electron-updater -S

2. 配置package.json

在构建electron项目的 build 配置项下增加 publish 相关配置, provider 设定为 generic url 为新版本文件存放的地址。这个最终会用来生成 latest.yml 版本描述文件,auto-update工作时,会查询该文件中的版本信息来判断是否有新版本可供下载。

"name" : "electron_upgrade_test" , "version" : "1.0.0" , "description" : "" , "main" : "main.js" , "scripts" : { "start" : "electron ." , "pack" : "electron-builder --dir" , "dist" : "electron-builder" , "release" : "build" "author" : "" , "license" : "ISC" , "build" : { "appId" : "your.id" , "mac" : { "category" : "penghk.app.category.type" "publish" : [ "provider" : "generic" , "url" : "http://127.0.0.1:3002/download/" "devDependencies" : { "electron" : "^7.1.7" , "electron-builder" : "^21.2.0" "dependencies" : { "electron-log" : "^4.0.2" , "electron-updater" : "^4.2.0"

3. 创建 main.js 主进程文件

updateHandle 函数用于监听版本更新相关的事件

const { app, BrowserWindow, ipcMain } = require('electron')
const { autoUpdater } = require("electron-updater")
function updateHandle() {
  autoUpdater.on('error', function (error) {
    sendUpdateMessage('检查更新出错 %s', error)
  autoUpdater.on('checking-for-update', function () {
    sendUpdateMessage('正在检查更新…')
  autoUpdater.on('update-available', function (info) {
    sendUpdateMessage('检测到新版本,正在下载…')
  autoUpdater.on('update-not-available', function (info) {
    sendUpdateMessage('现在使用的已经是最新版本')
  // 更新下载进度事件
  autoUpdater.on('download-progress', function (progressObj) {
    win.webContents.send('downloadProgress', progressObj)
  autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
    // 渲染层回复立即更新,则自动退出当前程序,然后进行程序更新
    ipcMain.on('updateNow', (e, arg) => {
      console.log("开始更新");
      autoUpdater.quitAndInstall();
    // 询问渲染层是否立即更新
    win.webContents.send('isUpdateNow')
  ipcMain.on("checkForUpdate",()=> {
    // 执行自动更新检查
    // 这里有两种"checkForUpdates"和"checkForUpdatesAndNotify"
    // 区别在于checkForUpdatesAndNotify检查到新版本时会调用系统的通知组件通知用户有新版本可供下载
    // 大家可以根据实际需要自行选择
    // autoUpdater.checkForUpdates();
    autoUpdater.checkForUpdatesAndNotify();
// 通过main进程发送事件给renderer进程,提示更新信息
function sendUpdateMessage(text) {
  win.webContents.send('message', text)
// 保持对window对象的全局引用,如果不这么做的话,当JavaScript对象被
// 垃圾回收的时候,window对象将会自动的关闭
let win
function createWindow () {
  // 创建浏览器窗口。
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
  // 加载index.html文件,拼接版本信息到URL的hash中,便于渲染层获取当前版本
  win.loadURL(`file://${__dirname}/index.html#v${app.getVersion()}`);
  // 打开开发者工具
  win.webContents.openDevTools()
  // 当 window 被关闭,这个事件会被触发。
  win.on('closed', () => {
    // 取消引用 window 对象,如果你的应用支持多窗口的话,
    // 通常会把多个 window 对象存放在一个数组里面,
    // 与此同时,你应该删除相应的元素。
    win = null
  // 监听更新相关事件
  updateHandle();
// Electron 会在初始化后并准备
// 创建浏览器窗口时,调用这个函数。
// 部分 API 在 ready 事件触发后才能使用。
app.on('ready', createWindow)
// 当全部窗口关闭时退出。
app.on('window-all-closed', () => {
  // 在 macOS 上,除非用户用 Cmd + Q 确定地退出,
  // 否则绝大部分应用及其菜单栏会保持激活。
  if (process.platform !== 'darwin') {
    app.quit()
app.on('activate', () => {
  // 在macOS上,当单击dock图标并且没有其他窗口打开时,
  // 通常在应用程序中重新创建一个窗口。
  if (win === null) {
    createWindow()

4. 创建 index.html 渲染层视图文件

<!DOCTYPE html>
<html lang="zh-cn">
    <meta charset="UTF-8">
    <title>Version Auto Upgrade Demo</title>
</head>
    <h1>Version <span id="version"></span></h1>
    <div id="container"></div>
    <script>
        // 更新版本信息
        const version = window.location.hash.substring(1);
        document.getElementById('version').innerText = version;
        // 消息容器
        const container = document.getElementById('container');
        const { ipcRenderer } = require('electron');
        ipcRenderer.send("checkForUpdate");
        ipcRenderer.on("message", (event, text) => {
            const message = document.createElement('div');
            message.innerText = text;
            container.appendChild(message);
        // 注意:“downloadProgress”事件可能存在无法触发的问题,
        // 因为如果安装文件过小的话,很快就下载完成,导致没能达到触发条件。
        ipcRenderer.on("downloadProgress", (event, { percent })=> {
            console.log(percent);
        // 接收到主进程有新的版本已经下载完成,询问是否更新。
        ipcRenderer.on("isUpdateNow", () => {
            if(confirm('确定要现在升级吗?')){
                ipcRenderer.send("updateNow");
    </script>
</body>
</html>

附录1:快速搭建本地静态文件服务器

搭建本地静态文件服务器,方便本地调试。

  • 在项目目录下创建静态文件存放目录 mkdir -p update_server/download
  • 全局安装http-server npm i http-server -g
  • 启动文件服务器 http-server ./update_server -p 3002
  • 将打包好的新版本文件放入 download 目录
  • 检查是否可以正常访问 http://127.0.0.1:3002/download ,如下图
  • 附录2:latest-mac.yml 示例

    version 为版本字段,来源于打包时项目中的 package.json 文件的 version 字段,如果用户当前程序版本低于该版本,则提示用户进行更新。

    sha512 字段为对应文件的Hash值,用于校对文件的完整合法性。

    version: 1.0.1
    files:
      - url: electron_upgrade_test-1.0.1-mac.zip
        sha512: w5kTV0E2duVr1zw2ZPhJZncWXXwY6Muu6gCGpb3CNQWwqtM/WlCfKMsIIMCZH/FHeoDxF3hJhZR6yUIJSc02fg==
        size: 62878761
        blockMapSize: 67301
      - url: electron_upgrade_test-1.0.1.dmg
        sha512: x6ySqvUl8NXZ88rAnn64J36ra9H+Tgecp/QG3MtaNZgFAsp8BEl4UJT8HIXTpFmmMLxpcfVAdhE7Aibe8xQc9Q==
        size: 64808426
    path: electron_upgrade_test-1.0.1-mac.zip
    sha512: w5kTV0E2duVr1zw2ZPhJZncWXXwY6Muu6gCGpb3CNQWwqtM/WlCfKMsIIMCZH/FHeoDxF3hJhZR6yUIJSc02fg==
    releaseDate: '2020-01-03T06:36:08.231Z'
    

    最后,文章写得有点仓促,不免会出现不恰当的地方,欢迎大家评论区加以指正,谢谢!

    分类:
    前端
    标签: