在使用Electron开发的时候有一个需求:自动更新应用。
踩了一些坑,记录一下,希望可以帮到大家
我找到了两个方案
2.electron.build的electron-uploader
第一种方法的缺点
1.需要使用Squirrel框架,否则会报错Can not find Squirrel,并且打包还有其他要求
我使用的是第二种方法,原因如下
1.electron使用的electron.build进行打包的,那么用electron.build提供的自动更新当日是更好的
2.代码比较简单
话不多说,上代码
首先线安装插件
npm install electron-updater
还使用到了electron的进程通讯
代码如下
自动跟新配置文件upload.js
const { ipcMain } = require('electron')
import { autoUpdater } from "electron-updater";
export default function handleUpdate(win){
//是否自动下载,默认设置为不自动下载
autoUpdater.autoDownload = false
//设置更新路径
autoUpdater.setFeedURL("http://192.168.0.148:9091")
// 更新发生错误时触发
autoUpdater.on('error', (error)=> {
win.webContents.send('message', "更新出错")
win.webContents.send('installErr', error)
})
//检查更新是否已开始时发出
autoUpdater.on("checkingForUpdate",()=>{
win.webContents.send('message', "正在检查更新。。。")
})
//检查应用可以更新,不自动下载
autoUpdater.on("update-available",(e,info)=>{
win.webContents.send('message', "应用可以更新")
win.webContents.send('updateAvailable', info)
})
//检查应用没有新版本
autoUpdater.on("update-not-available",()=>{
win.webContents.send('message', "应用没有更新")
})
//应用下载完成事件
autoUpdater.on("update-downloaded",(event)=>{
win.webContents.send('message', "下载完成事件")
win.webContents.send('requestInstall', event)
})
//应用下载进度条事件
autoUpdater.on("download-progress",(progressObj)=>{
win.webContents.send('message', "应用下载中")
let info = {
bytesPerSecond: progressObj.bytesPerSecond,
percent: progressObj.percent,
transferred: progressObj.transferred,
total: progressObj.total
}
win.webContents.send('downloadProgress', info)
})
//安装前的事件
autoUpdater.on("before-quit-for-update",()=>{
win.webContents.send('message', "正在安装请稍后")
})
//询问服务器是否有更新。 使用该 API 前必须先调用 setFeedURL
//查看是否有更新事件
ipcMain.on('checkForUpdate', (event, data) => {
console.log("检查更新")
//将制动下载设置为false
autoUpdater.autoDownload = false
autoUpdater.checkForUpdates()
win.webContents.send('message', "正在检查更新")
})
// 手动下载事件
ipcMain.on('download', (event, data) => {
//将制动下载设置为true
autoUpdater.autoDownload = true
autoUpdater.checkForUpdates()
})
//确定安装事件
ipcMain.on('installApp', (event, data) => {
autoUpdater.quitAndInstall()
})
}
主进程文件background.js
import updateHandle from "./upload.js"
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 1800,
height: 1000,
show: false,//设置默认不显示
paintWhenInitiallyHidden: false,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
enableRemoteModule: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
nodeIntegrationInWorker: true,
}
})
// 设置默认最大化
win.maximize()
//设置显示
win.show()
// 创建菜单对象
// const menu = Menu.buildFromTemplate(getMenuConfig(win));
// 设置应用菜单
// Menu.setApplicationMenu(menu);
//设置为null表示隐藏菜单栏
Menu.setApplicationMenu(null);
win.webContents.openDevTools()
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (process.env.BABEL_ENV === "development") win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
}
// 初始化Update配置,在创建口创建完成后
updateHandle(win)
}
页面展示文件,接收和展示自动更新文件的内容upload.vue
<template>
<div>
<main>
<div class="right-side">
<div class="doc">
<div class="title alt">检查更新,不自动下载</div>
<el-button type="primary" round @click="checkUpdate">检查更新不自动下载, 不可用于开发环境</el-button>
<el-button type="primary" round @click="download">手动下载更新文件</el-button>
<el-button type="primary" round @click="installApp">安装</el-button>
<el-progress :text-inside="true" :stroke-width="20" :percentage="percent"></el-progress>
{{ appInfo }}
<div>{{ messageStr }}</div>
<br>
<div>{{ progressObj }}</div>
<div>{{ percent }}</div>
<br>
<div>{{ errorObj }}</div>
<div>{{ installObj }}</div>
</div>
</div>
</main>
</div>
</template>
<script>
let ipcRenderer = require("electron").ipcRenderer;
export default {
name: "systemExample",
data() {
return {
percent: 0,
show: 'true',
appInfo:{},
messageStr:"",
progressObj:{},
errorObj:{},
installObj:{},
}
},
mounted() {
// 主进程返回检查状态
ipcRenderer.on("message", (e, message) => {
this.$message.error(message)
this.messageStr = message
console.log("status--->", message)
});
// 更新进度
ipcRenderer.on('downloadProgress', (e, progressObj) => {
console.log("progressObj--->", progressObj);
this.$message.error("正在下载")
this.percent = (progressObj.percent).toFixed(2) || 0;
console.log("this.percent---->", Math.trunc(this.percent))
this.progressObj = progressObj
});
//接收更新的版本信息
ipcRenderer.on("updateAvailable", (e, info) => {
console.log("status--->", info)
this.appInfo = info
});
//下载成功请求安装
ipcRenderer.on("requestInstall", (e, info) => {
this.installObj = info
this.$confirm("下载完成,是否立即更新","提示",{
closeOnClickModal: false, // 禁止点击遮罩关闭弹框
closeOnPressEscape: false, // 禁止按 ECS 键关闭弹框
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(()=>{
console.info("下载完成,选择立即更新")
ipcRenderer.send('installApp');
this.$message({
type: 'success',
message: '更新成功'
})
}).catch(()=>{
console.info("下载完成,选择取消更新")
this.$message({
type:'info',
message: '取消更新'
})
})
});
//下载错误
ipcRenderer.on("installErr", (e, error) => {
this.errorObj = error
});
},
methods: {
// 下面方法点击按钮开始检查更新,
checkUpdate() {
ipcRenderer.send("checkForUpdate")
},
//安装
installApp(){
ipcRenderer.send("installApp")
},
//下载
download(){
ipcRenderer.send("download")
}
},
}
</script>
<style scoped>
</style>
实现了一个简单的自动更新
在使用electron.build打包的时候需要配置pluginOptions.electronBuilder.builderOptions.publish不然不会生成latest.yml文件,我的配置如下
"publish": [
{
"provider": "generic",
"url": "http://192.168.0.148:80"
}
]
测试可以使用http-erver运行一个简单的服务器,将我们打包好的高版本文件添加到服务器,将我们打包好的xxx.exe文件以及xxx Setup 1.2.0.exe.blockmap和latest.yml一起放入服务器,就可以实现自动更新了