一、背景在电子商务领域,商品是一个重要的组成部分,相应的商品管理系统负责创建、编辑、复制等功能商品。随着商品管理系统的成熟和稳定以及业务的扩展需求,催生了商品中台。可以在很多业务(公司内部业务、外部业务等)中最大限度地复用已有的商品功能。而不是局限于当前团队的业务使用。在设计产品中心的前端系统时,我们使用了微前端和可视化技术,可以达到如下效果:可视化技术让各业务方和其他相关人员的操作可以直观的看到配置的数据。这一页。显示效果;微前端可以帮助商品中台更快更好的适配各业务方的项目。至此,本文的背景介绍就完成了,下面将讲解如何在产品中台前端系统中做微前端和可视化。2、可视化技术产品中台当前页面如下图所示:图中左侧的内容是产品可视化,其核心能力如下:图中右侧的所有变化都可以左侧实时更新显示,如主图、sku组合、价格、图文详情、产品参数等功能。图中左侧的可视化区域是一个标准的h5页面,可以看做是一个子页面,在ui上与外层父页面完全隔离,同时在数据。下面我将对可视化技术的原理进行完整的讲解,请继续阅读。3、可视化技术原理整体可视化技术示意图如下:从上图可以得到如下信息:子窗口显示在iframe中;子窗口使用vuex进行状态管理;子窗口和父窗口使用共享状态(vuestore)完成数据通信。看到这里,你可能会有以下疑问:iframe与父窗口的数据通信是通过postMessage来完成的,这里为什么不用postMessage呢?如何使用vuex完成iframe数据通信?回答第一个问题:为什么不用postMessage?实践过的人应该深有体会。如果使用postMessage,数据通信架构基本如下图所示:结合上图,可以分析postMessage有以下缺点:父窗口包含很多逻辑:父窗口需要处理数据vuex的,然后通过postMessage传输;数据通信方式不纯:vuex和postMessage相互结合相互转换,使得数据通信更加复杂,难以控制;不支持Vue.set、Vue.delete等;postMessage只能同步字符串,不能同步fn。基于以上不足,在数据通信方面,没有使用postMessage,而是用vuex代替postMessage完成iframe通信。回答第二个问题:如何使用vuex完成iframe数据通信?这个问题的答案是uni-render。通过它,父子窗口可以共享存储,而子窗口通过iframe显示。那么这个uni-render是什么,大家可以继续往下看,下面会给出第二个问题的具体答案。3.1uni-renderuni-render是一种无需postMessage就可以让父子窗口共享vuestore的技术方案。它包含以下关键内容:将iframe视为一个dom节点;父窗口渲染子窗口(iframe)暴露的组件;父子窗口共享vuestore;uni-render的技术示意图如下:这里我结合产品中心配置可视化区域做一个通俗的解释:首先我们将vue项目设置为多页面应用,页面为产品预览页面和产品管理页面;其次,调整vue入口,每个页面对应一个入口;编写iframe组件和sandboxvue;在产品管理页面入口挂载沙盒vue和store到全局对象;在产品预览入口处,将global.parent下的sandboxvue和store分别挂载到window和global;最后,其他内容按照vue多页面的写法写就可以了。通过以上6个步骤,使用iframe作为展示容器的商品预览页面和商品管理页面就可以共享店铺了。说到这里,小伙伴们可能会有疑问,为什么要用sandboxvue?这是因为vue的单例机制,子窗口(商品管理页面)由父窗口(商品管理页面)newVue渲染,所以在子窗口使用use,filter,mixin,globaldirectives,globalcomponents等会覆盖父窗口的vue对象。所以需要隔离出一个和vue一样的cleanvue,然后用隔离出来的sandboxvue来渲染子窗口(商品预览页)的内容。这样就可以实现父子窗口的vue相互独立。下面将介绍一些具体的实现,比如iframe组件、沙盒vue、入口设计等。iframe组件的实现很简单,如下图:这里不再赘述。sandboxvue的实现很巧妙,如下图所示:在Function上挂一个$$clone函数,这样vue下就会有一个$$clone函数。通过执行Vue.$$clone(),将vue的各种属性挂载到SandboxVue上。还返回SandboxVue。你可以获得一个干净的沙盒vue。注意:这里的vue指的是vue2。目前vue3没有单例机制,没有必要在vue3中沙盒vue。vue多页面入口设计,如下图:对应上面通俗讲解的第4步和第5步。至此,uni-render技术方案讲解完毕。众所周知,大部分h5和pc建站的数据通信方案都绕不开postMessage。而我们使用uni-render让父窗口和iframe子窗口的数据通信不再需要postMessage,只使用vue生态中的vuex进行数据通信。这带来了很多好处,好处如下:统一的数据通信方案;存储数据更纯粹的监视、计算、更强大的数据通信功能;精简代码,永远告别postMessage;支持同步功能,前路是星辰大海。3.2可视化总结综上所述,介绍了产品中台的可视化。我们使用uni-render技术方案,让商品预览页面(iframe)和商品管理页面之间的数据通信只需要通过vuex就可以完成。让可视化的实时更新更流畅,视觉交互更强大。介绍完可视化,我会继续介绍商品中台在微前端的实践,请继续阅读。4、产品中台微前端这里我们将产品中台设计为微前端架构,使其能够充分适应复杂的外部业务。这时候你可能会问,什么是微前端?4.1微前端的概念是:将多个小应用聚合成一个应用供用户使用,每个小应用都可以独立开发、独立运行、独立部署,与技术栈无关。可以把主应用想象成一个商场,把子应用想象成一个商户,这样很好理解。注:商品平台不是主应用,是嵌入外部业务的子应用,本身不嵌入外部业务。微前端和普通前端有什么区别?区别总结如下图:结合微前端的概念,再看上图,可以感受到微前端带来的优势和价值。4.2为什么做微前端总体来说主要有两个目的:将产品中台更快更好的嵌入到各个业务端项目中;为以后主应用的设计做准备。因此,我们将商品中台项目设计为微前端架构,可以很好的解决前端中台面临的各种问题。知道了目的,我们如何设计微前端呢?5、商品平台微前端设计目前微前端领域最主流的技术方案有两种:single-spa技术方案;iframe技术方案;基于这两种技术方案,业界已经产生了一些成熟的框架,如qiankun、qingtian(vivo自研)等,设计架构如下图所示:下面将介绍micro的技术实现-商品中台采用qiankun框架设计的前端架构。5.1在qiankun的设计架构中使用qiankun的核心原因是:在国内,qiankun是使用最多的微前端框架。整体效果也不错,所以我们中台需要设计qiankun的技术架构来适应那些基于qiankun的业务。在说设计架构之前,先介绍一下qiankun的技术原理,如下图所示:从图中可以看出,qiankun的核心在于微应用容器的创建。了解了技术核心之后,下面开始介绍设计架构。设计架构如下图所示:从图中可以看出,主要有8块内容,下面将依次介绍这8块内容。5.1.1在主应用中注册微应用的代码访问{name:'goods',entry:initEntry('goods'),container:'#root-view',render,//activeRule作为关键字用于区分不同的微应用activeRule:genActiveRule('/main/goods'),props:msg}微应用入口微应用打包5.1.2接口跨域解决方法接口跨域,主要有两种方法:主应用forwarding:接口宿主和主应用一致,由主应用根据路径关键字cmmdy转发。微应用配置:微应用服务器配置允许跨域这里我们选择第一种方式,即主应用转发。5.1.3路由适配这里需要注意的是,微应用路由器需要添加baseUrl,必须和主应用关键字activeRule保持一致。以下代码(速记)显示:constKEY='product'router=newVueRouter({mode:'history',base:IN_CMS?`/main/goods/${KEY}`:`/${KEY}`,routes})这个KEY变量是关键字。5.1.4多页面设置当前多页面设置代码如下图所示:每个页面作为一个独立的小应用导入,文件名设置与主应用的activeRule值保持一致。5.1.5数据通信考虑一个问题,主应用和微应用之间如何通信?对于通信,主要有两种方案:initGlobalState:也是运行时通信(官方方案);窗户:安装在窗户下方。initGlobalState方案的优缺点如下:优点:api提供了数据变化事件,双方都可以监听到数据的变化。缺点:微应用加载时,获取初始数据的时间来不及,不适合微应用数据初始化。window方案的优缺点如下:优点:微应用代码可以全周期获取数据,可以避免官方方案中获取数据太晚的问题。缺点:需要自己处理数据变化的监控。商品中心采用的数据通信方案是以上两种方案的结合,取长补短,相得益彰,两者兼用。5.1.6环境区分主要有以下两种场景:区分qiankun和非qiankun技术栈:使用window.\_\_POWERED\_BY\_QIANKUN\_\_来判断。区分同样使用qiankun的不同主应用:主应用和微应用约定参数,通过生命周期函数中的window对象或者props对象传递,进行判断。5.1.7本地联调思考一个问题。主应用程序没有本地服务。如何实现主应用和微应用的快速联调?解决方法如下:主应用注册微应用时,设置entry从localstorage中获取,手动修改localstorage中entry条目的值为微服务的本地地址,实现本地联调.核心代码如下:consttimestamp=newDate().getTime()constinitEntry=(subSys)=>{constLS_KEY_ENTRY=`__entry__${subSys}`constcustomEntry=localStorage.getItem(LS_KEY_ENTRY)if(customEntry){return`${customEntry}`}if(subSys==='goods'){return`//vshop-commodity.vivo.com.cn/goods/?t=${timestamp}`}return`${location.origin}/${subSys}/?t=${timestamp}`}通过以上代码,可以在主应用中动态适配入口地址,达到灵活联调的目的。这个block也可以做成一个配置中心,这样就不用手动去修改localstorage中的入口地址了。5.1.8权限管理是强业务相关内容的一部分,做好顶层解耦就可以了,本文不再赘述。5.1.9乾坤设计架构总结至此,商品平台中乾坤设计架构的核心内容已经讲解完毕。在使用qiankun的过程中,也遇到了一些问题,但是使用这个流行的框架的好处是,遇到问题的时候,可以查阅相关的文档和博客,基本上都能找到相关的解决方案。基于qiankun的设计架构,已经展现出不错的效果,也让产品中心可以将signle-spa技术方案嵌入到其他业务项目中。5.2踩坑经验分享过程中遇到的坑比较多。本文选择几个陷阱来分享。5.2.1uni-render遇到qiankun跨域问题现象:项目连接主应用,uni-render控制的预览页面空白,控制台报跨域错误。原因:iframe预览页面是产品中台的域名,子应用连接到主应用后主应用的域名,导致跨域。解决方法:在主应用和子应用的html入口文件头部设置document.domain,使两者的域保持一致。5.2.3uni-render、qiankun、ueditor的“化学反应”问题一:现象:qiankun子应用富文本组件ueditor功能异常。原因:qiankun劫持了ueditor,导致ueditor部分变量无法获取。解决方案:在主应用中,使用excludeAssetFilter防止ueditor的静态资源被qiankun劫持。问题二:现象:子应用中的ueditor请求url报错。原因:ueditor的请求url没有加上主应用请求的前缀。解决方法:在子应用环境下,通过ue.getActionUrl为ueditor的请求url添加前缀。问题三:现象:ueditor单图上传在子应用中失败。原因:子应用设置了domain,ueditor的单图上传是通过iframe实现的,但是iframe没有设置domain,导致上传失败。解决方法:重写ueditor的单图上传,把iframe改成xhr上传。至此,踩坑的心得也分享完了,还有一些坑要踩,这里就不赘述了。在整合几种技术的过程中,总会出现一些意想不到的问题。俗话说,兵来将挡,水来掩护,我们只需以端正的态度去面对和解决这些问题。6.总结综上所述,我们对商品平台的可视化和微前端做了一个整体的阐述,包括以下内容:呈现技术解决方案。通过qiankun解决了在产品中间嵌入single-spa技术方案的对外业务。uni-render结合了qiankun的踩坑经验。在解决一个场景或者问题的时候,技术的实现细节并不是最重要的,最重要的是从技术中分离出来的原则。最后用一句话结尾:原则高于技术。原理瞬间产生技术。作者:vivo互联网前端团队-杨坤
