場景
一個在某某行業為運營商提供服務的科技公司
首先會開發一個關於機器各種功能的運營系統(機器中心)
next,要為供應商提供資料分析的系統(資料中心)
next,為運營商提供各種促銷活動(營銷中心)
…。 (業務更多,需要的管理系統也很多)短期之內全部用一個前端專案開發,沒有問題。但是當業務量不斷擴充套件,從開發到使用者會有各種影響(當然分多個專案也沒問題,但是使用者需要記住N個連結)
image (1)。png
這麼就會出現問題
開發:
程式碼量大,打包慢,包體積大,時間越長
整個系統的ui主題不好管理
每一次迭代上線,影響面大
程式碼耦合混亂,不敢動,牽一髮何止動全身
使用者:訪問會越來越慢,很容易受到開發上線影響的自己的功能,主題千年不變等等。
思考
如何將一個
巨石
的管理系統改造拆分(各個中心的模組下面還有幾十個選單)
微前端是個啥
將前端應用分解成一些更小、更簡單的能夠獨立開發,測試、部署的小塊,而在使用者看來仍然是內聚的單個產品。微前端的三個要素,即:
獨立執行、獨立開發(與技術棧無關,應用之間不應該有任何直接或間接的技術棧、依賴、以及實現上的耦合)、獨立部署
優勢
複雜度可控
: 每一個UI業務模組可以由獨立的前端團隊開發,避免程式碼巨無霸,便於維護與開發效率。
獨立部署
: 每一個模組可單獨部署
技術選型靈活
: 在同一專案下可以使用如今市面上所有前端技術棧,也包括未來的前端技術棧。
容錯
: 單個模組發生錯誤,不影響全域性。
擴充套件
: 每一個服務可以獨立橫向擴充套件以滿足業務伸縮性,與資源的不必要消耗;
希望改造成這樣
對外,看上去是一個系統。對內又可以分多個web專案
常見的實現方式
傳統iframe
優點:應用之間自帶沙箱隔離
缺點:重複載入指令碼和樣式
需要解決的問題:
佈局問題:iframe必須給一個指定的高度,否則會塌陷
彈窗及遮罩層問題:只能在iframe範圍內垂直水平居中,沒法在整個頁面垂直水平居中(可使用全域性的彈窗)
瀏覽器前進/後退問題:iframe頁面重新整理會重置(比如說從列表頁跳轉到詳情頁,然後重新整理,會返回到列表頁),因為瀏覽器的位址列沒有變化(push基層進行路由跳轉)
每次子應用進入都是一次瀏覽器上下文重建、資源重新載入的過程。
2.執行時組合
(每個子應用獨立構建,執行時由主應用負責應用管理,載入,啟動,解除安裝,通訊機制)
優點:具有良好的體驗,真正的獨立開發,獨立部署
缺點:複雜,需要設計載入,通訊機制,無法做到徹底隔離(基於 shadow DOM 的樣式可以實現樣式隔離,比如qiankun。js),需要解決依賴衝突,樣式衝突問題瀏覽器的原生元件,相比第三方框架,原生元件簡單直接,符合直覺,不用載入任何外部模組,程式碼量小(現在流行的React,Vue都是元件框架)每個子應用需要使用 Web Components 技術編寫元件或者使用框架生成
優點:面向未來的技術
缺點:重構代價很大,所有的程式碼需要用web Components重寫
Web Components
//MDN地址https://developer。mozilla。org/zh-CN/docs/Web/Web_Components
目前國內關注度比較高的技術
目前使用比較多的是執行時組合的方案。關注度和成熟度最高的應該就是 single-spa。還有國內關注度很高的螞蟻金融的框架qiankun
qiankun 是一個生產可用的微前端框架,它基於 single-spa,具備 js 沙箱、樣式隔離、HTML Loader、預載入 等微前端系統所需的能力。qiankun 可以用於任意 js 框架,微應用接入像嵌入一個 iframe 系統一樣簡單(
想知道更多請去官網
)
說了這麼多,下面才是重點
當前有個專案遇到如下瓶頸
第三方js混亂(jquery,react,vue,angular一鍋亂燉)
大多都是jquery程式碼,程式碼量大,閱讀困難
業務特別多,頁面有百來個吧
等等。。。。。
(當然,不可否定,在當時,這是一個架構很好的專案)
最佳化目標
在不影響原來的專案基礎的情況下最佳化專案,以最小改動,使之既能繼承原有的能力,又符合現在的開發習慣和技術方向(
注入微服務的思想
)
解決方法
針對這個專案iframe方案是接入成本最廉價的選擇,同時也支援透過possMassage實現父子之間的通訊。而且,對於陳年已久的Jquery多頁面的老專案,qiankun對多頁應用沒有很好的解決辦法。每個頁面都去修改,成本很大也很麻煩,但是使用 iframe 嵌入這些老專案就比較方便。
(新建兩個子專案vue/react各一個,在原來的架構下,開發訪問)
需要解決的問題:
使用iframe,並且路由中以 **“#/iframe”** 開頭即可訪問並隱藏其他的內容,分開iframe與原有的內容的並且透過顯示隱藏進行切換
解決訪問關係,即本地開發和線上訪問(線上訪問打包後的內容,線下訪問本地能熱更新程式碼)本地訪問地址(自動擷取iframe後面的url並訪問)
//本地http://localhost:8080/main/index。html/#/iframe/http://localhost:3001//線上訪問地址(localhost改為ip地址):http://localhost:8080/main/index。html/#/iframe/test/dist/index。html
配置代理解決本地訪問跨域
由於原來的專案,屬於直接訪問檔案,所以子專案的打包需配置相對路徑
因為dist檔案是需要放在伺服器上執行的,資源預設放在根目錄下。開啟index。html可以發現,css和js檔案的引用使用的是絕對路徑。但對本地磁碟來說,
/指向磁碟根目錄
,所以會找不到引用的檔案。需修改專案的publicPath為‘。/’(需要看具體的專案)
由基層傳遞選單給子專案(由專案狀況決定,也可以單獨控制)
API請求
本地請求啟動代理即可(需要注意cookie情況)
由於iframe的缺陷,使用彈窗及遮罩層問題(基層提供全屏方案,即子專案呼叫基層的全屏的彈窗)
基層架構與子專案之間的資料交流
為符合線上線下都能使用(線下存在同源問題),使用postMessage實現,然後專案內部使用公共bus,傳播基層傳遞過來的訊息(依據專案的技術情況)
有個注意點:在react專案中可以等待基層將所有的資訊準備完畢並傳遞給子專案之後再渲染主要內容。但是在vue中延遲掛載app.mount('#app')會報錯。所以使用公共bus將基層資訊,傳播給子專案
執行方式
本地開發執行兩個專案,一個是基層的一個是獨立的專案