微前端

126 阅读3分钟

微前端:将不同功能按照不同的维度拆分成多个子应用,通过主应用来加载这些子应用。重点在于拆分,之后是合并。

微前端解决的问题:

  1. 不同团队(技术栈不同)同时开发一个应用
  2. 每个团队开发的模块都可以独立开发,独立部署
  3. 实现增量迁移

iframe实现微前端:

  1. 微前端最简单方案,通过iframe加载子应用
  2. 通信可以通过postMessage进行通信
  3. 完美的沙箱机制自带应用隔离 缺点:用户体验差(弹框只能在iframe中,在内部切换刷新会丢失状态)

Web Components实现微前端:

  1. 将前端应用程序分解为自定义HTML元素。
  2. 基于CustomEvent实现通信
  3. ShadowDOM天生的作用域隔离(缺点:浏览器支持问题、学习成本、调试困难、修改样式困难等)

Single-spa实现微前端:

  1. Single-spa通过路由劫持实现应用的加载(采用SystemJs),提供应用间公共组件加载+公共业务逻辑处理。子应用需暴露固定钩子 bootstrap、mount、unmount 接入协议。
  2. 基于props 父子应用间通信
  3. 无沙箱机制,需实现自己实现js沙箱+css沙箱。(缺点:学习成本、无沙箱机制、需对原有的应用进行改造、子应用间相同资源重复加载问题)

Module federation实现微前端:

  1. 通过联盟模块,将组件进行打包导出使用
  2. 共享模块的方式进行通信
  3. 无css沙箱+js沙箱(缺点:需webpack5)

依赖复用问题:

  1. 创建共享模块,独立打包部署到CDN上,通过加载应用时传入,或在子应用中引入。
  2. 通过联盟模块(需webpack5)进行打包处理公共资源。
  3. 两个应用之间加载资源的ip地址相同,即可复用(http缓存)

应用之间的组件复用问题:

  1. 应用中,将共享的组件进行单独打包,加载应用时进行传入。

Vite支出问题:

  1. 基于vite构建的项目中,含有 import、export 并没有被转码,导致直接报错。解决方案:vite打包后在生产环境下(umd格式)介入。

qiankun嵌套问题:

  1. 避免多重沙箱嵌套,子应用中需要关闭沙箱。

css沙箱不完美:

  1. strictStyleIsolation完全隔离问题,样式无法传递到子应用中。
  2. experimentalStyleIsolation 子应用dom结构插入到body中,样式无法生效。
  3. 会移除 globalState、addGlobalUncaughtErrorHandler\shadowDOM样式隔离方案。

micro-app中,关于WebComponent:

  1. 自定义元素(Custom element):允许用户自定义
  2. ShadowDOM样式隔离,是它的一部分
  3. 支持组件的特点、插槽、生命周期、属性 都是组件的特点
  4. 兼容性不好,IE不支持
  5. 支持vite、scss

template标签是浏览器内置的,默认不显示。

Shadow DOM含义与作用:

  1. 创建封闭的、隔离的DOM树,主要作用是,将DOM树的一部分与常规的DOM树隔离开,防止css和js从主文档影响到shadow tree的内容。 主要作用:样式隔离、脚本隔离、封装功能(可将HTML结构、css、js封装在一个独立的组件内,有助于创建可重用、可维护的组件,提高代码模块化)。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Shadow DOM Example</title>
</head>
<body>
  <div id="myComponent">I'm the host element.</div>

  <script>
    const host = document.getElementById('myComponent');

    // 创建一个 shadow tree 并将其附加到 host 元素上
    const shadow = host.attachShadow({ mode: 'open' });

    // 在 shadow tree 内添加内容
    const paragraph = document.createElement('p');
    paragraph.textContent = 'I\'m inside the shadow tree!';
    shadow.appendChild(paragraph);
  </script>
</body>
</html>

host 元素通过 attachShadow 方法创建了一个 shadow tree,并在 shadow tree 内添加了一个段落元素.

vite+qiankun