Electron系列 -- 实现自动更新/手动更新功能(下)

Eectron框架 Electron中文网 官网

electron 的自动更新不会像 React Native 一样直接下载 Web 代码静默更新,因为它还有主进程(Node.js)代码,因此需要走安装流程。

electron-updater 是一个用于 Electron 应用程序的第三方库,它提供了丰富的接口和功能来帮助开发者实现应用程序的自动更新

主要的优势还是支持自定义更新服务。公司发布新版本安装包,直接上传到自己的静态服务器即可,无需再搭建一个专门的更新服务

目录

一. 安装 electron-updater 实现自动更新

二. 客户端打包前, 进行latest.yml配置

三. 后端配合

四. 手动更新如何触发

五. 其他问题

总结


想了解打包, 欢迎查阅 Electron系列 -- vue项目嵌套electron打包成桌面应用(上)-CSDN博客

一. 安装 electron-updater 实现自动更新

安装依赖 electron-updater

npm install electron-updater

在根目录src下 新建 handleUpdate.js 文件, 粘贴下面的代码 

const { autoUpdater } = require("electron-updater");
const { dialog, ipcRenderer } = require("electron");
var mainWin = null;

const checkUpdate = (win, ipcMain) => {
  autoUpdater.autoDownload = true; // 自动下载
  autoUpdater.autoInstallOnAppQuit = true; // 应用退出后自动安装
  mainWin = win;
  
 const checkForUpdates = () => {
    // 检测是否有更新包并通知
    autoUpdater.checkForUpdatesAndNotify().catch();
  };  
  // 应用启动时检查更新
  checkForUpdates();

  // 设置每小时检查一次更新
  // setInterval(checkForUpdates, 1000 * 60 * 60);

  // 监听渲染进程的 install 事件,触发退出应用并安装
  ipcMain.handle("install", () => autoUpdater.quitAndInstall());

  autoUpdater.on("update-available", (info) => {
    console.log("有新版本需要更新");
  });
  autoUpdater.on("update-not-available", (info) => {
    console.log("无需更新");
  });
  //下载进度
  autoUpdater.on("download-progress", (prog) => {
    mainWin.webContents.send("update", {
      speed: Math.ceil(prog.bytesPerSecond / 1000), // 网速
      percent: Math.ceil(prog.percent), // 百分比
    });
  });
  //事件监听器的回调函数接收三个参数:
  //event:一个对象,提供了事件相关的信息和功能
  //releaseNotes:一个字符串,包含了新版本的发布说明或更新日志。
  //releaseName:一个字符串,通常包含了新版本的名称或版本号。
  autoUpdater.on("update-downloaded", (event, releaseNotes, releaseName) => {
    //更新已经被下载到本地,以便进一步处理
    mainWin.webContents.send("downloaded");

    let opts = {
      type: "info",
      buttons: ["现在重启", "稍后"],
      title: "应用程序更新",
      message: `收银台系统新版本已下载`, // 使用模板字符串来包含变量
      detail: "新版本已下载,是否现在重启应用程序以更新?",
    };

    dialog.showMessageBox(opts).then((response) => {
      if (response== 0) {
        // 用户选择安装更新,重启应用
        autoUpdater.quitAndInstall();
      }
    });

    // 下载完成后强制用户安装,不推荐
    // autoUpdater.quitAndInstall();
  });
};

module.exports = checkUpdate;

在background.js 中引入 handleUpdate.js文件 ,放置在createWindow方法中 , 调用它 

const handleUpdate = require("./handleUpdate");

...

//检查更新
handleUpdate(win, ipcMain)

...

二. 客户端打包前, 进行latest.yml配置

 在vue.config.js 中加入latest.yml配置

       //latest.yml配置
        publish: [
          {
            provider: "generic",
            url: https://xxxx/updateExe, //更新包地址 
          },
        ],

package.json 中修改 名字 版本号,

 

以window平台为例, 打包后会生成多个文件

  1. 应用打包,生成安装包和版本配置
    版本号取自 package.json 文件中的 version 选项。
    假设当前版本号是 1.0.0,我们首先更新版本号为 1.0.1,然后执行打包命令

  2. 以window平台为例, 打包后会生成多个文件, 以下两个文件需要上传 xxx_1.0.0.exe(安装包) 和 latest.yml(版本配置)

  3. 上传到服务器后,需要通过 publish 中配置的地址访问到,最终访问地址如下:

  • https://xxx/updateExe/xxx_1.0.0.exe  下载安装包
  • https://xxx/updateExe/latest.yml    检测版本更新

      ( 控制台是看不到更新请求的, 他是通过electron 主进程发起的, 但是我们可以通过抓包工具来捕捉到它 ,比如 Fiddler 等)

三. 后端配合

配置 nginx 使访问地址生效
我们将上一步的两个文件上传到服务器的 /data/updateExe 目录下,然后在 nginx 配置中添加一个 location 如下:

location /updateExe{
   add_header Access-Control-Allow-Origin *;
   add_header Access-Control-Allow-Credentials true;
   add_header Access-Control-Allow-Methods GET,POST;
   alias /data/updateExe;
   sendfile on;
   autoindex on;
}

使用 "nginx -s reload" 重新加载配置,访问文件的地址便生效了。

四. 手动更新如何触发

为什么要引入preload.js文件, 你可以把它认为是 Vue 项目与 Electron 之间的桥梁, 有了它我们就可以实现手动检测更新, 并实现更新进度条展示 

1. 新建一个preload.js 文件 ,放置在src 同级public静态目录中

// preload.js

const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("elecAPI", {
  onUpdate: (callback) => ipcRenderer.on("update", callback),
  checkForUpdate: () => ipcRenderer.send("checkForUpdate"),
});

2. 将preload.js 引入配置

 const win = new BrowserWindow({
    width: 1200,
    height: 1080,
    // autoHideMenuBar: 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,
      contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION, // 禁用上下文隔离
      webSecurity: false, //关闭安全策略, 解决跨域问题
      preload: isDevelopment
        ? path.join(__dirname, "../public/preload.js")
        : __dirname + "\\preload.js",
    },
  });

preload这里的写法非常有意思, 我也是踩坑小能手, 这是最终写法, 通过判断是否为开发环境 来实现不同的引入方法, 因为无论是在开发还是生产环境, 常规写法默认都会去找dist_electron/bundled/preload.js 文件, 第一次未打包, 你报错了, 打包一次再执行, 有该文件, 你有可以了, 二次修改后, 突然又异常了 !! 

3.在xxx.vue页面引入 

通过一个 clickTest事件来触发 

....
    //引入element-ui 的进度条组件 
            <el-progress
              :text-inside="true"
              :stroke-width="20"
              :percentage="update_info.percent"
              status="exception"
            ></el-progress>

<el-button @click="clickTest"></el-button>

....

data(){
  return{
    update_info:null
  }
}
....

method:{
 clickTest() {
      window.elecAPI.checkForUpdate();
 },

},
mounted(){
// 监听onUpdate事件, 监听到更新时间后显示进度条
 if (window.elecAPI && window.elecAPI.onUpdate) {
      window.elecAPI.onUpdate((_event, info) => {
        //参数1 网速 ,参数2 百分比
        console.log("onUpdate", _event, info);
        that.update_info = info;
      });
    }
}

handleUpdate.js 加入下面代码(已有请忽略 )

  //下载进度
  autoUpdater.on("download-progress", (prog) => {
    mainWin.webContents.send("update", {
      speed: Math.ceil(prog.bytesPerSecond / 1000), // 网速
      percent: Math.ceil(prog.percent), // 百分比
    });
  });

在background.js 中加入下面代码, 用于触发手动检查更新

  ipcMain.on("checkForUpdate", () => {
    try {
      autoUpdater.checkForUpdatesAndNotify().catch();
    } catch (error) {
      console.log(error);
    }
  });

五. 其他问题

1. 项目中在electron进程打印,console.log 没有反应?

通过添加环境变量,大部分能打印出来(实测)

ELECTRON_ENABLE_LOGGING: true

ELECTRON_ENABLE_STACK_DUMPING: true

总结

经过上述的好几个步骤,现在要发布新版本,只需要执行 2 个步骤。

  1. 更新版本号,打包。
  2. 上传到服务器。

如果不加手动触发更新, 也是可以的, 加个轮询机制, 每x个小时主动检查一次更新,否则只能应用打开的第一次检查一次, 陆续不会检测!

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值