随着众安业务的不断发展,内部分散的研发工具平台化、产品化的要求越来越紧迫。如何将零散的单点工具以业务为中心,提供一体化、端到端的产品服务是工具化整合的大方向。
多点工具整合的挑战:
1、多项目组独立运行
每个模块都是一个独立的项目组,人员体系独立,项目组间缺少对项目的理解和跨团队成员的相互支持。
2、多技术栈并行开发
当前项目同时存在React和Vue技术栈。随着技术的不断迭代和发展,给开发和运维带来极大的成本挑战。
3、风格各异的应用交互
Vue项目采用ElementUI框架,React项目采用Ant-Design框架。UI交互和主题配色都有很大区别。
搭建产品一体化平台的最终目标不仅仅是实现业务的集成,而是健全代码规范、交互、中间件、后台服务等相关内容的一体化建设。
前端一体化平台的目标:
1、简化开发复杂度,降低应用之间代码侵入性
2、前端异构框架的兼容整合,比如:支持多框架(Vue、React)
3、工具独立开发、独立运行、独立部署
4、为用户提供一致性交互体验,减少系统操作使用时的割裂感
经过细致和深入的调研,将以下五种方案列为备选方案:
Nginx路由转发
通过Nginx配置反向代理来实现不同路径映射到不同应用,例如www.abc.com/app1对应app1,www.abc.com/app2对应app2
优点:简单、快速、易配置
缺点:在切换应用时会触发浏览器刷新,页面重新加载时出现空白页面,影响用户体验
iFrame嵌套
父应用单独是一个页面,每个子应用嵌套一个iFrame,父子通信可采用postMessage或者contentWindow方式。
优点:
实现简单,子应用之间自带沙箱,天然隔离,互不影响
缺点:
每次进入子应用需要重新加载,页面加载慢,页面缓存多时会导致电脑卡顿
iFrame中的弹窗和遮罩层只能在iFrame范围内垂直水平居中,无法在整个页面垂直水平居中
URL不同步,浏览器刷新会导致url丢失,后退和前进无法操作
Web Components
每个子应用需要采用纯Web Components技术编写组件,是一套全新的开发模式。
优点:每个子应用拥有独立的script和css,也可单独部署
缺点:浏览器兼容性对于历史系统改造成本高
组合式集成
通过软件工程的方式在构建前、构建时、构建后等过程中,对应用进行拆分,并重新组合
优点:前端配置改造
缺点:要使用相同的框架,代码规范需统一
微前端(single-spa)
独立构建和部署各子应用,运行时由父应用进行路由管理、应用加载、启动、卸载、以及通信机制
优点:纯前端改造、体验良好、可无感知切换、子应用相互隔离
缺点:由于父子应用处于同一页面运行,需要解决子应用的样式冲突、变量对象污染的问题,各子应用需要重新设计和开发
经过比对所有方案的优缺点,并综合考量众安的实际情况后,最终选择了基于 single-spa 实现的微前端框架作为前端整合的最终方案。
整个微前端框架的实现逻辑主要包括以下4个步骤:
基座应用运行时,从服务器获取应用信息
获取应用信息后,绑定应用生命周期
当路由发生变化时,查找对应的应用
匹配成功后,加载对应应用
结合众安自身微前端框架的能力和众安各个研发工具的现状,最终构建了众安前端整合方案的架构:
整个基座是基于React+UmiJS框架开发。在基座中实现了公共的功能,如工作台、导航、统一登录、帮助文档等功能。为了达成整体目标,需要具备以下关键步骤和方法。
单页面多子应用加载(Vue使用Abstract Router/React 使用Memory Router)
菜单和页面主内容区的联动渲染(通过路由触发子应用加载)
实现子应用循环嵌套(子应用中集成微前端框架,使其具备基座的能力)
技术同学看到这里,肯定很想知道从代码维度如何实现以上效果?
接下来,我们通过技术干货将一些关键步骤分享跟大家。
项目基座与微前端框架集成
项目基座与微前端框架的集成是整个一体化平台建设的基石,它为子应用提供了注册、加载、通讯、鉴权能力。
激活子应用加载
激活子应用加载是整个前端一体化的重要步骤,子应用的加载通过两种方式来实现:
基座的路由配置
通过加载子应用
子应用与微前端的集成
Vue 框架集成
React 框架集成
基于微前端框架,众安已经完成了整合的第一阶段目标,第二阶段及后续仍需要对很多工具不断改造与精进,让整个用户体验及交互更顺畅。同时提高基座的可扩展性和配置能力,实现子应用的动态注册和集成。端到端的一体化不仅仅是多个应用的简单组合,还需要对前端标准、用户体验、子应用性能(模块提取,应用包优化等等)做深层次的优化。
最后,结合团队在落地实践过程中经常会被前端同学问到的一些问题,提供Q&A 帮助大家更好上手。
Q: 如何避免基座应用和子应用样式覆盖的问题?
A: 通过添加样式的应用前缀来解决前端样式覆盖的问题。
Q: 如何解决路由重定向和路由懒加载造成的页面白屏?
A: 移除不必要的路由重定向和懒加载的路由,重写Router的push、replace方法。
Q: 基座应用和子应用都是用flex布局,如何解决子应用获取真实高度的问题?
A: 通过修改应用加载时的className适配子应用容器的高度。
Q: 可以通过哪些方式实现基座应用与子应用的通讯?
A: 可以通过以下两种方式完成基座应用于子应用的通讯
通过配置的方式传递参数
在注册子应用的时候,可以在props中定义参数传递给基座应用
通过initGlobalState、MicroAppStateActions透传
Q: 如何解决基座应用获取子应用资源会报CORS的问题?
A: 可以通过以下步骤解决此问题
基座代理子应用的接口转发
子应用配置静态资源允许跨域