我們是袋鼠云數(shù)棧 UED 團(tuán)隊(duì),致力于打造優(yōu)秀的一站式數(shù)據(jù)中臺(tái)產(chǎn)品。我們始終保持工匠精神,探索前端道路,為社區(qū)積累并傳播經(jīng)驗(yàn)價(jià)值。
本文作者:星野
困境頻生前端代碼管理何解?
前端代碼管理一直是困擾著不少前端開發(fā)團(tuán)隊(duì)的難題,從開發(fā)到發(fā)布的整體工作流程中,除了常規(guī)的技術(shù)問(wèn)題外,往往還伴隨著溝通成本、維護(hù)成本及協(xié)作效率等問(wèn)題。這些問(wèn)題在團(tuán)隊(duì)規(guī)模較小的時(shí)候可能不太明顯,但是當(dāng)團(tuán)隊(duì)規(guī)模變大時(shí)矛盾就越發(fā)凸顯。
數(shù)棧前端開發(fā)團(tuán)隊(duì)負(fù)責(zé)著離線開發(fā)、實(shí)時(shí)開發(fā)、數(shù)據(jù)服務(wù)、數(shù)據(jù)資產(chǎn)等多條產(chǎn)品線的開發(fā)和維護(hù)工作,面對(duì)眾多的產(chǎn)品線,如何合理的管理代碼,成了團(tuán)隊(duì)需要思考的問(wèn)題,雖然借助了 Multirepo 進(jìn)行管理,但還是遇到了許多難題:
-
私有源維護(hù)成本增加
為復(fù)用相關(guān)業(yè)務(wù)邏輯,團(tuán)隊(duì)內(nèi)部抽象出一些私有包,由于不能在公網(wǎng)暴露,為了管理這些私有包團(tuán)隊(duì)使用了私有源,但由于搭建私有源服務(wù)器資源問(wèn)題,私有源常常不穩(wěn)定且下載速度慢,特別是對(duì)于需要源碼交付的某些客戶來(lái)說(shuō),安裝這些私有包更會(huì)遇到各種問(wèn)題,交付的時(shí)間和人力成本大大升高。
-
邏輯難復(fù)用,重復(fù)造輪子
各個(gè)倉(cāng)庫(kù)中會(huì)抽象出同一功能的組件,組件之間的共享往往難以同步,造成了「重復(fù)造輪子」現(xiàn)象。
-
工具/配置不統(tǒng)一,溝通成本高
各個(gè)倉(cāng)庫(kù)所使用的工具和配置沒有進(jìn)行統(tǒng)一,在進(jìn)行配置更新的過(guò)程中,往往需要同步到各個(gè)產(chǎn)品線負(fù)責(zé)人,溝通成本較高。
這些問(wèn)題嚴(yán)重拖慢了數(shù)棧前端團(tuán)隊(duì)從開發(fā)到發(fā)布的整體流程,同時(shí)增加了團(tuán)隊(duì)的維護(hù)成本和溝通成本,如何尋找新的工具解決這些問(wèn)題已迫在眉睫,在進(jìn)行了深入調(diào)研和多次討論的過(guò)程中,新的項(xiàng)目管理方式 Monorepo 在這時(shí)映入了我們的眼簾。
Multirepo VS Monorepo
那么 Multirepo 和 Monorepo 到底是什么呢?其實(shí)他們分別代表的是兩種前端代碼管理方式:
-
Multirepo
Multirepo 是一種分散式的前端代碼管理方式,按照功能或其他維度,將項(xiàng)目拆分為不同模塊并單獨(dú)維護(hù)于各自倉(cāng)庫(kù)中。作為傳統(tǒng)的管理方式,Multirepo 具備靈活度高、安全控制等特點(diǎn),但同時(shí)也帶了管理成本和寫作成本的增加,依賴升級(jí)等問(wèn)題。
-
Monorepo
Monorepo 是集中式管理的前端代碼管理方式,將所有的項(xiàng)目在集中一個(gè)代碼倉(cāng)庫(kù)中進(jìn)行管理,嚴(yán)格的統(tǒng)一和收歸,有利于統(tǒng)一的升級(jí)和管理。作為新型的管理方式,Monorepo 有效降低了運(yùn)營(yíng)及協(xié)作成本,但「一個(gè)代碼倉(cāng)庫(kù)」的管理模式帶來(lái)了項(xiàng)目體積的上升,獲取時(shí)間延長(zhǎng),同時(shí)安全性也有所下降。
上圖為 Multirepo 和 Monorepo 的對(duì)比圖,從圖中我們可以簡(jiǎn)要?dú)w納:
- Multirepo 由多個(gè)倉(cāng)庫(kù)組成的項(xiàng)目管理方式,每個(gè)倉(cāng)庫(kù)有著獨(dú)立的工作流、組件與配置。
- Monorepo 將不同倉(cāng)庫(kù)整合成為一個(gè)倉(cāng)庫(kù),并共享工作流、組件與配置。
兩種管理方式各有千秋,不能簡(jiǎn)單的定義哪種方式更好,但 Monorepo 的共享機(jī)制、統(tǒng)一管理及協(xié)作成本低等優(yōu)勢(shì),顯然更符合深陷復(fù)雜產(chǎn)品線挑戰(zhàn)的數(shù)棧前端團(tuán)隊(duì)的需求,選擇 Monorepo 也是團(tuán)隊(duì)探索效率提升的必然道路。
合適才最好 Monorepo 方案規(guī)劃
確定了新的管理方式后,接下來(lái)面對(duì)的就是如何與數(shù)棧相適配的問(wèn)題。市面上關(guān)于Monorepo的解決方案和相關(guān)工具有很多,雖然 rush、nx 之類的工具能夠在特定的領(lǐng)域提供較好的解決方案,但卻并不符合我們的實(shí)際需求。
在調(diào)研了社區(qū)的各種 Monorepo 實(shí)現(xiàn)和解決方案之后,結(jié)合我們自身的業(yè)務(wù)場(chǎng)景和需求,最終我們選擇了 pnpm 和 turborepo 作為底層的包管理工具和任務(wù)調(diào)度工具,因?yàn)橹挥凶詈线m的產(chǎn)品才是最好的解決方案。
-
包管理工具-pnpm
在前端社區(qū)中,npm、 yarn、 pnpm 三個(gè)包管理工具三足鼎立,而我們最終選擇了 pnpm 原因在于:pnpm 對(duì) monorepo 有著較好的支持,同時(shí)對(duì)比其他兩個(gè)包管理工具,pnpm 在性能等各個(gè)方面有著顯著的優(yōu)勢(shì)
-
任務(wù)調(diào)度工具-turborepo
任務(wù)調(diào)度方面,社區(qū)中也存在很多優(yōu)秀的工具,如 rush、nx、lerna、turborepo等,綜合對(duì)比之后,我們選擇了配置簡(jiǎn)單易懂、調(diào)度更加科學(xué)的 turborepo 作為我們的任務(wù)調(diào)度工具:
不斷探索 Monorepo 落地實(shí)踐
在確定了底層包管理工具和任務(wù)調(diào)度工具后,數(shù)棧&Monorepo 整體架構(gòu)方案也明確了:
Monorepo 解決了之前使用 Multirepo 時(shí)存在的問(wèn)題,幫助我們更好的管理代碼,接下來(lái)我們將結(jié)合 Multirepo 存在的問(wèn)題來(lái)詳細(xì)說(shuō)明 Monorepo 是如何在數(shù)棧產(chǎn)品中落地的。
-
統(tǒng)一配置
Multirepo 存在的一個(gè)顯著問(wèn)題是配置的不統(tǒng)一導(dǎo)致的難以維護(hù),所以我們需要對(duì)格式化、代碼檢測(cè)、打包等相關(guān)流程的配置進(jìn)行規(guī)范化和統(tǒng)一,同時(shí)針對(duì)不同產(chǎn)品線的細(xì)微差別,也需要支持其靈活的擴(kuò)展。因此我們?cè)?Monorepo 倉(cāng)庫(kù)的根目錄提供了統(tǒng)一的基礎(chǔ)配置,同時(shí)如需要進(jìn)行調(diào)整,不同產(chǎn)品線可以繼承該配置并進(jìn)行必要的修改。
-
邏輯復(fù)用
Multirepo 存在的另一個(gè)顯著問(wèn)題就是邏輯難以復(fù)用,遷移之前的邏輯復(fù)用主要是靠抽象到私有包并發(fā)布,或者直接復(fù)制粘貼,整體效率低,流程長(zhǎng)且難以維護(hù)。遷移之后我們對(duì)各種配置等進(jìn)行了統(tǒng)一的同時(shí),也將公用的業(yè)務(wù)邏輯和組件整合到了倉(cāng)庫(kù)根目錄的packages目錄下,同時(shí)通過(guò) pnpm 的 workspace protocal 鏈接到各個(gè)產(chǎn)品線中以便復(fù)用。這樣不僅解決了邏輯復(fù)用的相關(guān)問(wèn)題,同時(shí)私有源也不用進(jìn)行維護(hù),Multirepo 下的私有源維護(hù)成本問(wèn)題得以解決。
-
權(quán)限校驗(yàn)
當(dāng)基礎(chǔ)配置和公共邏輯被暴露出來(lái)之后,就面臨著這些內(nèi)容可以被隨意修改的問(wèn)題,而這往往會(huì)影響所有的產(chǎn)品線,稍有不慎會(huì)造成巨大損失,因此我們需要給這些重要的內(nèi)容施以限制和保護(hù)。
我們基于 git hooks 做了一些工作,在 pre-commit 和 pre-push 階段分別對(duì)權(quán)限和分支名等內(nèi)容進(jìn)行了校驗(yàn),并定義了 Maintainer、Owner、Deverloper 三個(gè)角色,對(duì)應(yīng)的權(quán)限分別為:- Maintainer: 擁有全部權(quán)限,可以修改包括基礎(chǔ)配置文件等的所有內(nèi)容。
- Owner :各產(chǎn)品線或者公共組件主要負(fù)責(zé)人,擁有對(duì)應(yīng)范圍內(nèi)的所有權(quán)限。
- Developer: 該產(chǎn)品線或者公共組件的輔助開發(fā)人員,只擁有包括開發(fā)新功能等的部分產(chǎn)品線權(quán)限。
角色權(quán)限進(jìn)行明確的劃分之后,我們可以將基礎(chǔ)配置和公共邏輯等內(nèi)容的修改交給更有經(jīng)驗(yàn)的工程師。同時(shí)權(quán)限分配配置維護(hù)在本地,這樣可以更清晰的了解不同產(chǎn)品線對(duì)應(yīng)的人員,方便溝通。
-
自動(dòng)化遷移
從 Multirepo 遷移到 Monorepo 如果采用手動(dòng)的方式逐個(gè)遷移會(huì)有如下問(wèn)題:
1.遷移前的各產(chǎn)品線倉(cāng)庫(kù)存在多個(gè)版本需要維護(hù),手動(dòng)遷移多個(gè)版本工作內(nèi)容重復(fù)且效率較低。
2.人為的操作往往會(huì)出錯(cuò),且出錯(cuò)時(shí)溝通成本較高。因此我們?cè)谶w移的過(guò)程中實(shí)現(xiàn)了自動(dòng)化的遷移流程,主要流程如下:
- 自動(dòng)克隆原倉(cāng)庫(kù)的目標(biāo)分支內(nèi)容到 Monorepo;
- 刪除需要統(tǒng)一的配置如 commitlint 等配置;
- 刪除 babel, webpack 等相關(guān)重復(fù)依賴;
- 檢測(cè)并替換,采用pnpm的 workspace protocal 鏈接的內(nèi)部依賴引入方式;
- 刪除 yarn/npm 相關(guān)的 lock 文件,并安裝依賴生成最新的 pnpm-lock.yaml.
自動(dòng)化遷移的實(shí)現(xiàn),保證了遷移過(guò)程的快速且順利的進(jìn)行,各產(chǎn)品線的同學(xué)可以較為平滑的過(guò)渡到新的項(xiàng)目管理方式——Monorepo。
寫在最后
數(shù)棧前端團(tuán)隊(duì)正式遷移到了 Monorepo,解決了之前 Multirepo 項(xiàng)目管理方式下的私有源維護(hù)成本高,工具/配置不統(tǒng)一,邏輯復(fù)用鏈路長(zhǎng)且難以維護(hù)等問(wèn)題。在遷移的過(guò)程中,實(shí)現(xiàn)了大部分遷移工作的自動(dòng)化進(jìn)行,并對(duì)重要的配置等進(jìn)行了權(quán)限校驗(yàn)以進(jìn)行限制和保護(hù)。整體提升了數(shù)棧前端團(tuán)隊(duì)研發(fā)的效率,降低了協(xié)作和溝通成本,有效實(shí)現(xiàn)了降本增效。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-760581.html
最后
歡迎關(guān)注【袋鼠云數(shù)棧UED團(tuán)隊(duì)】~
袋鼠云數(shù)棧 UED 團(tuán)隊(duì)持續(xù)為廣大開發(fā)者分享技術(shù)成果,相繼參與開源了歡迎 star文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-760581.html
- 大數(shù)據(jù)分布式任務(wù)調(diào)度系統(tǒng)——Taier
- 輕量級(jí)的 Web IDE UI 框架——Molecule
- 針對(duì)大數(shù)據(jù)領(lǐng)域的 SQL Parser 項(xiàng)目——dt-sql-parser
- 袋鼠云數(shù)棧前端團(tuán)隊(duì)代碼評(píng)審工程實(shí)踐文檔——code-review-practices
- 一個(gè)速度更快、配置更靈活、使用更簡(jiǎn)單的模塊打包器——ko
- 一個(gè)針對(duì) antd 的組件測(cè)試工具庫(kù)——ant-design-testing
到了這里,關(guān)于袋鼠云數(shù)棧前端從 Multirepo 到 Monorepo 研發(fā)效率提升探索之路的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!