美文网首页
基于qiankun的微前端最佳实践-通信篇(Vuex)

基于qiankun的微前端最佳实践-通信篇(Vuex)

作者: 彩云Coding | 来源:发表于2020-08-04 17:35 被阅读0次

    大家好~~

    在开始介绍 qiankun 的应用通信之前,我们需要先了解微前端架构如何划分子应用。

    在微前端架构中,我们应该按业务划分出对应的子应用,而不是通过功能模块划分子应用。这么做的原因有两个:

    1. 在微前端架构中,子应用并不是一个模块,而是一个独立的应用,我们将子应用按业务划分可以拥有更好的可维护性和解耦性。
    2. 子应用应该具备独立运行的能力,应用间频繁的通信会增加应用的复杂度和耦合度。

    综上所述,我们应该从业务的角度出发划分各个子应用,尽可能减少应用间的通信,从而简化整个应用,使得我们的微前端架构可以更加灵活可控。

    上面的这段话是引自这篇好文,这篇文章中主要介绍了两种主应用和微应用的通信方式

    第一种是 qiankun 官方提供的通信方式 - Actions 通信,适合业务划分清晰,比较简单的微前端应用,一般来说使用第一种方案就可以满足大部分的应用场景需求。

    第二种是基于 redux 实现的通信方式 - Shared 通信,适合需要跟踪通信状态,子应用具备独立运行能力,较为复杂的微前端应用。

    我写这篇博客的主要原因是探究主应用和多个微应用之间如何使用Vuex来进行状态管理,这其实是对于上面通信方式中,第二种方式的补充。

    场景

    项目现状:

    1. 主应用是Vue技术栈,使用Vuex进行状态管理
    2. 多个微应用也是Vue技术栈,并且都可能使用Vuex进行状态管理

    想要解决的问题:

    1. 主应用与微应用的通信
    2. 微应用之间的通信

    通信方式的选择:

    1. qiankun 官方提供的通信方式 - Actions 通信。

      优点:

      • 使用简单;
      • 官方支持性高;
      • 适合通信较少的业务场景;

      缺点:

      • 子应用独立运行时,需要额外配置无 Actions 时的逻辑;
      • 子应用需要先了解状态池的细节,再进行通信;
      • 由于状态池无法跟踪,通信场景较多时,容易出现状态混乱、维护困难等问题;
    2. 使用Vuex进行状态管理

      优点:

      • 子应用无法随意污染主应用的状态池,只能通过主应用暴露的 shared 实例的特定方法操作状态池,从而避免状态池污染产生的问题。
      • 子应用将具备独立运行的能力

      缺点:

      暂时没有想到。。。。

    核心思想

    Vuex通信Store共享.jpg

    主要就是在做微前端集成时,将主应用的store共享给所有微应用,针对不同微应用可以进行模块化设置,这样使得共享的state更加易于管理。

    具体实现(微应用原本就没有使用Vuex进行状态管理)

    step1:主应用向微应用传递store实例。

    registerMicroApps(
          [
              {
                  name: "chai-project",
                  entry: "//localhost:8080",
                  container: '#yourContainer',
                  activeRule: "/chaiQiankunTest/ffff",
                  props: {
                    store //共享主应用的store实例
                  }
              }
          ],
          {
              beforeLoad: [
                  app => {
                      console.log("before load", app);
                  }
              ], // 挂载前回调
              beforeMount: [
                  app => {
                      console.log("before mount", app);
                  }
              ], // 挂载后回调
              afterUnmount: [
                  app => {
                      console.log("after unload", app);
                  }
              ] // 卸载后回调
          }
        )
    

    step2:微应用使用主应用共享的store实例

    针对第一种情况,就是在入口文件中引入vuex,并使用该插件,进而在创建vue实例的时候,传入主应用共享的store实例。

    import Vuex from 'vuex'
    Vue.use(Vuex);
    function render (props) {
      const store = props.store;
      // 在 render 中创建 VueRouter,可以保证在卸载微应用时,移除 location 事件监听,防止事件污染
      router = new Router({
        // 运行在主应用中时,添加路由命名空间 /chaiQiankunTest/ffff
        base: window.__POWERED_BY_QIANKUN__ ? 'chaiQiankunTest/ffff' : '/',
        mode: 'history',
        routes
      });
    
      // 挂载应用
      instance = new Vue({
        router,
        store,//主应用共享的store实例
        render: (h) => h(App)
      }).$mount('#app');
    }
    

    step3:验证主应用和微应用之间是否可以完成通信,状态同步。

    验证的思路就是

    (1)在主应用和微应用的页面上添加改变同一个state的方法,并且利用computed实时显示该state的状态值。

    (具体的实现代码这里就不详细给出)

    验证用例主要是

    (1)点击主应用按钮,修改state值之后,主应用和微应用的页面上都实时触发computed属性,展示最新状态值

    (2)点击微应用按钮,修改state值之后,主应用和微应用的页面上都实时触发computed属性,展示最新状态值

    验证的结果

    不论是点击主应用的按钮,还是点击微应用的按钮,主应用的computed属性成功被触发,微应用始终未能正常监听到状态值得改变,computed属性从未被触发。

    这里查阅了蛮多的资料,没能看到有大神对qiankun使用Vuex的经验总结(这里也发现自己有点过于依赖网络搬砖,有些问题积极思考是能够找到答案的)

    step4:bug修复

    微应用的computed始终没有被触发,底层原因就是其依赖属性this.$store.state.count是非相应式的,这会导致难以触发。

    computed: {
        childCount: {
          get (){
            return this.$store.state.count;
          }
        }
    }
    

    Vuex正常使用的时候,所有的状态值都是响应式的,可以直接用于Vue页面之中,但是这里是非响应式的,导致这个的原因其实十分简单。这里的store实例是由主应用传递过来的,store中的状态对于主应用的Vue实例而言是亲儿子,是响应式的,在微应用中,虽然可以使用共享store实例中的commit方法,但是对于微应用的Vue实例而言,不是亲儿子,是非响应式的,这样分析之后,解决方案就十分明确:

    在微应用中将共享的store实例进行响应式设置,这是Vue现有的API方法Vue.observable(store)

    如此处理之后,不论主应用还是微应用中,修改共享storestate状态值,在主应用和微应用中都能够实时感知,并对其做出响应的反馈。

    具体实现(微应用本身就有自己store实例)

    这种情况主要考虑的是两种方案

    1. 主应用需要提前得知子应用的store内容,将其与主应用的store进行某种融合,这样子应用在集成环境中以及在独立运行时都能够正常运行。

      缺点:这方方案会导致主应用和子应用相互耦合过强,并且主应用和子应用都要维护一份子应用的store,增加工作量,过于笨重。

    2. 主应用依旧只传递主应用的store,子应用的store依旧在使用,也就是在子应用中既可以操作主应用的store,也可以操作子应用的store

      优点:主应用只需关注需要交互的状态即可,不用关心子应用原本的store内容。子应用也只需关注自己的store内容即可,降低耦合,减轻复杂度。

    父子应用store分离的方案实现

    这里基于父应用已经共享自己的store,并且主应用和子应用之间已经能够完成对于主应用的state状态变化的响应。考虑如何在子应用中使用两个storenew Vue()中目前注入的是主应用的store,那子应用本身的store如何全局注册呢?仔细思考后,其实很简单,只需要在入口文件中添加如下一行代码:

    Vue.prototype.microStore = microStore;
    

    如此一来,在子应用的各个页面都能够通过this.microStore访问自身的store

    computed: {
        microCount: {
            get (){
                return this.microStore.state.microCount;
            }
        }
    }
    

    总结

    到此,关于在qiankun的集成中,主应用和子应用使用Vuex进行通信的基本使用方法介绍结束了,缺少了子应用和子应用之间的一个实验,大家有兴趣可以试试。

    参考

    1. 基于 qiankun 的微前端最佳实践(图文并茂) - 应用间通信篇
    2. 目标是最完善的微前端解决方案 - qiankun 2.0
    3. qiankun官网API指导

    相关文章

      网友评论

          本文标题:基于qiankun的微前端最佳实践-通信篇(Vuex)

          本文链接:https://www.haomeiwen.com/subject/jsywrktx.html