关于微前端的一些学习和总结

97 阅读4分钟
  • 微前端概念

微前端是一个主应用中,包含多个子应用的架构。因此iframe 也是一种微前端方案

  • 什么情况下,可以考虑使用微前端
  1. 应用太过于庞大,每次构建和部署都需要很长时间
  2. 想渐进式重构旧的系统,可以用微应用的方式,对部分业务做重构
  3. 当公司有多个前端团队,每个团队负责不同的业务线或产品功能的时候,也可以使用微前端的技术架构
  • ifame 作为微前端方案的一些问题:

    • UI 不同步,比如iframe 中有一个弹框,需要在主界面中居中,就会比较难以实现。
    • 加载缓慢,每次都需要重新加载资源,没有预加载的过程,也不能复用已经加载过的资源
    • 主应用和iframe 子应用之间,数据完全隔离,不能共享,因此存在着子应用的免登问题,数据实时同步的问题。
    • 每次刷新页面,iframe的url都会丢失,而且前进后退按钮没办法用。
  • qiankun 自动加载的流程

qiankun 使用了 import-html-entry 这个包来做处理。

  1. qiankun 会用 原生fetch方法,请求微应用的 entry 获取微应用资源,然后通过 response.text 把获取内容转为字符串;
  2. 将 HTML 字符串传入 processTpl 函数,进行 HTML 模板解析,通过正则匹配 HTML 中对应的 javaScript(内联、外联)、css(内联、外联)、代码注释、entry、ignore 收集并替换,去除 html/head/body 等标签,其他资源保持原样;
  3. 将收集的 styles 外链URL对象通过 fetch 获取 css,并将 css 内容以 的方式替换到原来 link标签的位置;
  4. 收集 script 外链对象,对于异步执行的 JavaScript 资源会打上 async 标识 ,会使用 requestIdleCallback 方法延迟执行;
  5. 接下来会创建一个匿名自执行函数包裹住获取到的 js 字符串,最后通过 eval 去创建一个执行上下文执行 js 代码,通过传入 proxy 改变 window 指向,完成 JavaScript 沙箱隔离;
  6. 由于 qiankun 是自执行函数执行微应用的 JavaScript,因此在加载后的微应用中是看不到 JavaScript 资源引用的,只有一个资源被执行替换的标识;
  7. 当一切准备就绪的时候,执行微应用的 JavaScript 代码,渲染出微应用
  • qiankun 方案和single-spa方案的区别:

    • qiankun 方案 在single-spa 架构的基础上,做了如下处理:

    1. 改手动加载为自动加载。

      single-spa 方式

      registerApplication({ 
          name: "@polyglot-mf/navbar", 
          app: () => System.import("@polyglot-mf/navbar"), 
          activeWhen: "/", 
      }); 
      registerApplication({ 
          name: "@polyglot-mf/clients", 
          app: () => System.import("@polyglot-mf/clients"), 
          activeWhen: "/clients", 
      });
      

    qiankun 的方式

      import { registerMicroApps, start } from 'qiankun';
    
      registerMicroApps([
        {
          name: 'vue app',
          entry: '//localhost:7100',
          container: '#container-vue',
          activeRule: '/micro-vue'
        },
        {
          name: 'react app',
          entry: '//localhost:7101',
          container: '#container-react',
          activeRule: '/micro-react'
        },
      ]);
      start();
    
    1. qiankun 提供了CSS和JS 的样式隔离方案,但single-spa 没有实现,需要自己去解决。

    • qiankun 的css 样式隔离方案

    qiankun 提供了基于shadowDOM实现的样式隔离以及使用postcss 的方式的样式隔离

    • qiankun 的JS隔离方案

    基于ES6的proxy,基于原始window伪造了一个新的window对象,同时借助Proxy对象定义了该伪造window的基本操作的行为,包括:set、get等等。

  • qiankun 的JS隔离方案

    • iframe 方案
    • qiankun 中三类沙箱
      • LegacySandbox:单实例代理沙箱,简单来讲就是只存在一个window实例,所有的操作都是对这一个实例的操作。(使用了Proxy的方式来代理window 对象)
      • ProxySandbox:多实例代理沙箱,通过对window的拷贝建立多个副本,在沙箱中对建立的副本进行操作.(使用proxy 的方式来代理window 的拷贝对象)
      • SnapshotSandbox:快照沙箱,基于 diff 方式实现的沙箱,用于不支持 Proxy 的低版本浏览器。(基于快照的方式)
  • qiankun 方案的一些缺点

    • 父子应用存在样式污染。父应用的样式,也会在子应用生效,子应用也可以在父应用生效。

    • 运行时越界, 假如使用qiankun 中的CSS隔离的方法,使用{ sandbox : { strictStyleIsolation: true } },或者 添加experimentalStyleIsolation: true属性。例如 body 构建 DOM 的场景(弹窗、抽屉、popover 等这种插入到主应用body 的dom 元素),必定会导致构建出来的 DOM 无法应用子应用的样式的情况,目前框架会开放API去改挂载的节点或者挂载的类名。

  • 无界的方案

使用iframe + Web Components 的方式来实现

JS 运行在iframe中, DOM结构使用shadowDOM的方式,运行在主应用中