得物商家客服桌面端 Electron 技术实践

asdnglove 2023-04-28 11:33:02

1. 业务背景

随着公司业务的快速发展,商家客服也纳入了我们的服务范围,商家客服工作台的定位是通过工具和数据服务商家,一站式解决用户购买咨询诉求。通过工具和运营策略协助商家提升服务品质,让品牌商家有动力运营好潜在的客户,从而达到提升用户服务的目标。桌面应用的转化在未来是客服产品的方向。

  • 已有 web 端聊天系统的前提下,商家客服为什么要迁移桌面应用?

首先我们收到部分商家客服反馈:

640.png

  • 用户是上帝,我们是很重视用户的反馈的,所以首先我们想的是如何在 web 端解决这些问题,下面我们逐一分析下以上问题我们能不能在网页端解决呢?

针对客服 A 同学问题:大多数客服职场的台式机是不会安装音频设备,如果人家没音频,没外音,我们能强迫他买个播放器吗,那肯定是不能的,如果是自营客服还有点处理方案,真需要,公司可以统一采购,但是 ToC 的显然不能强制做什么事情,所以此问题无解。

针对客服 B 同学问题:这句话怎么理解呢,是这样的,在一屏既有 web 浏览器,又有其他应用如飞书之类的 PC 应用叠着放,web notification 通知由于是浏览器级别的,提醒不到最上层,浏览器的提醒确实有点弱(看不到提醒会影响到客服的首响,首响会影响客服的绩效,咱公司对于用户的服务效率是比较严格的),所以此问题无解。

针对客服 C 同学问题:em。。。好的,您说的对,web 网页给商家客服的感觉就是我们平台有点赶不上形势。。。

基于上面的一些场景,想必大家已经对为何做桌面应用有个初步的了解,下面以一张图来看下 web 应用跟桌面应用的区别。

6401.png

2. 技术选型

  • 为什么会选择 Electron 而不是其他应用开发框架?

2.1 Electron 架构简介

6402.png

Electron 的构成主要是上面的 3 个大模块,每个模块各司其职,让 Electron 有了桌面应用的能力。

  • Chromium:可以为 Electron 提供 UI 渲染能力,再加上 Chromium 本身就是跨平台的,所以也不用考虑代码的兼容性。只要有 Chromium,就能用 JavaScript,HTML,CSS 这些前端开发工程师所熟知的三剑客来开发页面。

  • Node.js:Chromium 并不具备原生 GUI 操作的能力,所以 Node.js 正好补足了这个能力,能够调用操作系统的底层 API,比如 path、fs、crypto 这些模块,甚至能集成 C++。

  • Native APIs:Native API 让 Electron 有了跨平台和桌面端的原生能力,比如说它有统一的原生界面,窗口、托盘这些。

2.2 Electron 与其他框架的区别

下面是 Electron 与 Native、QT、NW 应用的对比图:

![截屏 20230131 15.49.19.png](https://cdn.poizon.com/ctoo/013115 / 截屏 2023-01-31 15.49.19.png)

  • Native (C++/C#/Objective-C) 不管从原生体验、包的体积、性能方面来说都是最佳的选择,但是开发门槛高,迭代速度慢。

  • QT 是基于 C++ 的跨平台开发框架,跨平台应用十分广泛 (Mac、Windows、ios、Android、Linux、嵌入式),众所周知的 WPS 就是用 QT 开发的。性能很好,甚至于可以媲美原生的体验,但是整体门槛还是比较高的。

  • Web 技术的代表 Electron 和 NW.js ,相比之前选择 Electron,Electron 有非常活跃的社区,有 102k star,有 Atom、vscode 这样的大型应用都是基于 Electron 开发的,性能相比于 natvie 是肯定要差一些,但综合来看,Electron 是作为开发桌面应用的目前首选。

  • 值得一提的是 Flutter desktop,从渲染原理看 flutter 是 skia 自绘性能优于 Electron,但问题还是稳定性和生态。Electron 由于是 nodejs+chromium,前端的生态可以直接用,所以 Flutter desktop 就不纳入考虑范围的,但值得关注。

除了以上这些,最主要的一点:Electron 能快速交付,业务层复用 web 系统的代码,只需要关注主进程就好了,并且也能满足业务需要的系统级别的一些功能。

6403.png

3. 技术实现

3.1 项目架构

6404.png

首先介绍下 Electron 框架里面两个重要的概念主进程和渲染进程。

主进程:主要负责创建和管理 BrowserWindow 实例以及应用程序事件。它可以执行注册全局快捷方式,创建系统菜单和对话框,响应自动更新事件等操作。主进程以及所有 Node.js 模块中都提供了一部分 Electron API。

渲染进程:渲染过程负责运行应用程序的用户界面,渲染进程中提供了所有 DOM API,Node.js API 和 Electron API 的子集。

6405.png

如上面截图,打开 Electron 项目之后会有多个进程,一个项目有且只有一个主进程,创建窗口等有关系统事件写在主进程中进行,但是渲染进程可能有多个。

那为什么会有多个渲染进程呢?

Electron 应用是 Chromium 内核,所以多进程的架构也来源于 Chromium,Chromium 会单独运行每个标签,任何一个标签页崩溃了都不会影响到其他标签。因此,每个进程在自己的空间中运行,由操作系统调度。如果某个进程触发了无限循环,也不会导致整个应用 down 掉。

在上文说到两个字 “迁移”,是的,我们在开发桌面应用之前有非常成熟的 web 端商家客服聊天系统了,所以我们在开发桌面应用的时候大多数时候是关心主进程的,渲染进程并不太需要关心。

3.2 主进程功能模块

3.2.1 通信模块

主要是调用 Electron 框架本身的 API 以及通用方法的封装。

6406.png

主进程到渲染进程的通信:

640.jpg

渲染进程到主进程的通信:

有两种方案,一种是在主进程开启了 nodeIntegration: true 之后在渲染进程里面可以使用 window.require ('Electron') 来引入写通信相关代码

6401.jpg

一种是需要在主进程编写 preload.js,在初始化窗口的时候引入

6402.jpg

通信的同步和异步问题

  • 【异步】渲染进程 -> 发送 -> 主进程

6403.jpg

  • 【同步】渲染进程 -> 发送 -> 主进程

6404.jpg

3.2.2 菜单模块

主要是调用 Electron 框架本身的 API,满足快速扩展菜单功能以及自定义菜单功能。

6405.jpg

但是商家客服项目没用到原生菜单,而是用了自定义的菜单。

没有使用原生菜单的主要原因是:

  • 原生菜单样式较死板,不能调整;

  • 自定义编写菜单能有各种自己想要的功能,可控制其展示。

3.2.3 托盘模块

托盘属于系统级的操作,所以是在主进程中设置的。在开始之前需要注意的地方,设置托盘必须在程序 ready 之后。实现较简单,代码如下:

6406.jpg

3.2.4 异常处理模块

主要调用 Electron 框架本身 API,结合 Node.js API,检测系统异常后自动刷新并上报,渲染进程的异常已经使用 sls&arms 处理,主进程的异常主要是通过 Electron 的 crashReporter API 来记录日志。

6407.jpg

上面提交参数有几个需要注意的点:

  • submitURL 是以 post 方式上传

  • extra 一个你可以定义的对象,附带在崩溃报告上一起发送。只有字符串属性可以被正确发送,不支持嵌套对象

3.3 渲染进程功能模块

渲染进程的代码大部分跟商家客服 web 端一致,很多只是迁移即可。

3.3.1 登录改造

登录信息本地化,在登录成功的时候,把账号信息缓存,下次打开应用的时候客服无需再重新输入,直接从缓存获取即可。

6407.png

3.3.2 静态资源

传统 Web 应用,将项目代码部署服务器,项目运行时,访问的是服务器静态资源,现在版本发布流程,走的是 cdn 资源,总而言之都是通过网络获取。

6408.png

Electron 提供将静态资源打包到安装程序,在安装时,将项目文件同步安装到用户电脑,使其具备访问本地文件,减少了请求占用资源,一定程度上也能改善因网速问题导致的静态资源不能实时获取,页面白屏问题。

6408.jpg

3.3.3 数据存储

Electron 应用里面的数据存储是通过 Electron-store 第三方库来实现的,实现比较简单,如下:

6409.jpg

3.3.4 渲染进程打包

这块为什么要单拎出来讲渲染进程打包呢,是因为 web 项目迁移变成应用渲染进程的时候不能像 web 应用一样直接打包,需要调整请求 API 代码,API 前缀需要区分本地调试和应用环境:

6409.png

使用 Electron, 将项目打包成离线应用。使用 file 协议,在本地读取静态资源。但是 ajax 请求如果用相对路径,打包之后,会直接找到根目录,如下截图:

64010.png

所以打包的时候需要给 ajax 提供完整的 url 路径。

4. 技术挑战

在从 0 到 1 搭建商家客服桌面端的过程中,遇到了很多的问题,Electron 社区虽然很活跃,但是不一样场景遇到的问题,几乎找不到对应的解决方案,所以很多都是在探索过程中不断的去完善。这里主要围绕发布构建流程和安全性来讲下,我们是怎么解决的。

4.1 安全性问题

Electron 客户端的安全问题也是非常重要的,那都遇到了哪些安全问题以及我们又是如何解决的呢,具体如下:

  • 渲染进程 XSS:Electron 实现的桌面端软件渲染层的原理实际是通过 chrome 内核渲染的,同样存在 XSS 注入的风险。举个例子:在 html 页面中可以执行命令:<img/src=x οnerrοr="require ('child_process').exec ('gnome-calculator')"> ,就可以打开当前操作系统的计算器。接入了公司统一的 XSS 治理方案,该问题即得到解决。

  • 用户认证信息泄漏问题:商家客服桌面端登录调用商家的授权接口,APP 网关有校验,可以确保登陆没有问题;

  • 本地缓存明文读取问题:本地数据泄漏,例如:indexDB、localStorage、sessionStorage 等,我们主要用加密和解密算法对本地缓存信息进行处理。

没有绝对的安全,我们能做的就是尽可能的提高安全门槛,过程中我们也积极同公司的安全部门进行沟通,让他们排查桌面端发布之后的安全漏洞,最终验证都是满足安全标准,符合发布的条件。

4.2 发布构建流程

应用发布涉及到渲染进程和主进程,渲染进程主要是负责给主进程提供渲染包,主进程使用 Electron-builder 库来打包部署所发布的包。

64011.png

前面已经说过,Electron 的好处是可以无缝集成 web 端的业务逻辑代码,这里上图左边红色的是 web 端构建出的产物,我们会把这部分构建产物同步到主进程的 app/render 目录下,即渲染进程目录,这样在打包应用包的时候,就能集成渲染进程的业务逻辑,而不需要维护两份 web 端的代码。

此方案还存在不少的缺陷,由于生产构建环境需要 window 环境,所以暂时不支持在远程打包,目前都是在本地 window 机器上打出完整的包之后再上传到 CDN,商家客服通过加载 CDN 的更新包来替换本地安装文件,实现软件的本地安装。

4.3 应用更新问题

应用开发离不开 “更新” 这个话题,比如飞书应用会时不时弹出一个更新窗口,让你选择是否更新,商家客服在推广桌面应用之后,也存在更新这个问题。在业务快速发展的同时,如何将业务需求更好的同步给商家使用,这是商家客服桌面应用面临的最大的挑战。

4.3.1 全量更新

4.3.1.1 手动下载安装

最基础的更新模式,主要思路是在打开 app(其他时候也行,我们业务主要是打开 app 的时候)的时候访问远程的 json 文件,文件内容包含版本号,更新内容等等最新版本的信息,拿到远程版本号会跟本地应用版本号做比较,如果版本号不一致,就询问用户是否更新,需要更新的话会下载到本地,用户手动点击安装即可。这个更新方式不推荐使用,如果你的应用一年更新一次,ok,是可以这么做的。

64012.png

4.3.2 增量更新

在网速快的情况下,全量更新跟增量更新几乎是没有区别的。但是网速慢的情况下它俩之间的差距会被放大,用户体验不是很好。我们不能想当然的以为所有用户网速都很好,这是不现实的,所以不管是 PC 应用还是移动端应用,大多数情况下是需要做增量更新。下面表格是网速不一样情况下的下载耗时对比:

WeChate37b6a37cfe5899d3d525368ea1b1270.png

4.3.2.1 electron-updater

现在就开始介绍在商家客服应用(windows 应用)中是怎么实现增量更新功能的。

更新在大的分类上区分全量以及增量更新,在每个小分类里面也区分强更新,弱更新(业务上的区分,底层实现没区别)。简单来说,强更新指的是用户必须更新,不更新将无法使用系统功能,弱更新指的是用户想要的时候再去触发应用的更新,完全由用户自主选择。

64013.png

更新流程

64014.png

其中 electron-updater 作用于 “更新应用” 这个节点,主要是依赖新旧版本 blockmap 文件的对比来实现增量更新。下面截图为 electron-builder 打包出来的 release 包,每次打包都会有对应的 blockmap 文件。

64015.png

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 文件替换

还有一种增量更新方式就是文件替换,只更新需要更新的模块,这种方式只更新需要渲染进程的资源,大部分情况下主进程的资源不用更改,所以下载的资源会比较小,更新较快,因为是在线热更新,更新完成后不用重新启动软件,只需要刷新页面重新加载资源即可。其实之前我觉的这样的思路挺好的,看下面的流程图也是可以实现的,也很符合商家客服桌面应用产品需求。

64016.png

可是后来发现其实忽略了以下两个点:

  • 替换用户本地文件这个本身有权限问题,比如 windows 用户安装到了 C 盘,写入文件是有管理员权限限制的;

  • 文件被占用问题,众所周知,当文件夹中存在正在被占用的文件时,删除会失败。所以在覆盖原文件同时需要退出应用避免占用,所以这个方式也不是很可靠。

5. 遇到的问题

Electron 的硬件加速功能,在 win7 或者 Linux 系统上,容易出现黑屏或者卡死。

解决方案:判断是不是 win7 及以下系统,如果是 app.disableHardwareAcceleration (),禁用当前应用程序的硬件加速。

  • Uncaught ReferenceError: require is not defined,这个报错是试图在渲染进程使用 node 的时候出现的,不是不能用,只要开启 主进程的 nodeIntegration: true 就好了, 但不建议,有安全问题。

解决方案:

64010.jpg

  • Note:you 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 是目前最适配于我们业务目标以及适配于开发资源的一个框架。目前已有线上稳定版本,逐步在推广到全部商家客服。接下来需要完善的开发流程,克服的技术难点有很多,商家客服工作台应用也会越来越完善。

---------------------------------------------------------------------------------------------------------------------------

每日小知识分享:每一个 HTML 文档中,都有一个不可或缺的标签:<head>,在几乎所有的HTML里, 我们都可以看到类似下面这段代码:

<head><meta charset=utf-8><meta http-equiv=content-type content=text/html; charset=utf-8><meta name=renderer content=webkit/><meta name=force-rendering content=webkit/><meta http-equiv=X-UA-Compatible content=IE=edge,chrome=1/><meta http-equiv=Content-Type content=www.llyz.net imtoken;charset=gb2312><meta name=viewport content=width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no></head>

head标签作为一个容器,主要包含了用于描述 HTML 文档自身信息(元数据)的标签,这些标签一般不会在页面中被显示出来,主要告知搜索引擎本页面的关键字以及对应网址,在SEO中传递相关权重起到非常重要的作用。

...全文
235 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

20

社区成员

发帖
与我相关
我的任务
社区描述
欢迎各位区块链技术应用的学者来交流
社区管理员
  • 小林同学i
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧