【开发心得】electon vue updater自动升级完整步骤与样例

前言: 之前的博文中预告了会在近期进行关于"electron-vue autoUpdater"完整案例的编写。这里兑现承诺。

直接先贴一下可用的git地址。

https://gitee.com/sun577586587/electron-vue-updater

测试的时候,请自行搭建http://localhost:8000/download/win的路径。(暂时不详细说明测试步骤,找时间补充个gif或者小视频吧,有问题欢迎先在评论讨论) 

环境:

【开发心得】electon vue updater自动升级完整步骤与样例

一、从零创建项目

1.新建项目

 vue init simulatedgreg/electron-vue electrom-vue-update

2.进入项目路径

cd electrom-vue-update/

3. yarn(或者npm install),安装下依赖

4. yarn dev (或者 npm run dev), 启动严重下

5. 安装element-ui

npm install element-ui -s

踩坑与处理:

Q1:启动报错,提示“task重复定义”

感谢原博主:

https://www.cnblogs.com/silverbeats/p/14945112.html

1 打包踩坑#

1.1 .Election-vue/build.js文件的坑#

1.1.1 重复定义task变量#

【开发心得】electon vue updater自动升级完整步骤与样例

可以知道打包时为什么会报这个错误了。

// 将上面的那个task变量改为task1,简单些
const tasks1 = ['main', 'renderer']
const m = new Multispinner(tasks1, {
	preText: 'building',
	postText: 'process'
})

1.1.2 找不到Multispinner依赖#

还是上图,可以看到图片中的第二行使用了Multispinner对象,在初始化项目时,是不会下载Multispinner相关依赖的,需要自行yarn或npm下载,并且导入一下

yarn add multispinner
npm install multispinner
const Multispinner = require('multispinner')

Q2:Cannot read property 'name' of undefined

"electron": "^2.0.4"  默认electron-vue的electron版本属实有点低。截止2021.07.04 最新版本
13.1.5 注意升级下,先删除node module中的electron,重新命令行安装,或者直接package.json中修改版本,然后重新yarn (npm install)
npm install electron -g

备选:安装logger 

npm install logger --save

二、自动更新

1.package.json 增加发布相关。(如果使用其他方式,可以在vue.config.js或者background.js中放置)

 "publish": [
      {
        "provider": "generic",
        "url": "http://localhost:8000/api/download/test/win" # 改成你具体的地址
      }
    ],

2. 编写upgrade.js(叫其他名称也行,只要在引入的时候引入正确就行)

import { autoUpdater } from 'electron-updater'
import { ipcMain } from 'electron'

let mainWindow = null
let globalSettings
// 给渲染进程发送消息
function sendUpdateMessage (text) {
  mainWindow.webContents.send('message', text)
}

export function upgradeAutoUpdaterHandle (feedUrl) {
  autoUpdater.setFeedURL(feedUrl)
  autoUpdater.checkForUpdates()
}

export function initAutoUpdaterHandle (window, settings, feedUrl) {
  mainWindow = window
  globalSettings = settings
  // 设置更新包的地址
  autoUpdater.setFeedURL(feedUrl)
  autoUpdater.on('error', (error) => {
    sendUpdateMessage({
      cmd: 'error',
      message: error
    })
  })
  // 监听开始检测更新事件
  autoUpdater.on('checking-for-update', (message) => {
    sendUpdateMessage({
      cmd: 'checking-for-update',
      message
    })
  })
  // 监听发现可用更新事件
  autoUpdater.on('update-available', (message) => {
    sendUpdateMessage({
      cmd: 'update-available',
      message
    })
  })
  // 监听没有可用更新事件
  autoUpdater.on('update-not-available', (message) => {
    sendUpdateMessage({
      cmd: 'update-not-available',
      message
    })
  })

  // 更新下载进度事件
  autoUpdater.on('download-progress', (progressObj) => {
    sendUpdateMessage({
      cmd: 'download-progress',
      message: progressObj
    })
  })
  // 监听下载完成事件
  autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) => {
    sendUpdateMessage({
      cmd: 'update-downloaded',
      message: {
        releaseNotes,
        releaseName,
        releaseDate,
        updateUrl,
        quitAndUpdate
      }
    })
  })

  // 开始更新安装
  ipcMain.on('upgradeVersion', () => {
    globalSettings.willQuitApp = true
    autoUpdater.quitAndInstall()
  })

  if (!globalSettings.isDevelopment) {
    autoUpdater.checkForUpdates()
  }
  // // 接收渲染进程消息,开始检查更新
  // ipcMain.on('checkForUpdate', () => {
  //   // 执行自动更新检查
  //   // sendUpdateMessage({cmd:'checkForUpdate',message:arg})
  //   logger.info('check for update');
  //   autoUpdater.checkForUpdates();
  // });
}

 

3.index.js引入

ipcMain.on('loginSuccess', (event, data) => {
  const feedUrl = `http://localhost:8000/download/win/`
  if (!globalSettings.uploaderInited) {
    initAutoUpdaterHandle(mainWindow, globalSettings, feedUrl)
    globalSettings.uploaderInited = true
  } else {
    upgradeAutoUpdaterHandle(feedUrl)
  }
})

4.app.vue

<template>
  <div id="app">
    <landing-page></landing-page>
    <el-dialog
        :title="dialogTitle"
        :visible.sync="dialogVisible"
        width="40%"
        :close-on-click-modal="closeOnClickModal"
        :close-on-press-escape="closeOnPressEscape"
        :show-close="showClose"
        center
    >
      <div style="width:100%;height:10vh;line-height:20vh;text-align:center">
        <el-progress
            status="success"
            :text-inside="true"
            :stroke-width="20"
            :percentage="percentage"
            :width="strokeWidth"
            :show-text="true"
        ></el-progress>
      </div>
      <div align="center">
        <el-button type=primary @click.prevent="upgrade" v-if="canUpgrade">更新</el-button>
        <el-button type=primary @click.prevent="upgradeLater"  v-if="canUpgradeLater">稍后</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
  import LandingPage from '@/components/LandingPage'
  import { ipcRenderer } from 'electron'
  export default {
    name: 'electrom-vue-update',
    components: {
      LandingPage
    },
    data () {
      return {
        dialogTitle: '正在更新新版本,请稍候...',
        dialogVisible: false,
        closeOnClickModal: false,
        closeOnPressEscape: false,
        showClose: false,
        canUpgrade: false,
        canUpgradeLater: false,
        percentage: 0,
        strokeWidth: 200
      }
    },
    methods: {
      upgrade () {
        ipcRenderer.send('upgradeVersion')
      },
      upgradeLater () {
        this.dialogVisible = false
      }
    },
    mounted () {
      ipcRenderer.on('message', (event, arg) => {
        if (arg.cmd === 'update-available') {
          this.dialogVisible = true
        } else if (arg.cmd === 'update-downloaded') {
          this.percentage = 100.0
          this.dialogVisible = '更新完成'
          this.canUpgrade = true
          this.canUpgradeLater = true
        } else if (arg.cmd === 'download-progress') {
          this.percentage = Math.round(parseFloat(arg.message.percent))
        } else if (arg.cmd === 'error') {
          this.dialogVisible = true
          this.canUpgradeLater = true
          this.dialogTitle = '版本更新错误,请和管理员联系'
        }
      })
      ipcRenderer.send('checkForUpdate')
    }
  }
</script>

<style>
  /* CSS */
</style>

 5. 合适的地方触发:

<script>
  import SystemInformation from './LandingPage/SystemInformation'
  import { ipcRenderer } from 'electron'
  export default {
    name: 'landing-page',
    components: { SystemInformation },
    methods: {
      open (link) {
        require('electron').shell.openExternal(link)
      },
      checkUpdate () {
        // 增加发送成功的数据 S
        ipcRenderer.send('loginSuccess', {
          loginAddress: 'http://localhost:8000/download/win/',
          loginUsername: 'root'
        })
      }
    },
    mounted () {
      this.checkUpdate()
    }
  }
</script>

附录: 

npm 与 yarn对比

npm                                     yarn

npm init                                yarn init              // 初始化
npm i | install                         yarn  (install)        // 安装依赖包
npm i x --S | --save                    yarn add  x            // 安装生产依赖并保存包名
npm i x --D | --save-dev                yarn add x -D          // 安装开发依赖并保存包名
npm un | uninstall  x                   yarn remove            // 删除依赖包
npm i -g | npm -g i x                   yarn global add x      // 全局安装
npm un -g x                             yarn global remove x   // 全局下载
npm run dev                             yarn dev | run dev     // 运行命令
上一篇:Entity Framework中编辑时错误ObjectStateManager 中已存在具有同一键的对象


下一篇:SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章)