爲什麼 single-spa 纔是微前端的正確開發模式
原文地址:https://juejin.cn/post/7183954579690618936
一、前言
說到微前端大家可能並不會感到陌生,在平時的項目開發中或多或少有接觸過,近幾年國內也是出現了一批比較火的微前端開發框架 qiankun、Micro App、EMP 等, 這些框架能夠讓我們快速的搭建起微前端的開發環境,能夠快速的與現有的項目進行融合,同時在面對一些常見的場景問題時也給出了具體的解決方案。
正因如此每當我問身邊的同學或者同事什麼是微前端時,他們都會講這些微前端框架官網的概念給我講一遍,比如獨立開發部署、技術棧無關、項目之間彼此隔離等,然後我就會反問這是真正的微前端嗎?或者說這是微前端正確的開發模式嗎?本系列文章會通過講解 single-spa[1] 帶大家重新認識微前端,以及微前端的正確開發模式。
二、什麼是微前端?
微前端是一種架構風格,旨在當一個項目需要由多個小而散的微應用組合時,這些微應用可以獨立開發、測試和部署,最終聚合成一個產品進行交付。
三、微前端具備的能力
必備能力
-
獨立開發部署
獨立開發部署的能力在微前端體系中至關重要,每個微應用都應具備有自己的持續交付流水線(包括構建、測試並部署到生產環境)。
-
增量升級
對於一個項目而言最理想的代碼結構應該是模塊清晰、易於拓展、便於維護等,但是由於一些各種各樣的原因導致項目裏總是會存在一些不合理不理想的代碼:
如果要對代碼進行徹底重構的話,最大的難點在於沒有足夠的時間和資源能夠支持一步到位,在重構的同時我們既要保證舊模塊 -> 新模塊的平滑過渡,還要保證新功能的持續迭代交付。
所以,爲了實施漸進式重構,我們需要一種增量升級的能力,這種增量升級的能力意味着我們能夠對產品功能進行低風險的局部替換。
-
技術棧落後、依賴版本低。
-
代碼耦合嚴重,牽一髮而動全身
-
代碼重構不徹底
-
兼容多技術棧
對於技術棧而言我們第一步是先要治理,再是兼容,治理也就是說我們 host 方要儘量要求所有的 guest(微應用) 方保持技術棧的統一,而對於一些已經存在的舊項目可以採取兼容的方式,後期再慢慢改造。
優質微前端要具備的能力
前面講完了微前端所必備的幾個能力,下面將介紹一個優質 / 完善的微前端還應該具備哪幾個能力,這也是 single-spa 作者在官網中重點提出的幾個能力,這裏極力推薦大家去看一下 singe-spa 的官網,他可以說是我們微前端界的紅寶書。
-
跨應用導入(Cross microfrontend imports)
跨應用導入的一個非常重要的功能就是能夠讓我們跨應用的去複用一些能力,這些能力可以是方法、組件、數據等,這樣能夠大大提高開發效率,避免相同功能的組件、方法重複的開發。
比如說下面這個例子,我們需要開發一個大型的購物後臺管理系統,這裏面就包括用戶管理模塊、商品模塊、訂單模塊等,這些模塊都是由不同的團隊進行開發的,對於每個微應用來說他們都是要知道當前登陸用戶的權限信息,此時我們就可以讓用戶管理模塊給其他微應用暴露出獲取用戶權限的方法。
// 在用戶管理模塊導出獲取用戶權限的方法 export function userHasAccess(permission) { return loggedInUser.permissions.some(p => p === permission); }
其他微應用就能直接通過 import 的方式導入該方法。
import {userHasAccess}from "@mc/perssonCenter/api.js"; const showLinkToInvoiceFeature = userHasAccess('invoicing');
如果我們沒有跨應用導入的功能,那就需要每個微應用都要去維護一套獲取用戶權限的接口,這是非常麻煩的。
-
應用間的通信(Inter-app communication)
跨應用通信即微前端項目間可以暢通無阻的進行通信,信息傳遞的方式分爲主動通知和被動通知。舉例來說,現實場景中,應用之間需要狀態同步,如用戶登出時,負責用戶功能的微前端項目能夠主動發起通知至其他微前端模塊,各模塊響應通知消息做出必要處理。
下面展示的是主動通知方式進行通信:
// 在商品微應用中導出清空用戶狀態的api,當用戶退出登錄時調用 export function clearUserStatus() { fetch('xxxx').then() }
在用戶管理微應用中,一旦用戶退出登錄就調用商品微應用清空用戶狀態的方法
import {clearUserStatus}from "@mc/shop/api.js"; // 退出登錄時調用 clearUserStatus()
而被動通知一般會採用發佈訂閱模式實現,所有微應用訂閱同一份全局狀態,一旦狀態發生改變就會通知所有的訂閱者,qiankun 當前就是採用這種方式。因此,對於一個組合而成的項目,一個通信鏈路有時候是必要的。
-
共享依賴(Shared dependencies)
共享依賴允許所有的應用在運行時能夠使用同一份第三方庫的代碼,他是依靠運行時模塊化實現的(systemjs / 瀏覽器 esm 的支持 / module federation)。
共享依賴也是當前社區呼聲比較高的需求,在 qiankun 的 issue 裏就看到過很多:
但是官方也並沒有給出答覆,後面我們會介紹爲什麼 qiankun 他很難去做依賴共享。那共享依賴有什麼作用呢?
-
治理各個微應用。
它能夠去統一各個微應用的第三方依賴版本,比如說我們我們當前主應用使用的是 react@17,另一個部門開發的項目是基於 react@16,這個時候就需要要求他們進行一個升級,因爲官網也強調最新的 react-hooks 特性就要求使用 hooks 時必須要在同一個 react 上下文中 [2]。
-
減少資源請求,提高頁面加載速度。
四、國內外是怎麼定義微前端的?
上面我們介紹的微前端的概念都是來自 single-spa ,他可以說是國外非常具有代表性的微前端框架,國內我們就選取一個非常具有代表性的微前端框架 —— qiankun,我們先來看一下 qiankun 它是怎麼定義微前端的:
我們看到前三個其實就是我們上面講的微前端必須具備的三個能力沒有問題,最大的差別就是第四個概念,qiankun 要求所有的微應用必須彼此之間相互隔離,運行時狀態不共享,這不是和我們前面講的優質微前端要具備的能力恰好相反嗎?qiankun 爲什麼要這麼設計?
這個問題我們可以仔細思考一下 qiankun 誕生時的背景:
-
項目技術棧雜亂無章,代碼質量較低
-
項目開發時缺少規範,導致項目一融合就會相互影響(css 衝突、js 衝突等)
-
項目改造人力成本大,新功能需要持續迭代 ...
面對這些問題,當前採用的最好的方案是開發出來一套能夠大大減少接入成本同時又能夠避免項目之間的相互影響的微前端框架,這也就有了大量的 css 隔離方案、js 隔離方案等。
我們再來看看 single-spa 他是怎麼看待衝突問題的:
single-spa 他明確了在微前端項目中全局樣式和局部樣式是可以存在的,下面他分別講了一些開發全局樣式和局部樣式的方法,比如最常見的局部樣式開發方案有 CSS Modules、Styled Components、PostCSS Prefix 等。
通過這個我們基本就能看出國內外對微前端的開發模式是不同的,single-spa 所提倡的是治理,要求所有的微應用都按照一定的開發規範去開發,這也和我們一開始給出的微前端的定義是相照應的——先拆再合,而國內的微前端框架是先合再拆,針對項目中已有的問題提供相應的解決方案,從而大大減小微前端項目的開發成本。所以他們走的方向也是不同的。
五、總結
本篇文章通過 single-spa 闡述了什麼是微前端,以及一個優質的 / 完善的微前端應該要具備哪些能力,最後介紹了國內外對微前端的一些不同的看法,總的來說國內的微前端框架它的優勢是利舊性好, 面對技術棧雜亂無章的,重疊嚴重,代碼質量較低的場景,都有比較好的效果,但是也就是因爲利舊性好才衍生出來一系列的問題,比如說如何在隔離的條件下做應用通信、依賴共享、跨應用導入等,也期待後面官方能給出相應的解決方案。
參考資料
[1]
single-spa: https://link.juejin.cn?target=https%3A%2F%2Fsingle-spa.js.org%2Fdocs%2Fmicrofrontends-concept
[2]
react 上下文中: https://link.juejin.cn?target=https%3A%2F%2Freactjs.org%2Fwarnings%2Finvalid-hook-call-warning.html
關於前端技術磚家
磚家,brickspert
前螞蟻集團前端技術專家
開源庫 ahooks 作者,10k+ star ⭐️
開源庫 antd mobile 前負責人,10k+ star ⭐️
你可以在以下渠道找到我:
公衆號:前端技術磚家
B 站:前端技術磚家
知乎:磚家
掘金:前端技術磚家
Github:brickspert
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/RzNvq8t5_UFYcJZLBBF2XQ