基于qiankun的微前端最佳實(shí)踐-通信篇(Vuex)

大家好~~

在開始介紹 qiankun 的應(yīng)用通信之前,我們需要先了解微前端架構(gòu)如何劃分子應(yīng)用。

在微前端架構(gòu)中,我們應(yīng)該按業(yè)務(wù)劃分出對(duì)應(yīng)的子應(yīng)用,而不是通過功能模塊劃分子應(yīng)用。這么做的原因有兩個(gè):

  1. 在微前端架構(gòu)中,子應(yīng)用并不是一個(gè)模塊,而是一個(gè)獨(dú)立的應(yīng)用,我們將子應(yīng)用按業(yè)務(wù)劃分可以擁有更好的可維護(hù)性和解耦性。
  2. 子應(yīng)用應(yīng)該具備獨(dú)立運(yùn)行的能力,應(yīng)用間頻繁的通信會(huì)增加應(yīng)用的復(fù)雜度和耦合度。

綜上所述,我們應(yīng)該從業(yè)務(wù)的角度出發(fā)劃分各個(gè)子應(yīng)用,盡可能減少應(yīng)用間的通信,從而簡(jiǎn)化整個(gè)應(yīng)用,使得我們的微前端架構(gòu)可以更加靈活可控。

上面的這段話是引自這篇好文,這篇文章中主要介紹了兩種主應(yīng)用和微應(yīng)用的通信方式

第一種是 qiankun 官方提供的通信方式 - Actions 通信,適合業(yè)務(wù)劃分清晰,比較簡(jiǎn)單的微前端應(yīng)用,一般來說使用第一種方案就可以滿足大部分的應(yīng)用場(chǎng)景需求。

第二種是基于 redux 實(shí)現(xiàn)的通信方式 - Shared 通信,適合需要跟蹤通信狀態(tài),子應(yīng)用具備獨(dú)立運(yùn)行能力,較為復(fù)雜的微前端應(yīng)用。

我寫這篇博客的主要原因是探究主應(yīng)用和多個(gè)微應(yīng)用之間如何使用Vuex來進(jìn)行狀態(tài)管理,這其實(shí)是對(duì)于上面通信方式中,第二種方式的補(bǔ)充。

場(chǎng)景

項(xiàng)目現(xiàn)狀:

  1. 主應(yīng)用是Vue技術(shù)棧,使用Vuex進(jìn)行狀態(tài)管理
  2. 多個(gè)微應(yīng)用也是Vue技術(shù)棧,并且都可能使用Vuex進(jìn)行狀態(tài)管理

想要解決的問題:

  1. 主應(yīng)用與微應(yīng)用的通信
  2. 微應(yīng)用之間的通信

通信方式的選擇:

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

    優(yōu)點(diǎn):

    • 使用簡(jiǎn)單;
    • 官方支持性高;
    • 適合通信較少的業(yè)務(wù)場(chǎng)景;

    缺點(diǎn):

    • 子應(yīng)用獨(dú)立運(yùn)行時(shí),需要額外配置無 Actions 時(shí)的邏輯;
    • 子應(yīng)用需要先了解狀態(tài)池的細(xì)節(jié),再進(jìn)行通信;
    • 由于狀態(tài)池?zé)o法跟蹤,通信場(chǎng)景較多時(shí),容易出現(xiàn)狀態(tài)混亂、維護(hù)困難等問題;
  2. 使用Vuex進(jìn)行狀態(tài)管理

    優(yōu)點(diǎn):

    • 子應(yīng)用無法隨意污染主應(yīng)用的狀態(tài)池,只能通過主應(yīng)用暴露的 shared 實(shí)例的特定方法操作狀態(tài)池,從而避免狀態(tài)池污染產(chǎn)生的問題。
    • 子應(yīng)用將具備獨(dú)立運(yùn)行的能力

    缺點(diǎn):

    暫時(shí)沒有想到。。。。

核心思想

Vuex通信Store共享.jpg

主要就是在做微前端集成時(shí),將主應(yīng)用的store共享給所有微應(yīng)用,針對(duì)不同微應(yīng)用可以進(jìn)行模塊化設(shè)置,這樣使得共享的state更加易于管理。

具體實(shí)現(xiàn)(微應(yīng)用原本就沒有使用Vuex進(jìn)行狀態(tài)管理)

step1:主應(yīng)用向微應(yīng)用傳遞store實(shí)例。

registerMicroApps(
      [
          {
              name: "chai-project",
              entry: "http://localhost:8080",
              container: '#yourContainer',
              activeRule: "/chaiQiankunTest/ffff",
              props: {
                store //共享主應(yīng)用的store實(shí)例
              }
          }
      ],
      {
          beforeLoad: [
              app => {
                  console.log("before load", app);
              }
          ], // 掛載前回調(diào)
          beforeMount: [
              app => {
                  console.log("before mount", app);
              }
          ], // 掛載后回調(diào)
          afterUnmount: [
              app => {
                  console.log("after unload", app);
              }
          ] // 卸載后回調(diào)
      }
    )

step2:微應(yīng)用使用主應(yīng)用共享的store實(shí)例

針對(duì)第一種情況,就是在入口文件中引入vuex,并使用該插件,進(jìn)而在創(chuàng)建vue實(shí)例的時(shí)候,傳入主應(yīng)用共享的store實(shí)例。

import Vuex from 'vuex'
Vue.use(Vuex);
function render (props) {
  const store = props.store;
  // 在 render 中創(chuàng)建 VueRouter,可以保證在卸載微應(yīng)用時(shí),移除 location 事件監(jiān)聽,防止事件污染
  router = new Router({
    // 運(yùn)行在主應(yīng)用中時(shí),添加路由命名空間 /chaiQiankunTest/ffff
    base: window.__POWERED_BY_QIANKUN__ ? 'chaiQiankunTest/ffff' : '/',
    mode: 'history',
    routes
  });

  // 掛載應(yīng)用
  instance = new Vue({
    router,
    store,//主應(yīng)用共享的store實(shí)例
    render: (h) => h(App)
  }).$mount('#app');
}

step3:驗(yàn)證主應(yīng)用和微應(yīng)用之間是否可以完成通信,狀態(tài)同步。

驗(yàn)證的思路就是

(1)在主應(yīng)用和微應(yīng)用的頁面上添加改變同一個(gè)state的方法,并且利用computed實(shí)時(shí)顯示該state的狀態(tài)值。

(具體的實(shí)現(xiàn)代碼這里就不詳細(xì)給出)

驗(yàn)證用例主要是

(1)點(diǎn)擊主應(yīng)用按鈕,修改state值之后,主應(yīng)用和微應(yīng)用的頁面上都實(shí)時(shí)觸發(fā)computed屬性,展示最新狀態(tài)值

(2)點(diǎn)擊微應(yīng)用按鈕,修改state值之后,主應(yīng)用和微應(yīng)用的頁面上都實(shí)時(shí)觸發(fā)computed屬性,展示最新狀態(tài)值

驗(yàn)證的結(jié)果

不論是點(diǎn)擊主應(yīng)用的按鈕,還是點(diǎn)擊微應(yīng)用的按鈕,主應(yīng)用的computed屬性成功被觸發(fā),微應(yīng)用始終未能正常監(jiān)聽到狀態(tài)值得改變,computed屬性從未被觸發(fā)。

這里查閱了蠻多的資料,沒能看到有大神對(duì)qiankun使用Vuex的經(jīng)驗(yàn)總結(jié)(這里也發(fā)現(xiàn)自己有點(diǎn)過于依賴網(wǎng)絡(luò)搬磚,有些問題積極思考是能夠找到答案的)

step4:bug修復(fù)

微應(yīng)用的computed始終沒有被觸發(fā),底層原因就是其依賴屬性this.$store.state.count是非相應(yīng)式的,這會(huì)導(dǎo)致難以觸發(fā)。

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

Vuex正常使用的時(shí)候,所有的狀態(tài)值都是響應(yīng)式的,可以直接用于Vue頁面之中,但是這里是非響應(yīng)式的,導(dǎo)致這個(gè)的原因其實(shí)十分簡(jiǎn)單。這里的store實(shí)例是由主應(yīng)用傳遞過來的,store中的狀態(tài)對(duì)于主應(yīng)用的Vue實(shí)例而言是親兒子,是響應(yīng)式的,在微應(yīng)用中,雖然可以使用共享store實(shí)例中的commit方法,但是對(duì)于微應(yīng)用的Vue實(shí)例而言,不是親兒子,是非響應(yīng)式的,這樣分析之后,解決方案就十分明確:

在微應(yīng)用中將共享的store實(shí)例進(jìn)行響應(yīng)式設(shè)置,這是Vue現(xiàn)有的API方法Vue.observable(store)

如此處理之后,不論主應(yīng)用還是微應(yīng)用中,修改共享storestate狀態(tài)值,在主應(yīng)用和微應(yīng)用中都能夠?qū)崟r(shí)感知,并對(duì)其做出響應(yīng)的反饋。

具體實(shí)現(xiàn)(微應(yīng)用本身就有自己store實(shí)例)

這種情況主要考慮的是兩種方案

  1. 主應(yīng)用需要提前得知子應(yīng)用的store內(nèi)容,將其與主應(yīng)用的store進(jìn)行某種融合,這樣子應(yīng)用在集成環(huán)境中以及在獨(dú)立運(yùn)行時(shí)都能夠正常運(yùn)行。

    缺點(diǎn):這方方案會(huì)導(dǎo)致主應(yīng)用和子應(yīng)用相互耦合過強(qiáng),并且主應(yīng)用和子應(yīng)用都要維護(hù)一份子應(yīng)用的store,增加工作量,過于笨重。

  2. 主應(yīng)用依舊只傳遞主應(yīng)用的store,子應(yīng)用的store依舊在使用,也就是在子應(yīng)用中既可以操作主應(yīng)用的store,也可以操作子應(yīng)用的store。

    優(yōu)點(diǎn):主應(yīng)用只需關(guān)注需要交互的狀態(tài)即可,不用關(guān)心子應(yīng)用原本的store內(nèi)容。子應(yīng)用也只需關(guān)注自己的store內(nèi)容即可,降低耦合,減輕復(fù)雜度。

父子應(yīng)用store分離的方案實(shí)現(xiàn)

這里基于父應(yīng)用已經(jīng)共享自己的store,并且主應(yīng)用和子應(yīng)用之間已經(jīng)能夠完成對(duì)于主應(yīng)用的state狀態(tài)變化的響應(yīng)??紤]如何在子應(yīng)用中使用兩個(gè)store,new Vue()中目前注入的是主應(yīng)用的store,那子應(yīng)用本身的store如何全局注冊(cè)呢?仔細(xì)思考后,其實(shí)很簡(jiǎn)單,只需要在入口文件中添加如下一行代碼:

Vue.prototype.microStore = microStore;

如此一來,在子應(yīng)用的各個(gè)頁面都能夠通過this.microStore訪問自身的store。

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

總結(jié)

到此,關(guān)于在qiankun的集成中,主應(yīng)用和子應(yīng)用使用Vuex進(jìn)行通信的基本使用方法介紹結(jié)束了,缺少了子應(yīng)用和子應(yīng)用之間的一個(gè)實(shí)驗(yàn),大家有興趣可以試試。

參考

  1. 基于 qiankun 的微前端最佳實(shí)踐(圖文并茂) - 應(yīng)用間通信篇
  2. 目標(biāo)是最完善的微前端解決方案 - qiankun 2.0
  3. qiankun官網(wǎng)API指導(dǎo)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容