qiankun 入门

289 阅读6分钟

介绍

qiankun 是基于 single-spa 做了二次封装的微前端框架,通过解决了 single-spa 的一些弊端和不足,来帮助大家实现更简单、无痛的构建一个生产可用的微前端架构系统。

为什么不使用 single-spa 呢?

single-spa 就做了两件事,加载微应用(加载方法还是用户自己提供的)、维护微应用状态(初始化、挂载、卸载)。了解多了会发现 single-spa 虽好,但是却存在一些比较严重的问题

  1. 对微应用的侵入性太强 single-spa 采用 JS Entry 的方式接入微应用。微应用改造一般分为三步:
  • 微应用路由改造,添加一个特定的前缀
  • 微应用入口改造,挂载点变更和生命周期函数导出
  • 打包工具配置更改 侵入性强其实说的就是第三点,具体操作过程如下:
    1. 使用 single-spa 接入微应用需要将微应用整个打包成一个 JS 文件,发布到静态资源服务器。
    1. 在主应用中配置该 JS 文件的地址告诉 single-spa 去这个地址加载微应用。 会产生什么问题呢?
    1. 就这第三点的改动就存在很大的问题了,将整个微应用打包成一个 JS 文件,常见的打包优化基本上都没了,比如:按需加载、首屏资源加载优化、css 独立打包等优化措施。
    1. 项目发布以后出现了 bug ,修复之后需要更新上线,为了清除浏览器缓存带来的影响,一般文件名会带上 chunkcontent,微应用发布之后文件名都会发生变化,这时候还需要更新主应用中微应用配置,然后重新编译主应用然后发布,这套操作过程比较繁琐,相当消耗时间。
  1. 样式隔离问题 single-spa 没有做这部分的工作。一个大型的系统会有很的微应用组成,怎么保证这些微应用之间的样式互不影响?
    这时只能通过约定命名规范来实现,比如应用样式以自己的应用名称开头,以应用名构造一个独立的命名空间,这个方式新系统还好说,如果是一个已有的系统,这个改造工作量可不小。

  2. JS 隔离 这部分工作 single-spa 也没有做。 JS 全局对象污染是一个很常见的现象,比如:微应用 A 在全局对象上添加了一个自己特有的属性,window.A,这时候切换到微应用 B,这时候如何保证 window 对象是干净的呢?

  3. 资源预加载 这部分的工作 single-spa 更没做了,毕竟将微应用整个打包成一个 js 文件。 现在有个需求,比如为了提高系统的用户体验,在第一个微应用挂载完成后,需要让浏览器在后台悄悄的加载其它微应用的静态资源,这个怎么实现呢?

  4. 应用间通信 这部分工作 single-spa 没做,它只在注册微应用时给微应用注入一些状态信息,后续就不管了,没有任何通信的手段,只能用户自己去实现

  5. 如何解决以上问题呢? 以上 5 个问题中第 2、3、5 还好说,可以通过一些方式来解决。 比如2采用命名空间的方式解决样式隔离问题,3通过备份全局对象,每次微应用切换时初始化全局对象的方式来解决 JS 隔离的问题。5通信问题可以通过传递一些通信方法,这点依赖了 JS 对象本身的特性(传递的是引用)来实现;
    但是第一个和第四个就不好解决了,这是 JS Entry 方式带来的问题,要解决这个问题,难度相对就会大很多,工作量也会更大。况且这些通用的脏活累活就不应该由用户来解决,而是由框架来解决。

为什么使用qiankun?

qiankun 基于 single-spa 做了二次封装,很好的解决了上面提到的第一个和第四个问题。把这些通用的脏活累活交给qiankun框架去做。

  1. HTML Entry

    qiankun 通过 HTML Entry 的方式来解决 JS Entry 带来的问题,让你接入微应用像使用 iframe 一样简单。

  2. 样式隔离

    qiankun 实现了两种样式隔离

    • 严格的样式隔离模式,为每个微应用的容器包裹上一个 shadow dom 节点,从而确保微应用的样式不会对全局造成影响
    • 实验性的方式,通过动态改写 css 选择器来实现,可以理解为 css scoped 的方式
  3. 运行时沙箱

    qiankun 的运行时沙箱分为 JS 沙箱和 样式沙箱

    JS 沙箱 为每个微应用生成单独的 window proxy 对象,配合 HTML Entry 提供的 JS 脚本执行器 (execScripts) 来实现 JS 隔离;

    样式沙箱 通过重写 DOM 操作方法,来劫持动态样式和 JS 脚本的添加,让样式和脚本添加到正确的地方,即主应用的插入到主应用模版内,微应用的插入到微应用模版,并且为劫持的动态样式做了 scoped css 的处理。

  4. 资源预加载

    qiankun 实现预加载的思路有两种,一种是当主应用执行 start 方法启动 qiankun 以后立即去预加载微应用的静态资源,另一种是在第一个微应用挂载以后预加载其它微应用的静态资源,这个是利用 single-spa 提供的 single-spa:first-mount 事件来实现的。

  5. 应用间通信

    qiankun 通过发布订阅模式来实现应用间通信,状态由框架来统一维护,每个应用在初始化时由框架生成一套通信方法,应用通过这些方法来更改全局状态和注册回调函数,全局状态发生改变时触发各个应用注册的回调函数执行,将新旧状态传递到所有应用。

架构

e960badc279544f4993c7eae209cdca1_tplv-k3u1fbpfcp-watermark.png

起步

主应用使用create-react-app创建react项目:

npx create-react-app bigass-micro-app

然后安装micro-app组件:

npm i @micro-zoe/micro-app --save

创建完了后,先用 React Router 来搭建基座应用的路由系统:

const App = () => {
  return (
    <BrowserRouter>
      <div>
        <header className={styles.header}>
          <Link to="/">基座 Home</Link>
          <Link to="/about">基座 About</Link>
        </header>

        <Routes>
          <Route path="/" element={<Home/>}/>
          <Route path="/about" element={<About/>}/>
        </Routes>
      </div>
    </BrowserRouter>
  );
}