
本文將分享我和我的團(tuán)隊(duì)在使用微前端時(shí)學(xué)到的重要經(jīng)驗(yàn)。在兩年的時(shí)間里,我們發(fā)現(xiàn)了這種架構(gòu)的許多問(wèn)題,也犯了同樣多的錯(cuò)誤。所以,現(xiàn)在分享出來(lái),以幫助你解決或避免它們。
讓我們首先回顧一下什么是微前端架構(gòu),然后深入了解它們的陷阱以及如何避免每一個(gè)陷阱。
微前端簡(jiǎn)述
Martin Fowler將微前端開發(fā)方法定義為:
一種架構(gòu)風(fēng)格,獨(dú)立交付的前端應(yīng)用程序被組成一個(gè)更大的整體。
當(dāng)應(yīng)用于Web開發(fā)時(shí),它意味著有許多獨(dú)立的小型前端應(yīng)用程序是同一個(gè)網(wǎng)站或Web應(yīng)用程序的一部分。正如這里已經(jīng)提到的,我的團(tuán)隊(duì)已經(jīng)成功地使用了這種方法。特別是我們有機(jī)會(huì)利用它的所有優(yōu)點(diǎn),如可擴(kuò)展性、技術(shù)獨(dú)立性和可維護(hù)性。另一方面,從長(zhǎng)遠(yuǎn)來(lái)看,我們注意到一些嚴(yán)重的問(wèn)題。所以,我們決定放棄這種架構(gòu)方式,轉(zhuǎn)而回到更傳統(tǒng)的單體架構(gòu)。
這意味著,我們不僅學(xué)到了微前端的優(yōu)點(diǎn),也學(xué)到了它們的主要缺點(diǎn)?,F(xiàn)在讓我們深入了解它們,看看我們應(yīng)該如何避免或解決它們。
1. 冗余的依賴關(guān)系
根據(jù)定義,每個(gè)微前端應(yīng)用程序都是獨(dú)立于其他應(yīng)用程序的。換句話說(shuō),一個(gè)微型前端架構(gòu)涉及到一個(gè)以上的前端應(yīng)用程序,它們也應(yīng)該能夠在沒有其他應(yīng)用程序的情況下工作。為了實(shí)現(xiàn)這一點(diǎn),它們中的每一個(gè)都有自己的依賴關(guān)系。所以,從整體上看,你會(huì)失去使用包管理器的好處。事實(shí)上,你的整個(gè)應(yīng)用程序很可能由許多版本的相同庫(kù)組成,分散在各個(gè)微前端。
這無(wú)疑是一個(gè)問(wèn)題,因?yàn)樗鼓愕木W(wǎng)絡(luò)應(yīng)用不必要地比它的單體對(duì)應(yīng)物大。這就落在了終端用戶身上,他們被迫下載更多的數(shù)據(jù)。此外,這還會(huì)影響到渲染時(shí)間,從而影響到Google Web Vitals 的得分,也影響到你的網(wǎng)站的SEO。
如何解決這個(gè)問(wèn)題
一個(gè)可能的解決方案包括三個(gè)步驟。首先,確定所有微前端的通用庫(kù)集。第二,創(chuàng)建一個(gè)包含所有共享庫(kù)的微前端。然后,更新你的微前端,使他們的構(gòu)建包從這個(gè)共享項(xiàng)目中導(dǎo)入所需的庫(kù)。
正如 Martin Fowler的原始博文中所描述的那樣,這個(gè)想法來(lái)自于應(yīng)用程序之間的共享依賴關(guān)系,這帶來(lái)了許多障礙,不能被認(rèn)為是一項(xiàng)容易完成的任務(wù)。因此,在你試圖實(shí)現(xiàn)這一目標(biāo)時(shí),請(qǐng)記住這一點(diǎn)。
2. 沖突和重疊的風(fēng)格
同樣,技術(shù)和團(tuán)隊(duì)的獨(dú)立性很好,但它也會(huì)帶來(lái)一些問(wèn)題。這在處理風(fēng)格問(wèn)題時(shí)尤其如此。事實(shí)上,從業(yè)務(wù)角度來(lái)看,每個(gè)微型前端都不能有自己的風(fēng)格。這是因?yàn)槟憧隙ú幌M愕膽?yīng)用程序看起來(lái)由許多補(bǔ)丁組成。所有的東西都應(yīng)該看起來(lái)一致,無(wú)論是在風(fēng)格、用戶界面還是用戶體驗(yàn)方面。
另一個(gè)由多個(gè)前端作為同一應(yīng)用程序的一部分而產(chǎn)生的問(wèn)題是,你可能最終會(huì)出現(xiàn)無(wú)意的CSS規(guī)則覆蓋。在處理微型前端時(shí),CSS方面的非預(yù)期的重疊是很常見的,而且你可能在部署你的應(yīng)用程序后才發(fā)現(xiàn)它們。原因是每個(gè)團(tuán)隊(duì)通常只在自己的應(yīng)用程序上工作,而在部署前沒有看到全貌。
這些問(wèn)題會(huì)對(duì)你的品牌聲譽(yù)產(chǎn)生負(fù)面影響。而且,終端用戶將為這些不一致的地方付出代價(jià),特別是在用戶界面方面。
如何解決這個(gè)問(wèn)題
當(dāng)涉及到 UI 和 UX 時(shí),唯一可能的解決方案是確保每個(gè)團(tuán)隊(duì)相互交談并考慮到相同的結(jié)果。此外,在上述共享微前端項(xiàng)目中添加樣式組件可能會(huì)有所幫助。然而,這將使每個(gè)微前端應(yīng)用程序都依賴于它,并因此破壞了底層的獨(dú)立性。但至少它會(huì)避免你的應(yīng)用程序作為一個(gè)整體看起來(lái)是異構(gòu)的。
如果你想避免 CSS 重疊,一個(gè)解決方案是在前端容器中添加一個(gè) ID <div>。然后,配置 webpack 以在每個(gè) CSS 規(guī)則之前插入此 ID。否則,您可以決定采用 CSS 方法,例如 BEM(Block-Element-Modifier)。這鼓勵(lì)你將網(wǎng)站視為可重用組件塊的集合,其類名在你的項(xiàng)目中應(yīng)該是唯一的。
3. 性能不佳
在同一個(gè)頁(yè)面上運(yùn)行一個(gè)以上的JavaScript前端應(yīng)用程序,會(huì)因此而降低整個(gè)應(yīng)用程序的速度。這是因?yàn)槊總€(gè)框架實(shí)例都需要CPU、內(nèi)存和網(wǎng)絡(luò)帶寬方面的資源。
另外,請(qǐng)記住,當(dāng)測(cè)試你的微型前端與其他人隔離時(shí),你可能不會(huì)注意到這一點(diǎn)。當(dāng)一個(gè)框架的多個(gè)實(shí)例同時(shí)運(yùn)行時(shí),問(wèn)題就開始了。這是因?yàn)?,如果它們是?dú)立運(yùn)行的,它們就不必像部署時(shí)那樣分享底層機(jī)器的資源。
如何解決這個(gè)問(wèn)題
解決這個(gè)問(wèn)題的一個(gè)想法是,加強(qiáng)團(tuán)隊(duì)溝通,避免做同樣的調(diào)用和闡述。然后,將他們的結(jié)果存儲(chǔ)在每個(gè)微前端都能訪問(wèn)的地方,或者讓他們?cè)趫?zhí)行繁重的操作之前進(jìn)行溝通,以驗(yàn)證之前是否已經(jīng)檢索或生成過(guò)相同的數(shù)據(jù)。
另外,當(dāng)涉及到性能時(shí),你必須用所有的微前端來(lái)測(cè)試應(yīng)用程序,而不要僅僅依靠對(duì)每個(gè)微前端的測(cè)試。
4. 前端之間的通信
最初,你不需要讓你的微型前端進(jìn)行通信,除非在極少數(shù)情況下。這可能會(huì)愚弄你,讓你以為會(huì)一直這樣。另外,雖然微前端的架構(gòu)模式是關(guān)于獨(dú)立性的,但這是與通信相對(duì)的。
當(dāng)應(yīng)用程序作為一個(gè)整體增長(zhǎng)時(shí),使你的微前端能夠毫不費(fèi)力地相互溝通可能會(huì)成為一個(gè)優(yōu)先事項(xiàng)。最重要的是,如果你想不斷地重復(fù)同樣的操作,特別是在它們不是空閑的情況下。
另外,如上所述,為了實(shí)現(xiàn)更高的性能,溝通是必要的。例如,你不希望你的應(yīng)用程序?yàn)榱藱z索相同的數(shù)據(jù)而兩次調(diào)用相同的API,并不必要地拖慢你的服務(wù)器。
如何解決這個(gè)問(wèn)題
解決方案是基于存儲(chǔ)在cookie或localStorage中的共享狀態(tài),或基于自定義定義的事件,實(shí)現(xiàn)一個(gè)自定義的信息傳遞層。正如你所想象的,實(shí)現(xiàn)這一點(diǎn)是有成本的,而且很快就會(huì)變得復(fù)雜和麻煩,難以處理。另外,要考慮到通信會(huì)引入開銷。所以,你必須確定你所構(gòu)建的東西會(huì)帶來(lái)真正的好處,并且不會(huì)使你的應(yīng)用程序變得更加緩慢。
5. 團(tuán)隊(duì)之間的溝通問(wèn)題
大型團(tuán)隊(duì)的溝通可能是一個(gè)問(wèn)題,但最糟糕的莫過(guò)于幾個(gè)團(tuán)隊(duì)之間的溝通。這是因?yàn)橛卸鄠€(gè)團(tuán)隊(duì)在不同的代碼庫(kù)上工作意味著尋找可重用的功能、函數(shù)和實(shí)用程序變得更加困難。這在代碼的可發(fā)現(xiàn)性方面是很糟糕的,因此也是可重用的。換句話說(shuō),你可能會(huì)很容易地在不同的微觀前臺(tái)出現(xiàn)相同組件的重復(fù)實(shí)現(xiàn)。
如何解決這個(gè)問(wèn)題
解決方案是在一開始就支持團(tuán)隊(duì)之間的溝通邏輯。如上所述,這涉及到為所采用的每種技術(shù)擁有一個(gè)具有可重復(fù)使用資源的項(xiàng)目。但是,有這樣一個(gè)項(xiàng)目而不保持更新,會(huì)使它變得毫無(wú)用處。
因此,你必須允許每個(gè)團(tuán)隊(duì)向其添加組件和庫(kù)。此外,擁有一個(gè)專門的團(tuán)隊(duì)可以使整個(gè)過(guò)程更容易。事實(shí)上,對(duì)于一個(gè)獨(dú)立和孤立的團(tuán)隊(duì)來(lái)說(shuō),可能不容易理解哪些元素將被一個(gè)以上的微型前端所共享。
此外,不要把技術(shù)獨(dú)立看成是幾個(gè)孤立的團(tuán)隊(duì)。恰恰相反,讓團(tuán)隊(duì)之間互相交流,并讓自己保持最新的狀態(tài),對(duì)項(xiàng)目的成功至關(guān)重要。因此,在采用微型前端架構(gòu)時(shí),培養(yǎng)一種溝通文化必須是關(guān)鍵因素之一。
總結(jié)
在這篇文章中,我們看了微前端架構(gòu)方法的五個(gè)最大的陷阱,并以我的團(tuán)隊(duì)兩年來(lái)每天與之打交道時(shí)積累的經(jīng)驗(yàn)為依據(jù)。盡管微前端方法讓開發(fā)者把一個(gè)前端應(yīng)用分成更小的獨(dú)立部分,但這并不意味著每個(gè)團(tuán)隊(duì)也應(yīng)該是孤立的。相反,分享解決方案、組件、資源和知識(shí)是成功的關(guān)鍵。
不幸的是,我們作為一個(gè)團(tuán)隊(duì)并不了解這一點(diǎn)。因此,我們被迫放棄了我們的微型前端之旅。但我們從這次冒險(xiǎn)中學(xué)到了很多東西,我希望分享導(dǎo)致我們失敗的主要原因以及如何避免或抵消它們是有用的。
原文標(biāo)題:??5 Pitfalls of Using Micro Frontends and How to Avoid Them??
作者:Antonello Zanini



























