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

大家好~~

在开始介绍 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))