背景
之前一直都是vue项目,打包成dist,然后放到electron的项目里,通过electron-packager打包,然后通过setup,打包成.exe文件,再把生成的exe发送给测试人员,在公司内部可以发送给测试人员,如果项目部署到酒店,那么每次更新再去给每个酒店发exe包,那就很麻烦,所以需要远程更新功能。下面就来说说如何实现electron实现远程更新
electron版本:8.0.0
1. electron官网下载electron-quick-start项目
electron官网
git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install && npm start
下载electron 可能不太好下 (ps:自己想办法)
2. 将vue项目的dist文件,放入electron-quick-start项目
打开main.js,这个是主进程文件,可以理解为vue项目的main.js, 打包的dist文件,可以理解为是渲染进程文件。
修改main.js的 mainWindow.loadFile(’./dist/index.html’) ,把这个路径改成dist文件的html路径
3.打包electron项目
- 下载依赖
npm i electron-builder
- 配置package.json,script
"scripts": {"dist": "electron-builder --win --x64"
},
- 配置package.json,build
"build": {"productName": "xxxx", //包名"appId": "","asar":true,"directories": {"output": "build"//到处文件名},"publish": [ //远程更新需要配置这个 为了生成.yml文件{"provider": "generic","url": "https://websrc.oss-cn-zhangjiakou.aliyuncs.com/download/",//这个是地址 后面会说到 本地测试 和 线上测试需要怎么填写}],"win": {"target": [{"target":"nsis"}],"icon": "build/favicon256.ico",//图标 找ui要 路径要对上"asarUnpack":["src/**","README.md"]},"nsis": { //这个相当于打包exe配置,比如配置可以用户安装位置..."oneClick": false,"perMachine": true,"allowElevation": true,"allowToChangeInstallationDirectory": true,"createDesktopShortcut": true,"runAfterFinish": true,"installerIcon": "build/favicon256.ico","uninstallerIcon": "build/favicon256.ico"}},
- 上面的操作完了,执行npm run dist看看能不能成功,多半会报错。
因为有两个文件很难下 electron-v8.0.0-win32-x64.zip 和 nsis-3.0.4.1.7z 如果你们报错缺少这些,或者下载失败的话,可以考虑先去吧这两个文件下载好了丢到缓存里。
electron-v8.0.0-win32-x64.zip 放到 C:\Users\你的用户名\AppData\Local\electron\Cache
nsis-3.0.4.1.7z 放到 C:\Users\你的用户名\AppData\Local\electron-builder\cache\nsis
下次需要这两个文件的时候,就不回去github拉取,因为拉取不到二报错了,会从你的缓存里去取,另外项目名不要起中文,否则会报错
4.实现远程更新
打包成功之后,我们来实现远程更新
- 下载依赖
npm install electron-updater --save
这里需要将electron-updater下载运行时依赖dependencies中,因为在程序运行会用到这个包。而不是开发依赖
- 修改main.js主进程代码
//控制应用程序生命周期和创建本地浏览器窗口的模块
const {app, BrowserWindow, ipcMain} = require('electron')
const { autoUpdater } = require('electron-updater')
const path = require('path')let mainWindow
function createWindow () {// Create the browser window.mainWindow = new BrowserWindow({width: 1900,height: 1100,minWidth: 1900,minHeight: 1100,useContentSize: true,transparent: false,fullscreenable:true,// frame: true, // PS:隐藏窗口菜单// resizable: false,movable: true,maximizable: true, //支持最大化webPreferences: {preload: path.join(__dirname, 'preload.js'),nodeIntegration: true,//electron为前端工程提供Node的环境,让程序能够正常运行。enableRemoteModule: true // 打开remote模块}})// mainWindow.loadFile('./index.html')mainWindow.loadFile('./dist/index.html')// Open the DevTools.// mainWindow.webContents.openDevTools()updateHandle()
}// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
function updateHandle() {let message = {error: '检查更新出错',checking: '正在检查更新⋯⋯',updateAva: '检测到新版本',updateNotAva: '现在使用的就是最新版本,不用更新',};// let uploadUrl = 'http://192.168.20.193:3000/download/';let uploadUrl = 'https://websrc.oss-cn-zhangjiakou.aliyuncs.com/download/';autoUpdater.setFeedURL(uploadUrl);//在下载之前将autoUpdater的autoDownload属性设置成false,通过渲染进程触发主进程事件来实现这一设置// autoUpdater.autoDownload = false;autoUpdater.on('error', function (error) {sendUpdateMessage(error)});autoUpdater.on('checking-for-update', function () {sendUpdateMessage(message.checking)});autoUpdater.on('update-available', function (info) {sendUpdateMessage(message.updateAva)});autoUpdater.on('update-not-available', function (info) {sendUpdateMessage(message.updateNotAva)});// 更新下载进度事件autoUpdater.on('download-progress', function (progressObj) {mainWindow.webContents.send('downloadProgress', progressObj)})autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {sendUpdateMessage('isUpdateNow');ipcMain.on('updateNow', (e, arg) => {autoUpdater.quitAndInstall();});});ipcMain.on("checkForUpdate",() => {//执行自动更新检查autoUpdater.checkForUpdates();})
}// 通过main进程发送事件给renderer进程,提示更新信息
function sendUpdateMessage(text) {mainWindow.webContents.send('message', text)
}
- 说一说 electron-updater
其实这个插件就是通过我们在打包配置build的时候配置的publish配置项,从而生成.yml文件,这个文件记录了版本号,url,等一下信息,他每隔十分钟,会拿本地的yml文件,和线上 或者本地的.yml对比,对比版本号 判断需不需要升级,所以在打包的时候,package.json的版本号一定要写对。
- 说一说package.json里的publish->url 和 main.js里的uploadUrl地址都是怎么回事
比如我们现在执行npm run dist成功了,在build文件夹会生成一个0.0.1版本的exe文件,我们在本地安装这个版本,然后我们把版本号改成0.0.2然后又生成一个exe文件,这个时候这个exe文件,就需要在一个地方放着,electron-updater会通过你写的地址,去对比差异,判断有没有新版本。 如果你在本地测试的话,可以node启一个服务,然后地址就写本地地址就可以了
本地测试 (express 静态资源托管)
//1.引入express框架 (url/querystring/path/fs/http等)
const express = require("express")
//中间件,为了获取posy请求参数
const bodyParser = require("body-parser")
//导入path模块,显示html页面
const path = require("path")//2.创建web服务器
const app = express()//3.监听端口
app.listen(3000,"localhost",()=>{console.log("端口3000正在监听着哦....")
})//4.资源托管 (http://localhost:3000的时候,内部会自动的找到静态资源www目录下的index.html)
app.use('/download', express.static('./client'))
我们在本地启动一个node服务,通过http://localhost:3000/download/latest.yml http://localhost:3000/download/xxxx.exe http://localhost:3000/download/xxx.blockmap 这个时候package.json里的publish->url 和 main.js里的uploadUrl地址 只需要写http://localhost:3000/download/即可。但是要记住,本地项目需要打包成exe才能测试。如果只是在开发环境 执行的electron .那样是测试不了的,会报错。Error: ENOENT: no such file or directory, open ‘C:\Users\mi\Desktop\abc\fistapp\dev-app-update.yml’
线上的话,找后端给你提供接口上传这些文件,或者你可以操作oss,直接找一个目录,存放npm run buidl生成的这三个文件即可,然后你获取一下地址,填到url uoloadurl上即可,只需要到该文件夹,不需要到具体某个文件
- 说一说electron-updater 生命周期
这个流程一定要看明白,不然到时候和渲染进程通信的时候,就会有需要问题
//3.检测更新
//3.1触发自动更新
ipcRenderer.send("checkForUpdate");
//3.2监听自动更新事件
ipcRenderer.on("message", (event, text) => {console.log('接受主进程的text',text);this.tips = text;if (text == '检测到新版本') {// update-availableconsole.log('检测到新版本'); //注意:“downloadProgress”事件可能存在无法触发的问题,只需要限制一下下载网速就好了ipcRenderer.on("downloadProgress", (event, progressObj)=> { // downloadProgressconsole.log(progressObj);this.downloadPercent = Math.floor(Number(progressObj.percent)) || 0;if (Math.floor(Number(progressObj.percent)) == 100) {this.is_upgrade_success = true}})} else if (text == '现在使用的就是最新版本,不用更新') {// update-not-availableconsole.log('现在使用的就是最新版本,不用更新');} else if (text == '检查更新出错') {// errorconsole.log('检查更新出错');} else if (text == 'isUpdateNow') { // 是否现在更新console.log('是否现在更新');this.DialogOuterVisible = true}
});
- 具体怎么操作实现远程更新
其实就收先可以打包electron-quick-start项目,然后把渲染进程和主进程的代码写好,然后打包一个高版本的放在线上服务器 或者 本地服务器,讲对应地址配到项目里,然后本地装一个低版本的,进入低版本,会自动对比本地版本,然后提示更新。点击更新即可
结尾
想表达的很多,但是写的不好,有遇到问题的可以评论区评论。