electron autoUpdater热更新

最近创建了一个electron-vue项目,用到了热更新,先看效果图:

话不多说,直接上代码。main目录下创建update.js

代码如下:

// 安装包helatest.yml所在服务器地址
const uploadUrl = 'http://127.0.0.1:8080/pc/'
const { autoUpdater } = require('electron-updater')
const { ipcMain } = require('electron') // ipcMain 主线程
const config = require("../../package.json")
const isDevelopment = process.env.NODE_ENV !== "production";
// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
export const updateHandle = (mainWindow) => {
    let message = {
        error: { status: -1, msg: '检测更新查询异常' },
        checking: { status: 0, msg: '正在检查更新...' },
        updateAva: { status: 1, msg: '检测到新版本' },
        updateNotAva: { status: 2, msg: '您现在使用的版本为最新版本,无需更新!' },
    }
    if (isDevelopment && !process.env.IS_TEST) { // 调试环境
        autoUpdater.currentVersion = config.version;
    }
    autoUpdater.setFeedURL(uploadUrl)
    //在下载之前将autoUpdater的autoDownload属性设置成false,通过渲染进程触发主进程事件来实现这一设置
    autoUpdater.autoDownload = false;
    // 检测更新查询异常
    autoUpdater.on('error', function (error) {
        sendUpdateMessage(mainWindow, message.error)
    })
    // 当开始检查更新的时候触发
    autoUpdater.on('checking-for-update', function () {
        sendUpdateMessage(mainWindow, message.checking)
    })
    // 当发现有可用更新的时候触发,更新包下载会自动开始
    autoUpdater.on('update-available', function (info) {
        // 主进程向renderer进程发送是否确认更新
        mainWindow.webContents.send('isUpdateNow', info)
        sendUpdateMessage(mainWindow, message.updateAva)
    })
    // 当发现版本为最新版本触发
    autoUpdater.on('update-not-available', function (info) {
        sendUpdateMessage(mainWindow, message.updateNotAva)
    })
    // 更新下载进度事件
    autoUpdater.on('download-progress', function (progressObj) {
        mainWindow.webContents.send('downloadProgress', progressObj)
    })
    // 包下载成功时触发
    autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
        autoUpdater.quitAndInstall() // 包下载完成后,重启当前的应用并且安装更新
    })
 
    // 收到renderer进程确认更新
    ipcMain.on('updateNow', (e, arg) => {
        console.log('开始更新... ...')
        autoUpdater.downloadUpdate();
    })
 
    ipcMain.on('checkForUpdate', () => {
        // 收到renderer进程的检查通知后,开始检查更新
        autoUpdater.checkForUpdates()
    })
}
 
// 通过main进程发送事件给renderer进程,提示更新信息
function sendUpdateMessage(mainWindow, text) {
    mainWindow.webContents.send('message', text)
}

在主进程中引入:

import { updateHandle } from './update' //引入

在主进程中引用:

为了显示更新进度条,友好的交互,封装了个update组件:

显示效果如图(可以根据需要在组件中设置更新是否可关闭,是否强制更新...)

组件代码:

<template>
    <transition name="fade">
        <div v-if="show">
            <div class="modal"></div>
            <div class="update">
                <div class="header">
                    <h2>发现新版本</h2>
                    <!-- 可关闭的更新 
                    <i class="close el-icon-close" @click="close"></i></div> -->
                    <!-- 不可以关闭的更新 -->
                    <i class="close"></i></div>
                <div class="body">
                    <p>更新进度</p>
                    <p class="percentage">{{downloadPercent}}</p>
                    <div class="progress">
                        <div class="length" :style="'width:'+downloadPercent"></div>
                    </div>
                </div>
            </div>
        </div>
    </transition>
</template>
 
<script>
    export default {
        name: "update",
        data() {
          return {
                  
          }
        },
        methods: {
            close() {
                this.$emit('update:show', false)
            }
        },
        props: {
            show: {
                type: Boolean,
                required: true,
                default: false
            },
            downloadPercent:{
                type: String,
                required: true,
                default: '0%',
            }
        }
    }
</script>
 
<style scoped>
    .fade-enter-active, .fade-leave-active {
        transition: opacity 0.5s;
    }
    .fade-enter, .fade-leave-to{
        opacity: 0;
    }
    .modal {
        position: fixed;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        opacity: 0.4;
        background: #000;
    }
    .update {
        width: 400px;
        height: 180px;
        background-color: #FFFFFF;
        border-radius: 10px;
        border: 1px solid #CCC;
        position: absolute;
        top: 40%;
        margin-top: -90px;
        left: 50%;
        margin-left: -200px;
        box-shadow: #FFFFFF 0 0 10px;
    }
    .update .header i.close {
        display: inline-block;
        position: absolute;
        top: 11px;
        right: 12px;
        width: 20px;
        height: 20px;    
        background-size: 100%;
        cursor: pointer;
    }
    .update .header {
        border-bottom: 1px solid #ccc;
        height: 50px;
        line-height: 40px;
    }
    .update .header h2 {
        text-align: center;
        font-size: 20px;
        margin-top: 5px;
    }
    .update .body {
        padding-top: 0px;
        text-align: center;
    }
    .update .body .percentage {
        margin-top: 20px;
    }
    .update .body .progress {
        width: 350px;
        height: 30px;
        border: 1px solid #CCCCCC;
        border-radius: 8px;
        margin: 10px auto;
    }
    .update .body .progress .length {
        background-color: #E4393c;
        border-radius: 8px;
        height: 30px;
    }
</style>

组件的调用(我是在App.vue中引入的,程序启动即加载更新,可根据实际需求设置):

在template中的div中引入即可

<update :show.sync="updateShow" :percent="updatePercent" :downloadPercent="updatePercent"></update>

对应的js:

<script>
  const {ipcRenderer} = require('electron')
  import update from './../renderer/components/frame/update'
  export default {
    name: 'textApp',
    components:{
      "update" : update
    },
    data () {
      return {
        updateShow:false,
        updatePercent:'0%',
      }
    },
    mounted:function(){
      //给渲染进程添加更新监听事件
      this.updateListenerRegister();
    },
    methods: {
      updateListenerRegister(){
        let that = this;
        // 软件热更新相关
        ipcRenderer.on("message", (event, data) => {
          switch (data.status){
              case -1:
                  that.$message.error(data.msg);
                  break;
              // case 0:
              //     this.$message(data.msg);
              //     break;
              case 1:
                  that.updateShow = true;
                  break;
          }
        });
        ipcRenderer.on("downloadProgress", (event, progressObj) => {
          // console.log("downloadProgress", progressObj);
          that.updatePercent = (progressObj.percent).toFixed(2)+'%';
          if (progressObj.percent >= 100) {
              that.updateShow = false;
          }
        });
        ipcRenderer.on("isUpdateNow", (event, versionInfo) => {
          // 自定义选择效果,效果自行编写 tip是我在 latest.yml 中手动添加的更新内容提示
          // 用的element-ui 可自行安装
          // that.$confirm('检测到最新'+ versionInfo.version+'版本已上线,是否立即升级?', "温馨提示",
          //   {confirmButtonText: "确定", cancelButtonText: "取消"} ).then(() => { //用户点击确认
          //     ipcRenderer.send("updateNow");
          //   }).catch(() => { //用户点击取消
          //     that.updateShow = false;
          //   });

          //不提示用户,强制更新
          ipcRenderer.send("updateNow");
        });
        ipcRenderer.send("checkForUpdate");
      },
    },  
  }
</script>

需要注意package.json中的这几个依赖的版本(electron-updater3.0以下的版本会报错,要是不知道咋解决,按照本博客中的版本试一下), 在网上看到的都是降低版本,什么版本号配什么,最后就发现 只需要把对应低版本升级了就可以了,还发觉一个问题,打包的文件不能是中文,不然更新的时候路径会有问题,但是打包好后安装的应用名称中文的话可以在nsis属性中shortcutName属性配置,不然安装后默认打包的名称)

配置应用安装的属性:

特别注意点

         ①本博客中我的路径是...../pc/目录下,对应的latest.yml和更新包一定要放在同一目录下,都在 .../pc/文件夹下

         ②打更新包的名称(即productName配置的名称)不可以为中文,否则下载路径中文变乱码找不到。

         ③默认打包的名称是对应着productName 配置的名称 Setup 版本号.exe,如果当把文件上传到服务器ubuntu环境,自动空格处添加了下划线导致在使用更新的使用出现下载路径404的错误。

        可以 加属性 "artifactName": "${productName}_Setup_${version}.${ext}",或者手动修改安装包的名称同时对应着修改更新包的名称。

        

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值