解密微前端:"巨石應用"的誕生

隨着咱們中後臺系統的複雜,每每會遇到多個團隊獨立維護的子應用接入統一的主應用中,這些子應用每每獨立開發、獨立部署、彼此徹底解耦,這時候往常的單一應用沒法知足業務的增加需求。而微前端即是用來解決隨着時間的推移業務複雜度的提高,某個單應用演變爲難以維護的「巨石應用」。css

這便文章並非一個源碼解析以及上手教程的文章,我但願從一個宏觀的角度介紹下微前端而且簡單聊一下微前端在咱們如今項目中的一些思考。html

先聊聊背景

我一直認爲拋離業務的技術改造都是沒有太大價值而且很難走遠的。這裏我先簡單介紹下我對目前項目所作的一個架構演變以及一些簡單思考。我目前所處一個大型的 B 端項目團隊,系統根據業務域劃分的子應用有幾十個,系統 PV 百萬+,因此在這樣一個龐大的系統中咱們的系統架構也經歷瞭如下一些變化。前端

模版架構

在我剛加入團隊的時候,咱們的系統仍是一個先後端未徹底分離的架構,模版提供了一個入口掛載根節點,前端在根節點上渲染 React / Vue 應用。web

不難發現這樣的架構存在必定的弊端:chrome

  • 後端解析模版,掛載模版;
  • 後端管控路由,前端失去了對路由的掌控權,而且多個團隊路由規則管控較難;
  • 每一次前端發佈須要先發布靜態資源再發布模版,發佈繁瑣容易出錯;
  • 這樣的開發方式相對來講較爲古老,對於喜歡搗鼓新事物的前端來講很難激發熱情;

可是值得慶幸的是,這時候咱們的系統已經有必定的分治思想了,主應用(這個時候應該說是 layout 層)和子應用單獨掛載在不一樣的模版片斷上,這也爲後面的 iframe 和微前端改造減小了很多工做量後端

其實,這樣的架構也有必定微前端的影子:) 。跨域

iframe 架構

後面隨着後端微服務化的轉型,後端已經不去關心路由的管控和頁面的掛載,轉而提供更加原子化的微服務。而對咱們前端來講:瀏覽器

  • 須要不依賴後端模版;
  • 須要管控路由並制定統一的路由規則;
  • 主子應用的沙箱隔離;
  • 儘可能對子業務的改動作到最小化,不少業務包袱很重;
  • 快速落地並實現高可用(沒辦法,開發時間永遠是一個戰勝不少選項的因素...);

可是隨着 iframe 架構的落地以及後續迭代的進行,咱們也發現了 iframe 方案的一些弊端:前端框架

  • 通訊方式簡單,簡單的 postmessage API 並不能知足業務的需求;
  • 樣式割裂,iframe 會致使諸如 Dialog 這樣子的全局蒙層僅在 ifame 區塊內展現,使咱們系統更像是「拼湊」出來的;
  • 性能瓶頸,路由的切換會致使 iframe 內子應用的從新加載,性能堪憂;
  • 跨域問題,chrome80 的 samesite 策略會致使 iframe 方案的跨域 cookie 沒法帶給後端;

微前端架構

最後在今年中旬的時候我這邊將 iframe 架構升級到了微前端 + iframe 並存的架構,並開發落地了一系列微前端相關的開發工具鏈(喜大普奔...)。cookie

so,爲何不是 iframe?

在我看來,微前端是一個思想,是一種開發模式和架構的演變,諸如 qiankun、icestark 等框架也僅是微前端實現的落地,合理的 iframe 實現何嘗不算是一種微前端實現的落地。咱們原來的 iframe 架構設計必定程度上也算是一種微前端思想,而且在我看來,iframe 對於這種跨團隊的中後臺巨無霸項目依然有着自然的優點,理由以下:

  • 框架無關:iframe 只加載部署完應用連接;
  • 獨立沙箱:iframe 擁有瀏覽器的獨立沙箱,子應用和主應用徹底不用考慮 js & css 污染問題;
  • 開發簡單:僅僅一個 iframe 標籤;

可是,與之而來的即是 iframe 的一些痛點:

  • UI 體驗很差:iframe 僅在制定的渲染塊內渲染,而子應用的一些相似於帶遮罩層的 Modal 等全局的 UI 組件只會在 iframe 內呈現;
  • 通訊困難:iframe 強大的沙箱機制帶來的反作用就是父子應用通訊困難,僅僅一個 postmessage API,跨域 cookie、Promise 等等都難以實現;
  • 路由丟失:子應用的 url 改變沒法及時同步父應用,隨着頁面的刷新,子應用的路由狀態丟失;
  • 加載時間長:每次子應用進入都是一次瀏覽器上下文重建、資源從新加載的過程;

儘管以上這些痛點或多或少的配合着一些 hack 的工具以及開發規範都有必定的解決方案,可是有更好的選擇爲何不嘗試呢:)

那麼,什麼是微前端?

這裏我不去講概念,道理你們都懂,概念一搜全都是。例如微前端很官方的詮釋:

Techniques, strategies and recipes for building a modern web app with multiple teams that can ship features independently

就像巨石應用並非一蹴而就的,接下來我來經過一個巨石應用的演變來向你們介紹我理解的微前端。

單個頁面

起初咱們的系統可能僅有一個業務模塊。路由硬編碼在項目裏,layout 層和業務子系統也寫在一塊兒。

多個頁面

隨着業務的增加,咱們的系統接入了更多的業務模塊,這個時候其實經過必定的路由配置和多頁的配置,項目也還算是沒太大問題。

可是這個時候須要引發警覺,若是再接入了更多的業務模塊還停留在當前的模式下,項目該怎麼維護?

更多的頁面?巨石應用!

隨着業務更進一步的增加,接入的業務模塊愈來愈多,不只咱們以導航維度擴充的子應用增多,甚至諸如首頁這樣子的頁面上也會有歸屬於多個業務域的區塊。總結起來就會分爲兩類場景:

  • 單實例:一個或多個頁面對應一個子應用,同一時刻僅有一個子應用渲染展現;
  • 多實例:一個頁面包含多個子業務應用區塊,同一時候有多個實例渲染展現;

這時若是沒有很好的處理和子系統的拆分,那麼咱們的應用就會變爲巨石應用...

  • 開發迭代並上線一個巨石應用比上線多個子應用要蛋疼的多...
  • 多人(多團隊)維護一個項目,你永遠不知作別人作了啥或者將要作啥...
  • 每每這樣子的應用,你們都是作加法而不去作減法,使得項目愈來愈大,無用代碼愈來愈多...

微前端,分而治之!

這時候咱們每每將系統根據業務域的劃分拆分紅不一樣的子應用,而承載這些子應用的 layout 層咱們拆分爲主應用,各個子應用獨立開發獨立發佈,而且由不一樣的業務團隊維護,以此來解決複雜的單體應用帶來的各類開發維護問題。

能夠看出,微前端即是採起分治的思想來避免單體應用演變成巨石應用的。

在我看來,在微前端的思想中,重點強調了幾點:

  • 獨立性:微前端的主應用以及各個子應用獨立開發、獨立部署,而且在必定程度上微前端子應用能夠獨立於主應用單獨運行;
  • 沙箱隔離:子應用有本身單獨的運行時,各個子應用之間的狀態不被共享;
  • 框架無關:子應用徹底能夠採起不一樣的框架進行開發,由於現有微前端框架實現中,主應用僅是加載子應用構建後的 bundle;

咱們的選擇

如今市面上的微前端框架有不少,例如阿里內部就有 icestack、qiankun 兩大比較成熟的開源微前端框架,以及社區上 singleSPA 等。那麼咱們該如何選擇適合咱們項目的微前端框架呢,這裏我簡單羅列了我在選擇微前端框架時候的一些思考:

  • 改動成本:任何業務團隊都不能逃避這個話題,你怎麼說服產品和老闆須要這麼長時間的技術改造(還存在必定風險)、你怎麼說服子應用方配合改造(相信我,子應用方不會願意去作 > 1 天改造的...);
  • 沙箱隔離:這個就很少說了,不少子應用會集成本身的埋點&監控體系,這樣的體系每每會掛載或者劫持全局變量的;
  • 路由不變性:在咱們 iframe 架構中,已經有一套比較完善的路由規則,那麼如何保證路由不變的前提下去作架構升級呢?
  • 通訊不變性:同上,在咱們的 iframe 架構中,已經有一套比較成熟的通訊工具,那麼能不能在保證 API 不變的前提下完成微前端的通訊呢?或者乾脆微前端能夠服用 iframe 的通訊工具?
  • 兼容 iframe:這麼龐大的系統不是一會兒就遷移到微前端的,而且咱們也不打算拋棄 iframe 架構(不願能所有業務都遷移的...)。那麼,如何保證兩套架構的共存?更進一步,如何保證兩套架構共存而後還能共享一套路由規則?
  • 灰度控制:子應用的大版本發佈每每會伴隨着灰度控制,那麼如何保證微前端接入後也能有完整的灰度流程?是作一個版本管控的工具仍是直接使用 htmlEntry?
  • 「遠古」應用接入:遠古應用保持 iframe 嵌入就最好了,那麼咱們能不能貪一點也能支持「遠古巨龍」的絲滑接入呢?

最後,結合上面的一些思考以及咱們如今的系統架構,我選擇了 qiankun 來落地咱們的微前端方案。而且爲了保證微前端接入以及版本管控的便捷,咱們

結語

以上即是我在作微前端改造時候結合業務系統的一些思考,若是有不對的地方歡迎指正。以後我也會輸出 qiankun 的源碼解析以及我所作的一些微前端工具的原理分析等文章(撒花...)。

相關文章
相關標籤/搜索