瞭解什麼是微前端

   譯者:Vincent.W  — 蛋殼公寓前端工程師   

https://juejin.im/post/5d1f19e3f265da1bab29ce5f

作爲前端開發人員,這些年來你一直在開發單體應用,即使你已經知道這是一個不好的做法。您將代碼劃分爲組件,使用 require 或 import 並將package.json中定義的npm包或已安裝的子git倉庫添加到項目中,但最終構建了一個整體。是時候改變它了。

爲什麼你的代碼是一個單體?

除了已經實現了微前端的應用之外,所有前端應用本質上都是單一的應用。原因是如果您正在使用 React 庫進行開發,並且如果您有兩個團隊,則兩個團隊都應該使用相同的React 庫,並且兩個團隊應該在部署時保持同步,並且在代碼合併期間始終會發生衝突。它們沒有完全分離,很可能它們維護着相同的倉庫並具有相同的構建系統。單體應用的退出被標誌爲微服務的出現。但是它適用於後端!????

什麼是微服務?

對於微服務,一般而言最簡單的解釋是,它是一種開發技術,允許開發人員爲平臺的不同部分進行獨立部署,而不會損害其他部分。獨立部署的能力允許他們構建孤立或鬆散耦合的服務。爲了使這個體系結構更穩定,有一些規則要遵循,可以總結如下:每個服務應該只有一個任務,它應該很小。所以負責這項服務的團隊應該很小。關於團隊和項目的規模,James Lewis 和 Martin Fowler 在互聯網上做出的最酷解釋之一如下:

在我們與微服務從業者的對話中,我們看到了一系列服務規模。報道的最大規模遵循亞馬遜關於Two Pizza Team的概念(即整個團隊可以由兩個比薩餅供給),意味着不超過十幾個人。在規模較小的規模上,我們已經看到了一個由六人組成的團隊支持六項服務的設置。

我畫了一個簡單的草圖,爲整體和微服務提供了直觀的解釋:

從上圖可以理解,微服務中的每個服務都是一個獨立的應用,除了UI。UI仍然是一體的!當一個團隊處理所有服務並且公司正在擴展時,前端團隊將開始苦苦掙扎並且無法跟上它,這是這種架構的瓶頸。

除了瓶頸之外,這種架構也會導致一些組織問題。假設公司正在發展並將採用需要 跨職能 小團隊的敏捷開發方法。在這個常見的例子中,產品所有者自然會開始將故事定義爲前端和後端任務,而 跨職能 團隊將永遠不會成爲真正的 跨職能 部門。這將是一個淺薄的泡沫,看起來像一個敏捷的團隊,但它將在內部分開。關於管理這種團隊的更多信息將是一項非常重要的工作。在每個計劃中,如果有足夠的前端任務或者sprint中有足夠的後端任務,則會有一個問題。爲了解決這裏描述的所有問題和許多其他問題,幾年前出現了微前端的想法並且開始迅速普及。

解決微服務中的瓶頸問題:Micro Frontends????

解決方案實際上非常明顯,採用了多年來爲後端服務工作的相同原則:將前端整體劃分爲小的UI片段。但UI與服務並不十分相似,它是最終用戶與產品之間的接口,應該是一致且無縫的。更重要的是,在單頁面應用時代,整個應用在客戶端的瀏覽器上運行。它們不再是簡單的HTML文件,相反,它們是複雜的軟件,達到了非常複雜的水平。現在我覺得微型前端的定義是必要的:

Micro Frontends背後的想法是將網站或Web應用視爲獨立團隊擁有的功能組合。每個團隊都有一個獨特的業務或任務領域,做他們關注和專注的事情。團隊是跨職能的,從數據庫到用戶界面開發端到端的功能。(micro-frontends.org)

根據我迄今爲止的經驗,對於許多公司來說,直接採用上面提出的架構真的很難。許多其他人都有巨大的遺留負擔,這使他們無法遷移到新的架構。出於這個原因,更柔軟的中間解決方案更加靈活,易於採用和安全遷移至關重要。在更詳細地概述了體系結構後,我將嘗試提供一些體系結構的洞察,該體系結構確認了上述提議並允許更靈活的方式。在深入瞭解細節之前,我需要建立一些術語。

整體結構和一些術語

讓我們假設我們通過業務功能垂直劃分整體應用結構。我們最終會得到幾個較小的應用,它們與單體應用具有相同的結構。但是如果我們在所有這些小型單體應用之上添加一個特殊應用,用戶將與這個新應用進行通信,它將把每個小應用的舊單體UI組合成一個。這個新圖層可以命名爲拼接圖層,因爲它從每個微服務中獲取生成的UI部件,併爲最終用戶組合成一個無縫 UI,這將是微前端的最直接實現????

爲了更好地理解,我將每個小型單體應用稱爲微應用,因爲它們都是獨立的應用,而不僅僅是微服務,它們都有UI部件,每個都代表端到端的業務功能。

衆所周知,今天的前端生態系統功能多樣,而且非常複雜。因此,當實現真正的產品時,這種直接的解決方案還不夠。

要解決的問題

雖然這篇文章只是一個想法,但我開始使用Reddit討論這個想法。感謝社區和他們的回覆,我可以列出一些需要解決的問題,我將嘗試逐一描述。

當我們擁有一個完全獨立的獨立微應用時,如何創建無縫且一致的UI體驗?

好吧,這個問題沒有靈丹妙藥的答案,但其中一個想法是創建一個共享的UI庫,它也是一個獨立的微應用。通過這種方式,所有其他微應用將依賴於共享的UI庫微應用。在這種情況下,我們剛剛創建了一個共享依賴項,我們就殺死了獨立微應用的想法。

另一個想法是在根級共享CSS自定義變量( CSS custom variables )。此解決方案的優勢在於應用之間的全局可配置主題。

或者我們可以簡單地在應用團隊之間共享一些SASS變量和混合。這種方法的缺點是UI元素的重複實現,並且應該對所有微應用始終檢查和驗證類似元素的設計的完整性。

我們如何確保一個團隊不會覆蓋另一個團隊編寫的CSS?

一種解決方案是通過CSS選擇器名稱進行CSS定義,這些名稱由微應用名稱精心選擇。通過將該範圍任務放在拼接層上將減少開發開銷,但會增加拼接層的責任。

另一種解決方案可以是強制每個微應用成爲自定義Web組件(custom web component)。這個解決方案的優點是瀏覽器完成了範圍設計,但需要付出代價:使用shadow DOM進行服務器端渲染幾乎是不可能的。此外,自定義元素沒有100%的瀏覽器支持,特別是IE。

我們應該如何在微應用之間共享全局信息?

這個問題指出了關於這個主題的最關注的問題之一,但解決方案非常簡單:HTML 5具有相當強大的功能,大多數前端開發人員都不知道。例如,自定義事件(custom events) 就是其中之一,它是在微應用中共享信息的解決方案。

或者,任何共享的pub-sub實現或T39可觀察的實現都可以實現。如果我們想要一個更復雜的全局狀態處理程序,我們可以實現共享的微型Redux,通過這種方式我們可以實現更多的相應式架構。

如果所有微應用都是獨立應用,我們如何進行客戶端路由?

這個問題取決於設計的每個實現, 所有主要的現代框架都通過使用瀏覽器歷史狀態在客戶端提供強大的路由機制, 問題在於哪個應用負責路由以及何時。

我目前的實用方法是創建一個共享客戶端路由器,它只負責頂級路由,其餘路由器屬於相應的微應用。假設我們有 /content/:id 路由定義。共享路由器將解析 /content,已解析的路由將傳遞到ContentMicroAppContentMicroApp是一個獨立的服務器,它將僅使用 /:  d 進行調用。

我們必須是服務器端渲染,但是有可能使用微前端嗎?

服務器端呈現是一個棘手的問題。如果你正在考慮iframes縫合微應用然後忘記服務器端渲染。同樣,拼接任務的Web組件也不比iframe強大。但是,如果每個微應用能夠在服務器端呈現其內容,那麼拼接層將僅負責連接服務器端的HTML片段。

與傳統環境集成至關重要! 但是怎麼樣?

爲了整合遺留系統,我想描述我自己的策略,我稱之爲“ 漸進式入侵 ”

首先,我們必須實現拼接層,它應該具有透明代理的功能。然後我們可以通過聲明一個通配符路徑將遺留系統定義爲微應用LegacyMicroApp 。因此,所有流量都將到達拼接層,並將透明地代理到舊系統,因爲我們還沒有任何其他微應用。

下一步將是我們的 第一次逐步入侵 :我們將從LegacyMicroApp中刪除主要導航並用依賴項替換它。這種依賴關係將是一個使用閃亮的新技術實現的微應用NavigationMicroApp 。

現在,拼接層將每個路徑解析爲 Legacy Micro App ,它將依賴關係解析爲 Navigation MicroApp,並通過連接這兩個來爲它們提供服務。

然後通過主導航遵循相同的模式來爲引導下一步。

然後我們將繼續從Legacy MicroApp中獲取逐步重複以上操作,直到沒有任何遺漏。

如何編排客戶端,這樣我們每次都不需要重新加載頁面?

拼接層解決了服務器端的問題,但沒有解決客戶端問題。在客戶端,在將已粘貼的片段作爲無縫HTML加載後,我們不需要每次在URL更改時加載所有部分。因此,我們必須有一些異步加載片段的機制。但問題是,這些片段可能有一些依賴關係,這些依賴關係需要在客戶端解決。這意味着微前端解決方案應提供加載微應用的機制,以及依賴注入的一些機制。


根據上述問題和可能的解決方案,我可以總結以下主題下的所有內容:

客戶端

  • 編排

  • 路由

  • 隔離微應用

  • 應用之間通信

  • 微應用UI之間的一致性

服務端

  • 服務端渲染

  • 路由

  • 依賴管理

靈活、強大而簡單的架構

所以,這篇文章還是很值得期待的!微前端架構的基本要素和要求終於顯現!

在這些要求和關注的指導下,我開始開發一種名爲microfe的解決方案。????在這裏,我將通過抽象的方式強調其主要組件來描述該項目的架構目標。

它很容易從客戶端開始,它有三個獨立的主幹結構:AppsManager Loader Router 和一個額外的MicroAppStore

AppsManager

AppsManager 是客戶端微應用編排的核心。 AppsManager的主要功能是創建依賴關係樹。當解決了微應用的所有依賴關係時,它會實例化微應用。

Loader

客戶端微應用編排的另一個重要部分是Loader。 加載器的責任是從服務器端獲取未解析的微應用。

Router

爲了解決客戶端路由問題,我將 Router 引入了 microfe。與常見的客戶端路由器不同,microf的功能有限,它不解析頁面而是微應用。假設我們有一個URL /content/detail/13 和一個ContentMicroApp。在這種情況下,microfe 將URL解析爲 /content/,它將調用ContentMicroApp /detail/13 URL部分。

MicroAppStore

爲了解決微應用到微應用客戶端的通信,我將MicroAppStore引入了 microfe。它具有與Redux庫類似的功能,區別在於:它對異步數據結構更改和reducer 聲明更靈活。


服務器端部分在實現上可能稍微複雜一些,但結構更簡單。它只包含兩個主要部分 StitchingServer 和許多MicroAppServer

MicroAppServer

MicroAppServer 的最小功能可以概括爲 init 和 serve。

雖然 MicroAppServer 首先啓動它應該做的是使用 微應用聲明 調用 SticthingServer 註冊端點,該聲明定義了 MicroAppServer 的微應用 依賴關係, 類型 和 URL架構。 我認爲沒有必要提及服務功能,因爲沒有什麼特別之處。

StitchingServer

StitchingServer 爲 MicroAppServers 提供註冊端點。當 MicroAppServer 將自己註冊到 StichingServer 時,StichingServer 會記錄MicroAppServer 的聲明。

稍後,StitchingServer 使用聲明從請求的URL解析 MicroAppServers。

解析MicroAppServer 及其所有依賴項後,CSS,JS和HTML中的所有相對路徑都將以相關的 MicroAppServer 公共URL爲前綴。另外一步是爲CSS選擇器添加一個唯一的 MicroAppServer 標識符,以防止客戶端的微應用之間發生衝突。

然後 StitchingServer 的主要職責就是:從所有收集的部分組成並返回一個無縫的HTML頁面。

其他實現一覽

甚至在2016年被稱爲微前端之前,許多大公司都試圖通過 BigPipe 來解決Facebook等類似問題。如今這個想法正在獲得驗證。不同規模的公司對該主題感興趣並投入時間和金錢。例如,Zalando開源了其名爲Project Mosaic的解決方案。我可以說,微型和 Project Mosaic.遵循類似的方法,但有一些重要的區別。雖然microfe採用完全分散的路由定義來增強每個微應用的獨立性,但Project Mosaic更喜歡每條路徑的集中路由定義和佈局定義。通過這種方式,Project Mosaic可以實現輕鬆的A/B測試和動態佈局生成。

對於該主題還有一些其他方法,例如使用iframe作爲拼接層,這顯然不是在服務器端而是在客戶端。這是一個非常簡單的解決方案,不需要太多的服務器結構和DevOps參與。這項工作只能由前端團隊完成,因此可以減輕公司的組織負擔,同時降低成本。

已經有一個框架叫做 single-spa 該項目依賴於每個應用的命名約定來解析和加載微應用。容易掌握想法並遵循模式。因此,在您自己的本地環境中嘗試該想法可能是一個很好的初步介紹。但是項目的缺點是你必須以特定的方式構建每個微應用,以便他們可以很好地使用框架。

最後的想法

我相信微前端話題會更頻繁地討論。如果該主題能夠引起越來越多公司的關注,它將成爲大型團隊的事實發展方式。在不久的將來,任何前端開發人員都可以在這個架構上掌握一些見解和經驗,這真的很有用。

考慮貢獻

我正在大力嘗試微前端,在我的腦海中有一個崇高的目標:創建一個微框架框架,可以解決大多數問題,而不會影響性能,易於開發和可測試性。如果您有任何明智的想法,請不要猶豫,訪問我的repo,打開問題或通過下面的評論或 Twitter DM 與我聯繫。我會在那裏幫助你!????

專注分享當下最實用的前端技術。關注前端達人,與達人一起學習進步!

長按關注"前端達人"

發佈了75 篇原創文章 · 獲贊 529 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章