您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

微前端框架实践

时间:2023-05-31 15:17:50  来源:  作者: 阿里技术

阿里妹导读

我们对微前端框架的内容做了一个详细的介绍,并从零开始用Typescript实现了微前端的基本功能。

本文我们首先实现一个可进行子应用注册和资源加载的微前端框架,实现在一个vue3主应用中加载3个不同技术栈(vue2、react15、react16)的子应用,并且页面上渲染出各个子应用的内容;

然后,我们对该微前端框架实现扩展,实现

运行环境隔离(沙箱)

css样式隔离

应用间通讯(含父子通信、子应用间通信)

全局状态管理(全局store的简单使用)

利用应用缓存和预加载子应用提高加载性能

一、前置准备

再开发我们自己的微前端框架之前,我们需要做一定的架构设计准备。我们考虑微前端架构设计时的整体思路,并画出项目架构图。

1.1 微前端框架实现思路

采用路由分发式(本文使用的是hash模式)

主应用控制路由匹配和子应用加载,共享依赖加载

子应用做功能,并接入主应用实现主子控制和联动

1.2 分析框架& 项目架构图

首先分析需求:

1.主应用功能:

a.注册子应用;

b.加载、渲染子应用

c.路由匹配(activeWhen, rules- 由框架判断)

d.获取数据(公共依赖,通过数据做鉴权处理)

e.通信(父子通信、子父通信)

2.子应用功能:

a.渲染

b.监听通信(主应用传递过来的数据)

3.微前端框架功能

a.子应用的注册

b.有开始内容(应用加载完成)

c.路由更新判断

d.匹配对应的子应用

e.加载子应用的内容

f.完成所有依赖项的执行

g.将子应用渲染在固定的容器内

h.公共事件的管理

i.异常的捕获和报错

j.全局的状态管理的内容

k.沙箱的隔离

l.通信机制

4.服务端的功能:提供数据服务

整体项目架构图如下:

二、开发微前端框架

本节我们开始开发主子应用并且实现微前端框架的基础功能

* 首先,我们实现主子应用的开发:按照我们的实际项目需求进行子应用的搭建和改造工作,每种子应用改造的方式大同小异;并且开发主应用,主应用起着整体的调度工作,按照对应的路由匹配规则渲染对应的子应用

* 然后我们实现微前端框架的基础功能,包括:应用注册、路由拦截、主应用生命周期添加、微前端生命周期添加、加载和解析html及js、渲染、执行脚本文件等内容。

2.1 准备子应用

技术选型

本文采用Vue3技术栈开发主应用,并准备了3个不同技术栈的子应用:

子应用:

vue2子应用(实现home主页)

React15子应用(博客页)

React16子应用(照片页)

项目目录结构

注:在开发微前端框架前,我们首先需要准备3个子应用,子应用的具体实现并非重点,完整代码可见:blog-website-mircroFE-demo:https://code.alibaba-inc.com/sunxiaochun.sxc/blog-website-mircroFE-demo,项目目录结构如下:

子应用改造接入微前端

当我们有了几个子应用后,需要对其进行一些改造,从而使其能接入微前端。

设置启动脚本

当新建好3个子应用后,我们的目录结构是这样的

以启动react16子应用为例,cd react16 &&yarn start 只能启动单个react子应用,我们需要配置一个命令来一次性启动所有子项目:

这样,在根目录下执行yarn start即可一次性启动3个子应用

2.2 主应用开发

主应用负责所有子应用的卸载、更新和加载整个流程,主应用是链接子应用和微前端框架的工具。

构建主应用基本页面

主应用需要负责整体页面布局,使用vue3开发主应用mAIn,其主体框架如下:

可以看到,主应用在页面中设置了一个子应用的容器

子应用内容

,在这个区域中,我们展示不同的子应用内容。

在主应用中进行子应用注册

有了主应用之后,首先需求在主应用中注册子应用的信息。需要存储的子应用信息:

name:子应用唯一id

activeRule:激活状态(即在哪些路由下渲染该子应用)

container: 渲染容器(子应用要放在哪个容器里显示)

entry 子应用的资源入口:(从哪里获取子应用的文件)

通过主应用注册子应用:设置一个subNavList存储子应用信息的注册信息,本文的3个子应用的注册信息如下

然后编写微前端框架中注册子应用的方法,将子应用注册进微前端框架(这里为了简单直接挂载到window)里

最后在主应用中注册子应用

2.3 实现路由拦截

有了子应用列表后,我们需要启动微前端,以便来渲染对应的子应用,本节实现的是:主应用控制路由匹配和子应用加载

路由拦截方法

下面我们编写微前端中路由拦截方法,实现思路:

监听路由切换 & 重写路由切换事件pushState和replaceState

并且监听浏览器的前进/后退按钮window.onpopstate

在启动微前端框架时调用我们重写的路由监听方法

根据路由查找子应用

子应用注册时保存了子应用列表的信息,对于当前路由,需要找到其对应的子应用。如下。我们编写一个根据当前路由获取子应用的通用方法

然后,我们编写启动微前端框架的路由查找方法,实现当进入项目,对于首个展示的子应用,先验证当前子应用列表是否为空,不为空根据route匹配找到当前对应的子应用,如果子应用存在,则跳转到子应用对应的url。

2.4 生命周期

实现路由拦截后,对于如何挂载和卸载该路由下的子应用,就需要去实现一套生命周期。

子应用生命周期

子应用通常有下面三个生命周期:

1.bootstrap:开始加载应用,用于配置子应用的全局信息等

2.mount:应用进行挂载,用来渲染子应用

3.unmount:应用进行卸载,用于销毁子应用

这是一个协议接入,只要子应用实现了boostrap、mount和unmount这三个生命周期狗子,有这三个函数导出,我们的框架就可以知道如何加载这个子应用。

主应用生命周期

主应用的生命周期主要有三个:

1.beforeLoad:挂载子应用前,开始加载

2.mounted 挂载子应用后,渲染完成,

3.destoryed 卸载子应用卸载完成,

我们改写微前端框架提供的方法,加入生命周期的内容

在主应用中利用微前端提供的注册微应用的方法registerMicroApps中设置主应用的生命周期,并通过主应用生命周期去控制子应用的内容显示

微前端框架生命周期

微前端的生命周期:如果路由变化时,对子应用进行对应的销毁和加载操作

首先,编写微前端框架监听子应用是否做了切换的方法isTurnChild、以及根据路由获取子应用的方法findAppByRoute

其次,编写微前端框架的生命周期lifeCycle方法

实现思路是:微前端挂载到主应用,执行注册函数时,传入的就是主应用的生命周期,遍历执行这个主应用的所有生命周期,微前端框架就可以实现将子应用注册到主应用。

这样,当微前端框架监听到对应的子应用切换时,就执行微前端的生命周期

最终效果:当我们切换路由时(例如从vue2子应用切换到react15子应用时),控制台打印如下:

2.5 获取需要展示的页面

为了展示子应用页面,首先需要做的:主应用获取子应用的生命周期,结构,方法,文件等。这样主应用才能控制子应用的渲染和加载。

主应用的生命周期有三个:beforeLoad开始加载、mounted 渲染完成、destoryed 卸载完成。实际上,我们在主应用生命周期beforeLoad中去获取页面内容(加载资源):

子应用显示页面本质上是通过get请求.NETwork中的doc)去获取页面信息,由此我们就可以在微前端框架中通过get请求去获取到子应用对应的页面,根据url通过fetch拿到页面内容,最后再将内容赋值给对应的容器就可以显示子应用对应的页面了,

但是直接赋值给容器,容器是没法解析html中的标签,对于link和script(src,js代码)元素,需要专门提取出来这些元素进行处理

加载和解析html

因为所有的网站都是以HTML作为入口文件的,这份HTML中实际已经包含了子应用的所有信息(网页结构、js与css资源等),在微前端框架中,可以通过找到HTML中的静态资源并加载,从而渲染出对应的子应用。

有了加载和解析子应用的HTML的方法,就需要在加载子应用的生命周期中进行调用

加载和执行js

上面我们只加载了HTML资源,但实际上子应用除了dom资源外,还有script资源也需加载。

实现思路:在getResource方法中我们递归寻找元素,将 link、script元素找出来并做对应的解析处理即可。对于dom资源,直接进行渲染,对于script资源有两种情况:

1.内部script脚本

2.外部scriptUrl链接资源

我们分别进行处理

结果如下:

congratulations!

到现在我们就实现了在一个vue3主应用中加载3个不同技术栈(vue2、react15、react16)的子应用,并且成功在页面上展示了出来!

三、微前端框架-辅助功能

上文我们已经解决了微前端中应用的加载和切换,本节我们给微前端添加其他辅助功能,例如:预加载、应用通讯、全局store等功能

3.1 运行环境隔离 - 沙箱

为了避免应用间发生冲突,不同子应用之间的运行环境应该进行隔离,防止全局变量的互相污染。沙箱有两种实现:快照沙箱 & 代理沙箱

快照沙箱

快照沙箱就是在应用沙箱挂载和卸载的时候记录快照,在应用切换时依据快照来恢复环境。

具体实现思路是:记录当前执行的子应用的变量,当子应用切换的时候,将变量置为初始值。

代理沙箱

代理沙箱是利用ES6的proxy去代理window,监听window的改变,是更现代化的沙箱方法。

具体实现思路:设置一个空对象defaultValue去储存子应用的变量

当window改变时,将改变值以key,value的形式存储到defaultValue中;当需要获取window属性值的时候,也在代理的get中去返回defaultValue对应的值

沙箱销毁的时候inactive也只需要将defaultValue置为{}

3.2 CSS样式隔离

利用沙箱解决了JS之间的副作用冲突,接下来我们需要解决CSS之间的冲突,为CSS做样式隔离。

常用样式隔离方法有:

1.css modules:利用webpack配置打包机制进行css模块化处理,通过编译生成不冲突的选择器名

2.shadow dom :创建个新的元素进行包裹,但语法较新,兼容性较差,设置shadow dom的步骤:

a.设置mode 利用attachShadow得到shadow

b.为shadow dom添加内容

3.minicss (本框架选用):一个webpack插件,该插件将css打包成单独的文件,然后页面通过link进行引用

4.csss in js:将应用的css样式写在JAVAScript文件里,最终生成不冲突的选择器。

3.3 应用间通信

对于应用通讯,有两种实现方式:props和customevent

基于Props的方式

这里有一个父子通信的实例场景:子应用动态控制主应用nav的显示与隐藏。如下,在react16子应用中编写了login登陆页面,在该页面中不应显示导航条nav

实现如下:首先,子应用需要一个控制主应用中nav显示和隐藏的方法。所以我们在主应用的store中维护一个navStatus属性,表示导航条nav是否显示和隐藏至,暴露一个修改该navStatus属性的方法changeNav

将该状态绑定至主应用导航条中,

然后,将主应用的所有store内容(包含navStatus)用Props的方式传递给所有子应用。

修改子应用的mounted生命周期方法,注册子应用时将含有navStatus属性的appInfo传递给子应用

最后,以react16子应用为例,在react16子应用中拿到主应用传递来的信息,并在子应用的渲染中隐藏nav。

上述是一个主子应用通信的实例,对于子应用之间的通讯,也可以利用基于props的方式:子应用1 跟父应用交互,父应用再传递给子应用2。

基于CustomerEvent的方式

另一种应用间通讯的模型是挂一个事件总线,应用之间不直接相互交互,都去一个事件总线上注册和监听事件。实现思路:通过new CustomEvent对象去监听事件(on)和触发事件(emit),如下:

首先,利用customEvent创建Custom类

有了Custom类后, 我们在微前端框架中创建一个custom对象,为其添加事件监听方法test,并将其挂载到全局window上

这样,在子应用里,我们就可以通过window.custom来获取custom对象。

3.4 全局状态管理 - 全局store

建立微前端中的全局状态管理基于发布订阅模式,通过主应用监听某个方法、子应用添加订阅者来监听到一些全局状态的改变。

具体实现思路是:利用store保存数据,observer管理订阅者(subscribeStore方法用于添加订阅者),并提供获取和更新store的getStore和updateStore的方法。

有了全局状态,如何在主应用中引入即可。若要在子应用中也使用store,将store挂载到window上,子应用直接访问window.store即可,使用全局变量也是应用通讯的一种方式。

3.5 提高加载性能

应用缓存

当前,当切换不同的子应用时,都会重新加载页面,若页面资源非常多,加载会比较缓慢,所以需要在微前端框架中对应用进行缓存,提升加载性能。

应用缓存的实现思路是:

定义一个cache对象,根据子应用的appName来做缓存

如果当前子应用的html已经解析并且加载过,就返回已经加载过的内容。如果没有,则走正常加载和解析的流程

预加载子应用

提升加载性能的另一个思路是预加载子应用,即在启动微前端框架时,先获取当前要加载的子应用,再预加载剩下的所有的子应用。

这样,在做子应用切换时,避免一定的延迟感~

四、写在最后

在之前的内容中,我们对微前端框架的内容做了一个详细的介绍,并从零开始用Typescript实现了微前端的基本功能,对这样的一个简易微前端框架,仍有可以扩展和继续学习的地方。例如

如何实现微前端框架的自动发布?如何通过npm来发布我们编写的框架?能否创建一个自动部署平台来实现应用的自动化部署?

现有热门的微前端框架(qiankun、single-spa、icestark)是如何实现微前端框架的应用注册&加载、沙箱隔离、全局状态管理、预加载这些功能?

参考资料:

从零到一实现企业级微前端框架,保姆级教学:https://juejin.cn/post/7004661323124441102

微前端连载 6/7:微前端框架 - qiankun 大法好:https://juejin.cn/post/6846687602439897101

从零打造微前端框架:实战“汽车资讯平台”项目:https://coding.imooc.com/class/chapter/520.html#Anchor



Tags:框架   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Web Components实践:如何搭建一个框架无关的AI组件库
一、让人又爱又恨的Web ComponentsWeb Components是一种用于构建可重用的Web元素的技术。它允许开发者创建自定义的HTML元素,这些元素可以在不同的Web应用程序中重复使用,并且...【详细内容】
2024-04-03  Search: 框架  点击:(8)  评论:(0)  加入收藏
Htmx,它到底是框架还是库?
在最近的前端开发技术的探讨中,htmx经常成为热议的话题。一些人批评它,认为尽管htmx批评现代前端框架过于复杂,但它自己却似乎也是一个复杂的框架。这种看法值得我们深入思考。...【详细内容】
2024-03-28  Search: 框架  点击:(16)  评论:(0)  加入收藏
五大跨平台桌面应用开发框架:Electron、Tauri、Flutter等
一、什么是跨平台桌面应用开发框架跨平台桌面应用开发框架是一种工具或框架,它允许开发者使用一种统一的代码库或语言来创建能够在多个操作系统上运行的桌面应用程序。传统上...【详细内容】
2024-02-26  Search: 框架  点击:(47)  评论:(0)  加入收藏
Spring Security权限控制框架使用指南
在常用的后台管理系统中,通常都会有访问权限控制的需求,用于限制不同人员对于接口的访问能力,如果用户不具备指定的权限,则不能访问某些接口。本文将用 waynboot-mall 项目举例...【详细内容】
2024-02-19  Search: 框架  点击:(39)  评论:(0)  加入收藏
Go Gin框架实现优雅地重启和停止
在Web应用程序中,有时候我们需要重启或停止服务器,无论是因为更新代码还是进行例行维护。在这种情景下,我们需要保证应用程序的可用性和数据的一致性。这就需要优雅地关闭和重...【详细内容】
2024-01-30  Search: 框架  点击:(67)  评论:(0)  加入收藏
链世界:一种简单而有效的人类行为Agent模型强化学习框架
强化学习是一种机器学习的方法,它通过让智能体(Agent)与环境交互,从而学习如何选择最优的行动来最大化累积的奖励。强化学习在许多领域都有广泛的应用,例如游戏、机器人、自动驾...【详细内容】
2024-01-30  Search: 框架  点击:(68)  评论:(0)  加入收藏
OpenHarmony - 基于ArkUI框架实现日历应用
前言对于刚刚接触OpenHarmony应用开发的开发者,最快的入门方式就是开发一个简单的应用,下面记录了一个日历应用的开发过程,通过日历应用的开发,来熟悉基本图形的绘制,ArkUI的组件...【详细内容】
2024-01-16  Search: 框架  点击:(54)  评论:(0)  加入收藏
阿里“AI替换万物”框架火爆社区,网友:偶像不需要真人了?
白交 发自 凹非寺量子位 | 公众号 QbitAIReplace Anything as you want。现在只需框住你需要保留的区域,AI就可以替换万物了!比如让霉霉穿上中国旗袍,结果发饰、服装、背景等各...【详细内容】
2024-01-15  Search: 框架  点击:(66)  评论:(0)  加入收藏
分布式事务框架选择与实践
分布式事务是处理跨多个服务的原子操作的关键概念,而选择适合应用场景的框架对于确保事务一致性至关重要。以下是几个常见的分布式事务框架,并讨论它们的使用和实践。1. XA协...【详细内容】
2024-01-05  Search: 框架  点击:(96)  评论:(0)  加入收藏
JavaScript前端框架2024年展望
Angular、Next.js、React和Solid的维护者和创作者们展望2024年,分享了他们计划中的改进。译自2024 Predictions by JavaScript Frontend Framework Maintainers,作者 Loraine...【详细内容】
2024-01-05  Search: 框架  点击:(91)  评论:(0)  加入收藏
▌简易百科推荐
Web Components实践:如何搭建一个框架无关的AI组件库
一、让人又爱又恨的Web ComponentsWeb Components是一种用于构建可重用的Web元素的技术。它允许开发者创建自定义的HTML元素,这些元素可以在不同的Web应用程序中重复使用,并且...【详细内容】
2024-04-03  京东云开发者    Tags:Web Components   点击:(8)  评论:(0)  加入收藏
Kubernetes 集群 CPU 使用率只有 13% :这下大家该知道如何省钱了
作者 | THE STACK译者 | 刘雅梦策划 | Tina根据 CAST AI 对 4000 个 Kubernetes 集群的分析,Kubernetes 集群通常只使用 13% 的 CPU 和平均 20% 的内存,这表明存在严重的过度...【详细内容】
2024-03-08  InfoQ    Tags:Kubernetes   点击:(12)  评论:(0)  加入收藏
Spring Security:保障应用安全的利器
SpringSecurity作为一个功能强大的安全框架,为Java应用程序提供了全面的安全保障,包括认证、授权、防护和集成等方面。本文将介绍SpringSecurity在这些方面的特性和优势,以及它...【详细内容】
2024-02-27  风舞凋零叶    Tags:Spring Security   点击:(54)  评论:(0)  加入收藏
五大跨平台桌面应用开发框架:Electron、Tauri、Flutter等
一、什么是跨平台桌面应用开发框架跨平台桌面应用开发框架是一种工具或框架,它允许开发者使用一种统一的代码库或语言来创建能够在多个操作系统上运行的桌面应用程序。传统上...【详细内容】
2024-02-26  贝格前端工场    Tags:框架   点击:(47)  评论:(0)  加入收藏
Spring Security权限控制框架使用指南
在常用的后台管理系统中,通常都会有访问权限控制的需求,用于限制不同人员对于接口的访问能力,如果用户不具备指定的权限,则不能访问某些接口。本文将用 waynboot-mall 项目举例...【详细内容】
2024-02-19  程序员wayn  微信公众号  Tags:Spring   点击:(39)  评论:(0)  加入收藏
开发者的Kubernetes懒人指南
你可以将本文作为开发者快速了解 Kubernetes 的指南。从基础知识到更高级的主题,如 Helm Chart,以及所有这些如何影响你作为开发者。译自Kubernetes for Lazy Developers。作...【详细内容】
2024-02-01  云云众生s  微信公众号  Tags:Kubernetes   点击:(50)  评论:(0)  加入收藏
链世界:一种简单而有效的人类行为Agent模型强化学习框架
强化学习是一种机器学习的方法,它通过让智能体(Agent)与环境交互,从而学习如何选择最优的行动来最大化累积的奖励。强化学习在许多领域都有广泛的应用,例如游戏、机器人、自动驾...【详细内容】
2024-01-30  大噬元兽  微信公众号  Tags:框架   点击:(68)  评论:(0)  加入收藏
Spring实现Kafka重试Topic,真的太香了
概述Kafka的强大功能之一是每个分区都有一个Consumer的偏移值。该偏移值是消费者将读取的下一条消息的值。可以自动或手动增加该值。如果我们由于错误而无法处理消息并想重...【详细内容】
2024-01-26  HELLO程序员  微信公众号  Tags:Spring   点击:(86)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19   Java中文社群  微信公众号  Tags:SpringBoot   点击:(86)  评论:(0)  加入收藏
花 15 分钟把 Express.js 搞明白,全栈没有那么难
Express 是老牌的 Node.js 框架,以简单和轻量著称,几行代码就可以启动一个 HTTP 服务器。市面上主流的 Node.js 框架,如 Egg.js、Nest.js 等都与 Express 息息相关。Express 框...【详细内容】
2024-01-16  程序员成功  微信公众号  Tags:Express.js   点击:(88)  评论:(0)  加入收藏
站内最新
站内热门
站内头条