Electron 更新
更新方式
- 全量更新
全量更新指的是 用户从头到尾重新安装一遍 .工作原理是:他会去线上匹配 yml 文件里面的版本号,
当你的 package.json 里面的版本号要是小于线上的版本号的时候,就会提示用户更新,然后用户点击更新的时候,就会去下载最新的安装包,然后安装,安装完成之后,会自动打开应用,然后关闭旧版本的应用
- 增量更新
增量更新指的是 用户只更新了部分文件,而不是从头到尾重新安装一遍 .工作原理是:他会去线上匹配 asr 文件 .它只是下载了 asr 文件 然后匹配(这里涉及了权限问题)
全量更新
第一步:
把新版本的安装包放到服务器上.重点是 yml 文件必须有
第二步:
- 找到 electron 文件夹下面的 builder.json 文件,修改这个里面的地址
ts
"publish": [
{
"provider": "generic",
"url": "https://www.dianyuan.com/upload/electron"
}
],
- 找到 config 文件夹下面的 config.default.js 文件,增加更新包路径
ts
"use strict";
const path = require("path");
/**
* 默认配置
*/
module.exports = (appInfo) => {
const config = {};
/**
* 开发者工具
*/
config.openDevTools = false;
// 假设打包
config.isPackaged = true;
/**
* 应用程序顶部菜单
*/
config.openAppMenu = true;
/**
* 主窗口
*/
config.windowsOption = {
title: "EE框架",
width: 980,
height: 650,
minWidth: 400,
minHeight: 300,
webPreferences: {
//webSecurity: false,
contextIsolation: false, // false -> 可在渲染进程中使用electron的api,true->需要bridge.js(contextBridge)
nodeIntegration: true,
//preload: path.join(appInfo.baseDir, 'preload', 'bridge.js'),
},
frame: true,
show: false,
icon: path.join(appInfo.home, "public", "images", "logo-32.png"),
};
/**
* ee框架日志
*/
config.logger = {
encoding: "utf8",
level: "INFO",
outputJSON: false,
buffer: true,
enablePerformanceTimer: false,
rotator: "day",
appLogName: "ee.log",
coreLogName: "ee-core.log",
errorLogName: "ee-error.log",
};
/**
* 远程模式-web地址
*/
config.remoteUrl = {
enable: false,
url: "http://electron-egg.kaka996.com/",
};
/**
* 内置socket服务
*/
config.socketServer = {
enable: false,
port: 7070,
path: "/socket.io/",
connectTimeout: 45000,
pingTimeout: 30000,
pingInterval: 25000,
maxHttpBufferSize: 1e8,
transports: ["polling", "websocket"],
cors: {
origin: true,
},
channel: "c1",
};
/**
* 内置http服务
*/
config.httpServer = {
enable: false,
https: {
enable: false,
key: "/public/ssl/localhost+1.key",
cert: "/public/ssl/localhost+1.pem",
},
host: "127.0.0.1",
port: 7071,
cors: {
origin: "*",
},
body: {
multipart: true,
formidable: {
keepExtensions: true,
},
},
filterRequest: {
uris: ["favicon.ico"],
returnData: "",
},
};
/**
* 主进程
*/
config.mainServer = {
protocol: "file://",
indexPath: "/public/dist/index.html",
};
/**
* 硬件加速
*/
config.hardGpu = {
enable: true,
};
/**
* 异常捕获
*/
config.exception = {
mainExit: false,
childExit: true,
rendererExit: true,
};
/**
* jobs
*/
config.jobs = {
messageLog: true,
};
/**
* 插件功能
*/
config.addons = {
window: {
enable: true,
},
tray: {
enable: true,
title: "EE程序",
icon: "/public/images/tray.png",
},
security: {
enable: true,
},
awaken: {
enable: true,
protocol: "ee",
args: [],
},
autoUpdater: {
enable: true,
windows: false,
macOS: false,
linux: false,
options: {
provider: "generic",
url: "http://kodo.qiniu.com/",
},
force: false,
},
};
/* 更新包路径 */
config.autoUpdatePath = "https://www.dianyuan.com/upload/electron";
return {
...config,
};
};
- 第三步: 在 electron 文件夹下面新建一个 utils 文件夹,然后新建一个 autoUpdater.js 文件
ts
const { dialog } = require("electron");
const { autoUpdater } = require("electron-updater");
//自动下载更新
autoUpdater.autoDownload = false;
//退出时自动安装更新
autoUpdater.autoInstallOnAppQuit = false;
// 测试必须开启
autoUpdater.forceDevUpdateConfig = true;
module.exports = (event, path) => {
// 设置更新源url
autoUpdater.setFeedURL(path);
//检查是否有更新
autoUpdater.checkForUpdates();
//有新版本时
autoUpdater.on("update-available", (_info) => {
dialog
.showMessageBox({
type: "warning",
title: "更新提示",
message: "有新版本发布了",
buttons: ["更新", "取消"],
cancelId: 1,
})
.then((res) => {
if (res.response == 0) {
//开始下载更新
console.log("2222");
autoUpdater.downloadUpdate();
}
});
});
//没有新版本时
autoUpdater.on("update-not-available", (_info) => {
console.log("没有更新");
});
//更新下载完毕
autoUpdater.on("update-downloaded", (_info) => {
//退出并安装更新
autoUpdater.quitAndInstall();
});
//更新发生错误
autoUpdater.on("error", (_info) => {
console.log("更新时发生错误");
});
// 监听下载进度
autoUpdater.on("download-progress", (progress) => {
console.log(JSON.stringify(progress));
event.reply("controller.example.onlistener", progress);
});
};
分层
- 视图层
html
<template>
<div>
<button @click="checkForUpdates('all')">全局更新</button>
<button @click="checkForUpdates('part')">局部更新</button>
<el-progress
:text-inside="true"
:stroke-width="24"
:percentage="percentage"
status="success"
/>
</div>
</template>
<script setup>
import { ipc } from "@/utils/ipcRenderer";
import { ipcApiRoute } from "@/api/main.js";
import { onMounted, ref } from "vue";
const percentage = ref(0);
// 开启监听
onMounted(() => {
ipc.on("controller.example.onlistener", (event, result) => {
percentage.value = parseInt(result.percent);
});
});
const checkForUpdates = (data) => {
if (data == "all") {
ipc.send(ipcApiRoute.allupdate);
} else {
ipc.send(ipcApiRoute.partupdate);
}
};
</script>
<style lang="scss" scoped></style>
- 控制层
这里特别注意 event 就是第二个参数,必须要传递给 Services 层
ts
"use strict";
const { Controller } = require("ee-core");
const Log = require("ee-core/log");
const Services = require("ee-core/services");
/**
* example
* @class
*/
class ExampleController extends Controller {
constructor(ctx) {
super(ctx);
}
/**
* 所有方法接收两个参数
* @param args 前端传的参数
* @param event - ipc通信时才有值。详情见:控制器文档
*/
/**
* test
*/
async test() {
const result = await Services.get("example").test("electron");
Log.info("service result:", result);
return "hello electron-egg";
}
/*全局增量*/
async allupdate(args, event) {
await Services.get("example").allupdate(event);
}
/* 增量更新 */
async partupdate(event) {
await Services.get("example").partupdate(event);
}
}
ExampleController.toString = () => "[class ExampleController]";
module.exports = ExampleController;
- Services 层
ts
"use strict";
const autoUpdater = require("../utils/autoUpdater");
const { Service } = require("ee-core");
/**
* 示例服务(service层为单例)
* @class
*/
class ExampleService extends Service {
constructor(ctx) {
super(ctx);
}
/*全局增量*/
async allupdate(event) {
console.log("quanjuzengliang");
// const { app } = this;
// const mainWindow = app.electron.mainWindow;
// const win = mainWindow.webContents;
console.log(this.config.autoUpdatePath);
const path = this.config.autoUpdatePath;
autoUpdater(event, path);
}
/* 增量更新 */
async partupdate() {
console.log("点击了局部更新");
return "点击了局部更新";
}
}
ExampleService.toString = () => "[class ExampleService]";
module.exports = ExampleService;