有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。
前言
隨著技術發展越來越進步,除了程式語言的框架越來越多以外,連專案的架構也越來越複雜了,今天這篇文章就來探討一個算是近年越來越多開發者在討論的專案架構:Monorepo。
什麼是 Monorepo?
在一般的開發模式中,通常都是一個專案用一個倉庫進行管理,假如今天要設計一個內容管理系統的產品,一般來說會提供以下兩種服務。
- 後臺管理系統。
- 前臺頁面(H5)。
這時候按照以往的開發方式,我們會創立兩個倉庫分別去管理這兩個網站,這種專案架構的設計方式稱之為:Multi-repo。
反之,當我們把這兩個網站都用一個 倉庫 進行管理,這種做法就是 Monorepo。
為什麼我們需要 Monorepo?
看完上述 Monorepo 的介紹,可能讀者還是會覺得有點懵,覺得集中管理跟分開管理並沒有相差多少,其實除了專案上的集中管理外,Monorepo 能做到的事情還有很多。
其實 Monorepo 除了管理專案之外,也可以管理一些共用的元件,甚至是共用的 utils
,這樣就不用很麻煩的在兩個專案上進行 ctr c + v
,通常在 Monorepo 上會用以下的專案架構進行設計。
apps
|- 後臺網站
|- 前臺網站
node_modules
packages
|- components
|- utils
在 apps 的檔案中,我們會放置真正會被執行的專案,假如日後這個專案是有機會要被 build
成 docker image
的話,這時候就可以根據 apps 檔案中的專案產出相對應的 docker image
,以上述的例子來看就是會產生出 後臺網站 以及 前臺網站 這兩個 image。
在 packages 的檔案中,我們就可以放置各種需要被共用的元件或者是 utils,在這邊開發的共用內容就可以同時被 apps 檔案內的專案使用,這樣的架構設計也可以讓程式碼寫起來相當乾淨。
Package Manager
在 Monorepo 的世界中一個 倉庫 底下會有很多個專案,每個專案都會有自己的 package,假如沒有一個好的 package manager 來管理這些 package 的話,最後就會讓整個 倉庫 很難被控制,因此接下來要花一點篇幅來稍微闡述一下 package manager 的用法。
以前端來說比較著名的 package manager 有以下幾個:
- npm
- Yarn
- pnpm
- Rush
通常 package manager 只負責用來處理依賴的安裝,然而在 Monorepo 的架構中,我們通常都會有好幾個專案在同一個檔案中,這時候就必須要使用 package manager 的一個重要觀念:workspaces。
workspaces 簡單來說就是可以方便讓你一鍵安裝所有的依賴至 workspaces 所管理的目錄內,或者是方便你安裝依賴在 workspaces 所管理的目錄。
想要設定 workspaces 管理的目錄也很簡單,只要在 package.json
中填上想要被管理目錄路徑就好,像下圖這樣:
在上圖中讓 workspaces 所管理的目錄就包括 apps 檔案以及 packages 檔案內的所有第一層的檔案。
想要將依賴利用 workspaces 安裝到指定的目錄也很簡單,只要打上 yarn workspace folderName add packageName
即可。
這時候開啟 web 目錄中的 package.json
就會發現 styled-components
真的被安裝進去了非常方便。
想要移除依賴也很簡單,只要把剛剛指令中的 add
改成 remove
就好。
這時候的 package.json
也就會刪除掉依賴的相關資源。
Turborepo
接下來就正式進入本篇文章的重頭戲:Turborepo 。
Turborepo 支援的 package manager 有 Yarn、npm、pnpm,這邊以 Yarn 當作範例。
為了快速產生一個完整可用的專案架構,這邊可以執行 npx create-turbo@latest
這樣就可以快速產生一個基於 Turborepo 架構而生的 Monorepo
專案。
接下來進入 repo 內可以看到有一個蠻特別的檔案叫 turbo.json
,這個檔案主要可以用來設定一些執行指令的 pipeline
,而 pipeline
主要的功能就是當你在執行 yarn run xxx
時,這個指令在執行時應該要有哪些規範,想要了解更多 pipeline 設定的讀者也可以參考這個網站。
例如這邊的 dev 有一個 cache
為 false
的設定,就代表著每次執行 dev
這個指令時都不要使用先前的 cache
以確保每次的開發環境都會是最新的環境。
可以看到在 turbo.json
配置項的 pipeline
基本上跟 package.json
的 scripts
指令互相對應。
可以看到在 turbo.json 這隻檔案設定的 pipeline 基本上跟 package.json 的 scripts 指令都有互相對應。
其實在 apps 目錄內的專案都有各自的 package.json
,只要在這些專案的 package.json
內都有 dev
這個 script,Turborepo 就會自動執行這些內容。
最後再補充一點,讀者在觀察專案架構時可以看到有一個叫 packages
的目錄,這個目錄內內容基本上就是要提供一些共用的內容給 apps
中的專案。
假如要讓 packages
內的某個檔案容給 apps 內的某個專案用,這時候就可以在該專案 package.json
中填上對應包名,並且把版本號設定為 *
,這樣就可以順利在該專案內引用 packages
中的內容啦!
Turborepo 開發
由於這次的範例是利用 Yarn 做為 package manager,因此這邊可以下 yarn dev
來啟動開發環境,這邊可以看到有一個引數是 --parallel
,這個引數是可以讓我們依序啟動專案的引數,如此一來在開發環境下就不會忘記有哪個專案沒被啟動了。
之後就可以在 localhost:3000
以及 localhost:3001
看到兩個專案的畫面啦!
總結
今天介紹了 Monorepo 的專案架構,雖然 Monorepo 的架構看似非常好用,但其實這種專案架構設計並不適合所有的產品,假如今天大家有想要試玩看看 Monorepo 但又不知道可以怎麼下手的話,也可以利用 Monorepo 的架構設計一些 UI 庫。
而且現在很多主流的 UI 庫 都有使用 Monorepo 作為架構,例如:Material UI 使用 lerna 、 NextUI 使用文章介紹的 turborepo 等等,假如之後讀者有遇到類似的使用情境不妨可以嘗試看看 Monorepo 架構喔。
程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
作者:Andy Chen 來源:medium