微前端简介、注意事项及常见技术方案

1 概述

微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用,各个前端应用还可以独立运行独立开发独立部署。

实现微前端不管是采用什么方案,本质都是一样的,微前端各个部分之间相互独立、独立部署的能力本质是在允许构建孤立或松散耦合的服务

微前端的一般结构如下:

在这里插入图片描述

2 使用场景

1)治理巨石应用

单体应用不断膨大导致理解和修改的成本上升,代码的提交到实际部署的周期越来越长,并且很容易出现问题。

这时,我们可以把原有功能抽离为单独的子应用,而新的功能模块作为新的子应用嵌入,在逐渐重构的过程中,既要保证中间版本能够平滑过渡,还能持续交付新的功能。

2)应用功能自由组合拆分及定制化开发

在业务方面,经常可能会面临不同特定的定制化需求或者功能组合,那实际上我们可以对每个单独的功能作为一个单独的子系统开发、子系统间的耦合,只需要规定好相应的通讯方式和内容,不需要关注对方的实现,在需要的时候自由组合即可。

3 使用微前端需要关注什么

在实践一个微前端的架构,我们需要关注哪些切实的问题呢?

通讯和状态管理

微前端的实现本质也是一种组合的思想,子应用间的组合跟功能中组件的组合有类似之处,组件之间的组合最重要的就是通讯和状态管理

不同的子应用之间组合而成,无法避免状态管理的问题,无论是全局下的状态管理、几个子应用间的局部状态管理,还是单个子应用间的状态管理,以及状态的上传和下发,都将是我们需要去考虑的问题。

在采用微前端架构的时候,很多时候遇到的问题可以转化成:如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依次地,可能会引起另一个 view 的变化。

这本质上是两个问题:

  • 子会响应父的状态变化,父会在子初始化之后初始化,子会在父变更后变更,导致子状态必须在子组件内部
  • vue/react 以及状态管理,只有子向父 dispatch 事件的能力,父无法向子 dispatch 事件

实现一个发布订阅模型就能解决这个问题,这也是为什么 qiankun 之类的微前端方案的应用间通讯方式是使用发布订阅的方式进行的,这样 parent 和 child 就可以彼此通过事件传递消息,且独立变化。

工作空间的独立

1)js沙箱

因为每一个子应用都是一个单独的项目和应用,在同一个页面中出现多个子应用是很常见的场景。

出于安全考虑,例如全局变量污染、多版本库等,还有各种复杂场景下的执行问题,我们需要对每个子应用间的 js 的工作空间进行隔离,使每个子应用内的执行自洽,只关注输出和输入,js沙箱的实现成为微前端方案中需要关注的一点

js沙箱是一种安全机制,为 js 代码创建了一个隔离的运行环境,使得在沙箱中运行的代码不会对全局环境产生影响,沙箱环境可以限制代码对某些资源的访问权限,比如全局变量、浏览器 API 等

js沙箱机制相关资料:https://zhuanlan.zhihu.com/p/527437146

2)css沙箱

虽然是微前端的结构,但本质上同一个页面中每个子应用的挂载依旧在同一个 dom 树上,那子应用间的样式自然不应该出现互相干扰的情况,并且在子应用切换时可以自行装载和卸载。

PS:单纯的 iframe 实现微前端的方案虽然有很多问题,但是在 js 和 css 的隔离上无疑是成本最低且较好的实现

路由管理

1)路由劫持

方案原理大致是监听 hashchange 事件,劫持浏览器 history 下的 pushState 和 replaceState

2)主应用控制路由

实现思路是主应用使用现有的路由库(vue-router或react-router),子应用使用 webpack 提供的 import() 函数动态加载子应用的模块

3)子应用的资源加载方式

资源加载方式影响页面加载速度,主要分为 html entry 和 js entry,前者加载是按原来方式打包出来的一个 html 文件,后者是加载子应用打出来的整个 js 文件。

如果将整个微应用打包成一个 js 文件,那常见的打包优化都用不了,例如:按需加载、首屏资源加载优化、css独立打包等

预加载

在微前端的方案中,每个子应用都是独立的,如果不做处理的话,在一个页面存在多个子应用的情况下,每个子应用的加载都是独立的,在这种情况下可能会出现白屏情况,导致用户体验不好。

并且在实际使用中,浏览器大部分是处在空闲的,我们要怎么利用这样的空闲时间,去加载其他子应用的 js 呢?

公共依赖的处理问题

子项目多了之后,公共依赖如果处理不好,会造成各种重复工作,bug风险也会增长,不利于后期维护。

是否支持应用保活

在切换子应用后,之前的状态是否需要保存,事关 keep-alive 之类在微前端的架构中怎么做

子应用之间的互相嵌套

是否支持子应用之间的互相嵌套,子应用组件互相嵌套后的通讯和状态管理又需要怎么做

4 常见技术方案

iframe

通过 iframe 我们可以很方便地将一个应用嵌入到另一个应用中,而且两个应用之间的 css 和 js 是相互隔离的,互不干扰

优点:

  • css 和 js 天然隔离,互不干扰
  • 多个子应用可以并存,不需要对现有应用进行改造
  • 与技术栈无关

缺点:

  • 每次切换应用时,浏览器都需要重新加载页面
  • UI 不同步,DOM 结构不共享
  • 全局上下文完全隔离,内存变量不共享,子应用之间通信、数据同步过程比较复杂

single-spa

在 single-spa 方案中,应用被分为两类:基座应用和子应用,子应用是需要聚合的应用,基座应用是另外一个单独的应用,用于聚合子应用

和单页应用的实现原理类似,single-spa 会在基座应用中维护一个路由注册表,每个路由对应一个子应用。基座应用启动以后,当我们切换路由时,如果是一个新的子应用,会动态获取子应用的 js 脚本,然后执行脚本并渲染出相应的页面;如果是一个已经访问过的子应用,那么就会从缓存中获取已经缓存的子应用,激活子应用并渲染出对应页面

优点:

  • 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验
  • 多个子应用可并存
  • 与技术栈无关

缺点:

  • 需对原有应用进行改造,应用要兼容接入 single-spa 和独立使用
  • 使用复杂,子应用加载、隔离、通信等问题,需要自己实现
  • 子应用间相同资源重复加载
  • 启动应用时,要先启动基座应用

qiankun

qiankun 是在 single-spa 的基础上做了二次开发,在框架层面上解决了使用 single-spa 时需要开发人员自己编写子应用加载、通信、隔离等逻辑的问题,是一种比 single-spa 更优秀的微前端方案

优点:

  • 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验
  • 相比 single-spa,解决了子应用加载、隔离、通信等问题,使用起来相对简单
  • 多个子应用可并存
  • 与技术栈无关

缺点:

  • 需对原有应用进行改造,应用要兼容接入 qiankun 和独立使用
  • 相同资源重复加载
  • 启动应用时,要先启动基座应用

webpack5:module federation

webpack5 提供了一个新特性:module federation,基于这个特性,我们可以在一个 JavaScript 应用中动态加载并运行另一个 JavaScript 应用的代码,并实现应用之间的依赖共享

通过 module federation,我们可以在一个应用里面动态渲染另一个应用的页面,这样就实现了多个子应用的聚合

优点:

  • 切换应用时,浏览器不用重载页面,提供和单页应用一样的用户体验
  • 相同资源不需要重复加载
  • 应用启动后,无需加载与自己无关的资源
  • 免登友好

缺点:

  • 构建工具只能使用 webpack5
  • 对老项目不友好,需要对 webpack 进行改造
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值