作為前端開發(fā)人員,這些年來你一直在開發(fā)單體應(yīng)用题造,即使你已經(jīng)知道這是一個不好的做法。 您將代碼劃分為組件,使用?require?或?import?并將package.json中定義的npm包或已安裝的子git倉庫添加到項(xiàng)目中滚澜,但最終構(gòu)建了一個整體。 是時候改變它了嫁怀。
如果有想學(xué)習(xí)編程的初學(xué)者设捐,可來我們的前端直播授課群的哦:571671034里面免費(fèi)送整套系統(tǒng)的前端教程借浊!
為什么你的代碼是一個單體?
除了已經(jīng)實(shí)現(xiàn)了微前端的應(yīng)用之外萝招,所有前端應(yīng)用本質(zhì)上都是單一的應(yīng)用蚂斤。 原因是如果您正在使用 React 庫進(jìn)行開發(fā),并且如果您有兩個團(tuán)隊即寒,則兩個團(tuán)隊都應(yīng)該使用相同的React 庫橡淆,并且兩個團(tuán)隊?wèi)?yīng)該在部署時保持同步,并且在代碼合并期間始終會發(fā)生沖突母赵。 它們沒有完全分離逸爵,很可能它們維護(hù)著相同的倉庫并具有相同的構(gòu)建系統(tǒng)。 單體應(yīng)用的退出被標(biāo)志為微服務(wù)的出現(xiàn)凹嘲。 但是它適用于后端师倔!:scream:
什么是微服務(wù)?
對于微服務(wù)周蹭,一般而言最簡單的解釋是趋艘,它是一種開發(fā)技術(shù),允許開發(fā)人員為平臺的不同部分進(jìn)行獨(dú)立部署凶朗,而不會損害其他部分瓷胧。 獨(dú)立部署的能力允許他們構(gòu)建孤立或松散耦合的服務(wù)。 為了使這個體系結(jié)構(gòu)更穩(wěn)定棚愤,有一些規(guī)則要遵循搓萧,可以總結(jié)如下:每個服務(wù)應(yīng)該只有一個任務(wù),它應(yīng)該很小宛畦。 所以負(fù)責(zé)這項(xiàng)服務(wù)的團(tuán)隊?wèi)?yīng)該很小瘸洛。 關(guān)于團(tuán)隊和項(xiàng)目的規(guī)模,?James Lewis 和 Martin Fowler?在互聯(lián)網(wǎng)上做出的最酷解釋之一如下:
在我們與微服務(wù)從業(yè)者的對話中次和,我們看到了一系列服務(wù)規(guī)模反肋。 報道的最大規(guī)模遵循亞馬遜關(guān)于Two Pizza Team的概念(即整個團(tuán)隊可以由兩個比薩餅供給),意味著不超過十幾個人踏施。 在規(guī)模較小的規(guī)模上石蔗,我們已經(jīng)看到了一個由六人組成的團(tuán)隊支持六項(xiàng)服務(wù)的設(shè)置。
我畫了一個簡單的草圖畅形,為整體和微服務(wù)提供了直觀的解釋:
從上圖可以理解抓督,微服務(wù)中的每個服務(wù)都是一個獨(dú)立的應(yīng)用,除了UI束亏。 UI仍然是一體的铃在! 當(dāng)一個團(tuán)隊處理所有服務(wù)并且公司正在擴(kuò)展時,前端團(tuán)隊將開始苦苦掙扎并且無法跟上它,這是這種架構(gòu)的瓶頸定铜。
除了瓶頸之外阳液,這種架構(gòu)也會導(dǎo)致一些組織問題。 假設(shè)公司正在發(fā)展并將采用需要?跨職能?小團(tuán)隊的敏捷開發(fā)方法揣炕。 在這個常見的例子中帘皿,產(chǎn)品所有者自然會開始將故事定義為前端和后端任務(wù),而?跨職能?團(tuán)隊將永遠(yuǎn)不會成為真正的?跨職能?部門畸陡。 這將是一個淺薄的泡沫鹰溜,看起來像一個敏捷的團(tuán)隊,但它將在內(nèi)部分開丁恭。 關(guān)于管理這種團(tuán)隊的更多信息將是一項(xiàng)非常重要的工作曹动。 在每個計劃中,如果有足夠的前端任務(wù)或者sprint中有足夠的后端任務(wù)牲览,則會有一個問題墓陈。 為了解決這里描述的所有問題和許多其他問題,幾年前出現(xiàn)了?微前端?的想法并且開始迅速普及第献。
解決微服務(wù)中的瓶頸問題:Micro Frontends:tada:
解決方案實(shí)際上非常明顯贡必,采用了多年來為后端服務(wù)工作的相同原則:將前端整體劃分為小的UI片段。 但UI與服務(wù)并不十分相似庸毫,它是最終用戶與產(chǎn)品之間的接口仔拟,應(yīng)該是一致且無縫的。 更重要的是飒赃,在單頁面應(yīng)用時代利花,整個應(yīng)用在客戶端的瀏覽器上運(yùn)行。 它們不再是簡單的HTML文件盒揉,相反晋被,它們是復(fù)雜的軟件兑徘,達(dá)到了非常復(fù)雜的水平刚盈。 現(xiàn)在我覺得微型前端的定義是必要的:
Micro Frontends背后的想法是將網(wǎng)站或Web應(yīng)用視為獨(dú)立團(tuán)隊擁有的功能組合。 每個團(tuán)隊都有一個獨(dú)特的業(yè)務(wù)或任務(wù)領(lǐng)域挂脑,做他們關(guān)注和專注的事情藕漱。團(tuán)隊是跨職能的,從數(shù)據(jù)庫到用戶界面開發(fā)端到端的功能崭闲。(micro-frontends.org)
根據(jù)我迄今為止的經(jīng)驗(yàn)肋联,對于許多公司來說,直接采用上面提出的架構(gòu)真的很難刁俭。 許多其他人都有巨大的遺留負(fù)擔(dān)橄仍,這使他們無法遷移到新的架構(gòu)。 出于這個原因,更柔軟的中間解決方案更加靈活侮繁,易于采用和安全遷移至關(guān)重要虑粥。 在更詳細(xì)地概述了體系結(jié)構(gòu)后,我將嘗試提供一些體系結(jié)構(gòu)的洞察宪哩,該體系結(jié)構(gòu)確認(rèn)了上述提議并允許更靈活的方式娩贷。 在深入了解細(xì)節(jié)之前,我需要建立一些術(shù)語锁孟。
整體結(jié)構(gòu)和一些術(shù)語
讓我們假設(shè)我們通過業(yè)務(wù)功能垂直劃分整體應(yīng)用結(jié)構(gòu)彬祖。 我們最終會得到幾個較小的應(yīng)用,它們與單體應(yīng)用具有相同的結(jié)構(gòu)品抽。 但是如果我們在所有這些小型單體應(yīng)用之上添加一個特殊應(yīng)用储笑,用戶將與這個新應(yīng)用進(jìn)行通信,它將把每個小應(yīng)用的舊單體UI組合成一個桑包。 這個新圖層可以命名為?拼接圖層?南蓬,因?yàn)樗鼜拿總€微服務(wù)中獲取生成的UI部件,并為最終用戶組合成一個?無縫?UI哑了,這將是微前端的最直接實(shí)現(xiàn)
為了更好地理解赘方,我將每個小型單體應(yīng)用稱為?微應(yīng)用?,因?yàn)樗鼈兌际仟?dú)立的應(yīng)用弱左,而不僅僅是微服務(wù)窄陡,它們都有UI部件,每個都代表端到端的業(yè)務(wù)功能拆火。
眾所周知跳夭,今天的前端生態(tài)系統(tǒng)功能多樣,而且非常復(fù)雜们镜。 因此币叹,當(dāng)實(shí)現(xiàn)真正的產(chǎn)品時,這種直接的解決方案還不夠模狭。
要解決的問題
雖然這篇文章只是一個想法颈抚,但我開始使用Reddit討論這個想法。 感謝社區(qū)和他們的回復(fù)嚼鹉,我可以列出一些需要解決的問題贩汉,我將嘗試逐一描述。
當(dāng)我們擁有一個完全獨(dú)立的獨(dú)立?微應(yīng)用?時锚赤,如何創(chuàng)建無縫且一致的UI體驗(yàn)匹舞?
好吧,這個問題沒有靈丹妙藥的答案线脚,但其中一個想法是創(chuàng)建一個共享的UI庫赐稽,它也是一個獨(dú)立的微應(yīng)用叫榕。 通過這種方式,所有其他?微應(yīng)用?將依賴于共享的UI庫微應(yīng)用姊舵。 在這種情況下翠霍,我們剛剛創(chuàng)建了一個共享依賴項(xiàng),我們就殺死了獨(dú)立?微應(yīng)用?的想法蠢莺。
另一個想法是在根級共享CSS自定義變量(CSS custom variables)寒匙。 此解決方案的優(yōu)勢在于應(yīng)用之間的全局可配置主題。
或者我們可以簡單地在應(yīng)用團(tuán)隊之間共享一些SASS變量和混合躏将。 這種方法的缺點(diǎn)是UI元素的重復(fù)實(shí)現(xiàn)锄弱,并且應(yīng)該對所有?微應(yīng)用?始終檢查和驗(yàn)證類似元素的設(shè)計的完整性。
我們?nèi)绾未_保一個團(tuán)隊不會覆蓋另一個團(tuán)隊編寫的CSS祸憋?
一種解決方案是通過CSS選擇器名稱進(jìn)行CSS定義会宪,這些名稱由微應(yīng)用名稱精心選擇。 通過將該范圍任務(wù)放在?拼接層?上將減少開發(fā)開銷蚯窥,但會增加?拼接層?的責(zé)任掸鹅。
另一種解決方案可以是強(qiáng)制每個微應(yīng)用成為自定義Web組件(custom web component)。 這個解決方案的優(yōu)點(diǎn)是瀏覽器完成了范圍設(shè)計拦赠,但需要付出代價:使用shadow DOM進(jìn)行服務(wù)器端渲染幾乎是不可能的巍沙。 此外,自定義元素沒有100%的瀏覽器支持荷鼠,特別是IE句携。
我們應(yīng)該如何在微應(yīng)用之間共享全局信息?
這個問題指出了關(guān)于這個主題的最關(guān)注的問題之一允乐,但解決方案非常簡單:HTML 5具有相當(dāng)強(qiáng)大的功能矮嫉,大多數(shù)前端開發(fā)人員都不知道。 例如牍疏,?自定義事件(custom events)?就是其中之一蠢笋,它是在微應(yīng)用中共享信息的解決方案。
或者鳞陨,任何共享的pub-sub實(shí)現(xiàn)或T39可觀察的實(shí)現(xiàn)都可以實(shí)現(xiàn)昨寞。 如果我們想要一個更復(fù)雜的全局狀態(tài)處理程序,我們可以實(shí)現(xiàn)共享的微型Redux炊邦,通過這種方式我們可以實(shí)現(xiàn)更多的相應(yīng)式架構(gòu)编矾。
如果所有微應(yīng)用都是獨(dú)立應(yīng)用熟史,我們?nèi)绾芜M(jìn)行客戶端路由馁害?
這個問題取決于設(shè)計的每個實(shí)現(xiàn), 所有主要的現(xiàn)代框架都通過使用瀏覽器歷史狀態(tài)在客戶端提供強(qiáng)大的路由機(jī)制, 問題在于哪個應(yīng)用負(fù)責(zé)路由以及何時。
我目前的實(shí)用方法是創(chuàng)建一個共享客戶端路由器蹂匹,它只負(fù)責(zé)頂級路由碘菜,其余路由器屬于相應(yīng)的微應(yīng)用。 假設(shè)我們有?/content/:id?路由定義。 共享路由器將解析?/content?忍啸,已解析的路由將傳遞到ContentMicroApp仰坦。 ContentMicroApp是一個獨(dú)立的服務(wù)器,它將僅使用?/:id?進(jìn)行調(diào)用计雌。
我們必須是服務(wù)器端渲染悄晃,但是有可能使用微前端嗎?
服務(wù)器端呈現(xiàn)是一個棘手的問題凿滤。 如果你正在考慮iframes縫合?微應(yīng)用?然后忘記服務(wù)器端渲染妈橄。 同樣,拼接任務(wù)的Web組件也不比iframe強(qiáng)大翁脆。 但是眷蚓,如果每個?微應(yīng)用?能夠在服務(wù)器端呈現(xiàn)其內(nèi)容,那么?拼接層?將僅負(fù)責(zé)連接服務(wù)器端的HTML片段反番。
與傳統(tǒng)環(huán)境集成至關(guān)重要沙热! 但是怎么樣?
為了整合遺留系統(tǒng)罢缸,我想描述我自己的策略篙贸,我稱之為“?漸進(jìn)式入侵?”。
首先枫疆,我們必須實(shí)現(xiàn)拼接層歉秫,它應(yīng)該具有透明代理的功能。 然后我們可以通過聲明一個通配符路徑將遺留系統(tǒng)定義為?微應(yīng)用?:?LegacyMicroApp?养铸。 因此雁芙,所有流量都將到達(dá)拼接層,并將透明地代理到舊系統(tǒng)钞螟,因?yàn)槲覀冞€沒有任何其他微應(yīng)用兔甘。
下一步將是我們的?第一次逐步入侵?:我們將從LegacyMicroApp中刪除主要導(dǎo)航并用依賴項(xiàng)替換它。 這種依賴關(guān)系將是一個使用閃亮的新技術(shù)實(shí)現(xiàn)的?微應(yīng)用?:?NavigationMicroApp?鳞滨。
現(xiàn)在洞焙,拼接層將每個路徑解析為?Legacy Micro App?,它將依賴關(guān)系解析為?Navigation MicroApp?拯啦,并通過連接這兩個來為它們提供服務(wù)澡匪。
然后通過主導(dǎo)航遵循相同的模式來為引導(dǎo)下一步。
然后我們將繼續(xù)從Legacy MicroApp中獲取逐步重復(fù)以上操作褒链,直到?jīng)]有任何遺漏唁情。
如何編排客戶端,這樣我們每次都不需要重新加載頁面甫匹?
拼接層解決了服務(wù)器端的問題甸鸟,但沒有解決客戶端問題惦费。 在客戶端,在將已粘貼的片段作為無縫HTML加載后抢韭,我們不需要每次在URL更改時加載所有部分薪贫。 因此,我們必須有一些異步加載片段的機(jī)制刻恭。 但問題是瞧省,這些片段可能有一些依賴關(guān)系,這些依賴關(guān)系需要在客戶端解決鳍贾。 這意味著微前端解決方案應(yīng)提供加載?微應(yīng)用?的機(jī)制臀突,以及依賴注入的一些機(jī)制。
根據(jù)上述問題和可能的解決方案贾漏,我可以總結(jié)以下主題下的所有內(nèi)容:
客戶端
編排
路由
隔離微應(yīng)用
應(yīng)用之間通信
微應(yīng)用UI之間的一致性
服務(wù)端
服務(wù)端渲染
路由
依賴管理
靈活候学、強(qiáng)大而簡單的架構(gòu)
所以,這篇文章還是很值得期待的纵散! 微前端架構(gòu)的基本要素和要求終于顯現(xiàn)梳码!
在這些要求和關(guān)注的指導(dǎo)下,我開始開發(fā)一種名為microfe的解決方案伍掀。 :sunglasses:在這里掰茶,我將通過抽象的方式強(qiáng)調(diào)其主要組件來描述該項(xiàng)目的架構(gòu)目標(biāo)。
它很容易從客戶端開始蜜笤,它有三個獨(dú)立的主干結(jié)構(gòu):?AppsManager濒蒋,?Loader,?Router?和一個額外的?MicroAppStore把兔。
AppsManager
AppsManager 是客戶端微應(yīng)用編排的核心沪伙。 AppsManager的主要功能是創(chuàng)建依賴關(guān)系樹。 當(dāng)解決了微應(yīng)用的所有依賴關(guān)系時县好,它會實(shí)例化微應(yīng)用围橡。
Loader
客戶端微應(yīng)用編排的另一個重要部分是Loader。 加載器的責(zé)任是從服務(wù)器端獲取未解析的微應(yīng)用缕贡。
Router
為了解決客戶端路由問題翁授,我將 Router 引入了?microfe?。 與常見的客戶端路由器不同晾咪,?microf?的功能有限收擦,它不解析頁面而是微應(yīng)用。 假設(shè)我們有一個URL?/content/detail/13?和一個ContentMicroApp谍倦。 在這種情況下塞赂,?microfe?將URL解析為?/content/?,它將調(diào)用ContentMicroApp?/detail/13?URL部分剂跟。
MicroAppStore
為了解決微應(yīng)用到微應(yīng)用客戶端的通信减途,我將MicroAppStore引入了?microfe?。 它具有與Redux庫類似的功能曹洽,區(qū)別在于:它對異步數(shù)據(jù)結(jié)構(gòu)更改和reducer 聲明更靈活鳍置。
服務(wù)器端部分在實(shí)現(xiàn)上可能稍微復(fù)雜一些,但結(jié)構(gòu)更簡單送淆。 它只包含兩個主要部分?StitchingServer?和許多?MicroAppServer税产。
MicroAppServer
MicroAppServer?的最小功能可以概括為?init?和?serve。
雖然?MicroAppServer?首先啟動它應(yīng)該做的是使用?微應(yīng)用聲明?調(diào)用?SticthingServer?注冊端點(diǎn)偷崩,該聲明定義了?MicroAppServer?的微應(yīng)用?依賴關(guān)系辟拷,?類型?和?URL架構(gòu)。?我認(rèn)為沒有必要提及服務(wù)功能阐斜,因?yàn)闆]有什么特別之處衫冻。
StitchingServer
StitchingServer?為?MicroAppServers?提供注冊端點(diǎn)。 當(dāng)?MicroAppServer?將自己注冊到?StichingServer?時谒出,?StichingServer?會記錄?MicroAppServer?的聲明隅俘。
稍后,?StitchingServer?使用聲明從請求的URL解析?MicroAppServers笤喳。
解析M?icroAppServer?及其所有依賴項(xiàng)后为居,CSS,JS和HTML中的所有相對路徑都將以相關(guān)的?MicroAppServer?公共URL為前綴杀狡。 另外一步是為CSS選擇器添加一個唯一的?MicroAppServer?標(biāo)識符蒙畴,以防止客戶端的微應(yīng)用之間發(fā)生沖突。
然后?StitchingServer?的主要職責(zé)就是:從所有收集的部分組成并返回一個無縫的HTML頁面呜象。
其他實(shí)現(xiàn)一覽
甚至在2016年被稱為微前端之前膳凝,許多大公司都試圖通過BigPipe 來解決Facebook等類似問題。 如今這個想法正在獲得驗(yàn)證恭陡。 不同規(guī)模的公司對該主題感興趣并投入時間和金錢鸠项。 例如,Zalando開源了其名為Project Mosaic的解決方案子姜。 我可以說祟绊,微型和?Project Mosaic.遵循類似的方法,但有一些重要的區(qū)別哥捕。 雖然microfe采用完全分散的路由定義來增強(qiáng)每個微應(yīng)用的獨(dú)立性牧抽,但Project Mosaic更喜歡每條路徑的集中路由定義和布局定義。 通過這種方式遥赚,Project Mosaic可以實(shí)現(xiàn)輕松的A/B測試和動態(tài)布局生成扬舒。
對于該主題還有一些其他方法,例如使用iframe作為拼接層凫佛,這顯然不是在服務(wù)器端而是在客戶端讲坎。 這是一個非常簡單的解決方案孕惜,不需要太多的服務(wù)器結(jié)構(gòu)和DevOps參與。 這項(xiàng)工作只能由前端團(tuán)隊完成晨炕,因此可以減輕公司的組織負(fù)擔(dān)衫画,同時降低成本。
已經(jīng)有一個框架叫做?single-spa?瓮栗。?該項(xiàng)目依賴于每個應(yīng)用的命名約定來解析和加載微應(yīng)用削罩。 容易掌握想法并遵循模式。 因此费奸,在您自己的本地環(huán)境中嘗試該想法可能是一個很好的初步介紹弥激。 但是項(xiàng)目的缺點(diǎn)是你必須以特定的方式構(gòu)建每個微應(yīng)用,以便他們可以很好地使用框架愿阐。
最后的想法
我相信微前端話題會更頻繁地討論微服。 如果該主題能夠引起越來越多公司的關(guān)注,它將成為大型團(tuán)隊的事實(shí)發(fā)展方式缨历。 在不久的將來职辨,任何前端開發(fā)人員都可以在這個架構(gòu)上掌握一些見解和經(jīng)驗(yàn),這真的很有用戈二。
如果有想學(xué)習(xí)編程的初學(xué)者舒裤,可來我們的前端直播授課群的哦:571671034里面免費(fèi)送整套系統(tǒng)的前端教程!