聚合新旧应用,给业务治理提供支撑
1. 前言
随着务的不断演进,业务类别多、涵盖知识丰富,但由于前期各个业务小团队自行开发,存在以下问题:
1、门户较多,业务散,熟悉业务成本较高,且需要查阅多个站点的业务信息; 2、技术栈不统一,工程化工具、项目依赖版本不一致等导致工程框架维护成本较高,无法更专注的做新业务的开发; 3、多个工程有迭代和重构需求,且都是已上线投产项目,须保证系统改造的平滑过渡。
微前端方案的优势:技术栈独立,独立运行、自由组合,统一管理,支持渐进式重构,提出微前端方案解决目前的问题,统一门户,将现有的应用聚合到一个平台,一站式解决业务方的问题。
Github: github.com/simpleKeepe…
2. 聚合平台框架结构
所搭建的聚合平台框架结构如下图所示,现将业务线各个应用融合到一个平台,统一客服系统门户。为支撑后续旧业务整改以及新业务的演进,设计思路为先打散再自由组合,按照各种维度,分层分类,重新设计一级、二级、三级菜单。接入的四个系统的业务放置在下图中的应用主体部分,子系统既可以接入又可以按照原来的方式独立运行,又可通过对菜单权限的控制,实现子系统可插拔。
3. 聚合方案涉及的技术点
微前端的核心价值是“与技术栈无关”,接入范围较广,既能向后兼容,兼容久远的旧应用,又能向前兼容面向未来。前提是先有主应用,然后才有微应用或微组件,非常友好的聚合起来。
客服聚合平台以qiankun2为架构的基座搭建主应用,负责子应用配置、启动、共享状态监听、js/css隔离等功能,核心部分展开如下图所示。
3.1子应用的配置****
路由代理的配置方式如下图所示:
子应用相关配置:
3.2 应用间的通信
下图是父子应用之间的订阅/发布模型,qiankun 内部提供了 initGlobalState 方法用于注册 MicroAppStateActions 实例用于通信,子应用之间并不能直接进行通信,通常是先注册 观察者 到观察者池中,然后通过修改 globalState 可以触发所有的观察者函数,从而达到组件间通信的效果。
项目中的示例:
3.3子应用静态资源加载
3.3.1 HTML Entry方案
这里是利用import-html-entry工具处理 HTML 模块导入,资源入口采用的是HTML Entry方案,调用原生fetch拿到 HTML 中的静态资源,找出资源,就得解析 HTML 内容了,通过递归寻找元素,将 link、script、img 元素找出来并做对应的处理,然后载入主应用运行即可渲染子应用了
3.3.2 跨域问题
生产环境跨域须保证子应用上的所有静态资源支持主应用跨域获取静态资源,主要是nginx配置。
对于实在无法解决的跨域问题的静态资源,可如下图所示,设置请求该资源路径时不进行跨域验证,及配置mode:‘no-cors’。
开发环境父子应用的vue.config.js文件中本地服务的配置须开启跨域,如下图:
3.3.3 cookie携带问题
对于需要携带cookie请求的资源,主应用对应的请求须配置允许携带,配置如下图:
3.4 资源预加载与缓存机制
3.4.1 预加载
Qiankun通过window.requestIdleCallback() 这个函数实现,在浏览器空闲时间再去进行 prefetch子应用的静态资源,因此,除了首页加载可能出现较缓慢,切换到其他子应用时静态资源已加载,直接渲染就行,用户体验会有较快的响应速度。
3.4.2 缓存机制
Qiankun利用的时import-html-entry插件来请求静态资源,内部自带了缓存机制。
3.5 父子应用间隔离机制
3.5.1 css隔离
这里用到的是CSS Modules方案,通过css-loader插件,将所有的class编译成哈希字符串,一个独一无二的class的名字,不会与其他选择器重名。但是对于原生css部分,无法利用工程化的方式进行编译的,例如elementUI2中的'element-ui/lib/theme-chalk/index.css',需要手动修改受到干扰的css,
如下图所示:
3.5.2 js隔离
Qiankun2通过快照+ Proxy实现js沙箱隔离,快照和 Proxy 沙箱都是需要的,无非前者是后者的降级方案,因为不是所有浏览器都支持 Proxy 。
5. 子系统聚合后暴露的问题以及应对方法
(1)菜单权限控制,迁移子系统权限查询的接口到主应用,合并并处理,和主应用菜单进行权限匹配关联;
(2)菜单配置,随着后续业务演进,菜单也会越来越多,目前为主应用写死,治理不方便,后续计划通过配置方式自定义菜单顺序、绑定链接、名称等; (3)公共依赖管理,目前父子系统各自的依赖是隔离的,未实现共有依赖的共享,后续考虑共享依赖的处理方案。
6. 踩过的那些坑
(1)帮助中心和用户反馈vue-router版本由2升级为3,低版本接入qiankun2的主应用后只有初始化路由能正常跳转,菜单切换路由无法跳转;
(2)主应用拉取子应用存在的静态资源跨域的问题,需要nginx配置解决,由于运维工作过于饱和解决问题效率较低,也可劫持存在跨域问题静态资源的url请求,配置不检测跨域;
(3)本地调试涉及到url写相对路径须转换为绝对路径,qiankun的路由代理机制使子应用对应的路由会和浏览器的虚拟路由映射,影响最后相对路径解析成绝对路径的真实性。所有本地调试涉及本地资源(如图片或这mock接口)的链接加上baseUrl,如下图所示
(4)qiankun不支持document.write的这种写法,会导致微应用在接入时无法启动,例如web_crm_oa工程中引入tinymce的写法,如下图所示
(5)子系统最外层div不能相对于根元素(html,body)进行布局,因为子应用接入进来后不再是独立的html,而是以div的形式嵌入到父应用,布局相对发生变化。注意:position属性中的fix属性慎用,最外层div慎用position:abosute等;
(6)子系统最外层的高度如何设置的是100%会失效,因为qiankun对子系统做了css隔离,100%无法相对于父元素计算出实际高度,子系统最外层div需要写固定高度,然后做自适应。