★ 本人在公司项目中实现的Electron更新功能。

★ 将实现更新过程的每一步都总结了出来,以及过程中我遇到了哪些问题,如何去解决的问题,有哪些注意事项。

★ 使用贴合实际应用的HTTP服务器做为载体实现更新,而非github。

开始:

程序配置:

  1. 构建工具:Electron-builder

  2. 更新工具:Electron-updater

在进行更新时,Electron 框架提供了更新的模块。但是我的程序是使用Electron-builder进行的构建。我就使用了Electron-builder这个构建工具提供的自动更新的工具Electron-updater 来实现更新:在这里插入图片描述

更新的思路流程:

  1. 首先安装 electron-updater

    npm i electron-updater
    
  2. 进行更新的配置,官网有提供,在build下的 publish 中进行设置

    publish: {    provider: "generic", //generic通用HTTP服务器,当然有些人使用github做为更新载体这个地方的值就写github,我使用的是http服务器,在局域网中使用。url: "http://xxxxxx/electron-updater" // 指向服务器对应更新的目录,这个路径的后缀electron-updater是我自定义的,具体原因文章最后讲。channel: "latest",
    },
    
  3. 单独新建了一个文件,来写更新的逻辑代码,重点来咯…

    (下列代码意思都有详细注释)

    /*** 应用更新*/
    const { app, dialog, ipcMain, nativeImage } = require("electron");
    const { autoUpdater } = require("electron-updater");
    const log = require("electron-log"); // 为了输出更新的日志:为安装了 electron-log => npm i electron-log
    const path = require("path");function initAppUpdate(win) {// 配置日志,这个日志在 windows:C:\Users\Administrator\AppData\Roaming\你的程序名\logsautoUpdater.logger = log;autoUpdater.logger.transports.file.level = "info";// 禁用增量更新:代表用户每次进行更新,都会将服务器上完整的程序进行下载更新,而不会更新指定修改的块文件。// 当然肯定是增量更新更好,但是为什么我禁用了呢,文章最后讲。autoUpdater.disableDifferentialDownload = true// 退出时自动安装:当用户使用程序的时候,按兵不动。等待用户关闭程序了退出了之后,程序自动安装,这样下次用户再次打开就是更新后的程序,但我为了让客户感知到更新,我禁用了退出时自动安装。autoUpdater.autoInstallOnAppQuit = false;// 检查更新(应用启动时触发)app.whenReady().then(() => {autoUpdater.checkForUpdates();});// 监听下载完成事件(这里就是具体给用户展示的更新的对话框,这个对话框的视图在文章开头我贴出来了)autoUpdater.on("update-downloaded", () => {dialog.showMessageBox(win, {type: "info",buttons: ["稍后", "立即安装"],message: "更新已下载",detail: "新版本已就绪,是否立即安装?",defaultId: 1, // 默认选中"立即安装"(索引1)cancelId: 0, // 按Esc键等同于点击"取消"}).then((res) => {if (res.response === 1) autoUpdater.quitAndInstall(); // 如果他对话框点击“立即安装”,就退出开始安装});});// 错误处理autoUpdater.on("error", (err) => {log.error("更新失败", err);});checkUpdate(win);
    }// 渲染进程触发的检查更新(这个我在程序里有个专门让用户用来检测更新的地方)
    function checkUpdate(win) {ipcMain.handle("checkUpdate", async () => {const res = await autoUpdater.checkForUpdates();if (!res.isUpdateAvailable) {dialog.showMessageBox(win, {type: "info",buttons: ["我知道了"],message: "当前版本已经是最新版本",icon: loadIcon(),});}});
    }// 加载图标(兼容开发和生产环境)
    function loadIcon() {try {let iconPath = path.join(__static, "right.png");return nativeImage.createFromPath(iconPath);} catch (e) {console.error("加载图标失败:", e);return null;}
    }// 这个函数,要引入到主进程的启动程序文件里,还要将win传参给该函数
    // 为什么要传递win呢? 因为你不传的话,这个提示更新的dialog就和程序是两个程序。如果你传了win给dialog的话,dialog就在当前win上弹出。
    module.exports = { initAppUpdate };
    
  4. 将上面的 initAppUpdate 函数引入启动程序文件,我这里的是background.js

在这里插入图片描述

  1. 更新的配置到此已经都完成了。接下来要确定程序的版本号,在package.json 中有 version 这个键,设置一个程序版本号。比如你这次打包的程序是1.0.0,那么下次更新就是1.0.1。程序的更新是去检测版本号是不是更新了,版本号更新了才会拉取更新的程序文件。(每次更新构建的时候,记得提高版本号)

  2. 打包构建:运行 npm run electron:build ,在构建后的目录就会有 latest.yml 这个文件和 程序文件等。

  3. 构建成功后,你需要在服务器上建一个目录,用来放程序文件等。

    1. 在你服务器新建一个目录(我命名为 electron-updater),上传文件:

      1. 第一个文件:latest.yml 这个文件包含了更新的版本信息以及程序包的信息等。

      2. 第二个文件:xxx.exe,应用程序。

      3. 第三个文件:xxx.exe.blockmap ,块映射文件。用于增量更新,每次更新只更新变动的文件。

        但是有需要注意的事项:

        1. 你想要实现增量更新,需要将 .blockmap 块映射文件上传到对应的服务器目录下,并且你还要保留更新前版本的块映射文件。因为增量更新,需要比对更新前的块映射文件和准备要更新的块映射文件之间的差异,来实现增量更新。
        2. 比如:你服务器上的程序版本现在是1.0.0,现在程序要更新为1.0.1,那么你想让客户端实现增量更新,你的服务器需要放置的文件有
          1. 版本 1.0.1latest.yml 文件
          2. 版本 1.0.1xxx.exe 文件
          3. 版本 1.0.1xxx.exe.blockmap 文件
          4. 版本 1.0.0xxx.exe.blockmap 文件
        3. 还有一个增量更新的注意事项,写在下面了👇
    2. 先把你在服务器上创建的放置更新文件、程序文件的目录映射出去。也就是为了解决文章开始写到的配置 publish 的时候,其中有个 url:http://xxxxxx/electron-updater,这个 url 就是直接访问我们新建的这个目录。

      1. 我新建的目录名字叫做 electron-updater 目录名称。但是我在服务器上创建的 electron-updater 并不和 url 中的 electron-updater 是一个哦,是因为我用 electron-updater 这个路径代理了 electron-updater 这个目录,当然代理的路径也可以改为别的,那么这时 url 的对应路径也要改。

      2. 如何让 http://xxxxxx/electron-updater 访问到服务器上创建的 electron-updater 放置文件的目录呢?使用代理服务器!

        当我开发测试的时候,我使用的是 nginx 来映射的目录。测试了一下,发现实现了更新的功能、以及增量更新,一切都成功了。但是了解到使用方的服务器代理使用的 apache ,所以我又使用 apache 来实现,这次遇到问题了,在测试实现增量更新的时候,一直报错响应头的 Content-Type 错误,针对该错误我去 apache 添加响应头,测试依旧有新报错,随后就没有再去尝试了。所以开头写到了,我采用了完整更新,而非增量更新。完整更新都是可以正常下载更新,只有使用 apache 的时候增量更新有问题。但使用 nginx 是不用格外配置就可以成功实现 完整更新 和 增量更新,所以没有代理服务器要求的,使用 nginx 方便一些。

        1. nginx 配置

          在这里插入图片描述

        2. apache 配置

          # 映射本地目录到URL路径
          Alias "/electron-updater" "D:/xxx/electron-updater"
          ...
          

总结:

  1. 注意我在配置更新的时候,禁用了退出程序后自动更新,当然也可以打开这个配置哦。用户打开程序再次退出关闭后,自动更新程序,这个功能还是挺不错的。
  2. 保存路径:
    1. 程序更新日志保存路径:
      C:\Users\Administrator\AppData\Roaming\你的程序名\logs
    2. 程序更新下载后的保存路径:
      C:\Users\Administrator\AppData\Local\xxxxx_electron-updater\pending
  3. 一定要注意有新版本后,要提高程序的版本号,再 build 打包构建哦~
  4. 此外我还设置了一个小功能,就是不仅在程序刚打开的时候去检测是否有更新。用户在使用的过程中也加了按钮可以让用户点击查看是否需要更新,如果不需要更新,会提示用户此版本为最新版本,多么贴心的功能… (前面的代码里面有写到)

此时Electron的更新功能,或者说Electron的自动更新就算圆满结束!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/85477.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/85477.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/85477.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Apache RocketMQ 消息过滤的实现原理与腾讯云的使用实践

导语 本文将系统阐述 Apache RocketMQ 消息过滤机制的技术架构与实践要点。首先从业务应用场景切入,解析消息过滤的核心价值;接着介绍 Apache RocketMQ 支持的两种消息过滤实现方式,帮助读者建立基础认知框架;随后深入剖析 SQL 语…

安卓JetPack篇——LifeCycle原理

LifeCycle 一、什么是Lifecycle 具备宿主生命周期感知能力的组件。它能持有组件(如Activity或Fragment)生命周期状态的信息,并且允许其他观察者监听宿主的状态。 二、基本原理 1、安卓10以下版本 隐形的Fragment注入在LifecycleOwner&am…

CSS 圆角边框属性(`border-radius`)笔记

一、作用: 用于设置元素四个角的圆角效果,让元素不再死板,更加柔和。 二、基本语法: border-radius: 圆角大小; 单位:px(像素)或 %(百分比) 示例: div {  …

python自助棋牌室管理系统

目录 技术栈介绍具体实现截图系统设计研究方法:设计步骤设计流程核心代码部分展示研究方法详细视频演示试验方案论文大纲源码获取/详细视频演示 技术栈介绍 Django-SpringBoot-php-Node.js-flask 本课题的研究方法和研究步骤基本合理,难度适中&#xf…

计算机——硬盘分区和格式化

硬盘驱动器 硬盘驱动器(HDD)是一种成熟、经济的大容量存储解决方案。它的核心优势在于每GB成本低和超大容量。然而,其机械结构带来的速度瓶颈、噪音、功耗和对物理冲击的敏感性是其主要的缺点。随着 SSD 价格的持续下降和性能的绝对领先&…

从IEC到UL:技术主权竞争下的断路器合规性战略

1 国际标准体系割裂的现状 在全球低压电器领域,国际标准体系呈现出日益明显的割裂态势。当前主要存在四大标准体系:国际通用的​​IEC标准体系​​、欧洲采用的​​EN标准体系​​、北美实施的​​UL与CSA标准体系​​,以及具有地域特色的​…

第十六届蓝桥杯_省赛B组(D).产值调整

题目如下 这道题看似很简单,其实还是得观察一下,要不然就会… 话不多说回到题目,这个题的坑就在于当A,B,C三个产值相同的时候,再怎么变还是之前的产值,或者也可以通过另外一种方法理解: 通过一个案例来举…

设计模式 | 单例模式——饿汉模式 懒汉模式

单例模式 文章目录 单例模式一、饿汉模式(Eager Initialization)1. 定义2. 特点3. 饿汉单例模式(定义时-类外初始化)4. 实现细节 二、懒汉模式(Lazy Initialization)1. 定义2. 特点3. 懒汉单例模式&#xf…

dify本地部署及添加ollama模型(ubuntu24.04)

说明:ubuntu是虚拟机的,用的桥接模式,与本地同局域网不同ip地址。 参考VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP前提:需要有docker及docker-compose环境 参考ubuntu24安装docker及docker…

Python爬虫实战:研究multiprocessing相关技术

一、引言 1.1 研究背景与意义 随着互联网信息的爆炸式增长,网络爬虫已成为获取海量数据的重要工具。传统的单线程爬虫在面对大规模数据采集任务时效率低下,无法充分利用现代计算机多核 CPU 的优势。多线程爬虫虽然在一定程度上提高了效率,但受限于 Python 的全局解释器锁(…

6.18 redis面试题 日志 缓存淘汰过期删除 集群

Redis有哪2种持久化方式?分别的优缺点是什么? Redis 的重写 AOF 过程是由后台子进程 bgrewriteaof 来完成的。 过期删除策略和内存淘汰策略有什么区别? 内存淘汰策略是在内存满了的时候,redis 会触发内存淘汰策略,来淘…

什么时候会发生内存泄漏?

1. 内存泄漏是什么? 定义:内存泄漏是指程序中的对象已经不再需要,但由于被其他对象错误引用,导致垃圾回收器(GC)无法回收它,从而长期占用内存空间的现象。 2. 内存泄漏的危害 问题具体表现内存…

用RSA算法模拟类的适配器模式

“RAS算法”这个术语本身并不常见或标准,它可能指向两个主要领域的不同概念,具体取决于上下文: 更可能是拼写错误:指 RSA 算法(密码学) 这是最常见的情况。 “RAS” 极有可能是 “RSA” 的拼写错误。RSA 算…

CARSIM-与C#自动化测试方案

using System; using System.Runtime.InteropServices; using System.Collections.Generic;namespace CarSimAutomation {/// <summary>/// CarSim COM 自动化测试接口/// 封装所有 CarSim COM 功能用于自动化测试/// </summary>[ComVisible(true)][ClassInterface…

企微CRM系统中的任务分配与效率提升技巧

在数字化管理时代&#xff0c;企业微信(企微)与CRM系统的深度融合&#xff0c;为企业提供了更高效的客户管理与团队协作方案。企微CRM软件不仅整合了客户沟通、销售跟进、数据分析等功能&#xff0c;还能通过智能任务分配优化团队效率。本文将深入探讨企微CRM管理系统的任务分配…

day66—BFS—最短的桥(LeetCode-934)

题目描述 给你一个大小为 n x n 的二元矩阵 grid &#xff0c;其中 1 表示陆地&#xff0c;0 表示水域。 岛 是由四面相连的 1 形成的一个最大组&#xff0c;即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。 你可以将任意数量的 0 变为 1 &#xff0c;以使两座…

FramePack 安装指南(中文)

FramePack 安装指南&#xff08;中文&#xff09; -Windows FramePack 是最前沿的 AI 视频生成框架&#xff0c;以极小的硬件需求颠覆视频创作&#xff01;它能在仅 6GB 笔记本 GPU 内存上&#xff0c;驱动 13B 模型以 30 FPS 生成超长 120 秒视频&#xff0c;几乎无内容限制&…

Redis Sentinel 非集群模式高可用部署指南

1. Sentinel 在非集群模式的定位 一句话&#xff1a;在单主多从架构中&#xff0c;用 Sentinel 替你盯哨——探测故障、选举新主、通知客户端。 核心四职能&#xff1a; 职能作用点Monitoring定时 PING 主从&#xff0c;自身也互相探测Notification通过日志/PubSub/外部调用报…

2025Java面试八股文

文章目录 Java基础JVM多线程SpringSpring Boot数据库与SQL分布式系统其他 Java基础 自动装箱与拆箱&#xff1a;Java中基础数据类型与包装类之间的转换。例如&#xff0c;Integer x 1; 是装箱&#xff0c;int y x; 是拆箱。Object类常用方法&#xff1a;如clone()、getClass…

宝塔安装nginx-rtmp,音视频直播

前置&#xff1a;需要自己开发音视频直播&#xff0c; 注意不是实时音视频&#xff0c;不是一对一视频聊天&#xff0c;不是视频会议 方案有 srs &#xff0c;nginx-rtmp&#xff0c;live555&#xff0c;node-media-server&#xff0c;EasyDarwin等 今天是说 nginx-rtmp 怎么…