微前端

2022/2/10

# 微前端

微前端(Micro-Frontends)是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。

微前端并不是前端领域的新概念。早期希望前端工程能够像后台的微服务一样,项目分开自治,核心的诉求是:

  1. 兼容不同技术栈
  2. 将项目看作页面、组件,能够复用到不同的系统中
  3. 实现页面低成本接入是微前端的重要愿景之一,也是吸引大家持续探索的核心原因。

# single-spa

# micro-app

# 无界

# qiankun

qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。目标直指巨石应用业务难题,旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用 (Frontend Monolith) 后,随之而来的应用不可维护的问题。这类问题在企业级 Web 应用中尤其常见。

微前端的概念借鉴自后端的微服务,主要是为了解决大型工程在变更、维护、扩展等方面的困难而提出的。目前主流的微前端方案包括以下几个:

  • iframe
  • 基座模式,主要基于路由分发,qiankun 和 single-spa 就是基于这种模式
  • 组合式集成,即单独构建组件,按需加载,类似 npm 包的形式
  • EMP,主要基于 Webpack5 Module Federation
  • Web Components

严格来讲,这些方案都不算是完整的微前端解决方案,它们只是用于解决微前端中运行时容器的相关问题。

  1. who: 包含 qiankun 客户端、主应用 A、微应用 B 三部分,三者协作完成了微前端的设计。

在 qiankun 的框架下,一个页面集成到另外一个页面系统中,最关键的核心点就是将微应用封装成具有生命周期的页面组件,使得 qiankun 可以调用 React 或者 Vue 的 render 能力,将页面渲染到对应的 DOM 节点。

有个小细节就是微应用的 JS CSS 文件请求是属于 Ftech/XHR 类型,说明 js 文件的请求是 qiankun 客户端自行构造的。

这里必然要涉及前端的跨域问题,尤其是当主应用和微应用的域名不一致时,qiankun 客户端如何能够在跨域的限制之下获取到微应用的页面资源?一个解决方案是主应用提供一个鉴权秘钥下发的接口 signUrl,这个接口由微应用提供也可以,将秘钥信息下发到 cookie 中,通过配置 qiankun 自定义 fetch 方法,带上这些鉴权信息。官方也提供了一些通用方案以供参考。

# 微应用改造

一个业务系统并不是一开始就有被集成的价值的,往往是在业务发展到一定程度,经过市场验证其价值之后,大家才会明确这个业务系统具有微应用改造的价值,这就导致一个窘迫的境地:你需要改造已经成型的项目,使其成为可快速接入的微应用。

qiankun 的微应用改造相对比较简单,一般在开启严格沙箱模式之后,微应用和主应用之间建立比较好的环境隔离,你并不需要太多的工作。

  1. 首先样式隔离,参考下面 css 隔离。其核心的麻烦在于 qiankun 启动严格沙箱模式之后,会导致 dialog、Modal 等组件无法找到 body 节点,进而无法挂载到 DOM 中。
  2. 其次 JS 作用域隔离,这里主要是一些第三方库会在 window 上挂在单例实例,导致主应用和微应用之间单例配置相互覆盖,常见于日志上报、微信 SDK、QQ SDK 等第三方应用。解决方案分为两个方向:
    • 假如主应用存在则沿用主应用的配置:这种方式对主应用比较有利。以日志上报的配置为例,微应用的日志会上报到主应用空间下,那么主应用的日志监控会很完整。缺点则是微应用本身失去了这些监控信息。
    • 微应用对自身使用的单例进行隔离:这种方式对微应用比较有利。以 Axios 的配置为例,子应用可以实现类似中台应用的效果,可以探知到微应用在不同的主应用中的实际使用场景和数据统计。
    • 采用第二种方式时,假如主应用需要进行数据共享或者配置共享,可以通过主应用和微应用之间的参数和数据传递的方式来实现共享,微应用提供丰富的监听 hooks。

# FAQ

# 1. 如何解决第三方 SDK、JS 文件加载失败问题

  • 原因:微信和企业微信的 SDK 是不可以自行构建 Http 请求加载的,这是由于其安全策略导致的,且每次返回的内容有安全限制的改动,无法复用。

  • 结果:因此必须要在 html 的 header 中引入,但 qiankun 会对 html - header 所有 script、link 资源构造请求链接,进而导致获取第三方 SDK 的请求报错,整个 qiankun 客户端加载微应用进程报错,无法加载出对应页面。

  • 官网在常见问题给了三个解决方案:

    1. 使用 getTemplate 过滤异常脚本;
    2. 使用自定义 fetch 阻断 script 脚本;
    3. 终极方案 - 修改 html 的 content-type;

前两种方案需要在乾坤渲染函数中增加一个对应的参数,这里面有个坑点,则是 prefetchApps 不支持这些参数,因此一旦启用预加载函数,则会导致渲染函数的传入配置失效,因此需要关闭使用预加载函数。

# 2. css 隔离

  • 微前端核心理念:解耦 / 技术栈无关,简单来说就是希望微应用之间,基站应用和微应用之间的技术栈可以互相隔离,从而各种定制自己的技术体系来实现开发效率和产品质量的最优化配置,这也是微前端的核心价值体现。
  • 主流的沙箱模式是通过创建一个独立的作用域隔离作用域链,同时克隆全局变量来实现的,但是这种隔离 + 克隆方案并不完美,在复杂运行场景中,无论性能还是安全性都是难以保证的,特别是 CSS 的隔离。
  1. 首先是基础页面的 CSS,采用的是成熟的 CSS module 方案,简单来说就是将 CSS 变成局部生效,每个 class 生成一个独一无二的名字。从最早的 Less、SASS,到后来的 PostCSS,再到最近的 CSS in JS,都是为了解决 CSS 全局生效带来的副作用。
  2. 参考这里 (opens new window)
上次更新: 1/5/2024