前言: 之前的博文中预告了会在近期进行关于"electron-vue autoUpdater"完整案例的编写。这里兑现承诺。
直接先贴一下可用的git地址。
https://gitee.com/sun577586587/electron-vue-updater
测试的时候,请自行搭建http://localhost:8000/download/win的路径。(暂时不详细说明测试步骤,找时间补充个gif或者小视频吧,有问题欢迎先在评论讨论)
环境:
一、从零创建项目
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变量#
可以知道打包时为什么会报这个错误了。
// 将上面的那个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 // 运行命令