燕云中控微前端聚合架构方案
Last updated
Last updated
鉴于目前的中控平台数量已经日益增多,对于不同的平台之间的维护管理已经开始变得不断繁琐、甚至是是困难。 一个需要去解决不同平台的查询、使用、管理以及维护的聚合平台开始逐渐呼之欲出。 MicroFront前端微服务聚合平台:【燕☁️云】正是在这样的背景下开始诞生的,他的出现将会完全改变我们目前对于Admin平台的使用方式。 你不用再担心忘了网址而找不到地方,不用再被太多的Admin而弄得手忙脚乱。[燕☁️云] 一站式Admin聚合平台,给你一个一目了然,清晰可见的中控列表,给你一份如丝滑般优雅的操作体验。 下面让我们开始谈谈他是如何诞生的?,他究竟能做些什么?
用准确的说辞来讲,[燕☁️云]是一个前端微服务聚合平台,他所要做的便是将原本分散的每一个的中控Admin聚合起来, 给大家提供一个清晰可见、便于使用、方便维护和管理的一个聚合系统。[燕☁️云]有一个小目标,那便是为大家提供以下的服务:
聚合中控Admin系统,提供一个简单明了,便于使用、操作的单一Admin平台
提供一份无需重复刷新的丝滑用户体验,不用再为Iframe的重复刷新体验而感到烦躁
为应用之间的跳转、交流提供一座桥梁,让不同应用之间的跳转、通信变得优雅可人
既有连绵亦有隔阂,基于Scope Css以及Js Sandbox带来的应用级隔离,呵护每一个成员的小秘密
来自云☁️的呵护,一站式操作监控、数据分析、日志上报处理,让云☁️端之下的每一个小成员不必再为通用的操作而烦恼
最后,期待着每一片怀揣梦想的小云☁️,欢迎大家提出自己的想法和建议,让[燕☁️云]变得更加强壮,走的更远。 然后开始我们云☁️生的第一步。
首先让我们从一张思维导图开始,去思考一下宏平台([燕☁️云])与微应用(云☁️的小成员)之间的关系。 既然__[燕☁️云]是一个聚合平台,那么自然最为重要的便是如何实现这个聚合,在这里聚合的本质便是对于应用的挂载,那么如何去实现这个挂载便是整个[燕☁️云]系统的心脏所在。 除了如何去实现挂载这个核心的问题以外,我们还需要去思考的是无论是宏平台([燕☁️云]__)还是微应用(云☁️小成员),他们互相之间都是一个独立的个体。 那么作为一个独立的个体,他们各自之间都应该有着那些个性化的表现与行为呢? 在个体自身的行为以外呢?,他们如何去实现互相之间的通信与交流?,子应用又如何去维持原有的交互逻辑? [燕☁️云]作为一个掌控者,在实现了基本的挂载之后,又能够去提供哪些额外的功能呢? 在结束了这些对于云☁️生的基本哲学思考之后,我们开始迈出了真正的步伐。
云☁️的心脏:如何实现应用的挂载
#####挂载: 首先我们要理解什么是挂载,【挂载】顾名思义即将某一个子应用A呈现到父级应用平台上去, 这个过程包括1. 父级应用完成对于子应用的下载,2.将下载完成的应用呈现在父级应用上,3. 完成对于应用的卸载。 目前我们处于备选之中的挂载方案一共有三种:
Iframe挂载:基于HTML Iframe组件嵌入式挂载应用
HTML入口挂载:使用HTML作为入口对应用资源进行综合打包实现挂载
JS入口挂载:使用与SPA同样的方式,通过JS入口实现挂载 在经过综合的对比之后,我们选择了对用户体验更加友好的方案【基于HTML入口的挂载】,不过我们仍然会在下面比较三种不同的挂载实现方案,以更好的诠释我们为什么选择【基于HTML入口的挂载】。
#####比较: | | | 技术栈是否限制 | 单独打包 | 单独部署 | 单页应用体验 | 应用切换速度 | 应用独立性 | 应用间通信 | 开发成本 | 应用是否需要改造 | 发布是否需要重新打包 | 优点 | 缺点 | | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | | Iframe挂载 | 不限制 | 是 | 是 | 否 | 慢 | 高 | 困难 | 低 | 低 | 否 | 否 | 实现 难度低,应用完全独立 | 用户体验较差,无法保存状态,应用间硬性隔离,Cookie、Session、鉴权无法协调 | | HTML入口挂载 | 支持SPA,HTML | 是 | 是 | 是 | 快 | 中等 | 中等 | 高 | 中等 | 是 | 否 | 单页SPA用户体验 ,状态可保存| 实现难度较大,对系统整体性要求高 | | Js入口挂载| 仅支持SPA | 是 | 是 | 是 | 快 | 中等 | 中等 | 高 | 高 | 是 | 是 |单页SPA用户体验,状态可保存 |实现难度较大,对系统整体性要求高,应用打包需重复发布,对原有应用改动较大 | 首先谈一谈Iframe方案,Iframe最大的优势便是提供了浏览器的硬隔离方案,这是Iframe最大的优势,但同时也是其最大的缺点, 硬隔离带来了状态无法保存,应用间的上下文无法共享,由此带来了并不友好的用户体验。这也是我们最终舍弃此方案的原因。 其次是Js入口实现方案,这个方案与HTML入口方案的实现方式类似,但区别在于Js入口方案使用了与目前SPA应用相同的原理,而HTML入口方案则是将整个资源进行统一打包,然后一次性注入父级应用之中。 由此带来的是HTML入口方案能够支持更为广泛的技术栈,父级应用与子应用之间的关系更为灵活,这也是我们最终确定选择此方案的原因。 在确定了挂载方案之后,我们便可以开始讨论具体的挂载步骤了。
#####基于HTML入口的挂载: 3.1 挂载流程图
3.2 下载HTML入口 在完成了应用的注册以后,我们便能够得到应用的一些基本信息: code { name: 'app1', // 子应用名称 entry: 'http://localhost:7001', // 子应用域名 container: '#yourContainer', // 挂载节点 activeRule: '/app1', // 监听路由,当进入此路由时执行应用挂载 customProps: { // Props参数传递 some: 'value', } }
之后,通过【HTML_Import_Entry】下载子应用的HTML入口,解析Css、Js资源路径,并交给后续流程进行组装。
3.3 样式隔离与Js 沙盒 对于HTML入口方案而言,如何去实现应用的独立性,使其互不干扰,是非常重要的事情,这里主要两个部分来完成: 1.Scoped Css处理,将应用间的样式进行隔离 2.Js 沙盒处理,创建一个新的全局对象proxy代替window,并将子应用的JS进行包装使得其在proxy内运行,与外界隔离 3.4 Micro微应用打包与注册 将处理完成得到的HTML入口与生命周期钩子相结合,绑定应用各个生命周期的动作,完成整个应用的全部注册流程。 3.5 运行时加载与呈现 在完成应用的打包之后, 监听路由与主动事件的触发,执行应用对应的钩子函数,完成子应用的展现 3.6
#####更新与卸载: MicroService通过监听路由变化与主动API调用,然后将已经完成打包的微应用从HTML入口上实施卸载,从而实现微应用的更新与卸载。 更新与卸载的动作只是对于HTML入口与资源的卸载,重新装载不需要重复下载资源文件。
####- 云☁️(应用)的表现形式 在完成了最为核心的挂载操作之后,我们开始思考应用其自身的行为,这里我们将应用分为两种 宏平台与子应用, 并分别描述了身为父级与子级的两者之间各自的一些特性。
MicroService(宏平台) - [燕☁️云]
1.1 行为 作为整个系统的挂载体,MicroService除了实现应用的挂载以外,我们一直在思考作为一个载体,他应该是怎么样的?,下面我们列举了一些基本的特征: 承载,聚合,管理。这些是他的基本特征,也是我们后续去衍生出更多理念的基石。
MicroApplication(子应用) - 云☁️的小成员
####云☁️(应用)间的通信 对于一个聚合平台而言,如何去实现应用间的通信沟通,自然也是十分重要的,与接下来的独立模块相反,通信则是负责完成应用之间的协作,他具备以下的功能:
转接应用与原有服务之间的Ajax交互
负责宏平台向子应用的指令发送
承接子应用之间的沟通,例如:动态加载其他应用,应用间跳转,数据信息同步等
接收并处理子应用的信息发送请求,例如:监控日志、公用SDK调用、错误上报等 我们会在后续去介绍如何完成整个通信模块的搭建。
####云☁️(应用)的独立 作为选择HTML入口方案而不是Iframe方案最大的代价之一便是如何去实现应用间的隔离与独立性,而独立这个模块便是介绍如何去保证这些, 除了我们前面提过的Scoped Css和Js Sandbox,让我们看看还需要哪些操作才能共同保证应用的独立性。
Scoped Css:将Css进行Scope处理,保持应用间样式的独立性
Js SandBox:创建Js沙盒proxy,代理全局window,使应用逻辑互不污染
HTML入口挂载包:将应用资源打包成一个Promise Resolver,实现独立的挂载与更新
路由分隔:为每个应用分配唯一的路由,确保路由切换带来的应用更替操作不冲突
资源异步加载:将异步资源提前进行整合,确保应用异步资源加载的稳定性
应用与后台的交互:这既是应用独立的一部分也是应用通信的一部分,他确保了应用能够维持与原有服务器之间的Ajax交互
前面我们从微观的角度讨论了__[燕☁️云]是什么?,他要做什么以及要如何才能这些,我们详细讨论了挂载、行为、通信以及独立这四个最为核心的基础模块,下面让我们从宏观的角度来看下[燕☁️云]__整个系统的架构流程。
前置处理: 1. 对应用进行改造,导出Render函数,添加应用挂载生命周期钩子 2. 在云☁️ Control BFF中先注册需要实现挂载的应用 3. 获取Normandy权限,将应用与相关的人员进行绑定
开始挂载: 1. 用户访问云☁️ Sys系统 2. 获取用户绑定应用 3. 开始进行应用挂载 4. 检测当前应用路由,开始呈现应用 5. 云☁️ Control BFF 开始转发处理应用的交互行为 6. 监测路由变化,实现应用的更新与卸载
内部服务: 1. 云☁️ Sys与云☁️ Control BFF进行交互,完成应用间的沟通交流处理 2. 云☁️ Sys监控应用的行为,对应用的情况、行为、错误进行监控并向云☁️ Control BFF进行上报
到这里,我们一共谈了整个实现方案的一个基本实现的思路、以及实现的一个基本架构流程图。 最后,我们浅谈一下整个实现方案可能存在的风险点,以及每个模块的基本功能。
燕☁️云系统采用运行时加载,而非编译时加载,这意味着我们需要在运行时动态获取子应用资源,存在跨域风险
将 燕☁️云系统的权限与Normandy的权限进行绑定
不同的子应用可能存在不同鉴权方式,需要支持复合鉴权
应用除了基本的Ajax交互外可能存在其他的行为,例如:应用跳转、应用沟通,这些都需要额外处理
注册
挂载
呈现
鉴权
与应用交互
最后是我们对于__[燕☁️云]__平台的一个期望与扩展,这其中既有会在后续中马上会加入的功能,也有对于平台能够承担更多职责的一个期待。
#####一键式Admin中控监控、错误上报处理、数据分析
SDK应用信息交流平台
URL跳转拦截与重定向
跨平台多鉴权复用
全局数据共享平台
2.1 种类 我们在之前讨论过基于HTML入口挂载方案所能支持的技术栈,而这里种类正是我们所能够支持的应用的技术栈类型,让我们通过表格来了解每一种类型的详细信息。 2.2 生命周期 __[燕☁️云]具有如下图所示的生命周期,他们在整个应用中的责任主要有两块: 1: 完成应用的挂载、更新与卸载动作 2: 执行一些对应周期的操作,例如:数据预加载、信息沟通、应用初始化等等操作。 2.3 !!#ff0000__交互!! 如果说应用的挂载是整个系统的发动机,那么实现子应用的交互则是真正负责行驶的四驱, 首先我们通过一张图来了解一下交互的类型然后阐述一下为什么交互值得如此重要。 试想一下当我们完成了应用的加载与展示,但是如何去处理应用与后台服务的交互呢?,又如何完成 新的资源的加载以及链接的跳转呢?, 是的这个模块最为重要的意义在于维持应用原有的交互逻辑,而不使其因平台嵌入而丧失了原有的功能,我们在后面的模块会去介绍如何去实现并保证应用交互的稳定。
接下来让我们按照架构图来谈一下整个方案的实现流程: