您现在的位置是:首页 >其他 >electron更新机制网站首页其他

electron更新机制

stubborn丶lili 2024-06-26 14:24:01
简介electron更新机制

说明:

  1. 本文适用于win和mac这两个端
  2. mac端若要调试更新功能, 一定要把旧版本和新版本都配置mac的代码签名, 至于怎么配置, 主要就是先成为苹果开发者,然后去帐号那边下一个证书, 然后.....

一. 在package.json配置更新参数

参考: Publish - electron-builder

"build": {
    "productName": "打包后的名称",
    "appId": "com.app.autoupdatertester-nsis", // 随便写, 如果要上传到app Store, 则填写申请的appId
    "directories": {
      "output": "build"
    },
    "files": [
      "dist/electron/**/*"
    ],
    "dmg": { // mac打包的属性
      "contents": [
        {
          "x": 410,
          "y": 150,
          "type": "link",
          "path": "/Applications"
        },
        {
          "x": 130,
          "y": 150,
          "type": "file"
        }
      ]
    },
    "mac": {
      "icon": "src/icon/icon-mac.icns",
      "artifactName": "SlientPrint_${version}.${ext}",
      "target": [
        "dmg",
        "zip"
      ]
    },
    "win": {
      "icon": "src/icon/icon.ico",
      "artifactName": "SlientPrint_${version}.${ext}",
      "target": [
        "nsis"
      ]
    },
    "linux": {
      "icon": "src/icon"
    },
    "nsis": {
      "oneClick": false,
      "perMachine": true,
      "allowElevation": true,
      "allowToChangeInstallationDirectory": false,
      "uninstallDisplayName": "${productName}",
      "deleteAppDataOnUninstall": true
    },
    "publish": [
      {
        "provider": "generic", // 普通静态资源服务器填这个就行, 其他的看官网
        "url": "文件服务器地址,写到路径名就行了,别加文件名地址"
      }
    ]
  },

二. 项目中加入electron-updater, electron-log

electron-updater: 要用在生产环境里面的,所以要在package.json的dependencies字段里面. 

electron-log: 为了在调试更新时查看更新途中的日志, 排查问题

yarn add electron-updater, electron-log

三. 新建autoUpdater.js

import { app, BrowserWindow, ipcMain, dialog } from 'electron'
import log from '../config/logger'
import { autoUpdater } from 'electron-updater'
const fs = require('fs-extra')
const path = require('path')

// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
export function updateHandle({ mainWindow }) {
  //                            清除每次更新下载的文件,否则无法进行更新
  //= ==============================================================================================================
  // updaterCacheDirName的值与src/main/app-update.yml中的updaterCacheDirName值一致,在windows中会创建一个类似
  // C:UsersAdministratorAppDataLocalslient-print-updaterpending文件存储更新下载后的文件"*.exe"和"update-info.json"
  let updaterCacheDirName = 'slient-print-updater'
  const updatePendingPath = path.join(autoUpdater.app.baseCachePath, updaterCacheDirName, 'pending')
  log.warn('updatePendingPath:' + updatePendingPath)
  fs.emptyDir(updatePendingPath)
  let message = {
    error: '检查更新出错',
    checking: '正在检查更新……',
    updateAva: '检测到新版本,正在下载……',
    updateNotAva: '现在使用的就是最新版本,不用更新'
  }
   // 也可以通过代码配置文件服务地址
  autoUpdater.setFeedURL({
    provider: 'generic',
    url: '服文件地址'
  })
  // 设置是否自动下载,默认是true,当点击检测到新版本时,会自动下载安装包,所以设置为false
  autoUpdater.autoDownload = false
  autoUpdater.logger = log
  // 正在检查更新
  autoUpdater.on('error', function (error) {
    sendUpdateMessage(message.error, mainWindow)
  })
  autoUpdater.on('checking-for-update', function () {
    sendUpdateMessage(message.checking, mainWindow)
  })
  // 有新的可用更新
  autoUpdater.on('update-available', function (info) {
    sendUpdateMessage(message.updateAva, mainWindow)
  })
  //  没有可用的更新,也就是当前是最新版本
  autoUpdater.on('update-not-available', function (info) {
    sendUpdateMessage(message.updateNotAva, mainWindow)
  })

  // 更新下载进度事件
  autoUpdater.on('download-progress', function (progressObj) {
    mainWindow.webContents.send('downloadProgress', progressObj)
  })
  // 新安装包下载完成
  autoUpdater.on('update-downloaded', function (
    event,
    releaseNotes,
    releaseName,
    releaseDate,
    updateUrl,
    quitAndUpdate
  ) {
    ipcMain.on('isUpdateNow', (e, arg) => {
      log.warn('开始更新')
      autoUpdater.quitAndInstall()
    })

    mainWindow.webContents.send('isUpdateNow')
  })

  ipcMain.on('checkForUpdate', () => {
    // 执行自动更新检查
    log.warn('执行自动更新检查, isDestroyed:', mainWindow.isDestroyed())
    // 解决mac重启App 报错 的问题: object has been destroyed
    if (mainWindow &&!mainWindow.isDestroyed()) {
      autoUpdater.checkForUpdates()
    }
  })

  ipcMain.on('downloadUpdate', () => {
    // 下载
    log.warn('执行下载')
    autoUpdater.downloadUpdate()
  })
}

// 通过main进程发送事件给renderer进程,提示更新信息
function sendUpdateMessage(text, mainWindow) {
  mainWindow.webContents.send('message', text)
}

四. 在主进程中调用更新的函数main.js

import { updateHandle } from './autoUpdater.js'


function createWindow(key) {
    mainWindow = new BrowserWindow({
      webPreferences: {
        webSecurity: true,
        nodeIntegration: true,
        enableRemoteModule: true,
      },
      height: 600,
      useContentSize: true,
      width: 750,
      show: true,
    })
  mainWindow.loadURL(winURL)
  mainWindow.on('close', e => {
    if (process.platform !== 'darwin') {
        mainWindow = null
    } 
  })
  // 尝试更新, 只有当用户第一次打开app时才触发
  if (key == 1) updateHandle({ mainWindow })
}


app.on('ready', () => {
    createWindow(1)
})

五. logger.js代码

const log = require('electron-log')
log.transports.file.fileName = 'main.log';
log.transports.file.level = 'false';
// 达到最大上限后,备份文件并重命名为:main.old.log,有且仅有一个备份文件
log.transports.file.maxSize = 1048576;
log.transports.console.level = 'silly';

export default log

六. 渲染进程

<template>
  <div class="app-container">
    <el-dialog
      :title="title"
      :visible.sync="visible"
      width="400px"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      @closed="$emit('dialogClosed')"
      class="update-dialog"
      center
    >
      <span>{{ remark }}</span>
      <span slot="footer" class="dialog-footer">
        <el-button size="small" type="primary" @click="updateApp">立即升级</el-button>
        <el-button size="small" @click="visible = false">取 消</el-button>
      </span>
    </el-dialog>
  </div>
</template>


<script>
  import { ipcRenderer, remote } from 'electron'
  export default {
    name: 'landing-page',
    mounted: function () {
      // 给主进程发送事件
      ipcRenderer.send('web-created')
      // 检查更新
      ipcRenderer.send('checkForUpdate')
      // 监听自动更新事件
      ipcRenderer.on('message', (event, text) => {
        if (text === '检测到新版本,正在下载……') {
          this.$nextTick(() => {
            this.visible = true
          })
        }
      })
    },
    data() {
      return {
        title: '软件更新',
        remark: '发现新版本, 确定升级吗?',
        visible: false
      }
    },
    methods: {
      downloadUpdate() {
        this.downloadPercent = 0
        ipcRenderer.send('downloadUpdate')
        // //注意:“downloadProgress”事件可能存在无法触发的问题,只需要限制一下下载网速就好了
        ipcRenderer.on('downloadProgress', (event, progressObj) => {
          this.downloadPercent = parseInt(progressObj.percent || 0)
        })
        ipcRenderer.on('isUpdateNow', () => {
          ipcRenderer.send('isUpdateNow')
        })
      },
    },
}
</script>

七. 查看效果

 

 八.  main.log日志

 

 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。