微前端——前端開發新體驗

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"團隊在去年使用微前端架構重新構建了一個門戶站點。通過引入微前端架構,解決了單體架構下、多團隊協作所產生的相互影響,相互依賴的問題,使得團隊更大程度的獲得了自治權。本文選取業務模型,技術實踐,服務資產管理三個視角,通過分析項目迭代開發存在的問題,嘗試說明原有單體架構下的痛點,以及引入微前端如何解決痛點問題,從而改善各個團隊工作方式。最後,我們將總結分享在對門戶站點進行微前端改造過程中所汲取到的經驗和教訓。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"背景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"早前,團隊構建了一個一站式門戶站點,需要集成多個系統,包括:訂單系統,偏好推薦系統,產品系統等;歷時半年,選擇React & Redux作爲前端開發框架和工具,使用Kotlin作爲BFF開發語言,以單體應用的形式,團隊將該門戶站點發布到AWS中投入使用。此後的幾個月,隨着交付更迭,隨着越來越多團隊加入,我們遇到了一些團隊協作的問題。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"業務模型 - 交付計劃相互影響和高額的溝通成本"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以訂單,偏好推薦和產品爲例,下圖描述了該站點上各個團隊的業務模型:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/44\/4498f78785fd825b1318f93d5b176e47.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由圖中灰框可知,項目分爲前後端兩部分:前端和相應的BFF,多個團隊在相同的代碼倉庫中共享代碼,共享環境,協同開發。這種模型存在的問題是:當某團隊的一次更新影響範圍較廣時,很可能會影響到其他團隊開發計劃、發佈計劃。對於PM \/ BA而言,多團隊協作項目中不必要的耦合會使交付變得不安全且不可預測。一個功能的誕生,從探索,評估,計劃,到最終交付,需要跨團隊大量溝通,包括業務之間的相互影響,技術決策,交付計劃。爲了使所有團隊儘可能按計劃交付,我們不得不增加協調成本並提前計劃。不幸的是,通常問題不會在這一過程開始時發生,而是直到過程後期才被發現。它就像一枚複雜的炸彈,使估算無效,降低交付的穩定性和可預測性。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"技術實踐 - 強制遵循相同的實踐和技術棧"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下圖展示技術實踐具體情況:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/0d\/0d8a40b2f162268b6b0abc3afdb32bc1.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過上圖我們看出,多個貢獻者團隊以及一個管理團隊共享代碼庫,共享流水線,共享環境。而作爲一個交付團隊,因爲共享,不得不接受不熟悉的技術棧;被迫接受更多流水線運行時間以通過所有團隊的測試用例;因爲業務關聯而被迫相互學習業務知識。而相互獨立的代碼庫、熟悉的技術棧,輕量便捷的規範準則、合理而高效的流程,纔是一個交付團隊持續不斷追求的理想狀態。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"服務資產管理 - 框架或依賴升級帶來的影響"}]},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/bb\/bb965073b534f9508e52a68f4d3c2d98.jpeg","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從服務、資產的角度來講,受限於技術架構與實踐,多個團隊共用相同的工件與產品環境。爲了能夠讓每一個團隊都能正常工作,大家被迫妥協、接受滿足所有團隊的管理流程。而實際上各個團隊產品迭代發佈都是對工件和生產環境的更新,這種更新需要整體迴歸測試的保證。甚至線上產品事故支持時,我們需要解決當站點產生的事故,如何將錯誤準確導向特定的開發團隊的問題。所有團隊經過多次取捨與妥協後,失去了應有的自治權。一個重前端的項目中,整體式架構、多團隊協作開發的模式爲我們帶來的思考是:業務如何做到獨立交付?如何做到自主技術決策?如何保障團隊對服務、產品的絕對控制權?微前端架構很好的回答了以上三個問題。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"微前端架構及其價值"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"業務交付上,微前端作爲DDD在前端的擴展,按照與後端領域相同的拆分方法,可以將前端拆分成獨立的Micro App。各個Micro App僅與對應的BFF進行通訊,BFF只聚合下游服務,從下游服務獲取數據,從而讓Micro App在業務層面實現完全拆分。每個Micro App是一個完整的業務領域,擁有獨立業務價值,業務變化完全由各個團隊自己負責。業務變化幾乎不會影響整個站點。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/18\/189c8876440ac8ea321354e33edead27.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同時,作爲交付團隊,團隊可以專注於自己的業務領域,創建並維護邊界清晰的前端模塊,最大程度地降低各個領域之間耦合關係。這種清晰的業務邊界,極低的耦合關係迎合了PM\/BA的訴求:業務模塊足夠獨立,交付更加安全且可預測,交付計劃被影響的概率降低。在開發模式方面,給與團隊足夠的自主決策權。團隊可以自己決定代碼保存在哪裏,靈活選擇適合編程語言的編程規範,流水線組成,CD實踐等,如下圖所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/19\/197e3a1ca35d7cde2dce42a3850382d8.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過分離最終交付工件,團隊獲得了獨立的代碼庫,熟悉的技術棧,合適的規範,輕量靈活的流水線及高效的發佈流程。在服務資產管理方面,不同工件對應於獨立的產品環境,達到各個Micro App之間產品環境隔離的目的。這樣,對整個產品環境的迴歸測試變成了對某個Micro App的迴歸測試。各個團隊只需要響應自己維護產品的線上事故,對自己負責的Micro App制定On-Call support輪值計劃。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.geekbang.org\/infoq\/7c\/7c76909c23bb0fba7a6176d96c1aea65.png","alt":"圖片","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有關SingleSPA的更多信息,請參考這裏。此處僅以偏好推薦系統爲例,展示微前端體系結構中包含的所有重要組件。用戶通過root container訪問偏好推薦系統。一旦root container收到訪問偏好推薦系統的請求,它將通過import-map找到其最新的下載地址。從圖中可以看出,偏好推薦提醒作爲Micro App在環境中幾乎是完全隔離的,偏好推薦團隊可以根據需要輕鬆地對其進行更新。總結起來,微前端改變了多團隊的協作方式:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"團隊工作在基於業務領域劃分的端到端項目,這使我們的交付更加穩定和可預測:團隊可以更加關注領域內業務價值的實現以及對項目的迭代更新。業務迭代更新取決於團隊自身。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"能夠充分進行自主技術決策,維護小而聚合的代碼庫及相關基礎設施:團隊擁有完全自主的決定權,定製更靈活地,符合團隊自身和工作內容的技術實踐。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"獨立進行測試與部署:更新、升級的影響範圍被控制在每一個Micro App中,各團隊只需負責開發、維護自己的Micro App即可。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此外,而上文提到的import-map組件,本質上是一種動態加載JS的機制實現,這種機制爲吸引更多人、更多團隊、乃至第三方成爲所構建平臺的貢獻者提供了可能。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"實踐經驗與教訓"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"微前端架構給團隊帶來了極大的自治權,團隊在領域內、在自己維護的Micro App中獲得了極大的自主權,可以更加靈活的選擇更合適的方式解決實際的業務問題。在認清這些紅利外,微前端並不能解決所有問題,這種架構實踐並非沒有代價,主要表現在引入的性能問題,要求較高的DevOps以及管理複雜度。對此我們需要引入其他技術手段克服:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"性能:引入微前端框架,瀏覽器加載頁面時需要最先加載微前端框架代碼,而後加載各個組件和MFA,這無疑加重了瀏覽器的加載負擔。爲了減少頁面加載時間,一方面需要藉助工件最小化,Tree shaking,以及在Cloudfront & 瀏覽器等層面上的緩存等手段加快每一個JS腳本文件的加載速度;另一方面需要在確保功能完整的情況下,儘可能提高JS腳本並行加載能力。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DevOps:微前端架構實踐對團隊CD能力也有要求。可以說與CD實踐相輔相成。通過流水線保持Micro App引用最新,這需要較高的自動化要求和高度Infrastructure as Code實踐。而爲了高度的自動化,也需要足夠有信心的測試覆蓋,如此才能保持業務的持續交付,持續集成。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"管理複雜度:多個不同的Micro App組件同時加載,通過命名規範可以解決潛在的CSS\/JS衝突問題;由於UI在前端被分割成了一個個邊界清晰的Micro App,我們需要一定的設計規範,保持跨Micro App的設計一致性,如統一的配色樣式,風格接近的操作方式,行爲一致的錯誤處理等。我們相信,再追求高度自治的情況下,並不能以犧牲流暢統一的用戶體驗爲前提。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文轉載自:ThoughtWorks洞見(ID:TW-Insights)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文鏈接:"},{"type":"link","attrs":{"href":"https:\/\/mp.weixin.qq.com\/s\/YjNiLIIq0IuP7h5o4D4lGQ","title":"xxx","type":null},"content":[{"type":"text","text":"微前端——前端開發新體驗"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章