前端开发那些事儿

微前端qiankun实践

2020-11-30  本文已影响0人  lean_

什么是微前端

微前端不是一个新的技术名词,在2016年就有相关的技术概念,当时微前端实践均为iframe内嵌的方式来实现.

什么样的场景适合微前端架构

iframe? no!

利用iframe来进行微前端技术实践,固然是可行,但是有非常大的维护难度!

这里有一篇文章介绍了为什么不用iframe来做技术解决方案.

首先,利用iframe加载多个子应用的时候,会阻断主应用的onload渲染,导致主应用界面卡顿,降低用户体验.

其次,在iframe架构中,子应用和子应用之间,子应用和主应用之间的数据交互解决方案一般是通过postMessage来实现,维护难度较大.

再次,iframe架构中,UI不同步,比如子应用中的模态框,就不能做到真正的全屏弹窗,如果通过postMessage让主应用来弹窗的话,虽然可以做到全屏弹框,但是往往模态框内还有其他回调操作,处理这些回调操作又需要把数据利用postMessage传回子应用,这样的话就不能适应灵活的场景和需求.

综合以上因素,我觉得iframe不适合现有的微前端技术架构.

qiankun概念及特点介绍

qiankun是一个基于single-spa的微前端实现库,由蚂蚁金服开发并维护,目前qiankun在蚂蚁金服内部服务了超过 200+ 线上应用,有一定的稳定性.
qiankun的特点:

qiankun实例

在github上的demo地址

code.png

子应用端:

  1. 目前基于react web端的脚手架已支持直接作为子应用开发,可以做到开箱即用;

  2. 非react web端的项目需要做如下改动:

    • 在项目的入口文件处,也就是webpack的入口文件,增加并暴露出三个生命周期函数:
    
      import ReactDOM from 'react-dom';
      import App from 'provider';
      
          function render(props = {}) {
              const DOM = document.getElementById("microAppContainer3000");
              ReactDOM.render(<App {...props} />, DOM);
          }
    
      //作为独立应用,也可以渲染,作为独立应用时,不再调用其他生命周期函数
      if (!window.__POWERED_BY_QIANKUN__) {
        render();
      }
    
      //主应用在引导该应用注入的时候调用该函数
      export async function bootstrap() {
        render(props);
      }
    
      //主应用在挂载当前子应用的时候调用该函数,并注册全局状态change事件
      export async function mount(props) {
        props.onGlobalStateChange((state) => {
          render(props);
        });
        render(props);
      }
    
      //主应用在卸载当前子应用的时候的函数调用
      export async function unmount() {
          const DOM = document.getElementById("microAppContainer3000");
          ReactDOM.unmountComponentAtNode(DOM);
      }
    
    
  1. 子应用需要注意的事项

主应用端:

  1. 主应用需要维护的是当前状态下的子应用列表,并且在子应用需要时提供可靠的全局数据.
  2. qiankun支持两种在主应用中注册子应用的方式,
    • 调用loadMicroApp(app,config?)方法来启动子应用,这种方式不能监听子应用路由方式,适合调试模式以及子应用页面较为单一简单的情况下使用.
    • 调用registerMicroApps(apps)方法来注册子应用,通过将微应用关联到一些 url 规则的方式,实现当浏览器 url 发生变化时,自动加载相应的微应用的功能.适用于 route-based 场景.适合当前的开发模式.
     //主应用的入口文件
     import { registerMicroApps, start } from "qiankun";
    
    
     //创建全局标识,由于子应用共享全局window对象,所以子应用判断是否运行在qiankun环境下由此配置
     window.__POWERED_BY_QIANKUN__ = true;
    
     //实际开发中,子应用注册列表可以通过后端动态返回,从而做到权限动态控制
     registerMicroApps([
       {
         name: "react app 3000",
         entry: "//localhost:3000",
         container: "#microContainer3000",
         activeRule: (location) =>  location.hash.indexOf("micro/3000") > -1,
         props: {
           baseHash: "/micro/3000",
         },
       },
       {
         name: "react app 4000",
         entry: "//localhost:4000",
         container: "#microContainer4000",
         activeRule: (location) => location.hash.indexOf("micro/4000") > -1,
         props: {
           baseHash: "/micro/4000",
         },
       },
     ]);
    
    

举例说明

现在有A平台,部署地址为:http://www.a.com, 其html结构如下:

  <html>
    <body>
        <div>A平台</div>
        <div id="content"></div>
    </body>
  <html>

有B应用,部署地址为:http://www.b.com, 其html结构如下:

  <html>
    <body>
        <div id="app-root">B应用</div>
    </body>
  <html>

按照常规iframe集成方法将B应用集成到A平台内,A平台的最终产出的html节点:

  <html>
    <body>
        <div>A平台</div>
        <div id="content">
            <iframe src="http://www.b.com">
        </div>
    </body>
  <html>

按照qiankun的集成方法将B应用集成到A平台内的:A平台的最终产出的html节点:

  <html>
    <body>
        <div>A平台</div>
        <div id="content">
          <div id="qiankun-microapp-warpper">
            <div id="app-root">
              B应用
            </div>
          </div>
        </div>
    </body>
  <html>

同时qiankun还可以兼容iframe:

  <html>
    <body>
        <div>A平台</div>
        <div id="content">
          <div id="qiankun-microapp-warpper">
            <div id="app-root">
              B应用
            </div>
          </div>
          <iframe src="www.baidu.com">
        </div>
    </body>
  <html>
上一篇 下一篇

猜你喜欢

热点阅读