微前端落地系列-復(fù)盤

?前沿:哈嘍大家好,我是樹醬??,好久不見。本文主要為了做復(fù)盤,在去年基于qiankun微前端架構(gòu)的門戶建設(shè)中,遇到的一些問題,可能你會認(rèn)為:“哇,這也算問題嗎?太簡單了吧”。主要是分享在我認(rèn)知體系內(nèi)是如何解決的,如果對其中一些解決方案有更好的建議,記得在評論區(qū)留言~
?

上圖為落地過程中遇到的一些問題,接下來圍繞這些問題跟大家分享我的認(rèn)知體系是如何去解決的
1. 應(yīng)用權(quán)限控制如何做?
?權(quán)限控制一般分為:路由權(quán)限、按鈕權(quán)限(視覺權(quán)限)等,下面舉例說明
?
路由權(quán)限:比如當(dāng)用戶從門戶中登陸后,要訪問應(yīng)用A或者應(yīng)用A下的某個菜單頁面時,但該用戶并沒有該應(yīng)用的訪問權(quán)限,我們需要攔截它,不讓它進入
按鈕權(quán)限 (視圖權(quán)限):比如當(dāng)某個用戶不存在對某種資源進行刪除的權(quán)限的時候,我們會將原有的刪除操作按鈕給隱藏,以此來實現(xiàn)按鈕
??? 啊敏同學(xué):那我們怎么知道是否有權(quán)限,或者說怎么區(qū)分資源類型?
?
??:mark,首先我們先給每個資源定義一個code編碼,你可以理解為對這個資源的唯一標(biāo)記,它的身份id,比如我們可能是應(yīng)用、菜單或者按鈕。針對不同類型的資源,可以做用規(guī)則區(qū)分,比如??

1.1 路由權(quán)限
??? 啊樂同學(xué):那編碼規(guī)則確定了,我們?nèi)绾慰刂颇兀?/p>?
??:我們來假設(shè)一個用戶有一個資源集合的權(quán)限
[appliction:monitor、menu:monitor:flume、button:monitor:flume:delete]
首先先說路由權(quán)限控制,主要是為了判斷該用戶是否有應(yīng)用或者菜單的訪問權(quán)限,我們一般可以在router.beforeEach 導(dǎo)航守衛(wèi)中做攔截,一般分為兩種情況
動態(tài)路由:原先并未添加路由,根據(jù)上文提到的資源編碼來動態(tài)添加路由,可參考??樹醬之前寫的關(guān)于門戶的前端權(quán)限控制[1]
靜態(tài)路由:已經(jīng)初始化好路由,通過統(tǒng)一在門戶這個主應(yīng)用的路由根據(jù)獲取的資源編碼來判斷當(dāng)前訪問的用戶是否有應(yīng)用訪問權(quán)限,如果沒有則進行攔截,如下所示是門戶這個主應(yīng)用對路由的處理,因為當(dāng)子應(yīng)用加載后,主應(yīng)用會劫持原本子應(yīng)用的路由,舉個例子如下 ??

上圖中的hasPerssion方法就是通過判斷該用戶是否有某個應(yīng)用的資源編碼,以此來判斷是否有權(quán)限訪問,本質(zhì)上就是new RegExp正則匹配,如果沒有權(quán)限則跳轉(zhuǎn)到無權(quán)限訪問頁面

1.2 視覺權(quán)限
?啊敏同學(xué):那按鈕權(quán)限呢?如何處理
?
??:同樣需要依賴到資源編碼,然后通過自定義指令,比如v-perms來控制,指令源碼可點擊??指令控制[2] 如下圖所示是一個按鈕的具體使用

至于v-perms指令我們是如何給每個子應(yīng)用復(fù)用,通過門戶主應(yīng)用去注入到子應(yīng)用生命周期, 子應(yīng)用接收如下??

?啊敏同學(xué):樹醬,你上面提及的按鈕權(quán)限控制是基于
?<template>, 那如果是直接render函數(shù)渲染咋搞?
??:render函數(shù)中原理也是一樣的,只不過把指令換了一種方式,通過工具庫里面封裝findPermission函數(shù),來控制style的display屬性值,當(dāng)然你也可以用上文提到主應(yīng)用給子應(yīng)用的方式注入一個工具函數(shù)的方式,以此達到復(fù)用。如下所示??

2.應(yīng)用的異常監(jiān)控
?當(dāng)門戶落地后,如何去監(jiān)控子應(yīng)用的異常信息就顯得很重要,畢竟不同環(huán)境可能會出現(xiàn)不一樣的情況,那如何去追蹤和定位呢?
?
我們在qiankun的api文檔中找到了addGlobalUncaughtErrorHandler方法,用來監(jiān)聽全局的未捕獲異常

比如說我要監(jiān)聽?wèi)?yīng)用加載失敗,那我可以捕獲到的錯誤信息中的信息提示來做正則匹配

然后通過bus通信,通知頁面顯示應(yīng)用加載失敗頁面,如下所示

?????? 啊豪同學(xué):那你們怎么將異常信息上報的呢?
?
??:我們是通過sentry去做異常信息上報的,sentry本身會做異常捕獲,但是為了讓主應(yīng)用能夠統(tǒng)一捕獲子應(yīng)用的異常信息,做統(tǒng)一異常信息維護管理,所以在addGlobalUncaughtErrorHandler中做了主動上報
如果想了解sentry如何二次封裝,可以看樹醬之前寫的 前端監(jiān)控那些事[3]
3.如何讓新的子應(yīng)用實現(xiàn)快速集成
?前言:我們知道qiankun架構(gòu)中一個子應(yīng)用要集成到主應(yīng)用中,是需要創(chuàng)建生命周期函數(shù),比如mounted等以及修改打包方式。那如何快速讓新的子應(yīng)用實現(xiàn)快速集成呢?
?
我們是通過打造一個簡易版的腳手架工具,把涉及相關(guān)的功能用一套模版維護起來,然后通過維護好的這個模版,然后通過腳手架創(chuàng)建新項目,本質(zhì)上就是拉取這個模版,如下圖所示

具體開發(fā)可以參考之前寫的《前端那些事》從0到1開發(fā)簡單腳手架[4]
4.如何動態(tài)注冊應(yīng)用?
?前沿:為了讓主應(yīng)用可以去訪問不同的子應(yīng)用,我們需要在配置文件中定義好每個子應(yīng)用的入口entry以及訪問名稱,以此來注冊子應(yīng)用,我們一般會不同的環(huán)境有不同的配置,比如下圖所示
?

?????? 啊斌同學(xué):那這樣的話,每次修改子應(yīng)用的entry或者新增新的子應(yīng)用都得重新編譯門戶這個主應(yīng)用
?
??:是的,本地配置化是會存在這樣的問題,我們可以搭建一個配置中心來維護,然后通過接口調(diào)用的方式來獲取不同環(huán)境的,像下面這樣??

5.部署中遇到的問題
?前沿:部署微前端體系門戶涉及到私有云部署,公有云部署,還有基于容器化部署等等。過程中遇到一些問題
?
5.1 主應(yīng)用加載子應(yīng)用靜態(tài)資源跨域咋搞?
本質(zhì)上是因主應(yīng)用是通過fetch去獲取子應(yīng)用的靜態(tài)資源的,然后通過正則去解析出來子應(yīng)用的靜態(tài)資源信息,然后fetch下來,所以必須要求這些靜態(tài)資源支持跨域,如何配置如下圖所示,通過設(shè)置允許源了

Access-Control-Allow-Origin:跨域在服務(wù)端是不允許的。只能通過給Nginx配置Access-Control-Allow-Origin *后,才能使服務(wù)器能接受所有的請求源(Origin)
5.2 主應(yīng)用加載子應(yīng)用的靜態(tài)資源不是最新,導(dǎo)致加載失敗?
本質(zhì)上就是子應(yīng)用更新了代碼,而主應(yīng)用在fetch子應(yīng)用資源的時候,加載到緩存的資源,導(dǎo)致加載資源失敗,那么怎么解決呢?我們可以在子應(yīng)用的nginx中,設(shè)置cache-control,在每次請求資源的時候都檢查是否更新。

5.3 如何讓每個子應(yīng)用都擁有通用的ngixn配置?
為了解決以上問題,又要保證通用性,可以針對每個子應(yīng)用都是同樣的nginx配置,這時候可以通過在dockerfile中定義,在打包到容器時,把nginx.conf也打到容器中

5.4 如何正確部署主應(yīng)用和子應(yīng)用?
主要是兩種方案:
1.主應(yīng)用和子應(yīng)用部署到同一個服務(wù)器
這種情況適合公司服務(wù)器數(shù)量較少,核心就是把主應(yīng)用部署在一級目錄,其他子應(yīng)用放在二級目錄
2.主應(yīng)用和子應(yīng)用分別部署在不同服務(wù)器
這種情況又分為兩種,一種是所有子應(yīng)用都在一臺服務(wù)器,一種是不同子應(yīng)用在不同服務(wù)器,獨立運行。
最后,以上兩種方式都有好有壞,具體看你搭建的系統(tǒng)是內(nèi)部以ip訪問為主還是外部訪問域名為主,去根據(jù)實際情況應(yīng)用。如果是內(nèi)部系統(tǒng)建設(shè),子應(yīng)用以內(nèi)部訪問ip為主,子應(yīng)用都在獨立服務(wù)器,無需在配置過多域名,那可以直接用方案2,那如果是對外且域名有限,那方案1或許更合適。
具體的配置方式,我看qiankun官網(wǎng)文檔已經(jīng)更新,可查閱??文檔[5] 這里就不重復(fù)介紹
Reference
關(guān)于門戶的前端權(quán)限控制: https://juejin.cn/post/6900872985876856839
[2]指令控制: https://juejin.cn/post/6900872985876856839
[3]前端監(jiān)控那些事: https://juejin.cn/post/6844904080586850311#heading-4
[4]《前端那些事》從0到1開發(fā)簡單腳手架: https://juejin.cn/post/6844904137709060104
[5]??文檔: https://qiankun.umijs.org/zh/cookbook#%E5%9C%BA%E6%99%AF-1%EF%BC%9A%E4%B8%BB%E5%BA%94%E7%94%A8%E5%92%8C%E5%BE%AE%E5%BA%94%E7%94%A8%E9%83%A8%E7%BD%B2%E5%88%B0%E5%90%8C%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%88%E5%90%8C%E4%B8%80%E4%B8%AA-ip-%E5%92%8C%E7%AB%AF%E5%8F%A3%EF%BC%89
