electron 自动更新以及手动更新

从搭建开始 使用的是electron-vue 毕竟方便一点 如果只想安装electron 请参见我的另一个文章 https://segmentfault.com/a/11...

首先安装Electron:

代码语言:javascript
复制
vue init simulatedgreg/electron-vue project1

cd project1
npm install //第一次安装的伙伴需要访问外国网站 如何访问外国网站请参加另一个文章(好像被和谐了 那就+我们的交流群吧!)

安装的时候安装了 vue electron vue-router 不安装 vuex

打包选择的是: electron-builder 下次有时间再扯electron-packager

安装完毕之后启动运行

代码语言:javascript
复制
npm run dev

构建页面

更新进度页面

将他写成组件 update.vue

代码语言:javascript
复制
<template>
    <transition name="fade">
        <div v-if="show">
            <div class="modal"></div>
            <div class="update">
                <div class="header"><h2>应用更新</h2><i class="close" @click="close"></i></div>
                <div class="body">
                    <p>更新进度</p>
                    <p class="percentage">10%</p>
                    <div class="progress">
                        <div class="length"></div>
                    </div>
                </div>
            </div>
        </div>
    </transition>
</template>

<script>
export default {
name: "update",
methods: {
close() {
this.$emit('update:show', false)
}
},
props: {
show: {
type: Boolean,
required: true,
default: false
}
}
}
</script>

<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
.modal {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: .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-image: url(&#34;../assets/img/close.png&#34;);
    background-size: 100%;
    cursor: pointer;
}

.update .header {
    border-bottom: 1px solid #ccc;
    height: 40px;
    line-height: 40px;
}

.update .header h2 {
    text-align: center;
    font-size: 20px;
}

.update .body {
    padding-top: 20px;
    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;
    width: 10px;
    height: 30px;
}

</style>

安装模块

安装 electron-updater 包模块

代码语言:javascript
复制
npm install electron-updater --save

修改package.json 加入以下代码

代码语言:javascript
复制
    "publish": [
      {
        "provider": "generic",
        "url": "http://lee.com/app/update"
      }
    ],

配置更新服务器

我们的更新服务器是本地虚拟主机 以apache为例

配置apache服务器

我本地使用的是集成环境 很简单的操作 要是大家使用自定义安装的 往httpd-vhosts.conf里面添加配置就可以了

我们的域名是lee.com

修改hosts文件

修改 hosts文件 往里面添加 文件地址在 C:WindowsSystem32driversetc目录下

代码语言:javascript
复制
127.0.0.1 lee.com

核心文件

主进程中 主要是handleUpdate方法

代码语言:javascript
复制
import {app, BrowserWindow, ipcMain} from 'electron'
// 注意这个autoUpdater不是electron中的autoUpdater
import {autoUpdater} from "electron-updater"

/**

let mainWindow
const winURL = process.env.NODE_ENV === 'development'
? http://localhost:9080
: file://${__dirname}/index.html

function createWindow() {
/**
* Initial window options
*/
mainWindow = new BrowserWindow({
height: 563,
useContentSize: true,
width: 1000
})

mainWindow.loadURL(winURL)

mainWindow.on(&#39;closed&#39;, () =&gt; {
    mainWindow = null
});

//处理更新操作
function handleUpdate() {
const returnData = {
error: {status: -1, msg: '检测更新查询异常'},
checking: {status: 0, msg: '正在检查应用程序更新'},
updateAva: {status: 1, msg: '检测到新版本,正在下载,请稍后'},
updateNotAva: {status: -1, msg: '您现在使用的版本为最新版本,无需更新!'},
};

    //和之前package.json配置的一样
    autoUpdater.setFeedURL(&#39;http://xxx.com/app/update&#39;);

    //更新错误
    autoUpdater.on(&#39;error&#39;, function (error) {
        sendUpdateMessage(returnData.error)
    });

    //检查中
    autoUpdater.on(&#39;checking-for-update&#39;, function () {
        sendUpdateMessage(returnData.checking)
    });

    //发现新版本
    autoUpdater.on(&#39;update-available&#39;, function (info) {
        sendUpdateMessage(returnData.updateAva)
    });

    //当前版本为最新版本
    autoUpdater.on(&#39;update-not-available&#39;, function (info) {
        setTimeout(function () {
            sendUpdateMessage(returnData.updateNotAva)
        }, 1000);
    });

    // 更新下载进度事件
    autoUpdater.on(&#39;download-progress&#39;, function (progressObj) {
        mainWindow.webContents.send(&#39;downloadProgress&#39;, progressObj)
    });


    autoUpdater.on(&#39;update-downloaded&#39;, function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
        ipcMain.on(&#39;isUpdateNow&#39;, (e, arg) =&gt; {
            //some code here to handle event
            autoUpdater.quitAndInstall();
        });
        // win.webContents.send(&#39;isUpdateNow&#39;)
    });

    //执行自动更新检查
    autoUpdater.checkForUpdates();
}

handleUpdate();

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

ipcMain.on(&#34;checkForUpdate&#34;, (event, data) =&gt; {
    console.log(&#39;执行自动更新检查!!!&#39;);
    // event.sender.send(&#39;reply&#39;, &#39;hi lee my name is yuan, age is 17&#39;);
    autoUpdater.checkForUpdates();
});

}

app.on('ready', createWindow)

app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
});

app.on('activate', () => {
if (mainWindow === null) {
createWindow()
}
});

更新参数讲解

在有更新包的情况下会在主进程中触发下面的方法:

代码语言:javascript
复制
  autoUpdater.on('download-progress', function (progressObj) {
        // mainWindow.webContents.send('downloadProgress', progressObj)
        const winId = BrowserWindow.getFocusedWindow().id;
        let win = BrowserWindow.fromId(winId);
        win.webContents.send('downloadProgress', progressObj)
    });

progressObj :

代码语言:javascript
复制
 { "bytesPerSecond": 47132710, "delta": 39780007, "percent": 100, "total": 39780007, "transferred": 39780007 } 

bytesPerSecond: bps/s //传送速率 percent : 百分比 //我们需要这个就可以了 total : 总大小 transferred: 已经下载

发布更新

将新的安装包和latest.yml 放到对应的目录下 系统会自动去检测版本 如果有新版本会下载的!!

检测更新

创建触发更新的组件

代码语言:javascript
复制
    <div><h2>你好 我是1.2.4</h2>
        <button @click="updateApp" style="width:100px;height: 40px;">更新</button>
        <Update :show.sync="show" :percent="percent"></Update>
    </div>
</template>

<script>

import Update from &#34;@/components/update&#34;;

export default {
    name: &#34;index&#34;,
    components: {Update},
    data() {
        return {
           
            percent: 0,
            show: false
        }
    },
    mounted() {
        //更新进度
        this.$electron.ipcRenderer.on(&#39;downloadProgress&#39;, (event, data) =&gt; {
          
            this.percent = (data.percent).toFixed(2);
            if (data.percent &gt;= 100) {
                // this.show = false;
            }
        });

        /**
         * 主进程返回的检测状态
         */
        this.$electron.ipcRenderer.on(&#39;message&#39;, (event, data) =&gt; {
            switch (data.status) {
                case -1:
                    this.$Message.error(data.msg);
                    break;
                case 0:
                    this.$Message.loading(data.msg);
                    break;
                case 1:
                    this.show = true;
                    break;
            }
        });
    },
    methods: {
        updateApp() {
            this.$electron.ipcRenderer.send(&#39;checkForUpdate&#39;, &#39;asdad&#39;)
        }
    }
}

</script>

总结

由于我的虚拟机是在本地 所以下载速度超快 后来我将更新地址切换到远程服务器 下面是操作截图