淺談 Monorepo 帶來的效益:以 Turborepo 為例

前端小智發表於2022-04-07

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

前言

隨著技術發展越來越進步,除了程式語言的框架越來越多以外,連專案的架構也越來越複雜了,今天這篇文章就來探討一個算是近年越來越多開發者在討論的專案架構:Monorepo

什麼是 Monorepo?

在一般的開發模式中,通常都是一個專案用一個倉庫進行管理,假如今天要設計一個內容管理系統的產品,一般來說會提供以下兩種服務。

  1. 後臺管理系統。
  2. 前臺頁面(H5)。

這時候按照以往的開發方式,我們會創立兩個倉庫分別去管理這兩個網站,這種專案架構的設計方式稱之為:Multi-repo

反之,當我們把這兩個網站都用一個 倉庫 進行管理,這種做法就是 Monorepo

為什麼我們需要 Monorepo?

看完上述 Monorepo 的介紹,可能讀者還是會覺得有點懵,覺得集中管理跟分開管理並沒有相差多少,其實除了專案上的集中管理外,Monorepo 能做到的事情還有很多。

其實 Monorepo 除了管理專案之外,也可以管理一些共用的元件,甚至是共用的 utils,這樣就不用很麻煩的在兩個專案上進行 ctr c + v,通常在 Monorepo 上會用以下的專案架構進行設計。

apps
  |- 後臺網站
  |- 前臺網站
node_modules
packages
  |- components
  |- utils

在 apps 的檔案中,我們會放置真正會被執行的專案,假如日後這個專案是有機會要被 builddocker 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 中填上想要被管理目錄路徑就好,像下圖這樣:

image.png

在上圖中讓 workspaces 所管理的目錄就包括 apps 檔案以及 packages 檔案內的所有第一層的檔案。

想要將依賴利用 workspaces 安裝到指定的目錄也很簡單,只要打上
yarn workspace folderName add packageName 即可。

image.png

這時候開啟 web 目錄中的 package.json 就會發現 styled-components 真的被安裝進去了非常方便。

image.png

想要移除依賴也很簡單,只要把剛剛指令中的 add 改成 remove 就好。

image.png

這時候的 package.json 也就會刪除掉依賴的相關資源。

image.png

Turborepo

接下來就正式進入本篇文章的重頭戲:Turborepo 。

image.png

Turborepo 支援的 package manager 有 Yarn、npm、pnpm,這邊以 Yarn 當作範例。

為了快速產生一個完整可用的專案架構,這邊可以執行 npx create-turbo@latest 這樣就可以快速產生一個基於 Turborepo 架構而生的 Monorepo 專案。

image.png

接下來進入 repo 內可以看到有一個蠻特別的檔案叫 turbo.json ,這個檔案主要可以用來設定一些執行指令的 pipeline,而 pipeline 主要的功能就是當你在執行 yarn run xxx 時,這個指令在執行時應該要有哪些規範,想要了解更多 pipeline 設定的讀者也可以參考這個網站

image.png

例如這邊的 dev 有一個 cachefalse 的設定,就代表著每次執行 dev 這個指令時都不要使用先前的 cache 以確保每次的開發環境都會是最新的環境。

image.png

可以看到在 turbo.json 配置項的 pipeline 基本上跟 package.jsonscripts 指令互相對應。

可以看到在 turbo.json 這隻檔案設定的 pipeline 基本上跟 package.json 的 scripts 指令都有互相對應。

其實在 apps 目錄內的專案都有各自的 package.json ,只要在這些專案的 package.json 內都有 dev 這個 script,Turborepo 就會自動執行這些內容。

image.png

最後再補充一點,讀者在觀察專案架構時可以看到有一個叫 packages 的目錄,這個目錄內內容基本上就是要提供一些共用的內容給 apps 中的專案。

假如要讓 packages 內的某個檔案容給 apps 內的某個專案用,這時候就可以在該專案 package.json 中填上對應包名,並且把版本號設定為 * ,這樣就可以順利在該專案內引用 packages 中的內容啦!

image.png

Turborepo 開發

由於這次的範例是利用 Yarn 做為 package manager,因此這邊可以下 yarn dev 來啟動開發環境,這邊可以看到有一個引數是 --parallel ,這個引數是可以讓我們依序啟動專案的引數,如此一來在開發環境下就不會忘記有哪個專案沒被啟動了。

image.png

之後就可以在 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

原文:https://medium.com/starbugs/%...

相關文章