得物后台 *** (得物商家 *** 桌面端Electron技术实践)
如何解决NSIS 桌面电子技术的实践
1.业务背景
随着公司的快速发展。的业务,商家客户服务也已纳入我们的服务范围。商家 工作台的定位是通过工具和数据为商家服务,解决用户 一站式采购咨询需求。通过工具和运营策略,帮助商家提升服务质量,让品牌商家有动力去运营好潜在客户,从而达到提升用户服务的目的。桌面应用的转型是未来 产品的方向。已有web端聊天系统的前提下,商家 为什么要迁移桌面应用?,我们收到一些商家的 反馈
用户是上帝,我们是很重视用户的反馈的,所以我们想的是如何在web端解决这些问题,下面我们逐一分析下以上问题我们能不能在网页端解决呢?,针对 A同学问题:大多数桌面在客户服务工作场所不 不要安装音频设备。如果有人不 没有音频或外部声音,我们可以强迫他买一个播放器吗?那个 这是绝对不可能的。如果 是个体户,还是有一些解决办法的。如果真的需要,公司可以统一采购,但ToC显然可以 不要强迫他做任何事情,所以这个问题没有解决方案。
针对 B同学问题:你怎么理解这句话?这里 事情是这样的。在一个屏幕上,既有 浏览器,也有其他PC应用程序,如舒菲。因为web通知是浏览器级别的,所以它们可以 不要在顶层被提醒,浏览器 的提醒真的很弱(看不到提醒会影响 的之一声铃响,影响 的表现,我们公司 s对用户的服务效率是相当严格的),所以这个问题没有解决方案。
针对 C同学问题:艾米.好吧,你 你说得对。网页给商家 的感觉是我们平台有点落后的情况。
基于上面的一些场景,我想大家对为什么要做桌面应用已经有了初步的了解。让 让我们用一张图来看看web应用程序和桌面应用程序的区别。
2.技术选型
为什么会选择Electron而不是其他应用开发框架?2.1 Electron架构简介
电子主要由以上三大模块组成,各司其职,使电子具备了桌面应用的能力。Chromium:可以为电子提供UI渲染能力,Chromium本身是跨平台的,所以不需要考虑代码兼容性。只要有Chromium,就可以用前端开发工程师熟悉的JavaScript,HTML,CSS来开发页面。Node.js:Chromium没有原生GUI操作的能力,所以Node.js正好补充了这个能力,可以调用操作系统的底层API,比如path、fs、crypto甚至integrate c . Native API:Native API赋予了电子跨平台、跨桌面的原生能力。例如,它有一个统一的原生界面、窗口和托盘。
2.2 Electron与其他框架的区别
以下是电子和本地、QT和NW应用的对比图![截图2023013115.49.19.png](https://cdn.poizon.com/ctoo/013115/screenshot 2023-01-31 15.49.19.png)
Native(C /C#/Objective-C)无论从原生体验、封装大小还是性能来看都是更佳选择,开发门槛高,迭代速度慢。QT是基于C的跨平台开发框架,广泛应用于跨平台(Mac、Windows、ios、Android、Linux、embedded)。众所周知的WPS就是用QT开发的。性能很好,甚至堪比原版体验,但整体门槛还是比较高的。Web技术的代表,Electron和NW.js,有一个非常活跃的社区,比如102k star,Atom,vscode,都是基于Electron的,性能肯定比natvie差,但总体来说,Electron是开发桌面应用的首选。值得一提的是flutter desktop。从渲染原理来看,Flutter就是skia 的自拉伸性能优于电子 但问题仍然是稳定性和生态性。电子是nodejs铬,前端生态可以直接使用,所以不考虑Flutter desktop,值得关注。除了以上,最重要的一点是电子可以快速交付,业务层可以复用web系统的代码,只关注主流程,也可以满足业务所需的一些系统级功能。
3.技术实现
3.1 项目架构
介绍了电子框架中的两个重要概念,主进程和渲染进程。主进程主要负责创建和管理BrowserWindow实例和应用事件。它可以注册全局快捷方式,创建系统菜单和对话框,并响应自动更新事件。主进程和所有Node.js模块中都提供了一些电子API。
渲染进程渲染进程负责运行应用的用户界面,渲染进程中提供了DOM API、Node.js API和Electron API的所有子集。
如上图截图所示,打开电子项目后,会有多个流程。一个项目只有一个主进程,窗口创建等系统事件写在主进程中,但可能有多个渲染进程。
那为什么
会有多个渲染进程呢?Electron应用是Chromium内核,所以多进程的架构也来源于Chromium,Chromium会单独运行每个标签,任何一个标签页崩溃了都不会影响到其他标签。,每个进程在自己的空间中运行,由操作系统调度。如果某个进程触发了无限循环,也不会导致整个应用down掉。
在上文说到两个字“迁移”,是的,我们在开发桌面应用之前有非常成熟的web端商家 聊天系统了,所以我们在开发桌面应用的时候大多数时候是关心主进程的,渲染进程并不太需要关心。
3.2 主进程功能模块
3.2.1 通信模块
主要是调用Electron框架本身的API以及通用 的封装。
主进程到渲染进程的通信
渲染进程到主进程的通信
有两种方案,一种是在主进程开启了nodeIntegration: true之后在渲染进程里面可以使用window.require(#39Electron#39)来引入写通信相关代码
一种是需要在主进程编写preload.js,在初始化窗口的时候引入
通信的同步和异步问题
【异步】渲染进程-gt发送-gt主进程【同步】渲染进程-gt发送-gt主进程3.2.2 菜单模块
主要是调用Electron框架本身的API,满足快速扩展菜单功能以及自定义菜单功能。
商家 项目没用到原生菜单,而是用了自定义的菜单。
没有使用原生菜单的主要原因是
原生菜单样式较死板,不能调整;自定义编写菜单能有各种自己想要的功能,可控制其展示。3.2.3 托盘模块
托盘属于系统级的操作,所以是在主进程中设置的。在开始之前需要注意的地方,设置托盘必须在程序ready之后。实现较简单,代码如下
3.2.4 异常处理模块
主要调用Electron框架本身API,结合Node.js API,检测系统异常后自动刷新并上报,渲染进程的异常已经使用slsarms处理,主进程的异常主要是通过Electron的crashReporter API来记录日志。
上面提交参数有几个需要注意的点
submitURL 是以post方式上传extra 一个你可以定义的对象,附带在崩溃报告上一起发送 . 只有字符串属性可以被正确发送,不支持嵌套对象3.3 渲染进程功能模块
渲染进程的代码大部分跟商家 web端一致,很多只是迁移即可。
3.3.1 登录改造
登录信息本地化,在登录成功的时候,把账号信息缓存,下次打开应用的时候 无需再重新输入,直接从缓存获取即可。
3.3.2 静态资源
传统Web应用,将项目代码部署服务器,项目运行时,访问的是服务器静态资源,现在版本发布流程,走的是cdn资源,总而言之都是通过 获取。
Electron提供将静态资源打包到安装程序,在安装时,将项目文件同步安装到用户电脑,使其具备访问本地文件,减少了请求占用资源,一定程度上也能改善因网速问题导致的静态资源不能实时获取,页面白屏问题。
3.3.3 数据存储
Electron应用里面的数据存储是通过Electron-store第三方库来实现的,实现比较简单,如下
3.3.4 渲染进程打包
这块为什么要单拎出来讲渲染进程打包呢,是因为web项目迁移变成应用渲染进程的时候不能像web应用一样直接打包,需要调整请求API代码,API前缀需要区分本地调试和应用环境
使用Electron, 将项目打包成离线应用。使用file协议,在本地读取静态资源。ajax请求如果用相对路径,打包之后,会直接找到根目录,如下截图
所以打包的时候需要给ajax提供完整的url路径。
4.技术挑战
在从0到1搭建商家 桌面端的过程中,遇到了很多的问题,Electron社区虽然很活跃,不一样场景遇到的问题,几乎找不到对应的解决方案,所以很多都是在探索过程中不断的去完善。这里主要围绕发布构建流程和安全性来讲下,我们是怎么解决的。
4.1 安全性问题
Electron客户端的安全问题也是非常重要的,那都遇到了哪些安全问题以及我们又是如何解决的呢,具体如下
渲染进程XSSElectron实现的桌面端软件渲染层的原理实际是通过chrome内核渲染的,同样存在XSS注入的风险。举个例子在html页面中可以执行命令ltimg/src=x οnerrοr=#34require(#39child_process#39).exec(#39gnome-calculator#39)#34gt ,就可以打开当前操作系统的计算器。接入了公司统一的XSS治理方案,该问题即得到解决。用户认证信息泄漏问题商家 桌面端登录调用商家的授权接口,APP网关有校验,可以确保登陆没有问题;本地缓存明文读取问题本地数据泄漏,例如indexDB、localStorage、sessionStorage等,我们主要用加密和解密算法对本地缓存信息进行处理。没有绝对的安全,我们能做的就是尽可能的提高安全门槛,过程中我们也积极同公司的安全部门进行沟通,让他们排查桌面端发布之后的安全漏洞,最终验证都是满足安全标准,符合发布的条件。
4.2 发布构建流程
应用发布涉及到渲染进程和主进程,渲染进程主要是负责给主进程提供渲染包,主进程使用Electron-builder库来打包部署所发布的包。
前面已经说过,Electron的好处是可以无缝集成web端的业务逻辑代码,这里上图左边红色的是web端构建出的产物,我们会把这部分构建产物同步到主进程的app/render目录下,即渲染进程目录,这样在打包应用包的时候,就能集成渲染进程的业务逻辑,而不需要维护两份web端的代码。
此方案还存在不少的缺陷,由于生产构建环境需要window环境,所以暂时不支持在远程打包,目前都是在本地window机器上打出完整的包之后再上传到CDN,商家 通过加载CDN的更新包来替换本地安装文件,实现软件的本地安装。
4.3 应用更新问题
应用开发离不开“更新”这个话题,比如飞书应用会时不时弹出一个更新窗口,让你选择是否更新,商家 在推广桌面应用之后,也存在更新这个问题。在业务快速发展的,如何将业务需求更好的同步给商家使用,这是商家 桌面应用面临的更大的挑战。
4.3.1 全量更新
4.3.1.1 手动下载安装
最基础的更新模式,主要思路是在打开app(其他时候也行,我们业务主要是打开app的时候)的时候访问远程的json文件,文件内容包含版本号,更新内容等等最新版本的信息,拿到远程版本号会跟本地应用版本号做比较,如果版本号不一致,就询问用户是否更新,需要更新的话会下载到本地,用户手动点击安装即可。这个更新方式不推荐使用,如果你的应用一年更新一次,ok,是可以这么做的。
4.3.2 增量更新
在网速快的情况下,全量更新跟增量更新几乎是没有区别的。网速慢的情况下它俩之间的差距会被放大,用户体验不是很好。我们不能想的以为所有用户网速都很好,这是不现实的,所以不管是PC应用还是移动端应用,大多数情况下是需要做增量更新。下面表格是网速不一样情况下的下载耗时对比
4.3.2.1 electron-updater
现在就开始介绍在商家 应用(windows应用)中是怎么实现增量更新功能的。
更新在大的分类上区分全量以及增量更新,在每个小分类里面也区分强更新,弱更新(业务上的区分,底层实现没区别)。简单来说,强更新指的是用户必须更新,不更新将无法使用系统功能,弱更新指的是用户想要的时候再去触发应用的更新,完全由用户自主选择。
更新流程
其中electron-updater作用于“更新应用”这个节点,主要是依赖新旧版本blockmap文件的对比来实现增量更新。下面截图为electron-builder打包出来的release包,每次打包都会有对应的blockmap文件。
electron-updater更新实现主要流程
生产的blockmap文件1.使用7z压缩安装包
2.读取安装包的header
3.计算出每个file的offset和end得到相应的hash生产blockmap
使用blockmap文件1.下载云上的blockmap文件跟本地blockmap文件对比,从上面截图可以看出blockmap文件很小,所以下载并不会对应用性能产生影响
2.使用range,request(范围请求)请求更新内容的部分
4.3.2.2 文件替换
还有一种增量更新方式就是文件替换,只更新需要更新的模块,这种方式只更新需要渲染进程的资源,大部分情况下主进程的资源不用更改,所以下载的资源会比较小,更新较快,因为是在线热更新,更新完成后不用重新启动软件,只需要刷新页面重新加载资源即可。其实之前我觉的这样的思路挺好的,看下面的流程图也是可以实现的,也很符合商家 桌面应用产品需求。
可是后来发现其实忽略了以下两个点
替换用户本地文件这个本身有权限问题,比如windows用户安装到了C盘,写入文件是有管理员权限限制的;文件被占用问题,众所周知,当文件夹中存在正在被占用的文件时,删除会失败。所以在覆盖原文件需要退出应用避免占用,所以这个方式也不是很可靠。5.遇到的问题
Electron 的硬件加速功能,在 win7 或者 Linux 系统上,容易出现黑屏或者卡死。
解决方案判断是不是win7及以下系统,如果是app.disableHardwareAcceleration (),禁用当前应用程序的硬件加速。
Uncaught ReferenceError: require is not defined,这个报错是试图在渲染进程使用node的时候出现的,不是不能用,只要开启 主进程的nodeIntegration: true就好了, 但不建议,有安全问题。解决方案
Noteyou may have one or two (large) stale temporary file(s) left in your temporary directory (Generally this only happens on Windows 9x)这个是打包了半天都打不出来一个完整的包的情况下出现的。解决方案当时是因为我没删除原来的包导致我放打包文件的C盘满了。。。所以删除一些缓存就好了,nsis打包大概率都是跟磁盘有关。
下载npm包特别慢解决方案yarn安装;Electron相关的包优先使用 镜像安装;使用公司镜像安装公司内部包。
6.
一路开发下来,感慨很多,作为公司之一个Electron应用,不管是在开发上,打包上,或者说在部署上,都遇到了一些挑战,在网上也没有比较详细的文档,外面做的好的也不会把详细方案分享出来,即使遇到了这些问题,也不能否认Electron是目前最适配于我们业务目标以及适配于开发资源的一个框架。目前已有线上稳定版本,逐步在推广到全部商家 。接下来需要完善的开发流程,克服的技术难点有很多,商家 工作台应用也会越来越完善。
文/Uni
得物后台 得物后台