瞭解什麼是微前端

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

爲何你的代碼是一個單體?

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

什麼是微服務?

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

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

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

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

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

解決微服務中的瓶頸問題: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,已解析的路由將傳遞到ContentMicroApp。 ContentMicroApp是一個獨立的服務器,它將僅使用 /:id 進行調用。

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

服務器端呈現是一個棘手的問題。 若是你正在考慮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 的最小功能能夠歸納爲 initserve。

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

StitchingServer

StitchingServerMicroAppServers 提供註冊端點。 當 MicroAppServer 將本身註冊到 StichingServer 時,StichingServer 會記錄MicroAppServer 的聲明。

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

解析M icroAppServer 及其全部依賴項後,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 與我聯繫。 我會在那裏幫助你!🙂

翻譯:Vincent.W
原文:Understanding Micro Frontends

相關文章
相關標籤/搜索