前端面试-微前端

date
Aug 10, 2023
slug
frontend_interview_micro_frontend
status
Published
tags
前端
interview
summary
微前端
type
Post
微前端实现的方式有 iframe, web components, javascript模块加载器。
最常用的是javascript模块加载器(SystemJS),可以让我们在运行时动态的加载和卸载模块,从而实现微前端应用程序的动态部署和更新。

工作原理 (qiankun,跟single-spa应该差不多)

  • 应用加载:通过动态创建script标签的方式加载子应用的入口文件。加载完成后,会执行子应用里定义的生命周期函数
  • 生命周期管理:qiankun需要每个子应用都要暴露出bootstrap,mount和unmount三个生命周期函数。bootstrap在应用加载时被调用,mount在应用启动时被调用,unmount在应用卸载是被调用。
  • 沙箱隔离:qiankun通过proxy对象创建了一个javascript沙箱,用于隔离子应用的全局变量,防止子应用之间的全局变量污染。
  • 样式隔离:qiankun通过动态添加和移除样式标签的方式实现了样式隔离。当子应用启动时,会动态添加子应用的样式,当子应用卸载时,会动态卸载子应用的样式标签
  • 全局通信:qiankun提供了一个全局的通信机制,允许子应用之间进行通信
bootstrap:这个生命周期函数会在应用第一次挂载前执行一次。就是说在子应用的代码加载完成以后,页面渲染之前执行。
mount:当主应用判定需要激活这个子应用时会调用这个生命周期函数。在这个函数中实现子应用的挂载、页面渲染等逻辑。这个函数也只会执行一次
unmount:当主应用判定需要卸载这个子应用时会调用这个生命周期函数。在这个函数中实现组件卸载、清理事件监听等逻辑。
single-spa中做模块导入大量的用到了SystemJS,主要是为了解决模块化导出的一些问题

qiankun vs iframe

在选择 qiankuniframe 时,需要根据具体的使用场景来决定。如果你的子应用是基于现代前端框架(如 React、Vue、Angular 等)开发的单页应用,那么 qiankun 可能是一个更好的选择,因为它可以提供更好的用户体验和更高的开发效率。如果你的子应用是基于 jQuery 或者其他传统技术开发的多页应用,或者你需要在子应用中加载一些第三方的页面,那么 iframe 可能是一个更好的选择,因为它可以提供更强的隔离性。

不同前端框架的代码如何复用

Web Components的三驾马车,即Custom elements、Shadow DOM和HTML templates。
1)Custom elements
允许用户自定义一组JS API,完成UI和逻辑行为,这与主流框架中的组件自定义元素的概念是一致的。
2)Shadow DOM
自定义元素将生成一棵与主文档隔离的“影子”DOM树,而Shadow DOM的作用就是将这棵树附加到宿主元素中,保证了元素功能的私有和独立性。
3)HTML templates
提供了 template 和 slot 功能,用于自定义元素结构和模板复用。
1)优点
  • 框架0耦合
  • 浏览器原生支持
  • 主流框架支持
2)缺点
  • 兼容性
    • 目前原生浏览器中只有Chrome和Firfox提供了全面的支持,IE和Edge等并不友好。庆幸的是,官方polyfill可以提供IE11以及Edge和其他大部分浏览器的支持,这对B端产品来说,已经够了。
  • 数据绑定
  • 状态管理
  • 开发成本
    • Web Components目前并没有数据绑定和状态管理,导致我们无法像其他主流框架那样方便地更新视图、使用redux等进行数据状态管理。
是可以使用某个主流框架进行组件核心逻辑的开发,以Web Components作为桥梁,进行其他框架的复用手段比如把react组件用direflow构建成web components, 然后在angular里复用

隔离

single-spa

子应用样式的加载和卸载。single-spa 提供了 single-spa-css 这个工具来实现。
css-module实现子应用之间样式隔离
single-spa 采用了类似于快照模式的JS隔离机制,通过 single-spa-leaked-globals 来实现。
所谓快照模式,就是将启动子应用之前,对当前环境打一个快照,子应用退出之后,再重新加载这个快照来恢复环境。
在实现层面,我们可以针对每一种副作用设计一个 save 方法保存当前状态,在设计一个 load 方法来加载保存的状态。
框照模式的缺陷是对操作的顺序要求非常严格,当页面有多个子应用的时候,快照沙箱就会有多个实例存在,此时不同顺序的 saveload 会产生问题。
css公共依赖
这个问题和上面提到的处理“公共依赖”的问题是差不多的。官方给出两个建议:
  1. 将公共的 CSS 放到 importmap 里,也可以理解为在 index.html 里直接加个 link 获取 antd 的 CSS 完事
  1. 将所有的公共的 UI 库都 import 到 utility 里,将 antd 所有内容都 export,再把 utility 包放到 importmap 里,然后 import { Button } from '@your-org-name/utility'; 去引入里面的组件
其实上面两个方法都大同小异,思路都是在主应用一波引入,只是一个统一引入CSS,另一个统一引入 UI 库。

qiankun

shadow-dom
css module

静态资源文件(尽量别提)

qiankun 方案 优点
降低了应用改造的成本,通过html entry的方式引入子应用; 提供了完备的沙箱方案,包括js沙箱和css沙箱; 支持静态资源预加载能力。
缺点
适配成本较高,包括工程化、生命周期、静态资源路径、路由等方面的适配; css沙箱的严格隔离可能引发问题,js沙箱在某些场景下执行性能下降; 无法同时激活多个子应用,不支持子应用保活; 不支持vite等esmodule脚本运行。
静态资源路径要拼上父应用domain路径

应用复用依赖

  1. 子项目之间的依赖复用可以通过保证依赖的URL一致来实现。如果多个子项目都使用同一份CDN文件,加载时会先从缓存读取,避免重复加载。
  1. 在使用webpack构建的子项目中,要实现复用公共依赖,需要配置webpackexternals,将公共依赖指定为外部依赖,不打包进子项目的代码中。

    父子应用通信

    single-spa中:
    • custom events
    • 后端数据通信
    • localstorage
    • window全局挂载

    © bai xin 2021 - 2024

    沪ICP备20011311号-1