微前端框架single-spa子應用加載解析
作者:京東物流 寧衝
1 前言
什麼是微前端?
微前端是指存在於瀏覽器中的微服務。
本文主要通過對微前端框架single-spa的基座應用加載子應用的single-spa-vue函數庫進行分析,通過代碼維度分析讓大家瞭解在single-spa加載子應用的時候都做了哪些事情。如何通過優化single-spa-vue函數庫保持子應用的狀態。
由於是在代碼維度進行分析,要求讀者對single-spa有一定的瞭解,閲讀效果會更好。
2 single-spa加載子應用的過程
基座應用中配置的加載子應用配置,在配置子應用對象的app方法中會把子應用chunk-vendors.js、app.js插入到頁面,並且執行chunk-vendors.js、app.js兩個子應用依賴的js。
app方法執行結束以後,子應用依賴的js插入頁面以後的dom結構。
由上面app方法的執行過程,我們可以看出基座應用加載子應用,和vue框架打包後加載js資源的方式類似。那麼為什麼只需要加載子應用的app.js和chunk-vendors.js就可以把子應用渲染到頁面上面。下面我們再來看看子應用的入口文件main.js方法中是如何進行配置的。
3 子應用的main.js中的配置
在子應用main.js中我們可以看到,把常規的配置1替換為配置2的格式。
在配置2中我們會把當前vue的配置傳給single-spa-vue函數庫中。包括el、render方法、Vue對象。通過singleSpaVue的包裝,返回single-spa生命週期方法bootstrap、mount、unmount。
- bootstrap:引導函數,應用內容首次掛載到頁面前調用,只會執行一次。
- mount:掛載函數,子應用每次被掛載的時候都會執行。
- unmount:卸載函數,子應用每次被卸載的時候都會執行。
也就是説基座應用在加載子應用的時候就是通過single-spa-vue函數的處理,生成了single-spa的各個生命週期,給基座應用在加載子應用的時候調用。
下面我們來看看single-spa-vue究竟是如何生成各種生命週期函數的。
4 single-spa-vue源碼結構
single-spa-vue函數庫可以幫助我們來生成加載子應用的生命週期。你可以通過下面鏈接:single-spa-vue GIT地址,下載single-spa-vue函數庫的源碼。
single-spa-vue的源碼非常簡單,只有幾個生成single-spa生命週期的函數。
- single-spa-vue方法:single-spa-vue函數庫對外提供服務的唯一一個方法,用來接收配置項,並且返回一個包含各個single-spa生命週期的對象。
- single-spa-vue中的其他方法bootstrap、mount、update、unmount是用來生成single-spa對應生命週期函數的方法。
下面我們詳細介紹一下這幾個方法的作用和實現。
5 single-spa-vue源碼解析
single-spa-vue中提供的singleSpaVue方法會接收userOpts配置信息,配置信息會和默認的配置項defaultOpts合併以後再進行進行後續處理。
5.1 配置項defaultOpts
對於默認的配置項會有下面這幾項,這裏只介紹一下必填項,appOptions、Vue/createApp。其中的template在並沒有在single-spa-vue中被用到,但是在single-spa-html中有使用到。
// 默認配置項列表
const defaultOpts = {
// required opts
appOptions: null,
template: null,
// sometimes require opts
Vue: null,
createApp: null,
handleInstance: null
}
1)appOptions配置項介紹
- appOptions:應用的配置項,會在初始化Vue實例的時候作為參數傳給Vue方法,下面具體介紹一下appOptions中的配置項。
- el:子應用需要掛載的基座dom,即vue需要掛載的dom。
- render/template:vue的render/template配置項。
- data:初始化的參數對象,會在執行掛載函數mount的時候直接掛載到vue實例上。
2)Vue/createApp配置項介紹
Vue/createApp配置項是用來生成vue實例的,single-spa-vue函數庫可以通過傳入的Vue對象在mount方法中來生成vue實例。也可以傳入createApp方法,由子應用在createApp方法中返回vue實例。
下面我們會在生命週期生成方法中看到這些配置項的作用
5.2 入口方法:singleSpaVue
singleSpaVue方法會對入參先進行下列有效性校驗,具體校驗的內容有一下四項。
- 配置項userOpts是否為對象。
- 用來創建vue實例的配置Vue/createApp是否存在。
- 用來生成vue實例的配置項appOptions是否存在。
- vue實例掛載的dom是否正確appOptions.el有效性校驗。
有效性校驗通過以後,會調用bootstrap、mount、unmount、update方法用來分別生成single-spa加載子應用的生命週期函數。
下面詳細介紹一下各個生命週期函數是如何生成的。
5.3 引導函數:bootstrap
引導函數bootstrap,當應用內容首次掛載到頁面前調用。
bootstrap函數,會先判斷一下是否在配置項中存在loadRootComponent。配置項loadRootComponent筆者理解是可以用來加載當前子應用依賴的父級應用或者其他的依賴資源。
比如A頁面依賴B組件,那在加載A頁面的時候可以loadRootComponent方法中把B組件的靜態資源加載下來,並且渲染到頁面上,A頁面就可以直接使用B組件中提供的一些資源或者dom。
如果未配置loadRootComponent,則直接返回,不做任何處理。
5.4 子應用掛載生命週期:mount
在子應用每次被掛載到頁面上的時候,single-spa會執行mount生命週期函數,single-spa-vue在mount函數中用來初始化子應用的vue實例,並且把實例掛載到頁面上。
mount函數會接收三個參數,分別是singleSpaVue傳入的參數opts,single-spa-vue當前全局掛載的子應用實例列表mountedInstances,在基座應用中註冊的當前子應用的single-spa實例props
props入參接收的數據,這裏只用到了props的name屬性,用來標識當前掛載的子應用。
在mount方法中主要做了以下幾件事
1)格式化應用配置項appOptions
mount方法中會通過resolveAppOptions方法來格式化應用的配置項appOptions。
在resolveAppOptions方法來中如果appOptions是一個方法的話,則執行方法,並且傳遞基座應用通過customProps參數傳入的參數props。
子應用可以在appOptions方法中獲取父應用傳遞的參數、根據父應用的狀態做不同的處理等。
2)初始化子應用需要掛載的DOM對象。
初始化dom的配置和方法比較多,會從很多個配置項中來獲取el,代碼比較簡單,這裏就不贅述了。只列出來取值的優先級供大家參考。
appOptions.el > props.domElement > props.name
dom節點被格式化完成以後,下面就開始把頁面掛載到dom上面。
3)創建vue示例,並且掛載到頁面上
在掛載頁面之前會有一個配置項:replaceMode,replaceMode配置項是用來標識是否需要替換el節點下的內容。默認replaceMode為false是會在el節點下面新建一個class為single-spa-container的空白div來保存子應用。
以demo中的代碼為例:
默認replaceMode為false的情況下,基座中的的內容和vue1中的內容會並存。如下圖:
如果把replaceMode改為true的情況下,會發現基座中的內容會被vue1中的內容覆蓋掉。
如下圖:
設置掛載方式以後,就開始把子應用真正掛載到dom上面。
這裏支持兩種掛載方式,一種是使用vue3的createApp方式掛載,一種是使用vue2的new Vue方式進行掛載。這裏的掛載方式其實和我們在使用vue掛載到dom方式的配置是一樣的。
通過上面的步驟,此時子應用就被掛載到了html的頁面中的dom上了。
5.5 更新生命週期函數:update
當調用parcel.update()會觸發update方法,筆者由於並沒有用的高級特性parcel,在此處不再做過多介紹。
5.6 子應用卸載生命週期:unmount
當頁面url發生變化的時候,離開子應用頁面路由的時候會觸發unmount方法。
在unmount方法中主要做的事情有:
- 卸載vue應用
- 刪除vue實例
- 同時清空頁面dom。
執行unmount操作以後子應用的數據和dom就會被清除乾淨。
5.7 小結
以上就是single-spa官方提供的single-spa-vue函數庫來掛載子應用的全部流程。通過上面的分析,我們發現single-spa-vue函數庫會通過調用singleSpaVue方法返回一個包含bootstrap、mount、update、unmount四個方法的對象。在基座應用加載子應用的生命週期會執行對應的方法,通過執行方法把子應用掛載到基座應用或者從基座應用銷燬子應用。
通過single-spa-vue中加載子應用的過程,single-spa把各個子應用組裝成一個複雜的應用,在用户無感的情況下對各個子應用進行分別治理。
single-spa在加載子應用的時候,除了vue的版本之外,還有其他的版本,但是加載的思路類似,都是在函數庫中來把子應用加載到html中,此處不再介紹其他類型的加載。
single-spa其他加載子應用方式:single-spa-react、single-spa-html
6 子應用狀態保持
在實際開發的過程中筆者遇到有些頁面需要使用vue中的keep-alive來保留狀態,在頁面切換的過程中雖然頁面被銷燬但是頁面狀態需要在保留,但是我們在分析single-spa-vue的unmount方法實現的時候發現,如果頁面切換,子應用和vue實例被銷燬,此時子應用中的keep-alive是沒有生效的。
如下圖:
當在input中輸入內容以後,傳統的spa項目可以通過keep-alive來記錄狀態,當頁面路由切換以後,再切回來,仍然保持狀態。但是如果直接使用single-spa-vue,當子應用觸發unmount的時候input中的輸入內容1111會被清空。針對這種情況,筆者對single-spa-vue類庫進行了一些改造。
改造內容如下:
6.1 子應用由銷燬改為隱藏
在single-spa-vue配置項中增加了一個配置項,根據配置項中是否存在isKeepAlive配置項,來判斷把當前的dom隱藏掉,還是刪除。這樣當子應用unmount方法觸發的時候,子應用並未被刪除,而是仍然保留。
同時筆者對vue的route配置也進行了一些優化,當頁面不存在的時候,此時會把子應用中的一個空組件掛載到dom上面,避免雖然頁面被隱藏掉,但是dom仍然在html中,導致頁面dom過多。
6.2 子應用由新建改為顯示
在single-spa-vue配置項中調用mount方法掛載子應用的時候,會判斷當前子應用是否存在,如果子應用存在則直接把子頁面顯示出來,由於子應用並未被銷燬,此時子應用中的keep-alive就會一直生效,並且保存頁面的狀態。
通過對single-spa-vue類庫的mount、unmount方法的優化,用户在使用頁面的時候真正和使用vue那樣流暢,並且可以保持頁面狀態,提升用户的體驗。
- 應用健康度隱患刨析解決系列之數據庫時區設置
- 對於Vue3和Ts的心得和思考
- 一文詳解擴散模型:DDPM
- zookeeper的Leader選舉源碼解析
- 一文帶你搞懂如何優化慢SQL
- 京東金融Android瘦身探索與實踐
- 微前端框架single-spa子應用加載解析
- cookie時效無限延長方案
- 聊聊前端性能指標那些事兒
- Spring竟然可以創建“重複”名稱的bean?—一次項目中存在多個bean名稱重複問題的排查
- 京東金融Android瘦身探索與實踐
- Spring源碼核心剖析
- 深入淺出RPC服務 | 不同層的網絡協議
- 安全測試之探索windows遊戲掃雷
- 關於數據庫分庫分表的一點想法
- 對於Vue3和Ts的心得和思考
- Bitmap、RoaringBitmap原理分析
- 京東小程序CI工具實踐
- 測試用例設計指南
- 當你對 redis 説你中意的女孩是 Mia