隨着前端工程日益複雜,某些業務或者工具庫一般涉及到不少個倉庫,那麼時間一長,多個倉庫開發弊端日益顯露,由此出現了一種新的項目管理方式——Monorepo。本文主要以 Monorepo 的概念、MultiRepo的弊端、Monorepo 的收益以及Monorepo 的落地這幾個角度來認識和學習一下 Monorepo,文末會有思考題,歡迎你們來踊躍討論。前端
Monorepo 其實不是一個新的概念,在軟件工程領域,它已經有着十多年的歷史了。概念上很好理解,就是把多個項目放在一個倉庫裏面,相對立的是傳統的 MultiRepo 模式,即每一個項目對應一個單獨的倉庫來分散管理。react
現代的前端工程已經愈來愈離不開 Monorepo 了,不管是業務代碼仍是工具庫,愈來愈多的項目已經採用 Monorepo 的方式來進行開發。Google 寧願把全部的代碼都放在一個 Monorepo 工程下面,Vue 三、Yarn、Npm7 等等知名開源項目的源碼也是採用 Monorepo 的方式來進行管理的。git
通常 Monorepo 的目錄以下所示,在 packages 存放多個子項目,而且每一個子項目都有本身的package.json
:npm
├── packages
| ├── pkg1
| | ├── package.json
| ├── pkg2
| | ├── package.json
├── package.json
複製代碼
那 Monorepo 究竟有什麼魔力,讓你們如此推崇,落地如此之廣呢?json
要想知道 Monorepo 的優點,首先得弄清楚以前的開發方式有什麼痛點。微信
以前傳統的方式MultiRepo
當中,每一個項目都對應單獨的一個代碼倉庫。我以前也是用這種方式開發的,是真真切切地感覺到了這種方式帶來的諸多弊端。如今就和你們一一分享一下。markdown
在維護多個項目的時候,有一些邏輯頗有可能會被屢次用到,好比一些基礎的組件、工具函數,或者一些配置,你可能會想: 要不把代碼直接 copy 過來,多省事兒!但有個問題是,若是這些代碼出現 bug、或者須要作一些調整的時候,就得修改多份,維護成本愈來愈高。架構
那如何來解決這個問題呢?比較好的方式是將公共的邏輯代碼抽取出來,做爲一個 npm 包進行發佈,一旦須要改動,只須要改動一份代碼,而後 publish 就好了。函數
但這真的就完美解決了麼?我舉個例子,好比你引入了 1.1.0
版本的 A 包,某個工具函數出現問題了,你須要作這些事情:工具
1.1.1
版本的新包可能只是改了一行代碼,須要走這麼多流程。然而開發階段是很難保證不出 bug 的,若是有個按鈕須要改個樣式,又須要把上面的流程從新走一遍......停下來想一想,這些重複的步驟真的是必須的嗎?咱們只是想複用一下代碼,爲何每次修改代碼都這麼複雜?
上述的問題實際上是 MultiRepo
廣泛存在的問題,由於不一樣的倉庫工做區的割裂,致使複用代碼的成本很高,開發調試的流程繁瑣,甚至在基礎庫頻繁改動的狀況下讓人感到很抓狂,體驗不好。
在 MultiRepo 的開發方式下,依賴包的版本管理有時候是一個特別玄學的問題。好比說剛開始一個工具包版本是 v1.0.0,有諸多項目都依賴於這個工具包,但在某個時刻,這個工具包發了一個 break change
版本,和原來版本的 API 徹底不兼容。而事實上有些項目並無升級這個依賴,致使一些莫名的報錯。
當項目多了以後,很容易出現這種依賴更新不及時的狀況。這又是一個痛點。
因爲在 MultiRepo 當中,各個項目的工做流是割裂的,所以每一個項目須要單獨配置開發環境、配置 CI 流程、配置部署發佈流程等等,甚至每一個項目都有本身單獨的一套腳手架工具。
其實,很容易發現這些項目裏的不少基建的邏輯都是重複的,若是是 10 個項目,就須要維護 10 份基建的流程,邏輯重複不說,各個項目間存在構建、部署和發佈的規範不能統一的狀況,這樣維護起來就更加麻煩了。
說清楚 MultiRepo
的痛點以後,相信你也大概能理解爲何要誕生Monorepo
這個技術了。如今就來細緻地分析一下Monorepo
到底給現代的前端工程帶來了哪些收益。
首先是工做流的一致性,因爲全部的項目放在一個倉庫當中,複用起來很是方便,若是有依賴的代碼變更,那麼用到這個依賴的項目當中會立馬感知到。而且全部的項目都是使用最新的代碼,不會產生其它項目版本更新不及時的狀況。
其次是項目基建成本的下降,全部項目複用一套標準的工具和規範,無需切換開發環境,若是有新的項目接入,也能夠直接複用已有的基建流程,好比 CI 流程、構建和發佈流程。這樣只須要不多的人來維護全部項目的基建,維護成本也大大減低。
再者,團隊協做也更加容易,一方面你們都在一個倉庫開發,可以方便地共享和複用代碼,方便檢索項目源碼,另外一方面,git commit 的歷史記錄也支持以功能爲單位進行提交,以前對於某個功能的提交,須要改好幾個倉庫,提交多個 commit,如今只須要提交一次,簡化了 commit 記錄,方便協做。
若是你還歷來沒接觸過 Monorepo 的開發,到這可能你會疑惑了: 剛剛說了這麼多 Monorepo 的好處,但是我仍是不知道怎麼用啊!是直接把全部的代碼所有搬到一個倉庫就能夠了嗎?
固然不是,在實際場景來落地 Monorepo,須要一套完整的工程體系來進行支撐,由於基於 Monorepo 的項目管理,毫不是僅僅代碼放到一塊兒就能夠的,還須要考慮項目間依賴分析、依賴安裝、構建流程、測試流程、CI 及發佈流程等諸多工程環節,同時還要考慮項目規模到達必定程度後的性能問題,好比項目構建/測試
時間過長鬚要進行增量構建/測試、按需執行 CI等等,在實現全面工程化能力的同時,也須要兼顧到性能問題。
所以,要想從零開始定製一套完善的 Monorepo 的工程化工具,是一件難度很高的事情。不過社區已經提供了一些比較成熟的方案,咱們能夠拿來進行定製,或者對於一些上層的方案直接拿來使用。
其中比較底層的方案好比 lerna
,封裝了 Monorepo 中的依賴安裝、腳本批量執行等等基本的功能,但沒有一套構建、測試、部署的工具鏈,總體 Monorepo 功能比較弱,但要用到業務項目當中,每每須要基於它進行頂層能力的封裝,提供全面工程能力的支撐。
固然也有一些集成的 Monorepo 方案,好比nx
(官網寫的真心不錯,還有很多視頻教程)、rushstack
,提供從初始化、開發、構建、測試到部署的全流程能力,有一套比較完整的 Monorepo 基礎設施,適合直接拿來進行業務項目的開發。不過因爲這些頂層方案內部各類流程和工具鏈都已經很是完善了,若是要基於這些方案來定製,適配和維護的成本太高,基本是不可行的。
總而言之,Monorepo 的開發模式就是將各自獨立的項目,變成一個統一的工程總體,解決 MultiRepo 下出現的各類痛點,提高研發效率和工程質量。那最後我還有有一個問題,採用 Monorepo 解決了以前的痛點以後,產生了哪些新的問題呢?這些問題能夠解決嗎?歡迎你們在留言區一塊兒討論。
本文首發於公衆號《前端三元同窗》歡迎你們關注,原文:現代前端工程爲何愈來愈離不開 Monorepo?
字節跳動 IES 前端架構團隊急缺人才(p5/p6/p7大量HC),歡迎加我微信 sanyuan0704 一塊兒來搞事情。