在過去的幾星期裏,隨着 Martin Fowler 博客上,那篇 Cam Jackson 寫的微前端的文章發佈,處處都在討論 Microfrontend。做爲一個微前端 「專家」,我也分享一下:如何去落地微前端。前端
微前端是一種相似於微服務的架構,它將微服務的理念應用於瀏覽器端,即將單頁面前端應用由單一的單體應用轉變爲多個小型前端應用聚合爲一的應用。各個前端應用還能夠獨立開發、獨立部署。同時,它們也能夠在共享組件的同時進行並行開發——這些組件能夠經過 NPM 或者 Git Tag、Git Submodule 來管理。web
爲何須要微前端?
微前端不是銀彈,它和微服務同樣會帶來大量的挑戰。數據庫
遺留系統遷移。解決遺留系統,纔是人們採用微前端方案最重要的緣由
聚合前端應用。微服務架構,能夠解耦後端服務間依賴。而微前端,則關注於聚合前端應用。
熱鬧驅動開發。新的技術,既然很熱鬧,那麼就學吧。
微前端的實現,意味着對前端應用的拆分。拆分應用的目的,並不僅是爲了架構上好看,還爲了提高開發效率。bootstrap
爲此,微前端帶來這麼一系列的好處:後端
應用自治。只須要遵循統一的接口規範或者框架,以便於系統集成到一塊兒,相互之間是不存在依賴關係的。
單一職責。每一個前端應用能夠只關注於本身所須要完成的功能。
技術棧無關。你可使用 Angular 的同時,又可使用 React 和 Vue。
除此,它也有一系列的缺點:瀏覽器
應用的拆分基礎依賴於基礎設施的構建,一旦大量應用依賴於同一基礎設施,那麼維護變成了一個挑戰。
拆分的粒度越小,便意味着架構變得複雜、維護成本變高。
技術棧一旦多樣化,便意味着技術棧混亂
畢竟沒有銀彈。前端框架
如何設計微前端架構?
就當前而言,要設計出一個微前端應用不是一件容易的事——尚未最佳實踐。在不一樣的落地案例裏,使用的都是不一樣的方案。出現這種狀況的主要緣由是,每一個項目所面臨的狀況、所使用的技術都不盡相同。爲此,咱們須要瞭解一些基礎的微前端模式。服務器
架構模式
微前端應用間的關係來看,分爲兩種:基座模式(管理式)、自組織式。分別也對應了二者不一樣的架構模式:架構
基座模式。經過一個主應用,來管理其它應用。設計難度小,方便實踐,可是通用度低。
自組織模式。應用之間是平等的,不存在相互管理的模式。設計難度大,不方便實施,可是通用度高。
就當前而言,基座模式實施起來比較方便,方案上便也是蠻多的。框架
而不論種方式,都須要提供一個查找應用的機制,在微前端中稱爲服務的註冊表模式。和微服務架構類似,不管是哪一種微前端方式,也都須要有一個應用註冊表的服務,它能夠是一個固定值的配置文件,如 JSON 文件,又或者是一個可動態更新的配置,又或者是一種動態的服務。它主要作這麼一些內容:
應用發現。讓主應用能夠尋找到其它應用。
應用註冊。即提供新的微前端應用,嚮應用註冊表註冊的功能。
第三方應用註冊。即讓第三方應用,能夠接入到系統中。
訪問權限等相關配置。
應用在部署的時候,即可以在註冊表服務中註冊。若是是基於註冊表來管理應用,那麼使用基座模式來開發比較方便。
設計理念
在筆者實踐微前端的過程當中,發現瞭如下幾點是咱們在設計的過程當中,須要關注的內容:
中心化:應用註冊表。這個應用註冊表擁有每一個應用及對應的入口。在前端領域裏,入口的直接表現形式能夠是路由,又或者對應的應用映射。
標識化應用。 咱們須要一個標識符來標識不一樣的應用,以便於在安裝、卸載的時候,能尋找到指定的應用。一個簡單的模式,就是經過康威定律來命名應用。
應用生命週期管理。
高內聚,低耦合。
生命週期
前端微架構與後端微架構的最大不一樣之處,也在於此——生命週期。微前端應用做爲一個客戶端應用,每一個應用都擁有本身的生命週期:
Load,決定加載哪一個應用,並綁定生命週期
bootstrap,獲取靜態資源
Mount,安裝應用,如建立 DOM 節點
Unload,刪除應用的生命週期
Unmount,卸載應用,如刪除 DOM 節點、取消事件綁定
這部分的內容事實上,也就是微前端的一個難點所在,如何以合適的方式來加載應用——畢竟每一個前端框架都各自不一樣,其所須要的加載方式也是不一樣的。當咱們決定支持多個框架的時候,便須要在這一部分進入更細緻的研究。
如何拆分?
隨後,咱們要面臨的一個挑戰是:如何去拆分應用。
技術方式
從技術實踐上,微前端架構能夠採用如下的幾種方式進行:
路由分發式。經過 HTTP 服務器的反向代理功能,來將請求路由到對應的應用上。
前端微服務化。在不一樣的框架之上設計通信、加載機制,以在一個頁面內加載對應的應用。
微應用。經過軟件工程的方式,在部署構建環境中,組合多個獨立應用成一個單體應用。
微件化。開發一個新的構建系統,將部分業務功能構建成一個獨立的 chunk 代碼,使用時只須要遠程加載便可。
前端容器化。經過將 iFrame 做爲容器,來容納其它前端應用。
應用組件化。藉助於 Web Components 技術,來構建跨框架的前端應用。
實施的方式雖然多,可是都是依據場景而採用的。有些場景下,可能沒有合適的方式;有些場景下,則能夠同時使用多種方案。
路由分發式
**路由分發式微前端,即經過路由將不一樣的業務分發到不一樣的、獨立前端應用上。**其一般能夠經過 HTTP 服務器的反向代理來實現,又或者是應用框架自帶的路由來解決。以下圖所示:
就當前而言,路由分發式的架構應該是採用最多、最容易的 「微前端」 方案。可是
前端微服務化
**前端微服務化,是微服務架構在前端的實施,每一個前端應用都是徹底獨立(技術棧、開發、部署、構建獨立)、自主運行的,最後經過模塊化的方式組合出完整的前端應用。**其架構以下圖所示:
採用這種方式意味着,一個頁面上同時存在二個及以上的前端應用在運行。而路由分發式方案,則是一個頁面只有惟一一個應用。
組合式集成:微應用化
**微應用化,即在開發時,應用都是以單1、微小應用的形式存在,而在運行時,則經過構建系統合併這些應用,組合成一個新的應用。**其架構以下圖所示:
微應用化更多的是以軟件工程的方式,來完成前端應用的開發,所以又能夠稱之爲組合式集成。對於一個大型的前端應用來講,採用的架構方式,每每會是經過業務做爲主目錄,然後在業務目錄中放置相關的組件,同時擁有一些通用的共享模板。
微件化
**微件(widget),指的是一段能夠直接嵌入在應用上運行的代碼,它由開發人員預先編譯好,在加載時不須要再作任何修改或者編譯。**而微前端下的微件化則指的是,每一個業務團隊編寫本身的業務代碼,並將編譯好的代碼部署(上傳或者放置)到指定的服務器上,在運行時,咱們只須要加載相應的業務模塊便可。對應的,在更新代碼的時候,咱們只須要更新對應的模塊便可。下圖即是微件化的架構示意圖:
在非單面應用時代,要實現微件化方案,是一件特別容易的事。從遠程加載來對應的 JavaScript 代碼,在瀏覽器上執行,生成對應的組件嵌入到頁面的相應部分。對於業務組件也是相似的,提早編寫好咱們的業務組件,當須要對應的組件時再響應、執行。
前端容器化
前端容器:iframe
iframe 做爲一個很是 「古老」 的,人人都以爲普通的技術,卻一直很管用。它能有效地將另外一個網頁/單頁面應用嵌入到當前頁面中,兩個頁面間的 CSS 和 JavaScript 是相互隔離的——除去 iframe 父子通訊部分的代碼,它們之間的代碼是徹底不相互干擾的。iframe 便至關因而建立了一個全新的獨立的宿主環境,相似於沙箱隔離,它意味着前端應用之間能夠相互獨立運行。
結合 Web Components 構建
Web Components 是一套不一樣的技術,容許開發者建立可重用的定製元素(它們的功能封裝在代碼以外),而且在 web 應用中使用它們。
目前困擾 Web Components 技術推廣的主要因素,在於瀏覽器的支持程度。在 Chrome 和 Opera 瀏覽器上,對於 Web Components 支持良好,而對於 Safari、IE、Firefox 瀏覽器的支持程度,並無那麼理想。
業務拆分
與微服務相似,要劃分不一樣的前端邊界,不是一件容易的事。就當前而言,如下幾種方式是常見的劃分微前端的方式:
按照業務拆分。
按照權限拆分。
按照變動的頻率拆分。
按照組織結構拆分。利用康威定律來進一步拆分前端應用。
跟隨後端微服務劃分。實踐證實, DDD 與事件風暴是一種頗爲有效的後端微前端拆分模式,對於前端來講,它也很有有效——直接跟蹤後端服務。
每一個項目都有本身特殊的背景,切分微前端的方式便不同。即便項目的類型類似,也存在一些細微的差別。
微前端以外
若是微前端對於大家來講困境重重,還有一些不錯的架構模式能夠採用。
應用微化架構
應用微化架構,是一種開發時總體,構建時拆分,運行時分離的前端架構模式。即應用微化架構從一份代碼中,構建出適用於不一樣環境的多套目標代碼。實現上它是一種:
構建時拆分架構。
代碼刪除架構。笑,以刪代碼的方式,來造成每一個前端應用。
微前端準備式架構。即,隨時能夠拆分爲多個前端應用。
因爲它與微應用化的類似性,咱們將它與微應用化作一個對比。它與微應用化不一樣的是,應用微化是在構建時對應用進行拆分,而非在本地模式下對應用拆分。類似的是,它也是基於構建系統的應用拆分方式。
即:微應用化,是一個隨時可合併式架構。而應用微化,則是一個隨時可拆分式架構。
它不只僅是一個適合於前端的架構模式,也是一適用於後端的架構模式。
整潔前端架構
Clean Architecture 是由 Robert C. Martin 在 2012 年提出的架構模式。它具備這麼一些特色:框架無關性、可被測試、UI 無關性、數據庫無關性、外部機構(agency)無關性。
對於前端架構來講,Clean Architecure 其實是:Clean Architecture + MVP + 組件化。以下圖所示:
考慮到應用的規模,這裏以 Angular + TypeScript 做爲示例:
這種架構模式特別適合於:組織內即寫前端又同後端的團隊。它易於映射先後端 API,且可使用 usecase 做爲防腐層。
沒有銀彈。不得不說起的是,對於小規模的團隊來講,它帶來的弊端可能會遠遠大於好處——帶來大量冗餘的代碼。儘管經過 Angular Schematics 能夠經過參數來生成代碼,可是這種分層架構地於簡單的應用來講,仍是過於複雜、難以上手。對於不寫測試的項目來講 ,usecase 也不能帶來它們所承諾的好處。
結論微前端不是銀彈,當前也沒有最佳實踐,可是這是一個很是好的學習機會。---------------------