出於以下幾個目的,最近在用qiankun改造項目:
- 幾個項目共用同一個頭部,底部和登錄權限系統每次更新都需要同步N次代碼,再加上rc,uat兩個發布分支,就是3n次,想屎的心都有了
- 之前一直寫react,這個項目用vue,但總懷念使用react的時光,vue雖然更方便,但總感覺react寫起來更加可控,邏輯更清晰
- 首頁要做seo,可以在nuxt中使用微前端,也可以在spa中使用微前端(還沒實踐)
- 子項目可以獨立開發,獨立部署
- 主項目存放框架,子項目寫業務代碼,功能分開,方便代碼權限控制
- 為什么不用iframe:
- url 不同步。瀏覽器刷新 iframe url 狀態丟失、后退前進按鈕無法使用。
- UI 不同步,DOM 結構不共享。想象一下屏幕右下角 1/4 的 iframe 里來一個帶遮罩層的彈框,同時我們要求這個彈框要瀏覽器居中顯示,還要瀏覽器 resize 時自動居中…
- 全局上下文完全隔離,內存變量不共享。iframe 內外系統的通信、數據同步等需求,主應用的 cookie 要透傳到根域名都不同的子應用中實現免登效果。
- 慢。每次子應用進入都是一次瀏覽器上下文重建、資源重新加載的過程。
微前端的文檔可以直接去官網看,不是很多,不過能滿足基本需求,有問題還是去github問吧
下面說說本人在做微前端改造時遇到的一些坑,希望對大家有幫助
- 子應用導出鈎子函數
- 子應用vue.config中的headers設置成可跨域請求
- output設置成library,打包成umd庫格式
- 父應用使用了babel-pollfill,子應用不要在在bable-pollfill
- iconfont.js要取消樣式隔離才能生效
sandbox - boolean | { strictStyleIsolation?: boolean } - 可選,是否開啟沙箱,默認為 true。
當配置為 { strictStyleIsolation: true } 表示開啟嚴格的樣式隔離模式。這種模式下 qiankun 會為每個微應用的容器包裹上一個 shadow dom 節點,從而確保微應用的樣式不會對全局造成影響。
- 各子應用都用到的狀態放入全局(用@ice/stark-data中的store定義)
- 通過store.on監聽每次更改全局狀態時,都同步更新子應用的store,直接用store.get方法可以獲取狀態值,但無法監聽狀態值變化時視圖同步更新,所以最好還是放在應用本身的store中進行展示
- 原則是賦值操作在各應用中同步,但修改操作只在主應用這一個地方操作,高度解耦
- 如果是選擇在子應用中進行全局狀態的修改,那么需要在各應用中維護所有的狀態修改操作,高度耦合,導致后期的代碼維護十分困難
- 一開始用的initGlobalState,發現這個是雙向綁定的,即應用間要都有mutation或action,相當於要在每個子應用中寫相同的store代碼,不符合kiss准則,也對后期維護帶來相當大困難,所以還是采用@ice/stark-data,飛冰團隊的微前端通信方案
- 關於部署:
微應用的部署和原來項目的部署基本一致
- 注冊時entry的路徑不能和路由的base以及activeRule一致,不然會產生覆蓋(如都是/cloud,則會變為去請求/cloud目錄下的文件)
- 關於nginx的配置:
# 主應用
location / { if ($request_uri ~* '/$|\.html$') { add_header Cache-Control no-store; } root /opt/pumpkin/fronted/; index index.html; try_files $uri $uri/ /index.html; } # cloud子應用 location /cloud/ { if ($request_uri ~* '/$|\.html$') { add_header Cache-Control no-store; } alias /opt/pumpkin/fronted/; index index.html; try_files $uri $uri/ /index.html; } # mall子應用 location /mall/ { if ($request_uri ~* '/$|\.html$') { add_header Cache-Control no-store; } alias /opt/pumpkin/fronted/; index index.html; try_files $uri $uri/ /index.html; } # portal子應用 location /portal/ { if ($request_uri ~* '/$|\.html$') { add_header Cache-Control no-store; } alias /opt/pumpkin/fronted/; index index.html; try_files $uri $uri/ /index.html; }
由於都是history的路由模式,所以:
- 每個應用配置都要加上
try_files $uri $uri/ /index.html;
否則會出現刷新報404錯誤- 每個子應用都要單獨配置location,否則在訪問/cloud,/mall,/portal時刷新會報404
- 主應用和各應用相同依賴的版本號一定要一樣,不然會有莫名其妙的BUG
- 項目中使用了百度地圖等組件,會出現在子應用中無法使用的情況 ,在看源碼時發現子應用的document.body中添加script標簽失敗沒報錯,但無法正確添加到body中,類似性質的問題還有美洽客服的引用,pdfjs的引用兩種解決方法: