vivo 商品中台的可视化微前端实践
一、背景
在电商领域内,商品是一个重要组成部分,与其对应的商品管理系统,则负责商品的新建、编辑、复制等功能。随着商品管理系统的成熟稳定和业务上的扩展需求,催化出了商品中台的诞生。它可以将现有商品功能最大效率的复用在很多业务上(公司内业务、公司外业务等)。而不是仅限于当前团队的业务使用。
在设计商品中台的前端系统时,我们使用了微前端和可视化技术,其可以达到如下效果:
可视化技术可以让各个业务方的运营等相关人员,直观的看到其配置的数据在页面上的展示效果;
微前端可以帮助商品中台更快更好的适配到各个业务方的项目中。
至此,本篇文章的背景介绍完毕,下面将会阐述如何在商品中台前端系统中做微前端和可视化。
二、可视化技术
目前商品中台的页面如下图所示:
图中左侧内容,就是商品可视化,它的核心能力如下:
图中右侧所有的变动,都能在左侧得到实时更新和展示,如主图、 sku 组合、价格、图文详情、商品参数等功能。
图中左侧的可视化区域是一个标准的 h5 页面,可以把它看成一个子页面,它与外层的父页面在 ui 上是完全隔离的,同时在数据上又是共享的。
下面我将会对可视化技术原理做完整阐述,请大家继续往下看。
三、可视化技术原理
可视化整体技术原理图如下:
从上图可以获得以下信息:
子窗口用 iframe 展示;
子窗口用 vuex 做状态管理;
子窗口和父窗口通过共享状态 ( vue store )来完成数据通信。
看到这,小伙伴可能会有以下疑问:
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 展示的同时,父子窗口共享 store 。那这个 uni-render 是什么呢,可以继续往下读,将在下文给于第二个疑问的具体回答。
3.1 uni-render
uni-render 是一个让父子窗口可以不用 postMessage 就能共享 vue store 的技术方案。它包含以下关键内容:
将 iframe 当成一个 dom 节点;
父窗口渲染子窗口( iframe )暴露的组件;
父子窗口共享 vue store;
uni-render 的技术原理图如下:
这里,我结合商品中台配置可视化区域做一个通俗解释:
首先我们把 vue 项目设置为多页应用,页面分别是商品预览页、商品管理页;
其次,调整 vue 入口,每个页面对应一个入口;
编写 iframe 组件和沙箱 vue;
在商品管理页入口将沙箱 vue 和 store 挂载到 global 对象下;
在商品预览入口将 global.parent 下的沙箱 vue 和 store 分别挂到 window 下和 global 下;
最后,其他的内容按照 vue 多页写法正常编写即可。
通过上述 6 个步骤,就可以让用 iframe 做展示容器的商品预览页和商品管理页共享 store 啦。
这里,小伙伴可能会有疑问,为什么要使用沙箱 vue 呢?
这是因为 vue 的单例机制,子窗口(商品管理页)由父窗口(商品管理页) new Vue 渲染的, 因此在子窗口中使用 use 、 filter 、 mixin 、 全局指令 、 全局组件等, 会覆盖父窗口 vue 对象。所以需要隔离出一个干净的和 vue 一样的 vue ,然后用隔离出的沙箱 vue 来渲染子窗口(商品预览页)的内容。这样就可以 达到父子窗口的 vue 互不影响。
下面将介绍一些具体实现,如 iframe 组件、沙箱 vue 、入口设计。iframe 组件的实现非常简单,如下图所示:
这个不再解释了。
沙箱 vue 的实现非常巧妙,如下图所示:
在 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 做数据通信。这带来了非常多的好处,好处如下:
统一数据通信方案;
对 store 数据的 watch 、 computed 、更加纯正,数据通信功能更加强大;
精简代码,和 postMessage 永久告别;
支持同步函数,前方的路是星辰大海。
3.2 可视化总结
综上,商品中台的可视化介绍完了,我们通过 uni-render 技术方案让商品预览页( iframe )和商品管理页的数据通信只通过 vuex 即可完成。让可视化的实时更新更加流畅,可视化交互更加强大。
介绍完可视化,下面我将继续介绍商品中台在微前端上的实践,请大家继续往下阅读。
四、商品中台微前端
这里我们把商品中台设计成了微前端架构,使其能够完全适应复杂的外部业务。
这时,你可能会问,微前端是什么?
4.1 微前端是什么
概念如下:多个小型应用聚合为一个应用供用户使用,每个小型应用可以独立开发、独立运行、独立部署,与技术栈无关。大家可以把主应用想象成商场,那子应用就是商户,这样就好理解了。
注意:商品中台不是主应用,它是一个嵌入外部业务的子应用,不具备外部业务嵌入它本身。
微前端和普通的前端有什么区别呢?区别概括在下图中:
结合微前端概念,再阅读上图,可以感受到微前端所带来的优势和价值。
4.2 为什么要做微前端
整体概括下,主要有以下两个目的:
将商品中台更快、更好的嵌入到各个业务方项目中;
为后面主应用的设计做准备。
因此,我们把商品中台项目设计成了微前端架构,它可以很好的解决前端中台化所面临的各种问题。知道了目的,那么我们是如何去设计微前端的呢?
五、商品中台微前端设计
目前微前端领域最主流的技术方案有以下两种:
single-spa 技术方案;
iframe 技术方案;
基于这两种技术方案,业界产出一些成熟的框架,如 qiankun 、 qingtian ( vivo 自研)等。设计架构如下简图所示:
下面将介绍商品中台使用 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 接口跨域
解决接口跨域,主要有以下两种方式:
主应用转发:接口的 host 与主应用一致,由主应用根据路径关键字 cmmdy 进行转发。
微应用配置:微应用服务端配置允许跨域
这里我们选择了第一种方式,也就是主应用转发。
5.1.3 路由适配
这里需要注意的是:微应用 router 需要添加 baseUrl ,并且要与主应用关键字 activeRule 保持一致。如下代码(简写)所示:
const KEY = 'product'
router = new VueRouter({
mode: 'history',
base: IN_CMS ? `/main/goods/${KEY}` : `/${KEY}`,
routes
})
这个 KEY 变量就是关键字。
5.1.4 多页设置
目前多页设置的代码如下图所示:
每个页面作为一个独立的微应用引入, filename 设置与主应用 activeRule 值保持一致。
5.1.5 数据通信
思考一个问题,主应用与微应用之间如何通信?通信这块,主要有两种方案:
initGlobalState:也是运行时通信(官方方案);
window:挂载到 window 下。
initGlobalState 方案的优缺点如下:
优点:api 提供了数据的 change 事件,双方均能监听到数据变化。
缺点:微应用加载时,获取初始数据的时机太晚 ,不适合用作微应用数据的初始化。
window 方案的优缺点如下:
优点:微应用代码全周期内均可以获取数据,很好的避免官方方案中获取数据太晚的问题。
缺点:需要自己处理对数据变化的监听。
商品中台采取的数据通信方案是结合了上述两种方案,互相取长补短,都有使用。
5.1.6 环境区分
主要有以下两种场景:
区分 qiankun 与非 qiankun 技术栈:使用 window.__POWERED_BY_QIANKUN__ 即可判断。
区分同样使用 qiankun 的不同主应用:主应用与微应用之间约定参数,通过 window 对象或者生命周期函数中的 props 对象传递,来进行判断。
5.1.7 本地联调
思考一个问题,本地没有主应用的服务,怎么实现主应用与微应用间的快速联调?解决方案如下:
主应用注册微应用时,将 entry 设置为从 localstorage 中获取,在 localstorage 中手动修改入口 entry 的值为微服务的本地地址,就可以实现本地的联调。核心代码如下:
const timestamp = new Date().getTime()
const initEntry = (subSys) => {
const LS_KEY_ENTRY = `__entry__${subSys}`
const customEntry = 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}`
}
通过上述代码,即可在主应用中对入口地址进行动态适配,达到灵活联调的目的。这块还可以将其做成配置中心的形式,这样就不用在 localstorage 中手动修改入口地址。
5.1.8 权限管理
这部分是属于业务强相关内容,做好顶层解耦即可,本文不再阐述。
5.1.9 qiankun 设计架构总结
到此,商品中台的 qiankun 设计架构的核心内容阐述完了,使用 qiankun 的过程中,也遇到了一些问题,但使用这种流行框架的好处就是, 遇到问题时,可以去查阅相关文档和博客,基本上都可以找到相关的解决思路。基于 qiankun 的设计架构,表现出了不错的效果,也让商品中台能够以 signle-spa 的 技术方案嵌入到其他业务项目中。
5.2 踩坑经验分享
过程中遇到的坑较多,本文挑选几个踩坑经验分享出来。
5.2.1 uni-render 相遇 qiankun 跨域问题
现象:项目接入主应用,uni-render 控制的预览页面空白,控制台报跨域错误。
原因:iframe 预览页面为商品中台域名,而子应用接入主应用后为主应用域名,从而导致跨域。
解决方案:主应用、子应用 html 入口文件头部设置 document.domain ,使两者 domain 保持一致。
5.2.3 uni-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 上传。
至此,踩坑经验也分享完了,还有一些踩坑,这里就不再叙述了。在将几个技术融合在一起的过程中,总是会有一些预想不到的问题,正所谓兵来将挡、水来土掩,我们用正确的心态去面对和解决这些问题即可。
六、总结
综上,我们对商品中台的可视化和微前端做了整体的阐述,包含以下内容:
通过 uni-render 技术方案解决了可视化页面 iframe 和父页面的数据通信问题。
通过 qiankun 解决了商品中台嵌入基于 single-spa 技术方案的外部业务。
uni-render 结合 qiankun 的踩坑经验。
在解决一个场景或者问题时,技术的实现细节不是最重要的,最重要的是脱离技术的 Principles 。
最后用一句话结尾:Principles are higher than techniques. Principles produce techniques in an instant.
作者:vivo互联网前端团队-Yang Kun
vivo 商品中台的可视化微前端实践的更多相关文章
- 微前端 & 微前端实践 & 微前端教程
微前端 & 微前端实践 & 微前端教程 微前端 micro frontends https://micro-frontends.org/ https://github.com/neul ...
- 「微前端实践」使用Vue+qiankun微前端方案重构老项目的本地验证
10月份换了新的工作,参与完一个月的需求迭代后,接到了项目重构的任务.简单来说,需要在短时间内提出方案设想,同时进行本地验证,最终需要拿出一套技术替换方案来.于是,埋头苦干了一个月,总算干了点成绩出来 ...
- Node.js躬行记(9)——微前端实践
后台管理系统使用的是umi框架,随着公司业务的发展,目前已经变成了一个巨石应用,越来越难维护,有必要对其进行拆分了. 计划是从市面上挑选一个成熟的微前端框架,首先选择的是 icestark,虽然文档中 ...
- 基于微前端qiankun的多页签缓存方案实践
作者:vivo 互联网前端团队- Tang Xiao 本文梳理了基于阿里开源微前端框架qiankun,实现多页签及子应用缓存的方案,同时还类比了多个不同方案之间的区别及优劣势,为使用微前端进行多页签开 ...
- vivo 评论中台的流量及数据隔离实践
一.背景 vivo评论中台通过提供评论发表.点赞.举报.自定义评论排序等通用能力,帮助前台业务快速搭建评论功能并提供评论运营能力,避免了前台业务的重复建设和数据孤岛问题.目前已有vivo短视频.viv ...
- 微前端大赏二-singlespa实践
微前端大赏二-singlespa实践 微前端大赏二-singlespa实践 序 介绍singleSpa singleSpa核心逻辑 搭建环境 vue main react child 生命周期 结论 ...
- 干货 | 国内互联网公司是如何做微服务实践的?(附PPT下载)
微服务的概念最早由Martin Fowler与James Lewis于2014年共同提出,并随着Netflix最佳实践的发布而为业界所知.如今,在国内有了大量的微服务实践案例,5月18日,网易云联合云 ...
- vue-qiankun公司微前端项稳定目落地后的总结(附github仓库demo,将会持续更新)
️本文为博客园社区首发文章,未获授权禁止转载 大家好,我是aehyok,一个住在深圳城市的佛系码农♀️,如果你喜欢我的文章,可以通过点赞帮我聚集灵力️. 个人github仓库地址: https:gi ...
- 基于 iframe 的微前端框架 —— 擎天
vivo 互联网前端团队- Jiang Zuohan 一.背景 VAPD是一款专为团队协作办公场景设计的项目管理工具,实践敏捷开发与持续交付,以「项目」为核心,融合需求.任务.缺陷等应用,使用敏捷迭代 ...
随机推荐
- shell脚本部署redis以及redis主从复制和redis-cluster集群
# 关于脚本: # 使用root用户执行此脚本,提前关闭selinux: # 执行脚本之前,hostsIP内的IP修改成自己的机器IP: # hostsIp内的IP数量如果有增加或者减少,for循环的 ...
- DevOpts 前端开发和 Spug
DevOpts 前端开发和 Spug 朋友新工作是进行 DevOpts 前端开发,涉及 Spug. DevOps 是什么 DevOps 是一种思想.用于促进开发和运维之间的沟通.协作或整合. Tip: ...
- spring中容器和对象的创建流程
容器和对象的创建流程 1.先创建容器 2.加载配置文件,封装成BeanDefinition 3.调用执行BeanFactoryPostProcessor 准备工作: 准备BeanPostProcess ...
- [自动化]基于kolla的自动化部署ceph集群
kolla-ceph来源: 项目中的部分代码来自于kolla和kolla-ansible kolla-ceph的介绍: 1.镜像的构建很方便, 基于容器的方式部署,创建.删除方便 2.kolla-ce ...
- Tabluea、Smartbi可视化仪表盘创建流程图分享
你知道Tableau.Smartbi在可视化仪表盘制作步骤上有何差异吗?下面一起来了解吧~ 根据上面的流程图我们可以了解到,不同于Smartbi是在同一界面即可完成的,Tableau是由很多个工作表组 ...
- nginx之版本升级方法一
转至:https://www.cnblogs.com/sblack/p/12809034.html 非线上业务,纯属测试升级,线上业务不要采用此方法,可以采用官方推荐的平滑升级. 环境 Linux c ...
- Web安全学习
项目地址(参考):https://websec.readthedocs.io/zh/latest/basic/history.html 本文只能充当目录简介,具体还要自己深入学习. 序章 Web技术演 ...
- Hadoop原生对象存储Ozone
Hadoop 社区推出了新一代分布式Key-value对象存储系统 Ozone,同时提供对象和文件访问的接口,从构架上解决了长久以来困扰HDFS的小文件问题.本文作为Ozone系列文章的第一篇,抛个砖 ...
- 2022年官网下安装GIT最全版与官网查阅方法
目录 安装部署Git 1.百度搜索git,双击进入. 2.进入主页,双击如图位置. 3.进入下载列表,双击下载. 4.找到本地文件位置,双击安装,弹出界面,选择next 5.进入安装路径位置,修改路径 ...
- ShardingJdbc-分表;分库;分库分表;读写分离;一主多从+分表;一主多从+分库分表;公共表;数据脱敏;分布式事务
目录 创建项目 分表 导包 表结构 Yml 分库 Yml Java 分库分表 数据库 Yml 读写分离 数据库 Yml 其他 只请求主库 读写分离判断逻辑代码 一主多从+分表 Yml 一主多从+分库分 ...