2

微前端microApp实践

微前端的概念是由ThoughtWorks在2016年提出的,它借鉴了微服务的架构理念,核心在于将一个庞大的前端应用拆分成多个独立灵活的小型应用,每个应用都可以独立开发、独立运行、独立部署,再将这些小型应用融合为一个完整的应用,或者将原本运行已久、没有关联的几个应用融合为一个应用。微前端既可以将多个项目融合为一,又可以减少项目之间的耦合,提升项目扩展性,相比一整块的前端仓库,微前端架构下的前端仓库倾向于更小更灵活。

项目改造背景

因项目需要要做一个大数据融合平台,主要功能模块包括用户管理、流程管理、大数据治理算子应用,基础组件等混合构成的融合平台;公司目前已经存在用户管理、流程管理等成品;基本主内容也是和这些产品的功能一致,主框架只是控制着导航和头部信息;因此希望能够抱着复用的方式,更快的进行融合接入。

前端流行的微服务框架比对

参数singlespaqiankumicroapp
开发成本开发成本高开发成本中开发成本高
维护成本
技术栈不限技术栈不限技术栈不限技术栈
实现难易实现难实现中实现简单
原理监听 url change 事件监听 url change 事件WebComponent

经过对比,目前觉得micro-app使用简单,将所有功能都封装到一个类WebComponent组件中,从而实现在基座应用中嵌入一行代码即可渲染一个微前端应用。同时micro-app还提供了js沙箱、样式隔离、元素隔离、预加载、数据通信、静态资源补全等一系列完善的功能。子应用基本不需要过多的进行项目改造,相对使用成本更低

对接说明

  • 主框架依赖包引入
import microApp from '@micro-zoe/micro-app'
  • 主应用启动(并可以进行全局配置)
microApp.start({
  plugins: {
    global: [{
      loader(code, url, options) { // 必填
        console.log('全局插件')
        return code
      }
    }],
    }
  }
})

//相关参数
microApp.start({
inline: true, // 默认值false
destroy: true, // 默认值false
disableScopecss: true, // 默认值false
disableSandbox: true, // 默认值false
shadowDOM: true, // 默认值false
ssr: true, // 默认值false
})

  • 配置组件节点
      <micro-app
      style="height: 100%;"
        name='appnameUserCenter'
        :url='url'
        :data='microAppData'
        @created='handleCreate'
        @beforemount='handleBeforeMount'
        @mounted='handleMount'
        @unmount='handleUnmount'
        @error='handleError'
        @datachange='handleDataChange'
      ></micro-app>

生命周期列表

  1. created
    <micro-app>标签初始化后,加载资源前触发。
  2. beforemount
    加载资源完成后,开始渲染之前触发。
  3. mounted
    子应用渲染结束后触发。
  4. unmount
    子应用卸载时触发。
  5. error
    子应用渲染出错时触发,只有会导致渲染终止的错误才会触发此生命周期。
  • 路由匹配设置(模糊匹配,建议主应用history,微应用hash模式,)
  {
    path: '/mainPanel',
    name: 'mainPanel',
    component: mainPanel,
    children:[
      {
        path: '/mainPanel/dataCenter*',
        name: 'dataCenter',
        component:()=>dataCenter
      },
      {
        path: '/mainPanel/userCenter*',
        name: 'userCenter',
        component:()=>userCenter
      },
    ]
  }
  • 主微框架通讯
 microMenu(appName, path, hash) {

            if (!getActiveApps().includes(appName)) {
   
                path = '/mainPanel' + path+'/'
                    // child-vite 和 child-react17子应用为hash路由,这里拼接一下hash值
                    hash && (path += `/#${hash}`)
                    // 主应用跳转
                    this.$router.push(path)
                } else {
           
                    let childPath = null
                    // child-vite 和 child-react17子应用是hash路由,hash值就是它的页面地址,这里单独处理
                    if (hash) {
                    childPath = hash
                    } else {
                    // path的值形式如:/app-vue2/page2,这里/app-vue2是子应用的基础路由,/page2才是页面地址,所以我们需要将/app-vue2部分删除
                    childPath = path.replace(/^\/app-[^/]+/, '')
                    !childPath && (childPath = '/') // 防止地址为空
                    }
                    // 主应用通过下发data数据控制子应用跳转
                    microApp.setData(appName, { path: childPath })
                }
        }
  • 微框架及其路由跳转

(function () {
  let app = null;
  //创建vue实例
  const createVue = function () {
    app = new Vue({
      el: "#app",
      router,
      store,
      render: (h) => h(App),
    });
  };
  // 与基座进行数据交互
  const handleMicroData = function (callBack) {
    window.microApp.addDataListener((data) => {
      callBack(data);
    });
  };

  // 微前端环境下,注册mount和unmount方法
  if (window.__MICRO_APP_ENVIRONMENT__) {
    let {token} = window.microApp.getData();
    token && setToken(token);
    console.log("data-center token:", token);
    window[`micro-app-${window.__MICRO_APP_NAME__}`] = {
      //微前端挂载
      mount: () => {
        createVue();
        handleMicroData((data) => {
          //交互操作
          store.dispatch("settings/changeSetting", {
            key: "microFlag",
            value: true,
          });
          console.log("data-center addDataListener:", data);
          router.push(data.path);
        });
      },
      //微前端卸载
      unmount: () => {
        app.$destroy();
        app.$el.innerHTML = "";
        app = null;
        console.log("微应用child-vue2卸载了");
      },
    };
  } else {
    // 非微前端环境直接渲染
    createVue();
  }
})();

西安小哥
1.3k 声望88 粉丝

thinking、doing、do better、do much better than today。exchange 、sharing、improve as quickly as possible。