当前位置: 首页 > Web前端 > HTML

ModuleFederation在客服工单业务中的最佳实践

时间:2023-03-28 16:06:18 HTML

ModuleFederation:意思是modulefederation,在webpack5开始流行,也属于一种微前端方案。一、背景1、客服高频工作场景一线客服:基于一站式工作台中的在线工作台和电话工作台,根据问题查询与当前用户相关的工单明细或订单明细由用户反馈,并根据实际情况决定是否新建工单。二线客服:根据各渠道反馈的工单(其中一个主要来源是一线客服的反馈),根据工单内容,联系用户或其他相关方沟通并完成工单。2、使用iframe的背景在上面的场景中,我们可以知道,一线客服和二线客服不是同一批学生,而是属于不同的部门;由于业务上的一些差异,IM和工单是两个不同的前端项目。也是由不同的前端同学开发和维护的;即使使用微前端拆分后,IM、电话、工单属于不同的微应用,工单页面也无法直接导入IM和电话子应用中的工单详情页面。改造前,IM和电话工作台使用的工单详情页都是使用iframe嵌套,这是前期最简单、兼容性最好的方案。二、存在的问题1、iframe扩展问题我们知道,单个iframe占用内存大,打开速度慢。当只是偶尔使用的时候,这些可能问题不大,但是在一线客服有这样的场景,这些问题就会大大扩大,具体如下:用户,打开该用户的多个工单详情或订单详情。一线客服对接多个用户进行咨询。工单/订单详情因为客服有不同会话切换的需求,IM端缓存不同会话页面(比如keep-alive),会导致内存消耗剧增,切换响应速度变慢,甚至导致浏览服务器崩溃,客服体验差,最终导致客服效率降低。2.内存不断增加。模拟用户在IM中打开新客户消息,点击创建工单,点击工单详情,然后打开新客户消息。重复以上动作的页面文件数、内存占用、页面节点数趋势图如下:由于页面缓存的存在,可以看出内存占用越来越高,从超过一分钟左右从100MB到500多MB,可以判断当用户进行这样的操作时,其内存占用率会持续上升,虽然大多数情况下浏览器的垃圾回收机制会启动,但是由于:page-levelcache让垃圾回收没那么有效客服长期工作下,内存会不断上升,最后应用会越来越慢,甚至导致崩溃,有的客服已经已经报过崩溃的问题:3.响应速度慢。首先看打开工单详情的视频,如下:视频中打开的工单详情不是首屏也需要2.8秒打开,首屏甚至需要7秒已开通!注:此处及后续数据均在测试环境中采集。由于是内部实现的新标签页,不适合LCP(LargestContentfulPaint,最大内容渲染),TTI(TimetoInteractive,交互时间)等不能很好的采集,主要是根据时间数据在谷歌性能工具中的截图,更接近TTI。3、类型选择及对应策略根据目前的情况,iframe不能再使用了。那么有什么方案可以满足我们目前的情况呢?首先,梳理一下我们目前的诉求。这个需求主要有两个方面:一个当然是解决上面的问题,提升性能,提升客户服务体验。另一方面,它需要对前端足够友好,可以实现,具有良好的兼容性,同时也保持了目前前端的低维护成本。摆在我们面前的常用解决方案大致有两种。以qiankun为代表的npm包和微前端方案,性能维护npm好,与本地组件无异。性能是最好的。工单一发布,IM就得跟着发布,这是不能接受的。前端好,项目解耦,IM端不需要关心工单端的迭代和具体技术。1、npm包合适吗?首先我们看一下我们需要引用的页面本身,如下图:是一个复杂的业务。三个相关性高、更新频率高的高级页面级组件,根本不适合做低频率的npm包。乾坤或其他类似的微前端解决方案在我们的特定场景中也存在一些问题:2.1。对嵌套场景的支持度不高。在我们的一站式工作台整体解决方案中,qiankun已经被用于工单转账、IM、电话拆分为三个子应用。如果IM引用工单子应用,就会形成应用之间的嵌套,如下图:搜索微前端嵌套方案:社区官方不支持嵌套方案:qiankun微前端实践总结(2)——本节掘金讲解嵌套方案。可以看到虽然官方没有推荐方案,但是社区已经有相关实践,但是支持不够好,而且这些实践都是基于webpack构建的基础qiankun对vite不友好:看issue和想问问以后是否考虑支持vite·Issue#1257·umijs/qiankun,最近才慢慢增加对vite的支持。结语:无论是webpack还是vite,以沙盒隔离为主要方案的微前端对嵌套场景的支持度都不是很高,未来如果嵌套更多、更深甚至循环嵌套,将会难了起来。2.2.该场景不适用于沙箱隔离的微前端方案。每次引用时,它仍然引用并解析加载项目初始化所需的文件。即使你引用了一个小组件,它也会这样做,它仍然会影响组件加载的速度。所以主要解决项目维度的引用、隔离和性能问题。它不适用于模块或组件作为尺寸的情况,它仍然有点重。那么有没有这样一种解决方案,可以像npm包一样智能,只加载相应的组件代码,可以像微前端一样直接引用,与项目无关?答案是肯定的,那就是本次的主角——ModuleFederation(模块联邦)。4.ModuleFederation模块联合,最早在webpack5开始普及,可以看文档:ModuleFederation|webpack中文文档,也属于微前端解决方案。1.让我们关注它能做什么。我觉得可以用一句话来概括:它允许一个在线部署项目在运行时加载其他在线部署项目中的组件。关键点在于:它没有沙盒隔离方案,与宿主环境共享一个window环境。加载时,只加载目标组件及其相关内容。组件或页面在之前的项目目录下的位置和结构不用改变,直接根据对应的目录层级。当可以引用使用的时候,和本项目的组件的使用是一致的,因为它只是一个组件,只是远程加载而已。模块是延迟加载的,这通常在同一个项目中完成。那我们是不是也可以在项目A中将一个组件及其依赖打包成一个chunk包,在项目B中按照约定的地址异步导入刚才项目A的chunk包,运行起来使用呢?答案是ModuleFederation。2.1.一些概念。远程组件提供者称为远程端,远程组件使用者称为主机端。一个项目既可以是远程的也可以是主机的,可以使用来自多个不同项目的组件,并且可以为其他几个项目提供不同的组件。基于此,我们甚至可以创建一个去中心化的应用集群,大致是这样的:2.2.社区应用,此技术已在多家知名厂商应用:探索webpack5新特性Modulefederation在腾讯文档中的应用-掘金(腾讯)微前端知识与实战最全总结(EMP技术解决方案)——掘金(YY)2.3、vite中的ModuleFederation解决方案vite插件vite-plugin-federation提供了对webpack进行benchmark的能力,但是加载方式改成了ESM,其插件接口设计为几乎和webpack的参数设计一样。vite-plugin-federation也是vite官方推荐并收录的插件,已经收录在社区插件列表GitHub-vitejs/awesome-vite:??与Vite.js相关的精选列表。2.4.具体到我们场景中的工单工作台应用,作为远程??终端,可以提供工单明细、订单明细、创建工单、薪酬模块等多个页面级组件。作为宿主的IM或电话工作台应用程序可以使用上述组件。3、具体实践由于我们两个项目都是使用vue3+vite的方案,所以使用vite-plugin-federation插件是我们最好的选择。首先需要在host端和remote端安装插件,如下:yarnadd@originjs/vite-plugin-federation-D注意:这里为了展示方便,使用官方插件。事实上,由于项目相关原因,我们会更新官方插件。做了一些改动。3.1.工单工作台作为远程配置(1)在插件中注册需要提供的组件,并提供需要共享的三方依赖(2)在远程端配置完成并打包后,对应的入口文件、chunk文件和依赖包文件:3.2、IM和telephoneworkbench作为host端的配置(1)插件配置,设置远程包地址(2)引用和注册组件,main.ts文件此时如下,ticket-share是host端在vite插件中注册的包名,而Detail是remote端声明的组件名(exposes字段)。除了全局注册,还可以在任何需要引用的地方引用。(3)在需要的地方引入和使用组件的使用,根据业务情况传递props。道具的使用与普通组件相同。至此我们已经完成了所有的配置,之后我们只需要打包并在线运行即可。五、重构后的效果1、加载速度我们再看一个视频。大家可以和第一个视频对比一下,可以看出非常直观的区别。首屏副屏(非首屏)iframe7076ms2594msmodulefederation1279ms428ms注:以上数据是在测试环境下平均十次得到的,测试值更接近TTI。从数据中可以看出,在首屏环境下(即没有任何缓存)模块联邦加载速度提升了5.5倍。并且在二次加载场景下(该场景是客服使用频率最高的场景),速度提升了6倍!2.记忆我们还是在初始场景的基础上模拟客服为多个用户打开多个工单/订单明细的情况。如上图所示,我们首先可以发现并没有内存泄漏!同一时间段内,内存使用率仅达到55MB,随后回落。打开单个工单详情的内存增加已从10MB减少到不到1MB。因为除了模块联合带来的直接好处之外,我们还享受到了它的额外好处。由于modulefederation本身是指一个组件,我们可以利用vue组件本身的特性,为多个工单明细复用同一个实例!3、客服反馈上线后,我们从未收到过工单详情打开慢,或者浏览器崩溃的反馈没有了!六、后续规划1、模块联合的缺点:维护共享库并非没有任何缺点。在配置过程中,我们可以看到需要配置share字段,即不同项目需要共享的三方库。比如A项目使用了vue,B项目也使用了vue,所以需要声明vue,插件会自动拆分vue,这样A和B项目就可以共享使用了。需要声明远程端和主机端。声明如下:shared:{vue:{//远程端的字段为requiredVersionversion:'3.1.5'},axios:{version:'0.21.1'},vuex:{version:'4.0.0'},'vue-router':{version:'4.0.8'}}但是这里有一个对开发者很不友好的地方:需要手动找出组件的共享包。共享有时是强制性的。如果漏掉了一些包,可能会导致页面出错或者崩溃,想象一下页面同时有两个Vue库。有时需要在约定的版本范围内维护。有时候一个包太旧或者太新,加载的时候都会报错。总之,共享包的维护成本非常高。大的!2、方案需要建立daily和productionhooks,然后自建服务监控这些hooks,对比三方库的包差异和版本差异,抛出相应的warning引入检查。搭建完成后查看remote模块部分。因为不是每一次改动都会让测试回归,而是每一次改动都可能导致页面崩溃。插件进一步封装,开发者无需关心三方依赖的管理。3、与去申请资产的发布冲突由于资产的发布自然需要引入版本号,所以每次迭代中所有资源的地址都会带入版本号中。远程组件引用需要根据协议在远程端确定一个入口文件地址。这个地址基本上是固定的。因此,目前无法使用资产发布远程项目。下一步是改用接口,二是团队之间协商处理这个问题。4.更大方向的想象还记得“可以搭建一个去中心化的应用集群”的画面吗?组件引用不仅出现在团队内部,还可能在团队之间共享。例如,创建工单模块会被智能系统等团队引用。也就是说各个团队内部或者一个团队内部的组件或者模块相互引用,目前主要是通过iframe来解决,可以通过模块联邦来解决。而公司也可以有这样一个平台,将模块联合团队、业务模块展示管理、共享依赖验证、告警或自动修复等功能整合在一起,实现业务级团队内外的高效协作。延伸阅读:【1】https://juejin.cn/post/685656...【2】https://github.com/umijs/qian...\【3】https://webpack.docschina.org...【4】https://juejin.cn/post/684490...【5】https://juejin.cn/post/691149...【6】https://github.com/vitejs/awe...【7】https://github.com/vitejs/awe...text/LIUZHOUCHANG关注得物科技,做最时尚的科技人!