electron 自动更新 热跟新 自动跟新之后不用重新安装
使用electron-upadta 自动跟新之后需要用户在重新安装一遍程序,用户体验不好,开发electron-hot-updata 插件,直接热更新,更新之后不需要用户重新安装程序
先看实际效果
electrin-hot-updata
引用文本 阿松大
electron的项目用 electron 自动更新,更新之后需要手动安装程序,有需求就有产出;
electron-hot-updata插件,使用本插件热更新,动态替换electron 执行文件达到热更新;
使用方法
安装插件
npm i electron-hot-updata
Installing
A step by step series of examples that tell you how to get a development env running.
1. 因为electron 默认是安装在C:\Program Files\ 目录下 操作文件需要管理员权限;
// 在electron-build 的package.json 里面配置权限;
// 我的项目是基于vue 我就直接在vue.config.js 里面配置
//因为electron 默认是安装在C:\Program Files\ 目录下 操作文件需要管理员权限;
module.exports = {
...,
"win": {
"requestedExecutionLevel": "highestAvailable" // highestAvailable 最高权限
},
}
2. 配置项目服务器地址
// vue.config.js
1.配置项目服务器地址
module.exports = {
...,
publish: [{
"provider": "generic",
url: "http://192.168.0.191/electron/" // 更新文件服务器地址 放你后台的地址
}],
}
配置之后执行electron-build 打包之后会自动生成 latest.yml 文件
2.sasr 配置 //看你自己需求 可有可无
module.exports = {
...,
sasr: false // 执行文件是否打包成sasr文件
}
sasr:false // 打包出来的就是 html + css + js
sasr:true // 打包之后就是sasr 文件
##
http://192.168.0.191/electron/ 下面存放两个文件
latest.yml
系统打包之后自动生成
app.zip
//app.zip 分两种情况
1.sasr:false
项目/dist_electron/win-unpacked/resources/ 下找到app文件夹 打包成 app.zip 文件
2.sasr:true
项目/dist_electron/win-unpacked/resources/ 下找到 app.sasr文件 打包成app.zip 文件
3. 版本号 如果你有更好的修改项目版本号办法 直接无视这一块
electron 版本区分默认依靠 项目>package.json>version;
所有每次打包之后 都要修改版本号 ;
靠版本号来区分是否需要更新
在vue.cinfog.js 里面添加以下代码
<!-- 一下代码每次运行项目都会修改版本号 -->
const path = require('path')
const fs = require('fs');
const resolve=(dir)=> {
return path.join(__dirname, dir)
}
const AddZero = (time)=> {
if (time < 10) {
return "0" + time
} else {
return time
}
}
let packageTxt = fs.readFileSync('./package.json', 'utf8');
let versionData = packageTxt.split('\n');
let packageJson = JSON.parse(packageTxt);
let VersionArr = packageJson.version.split('.');
let date = new Date();
let today = date.getFullYear() + "" + AddZero((date.getMonth() + 1)) + "" + AddZero(date.getDate())
if (today == VersionArr[1]) {
VersionArr[2] = parseInt(VersionArr[2]) + 1
} else {
VersionArr[1] = date.getFullYear() + "" + AddZero((date.getMonth() + 1)) + "" + AddZero(date.getDate())
VersionArr[2] = 1;
}
let versionLine = VersionArr.join('.');
for (let i = 0; i < versionData.length; i++) {
if (versionData[i].indexOf('"version":') != -1) {
versionData.splice(i, 1, ' "version": "' + versionLine + '",');
break;
}
}
fs.writeFileSync('./package.json', versionData.join('\n'), 'utf8');
根目录新建 hot-updata.js
// hot-updata.js 里面代码
import {electronHotupdata} from "electron-hot-updata"
const electronHotupdatas= new electronHotupdata(this)
const path = require('path');
import {
ipcMain,
app
} from 'electron'
let mainWindow=null
export function updateAva(windows,provider,Version){
mainWindow=windows
// 设置地址
electronHotupdatas.setProvider(provider)
// 设置版本号
electronHotupdatas.setNewVersion(Version)
// *** 一般情况下不介意修改地址
// electron 默认安装在 C:\Program Files\ 目录下 如果热更新地址不对 electronHotupdatas.setBaseUrl 动态修改地址
// electronHotupdatas.setBaseUrl(baseUrl)
// 监听获取版本失败
electronHotupdatas.on("get-version-failed",(message)=>{
sendHotUpdateMessage({
cmd: 'get-version-failed',
message: message
})
})
// 监听没有新版本
electronHotupdatas.on("no-new-version",(message)=>{
sendHotUpdateMessage({
cmd: 'no-new-version',
message: message
})
})
// 监听有新版本 可更新
electronHotupdatas.on("new-version-available",(message)=>{
sendHotUpdateMessage({
cmd: 'new-version-available',
message: message
})
})
// 监听获取版本失败 更新失败
electronHotupdatas.on("downloaded-failed",(message)=>{
sendHotUpdateMessage({
cmd: 'downloaded-failed',
message: message
})
})
// 监听更新完成
electronHotupdatas.on("complete-downloaded",(message)=>{
sendHotUpdateMessage({
cmd: 'complete-downloaded',
message: message
})
})
// 跟新完成立即重启程序
ipcMain.on("relaunch",()=>{
app.relaunch()
app.exit()
})
// 触发更新事件
ipcMain.on("start-updata",(message)=>{
electronHotupdatas.startUpdata()
})
// 获取跟新进度
electronHotupdatas.on("downloaded-progressNumber",(message)=>{
sendHotUpdateMessage({
cmd: 'downloaded-progressNumber',
message: message
})
})
// 触发获取新版本事件
ipcMain.on("startLoop",(message)=>{
electronHotupdatas.startLoop()
})
}
//给渲染进程发送消息
function sendHotUpdateMessage(text) {
mainWindow.webContents.send('hotMessage', text)
}
在background.js 调用 hot-updata.js
import { app, protocol, BrowserWindow,Menu } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
// 自动更新
import {updateAva} from './hot-updata.js' ;
const isDevelopment = process.env.NODE_ENV !== 'production'
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
])
async function createWindow() {
// Create the browser window.
const win = new BrowserWindow({
width: 900,
height: 800,
frame:true,
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 as unknown) as boolean,
// contextIsolation: !(process.env
// .ELECTRON_NODE_INTEGRATION as unknown) as boolean,
nodeIntegration:true,
contextIsolation:false,
webSecurity: false,
// preload:'./src/preload.js' ,
preload:__dirname+'\\preload.js' , // 必须要引入 preload.js 不然获取不到electron
}
})
Menu.setApplicationMenu(null)
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 as string)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
win.webContents.openDevTools()
// win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string)
}
// http://192.168.0.191/electron/ 是我本地的测试地址 换成你服务器的地址
updateAva(win, 'http://192.168.0.191/electron/',app.getVersion());
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
// if (isDevelopment && !process.env.IS_TEST) {
// // Install Vue Devtools
// try {
// await installExtension(VUEJS_DEVTOOLS)
// } catch (e:any) {
// console.error('Vue Devtools failed to install:', e.toString())
// }
// }
createWindow()
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}
在app.vue 里面调用electron 获取最新版本
// ts
const ipcRenderer = (window as any).ipcRenderer
// js
const ipcRenderer =window.ipcRenderer
// window.ipcRenderer === undefined 说明没有引入 preload.js
created() {
let _this = this;
if (ipcRenderer) {
window.setInterval(() => {
console.log("循环开始检查更新....")
ipcRenderer.send("startLoop");
}, 10000);
ipcRenderer.on("hotMessage", (event: any, arg: any) => {
console.log(arg);
if (arg.cmd == 'new-version-available') {
_this.modalVisible = true
} else if (arg.cmd == 'downloaded-failed') {
console.log('更新失败')
} else if (arg.cmd == 'downloaded-progressNumber') {
console.log('获取跟新进度' + arg.message)
_this.progress = arg.message
} else if (arg.cmd == 'complete-downloaded') {
console.log('更新完成')
// 更新完成 立即 重启程序
ipcRenderer.send("relaunch");
}
});
}
}
preload.js
const electron = require('electron');
window.ipcRenderer = require('electron').ipcRenderer;
window.remote = require('electron').remote;