博客 / 詳情

返回

Monorepo:讓你的項目脱胎換骨,既能代碼複用,又能獨立部署!

本文由體驗技術團隊Kagol原創。
你的項目是不是正在不斷膨脹,構建速度越來越慢,包體積越來越大,性能越來越慢了?

想拆分到不同的倉庫中分開維護,又擔心代碼不方便複用?

你可能需要將項目改造成 Monorepo 啦!

我將帶大家把一個現有項目改造成 Monorepo 方式,便於擴展和多項目複用。

如果你也有類似的需求,可以點贊、收藏下本文,關鍵時刻也許能幫上忙。

1 為什麼需要做 Monorepo 改造

使用 monorepo 方式組織代碼的前提是:

你有多個項目,並且需要在多個項目中複用組件和邏輯。

如果每個項目都是完全獨立的,沒有什麼共用的代碼(幾乎不太可能),那也許你就不需要用 monorepo 啦。

1.1 Monorepo 的好處

使用 Monorepo 方式組織項目代碼,至少有以下好處:

  1. 便於代碼複用:多個倉庫都會用到的組件、工具函數、類型聲明、樣式等,可以放到 common 子包中,需要的倉庫直接 npm install 這個子包就行,就跟 npm install 一個 npm 包一樣容易。
  2. 獨立構建和部署:每個子包都是一個獨立的項目,有自己的 package.json 文件,獨立安裝依賴、獨立端口和本地啓動、獨立測試、獨立構建和部署,互不影響。
  3. 降低切換成本:由於只有單一倉庫,clone 代碼、切換分支、安裝依賴比較方便,不用在不同文件夾之間切換。
  4. 節約磁盤空間:pnpm 天然具備 monorepo 能力,支持全局依賴管理,所有子包之間共享依賴,節約磁盤空間。
  5. 方便提交PR:由於是單倉庫,增加新組件或給組件增加新特性,只需要提交一個 MR、編寫一次 MR 描述、關聯一次需求/缺陷單。
  6. 方便代碼檢視:一個完整的特性只需要統一在一個 MR 中檢視,不用在多個倉庫/多個 MR 之間切換。
  7. 靈活便於擴展:後續增加新的工程只需要在 packages 下增加一個子包,不需要申請新的代碼倉庫,也降低後續倉庫維護成本,比如:配置保護分支 / GitHub Actions / 倉庫標籤等。

1.2 如果不用 Monorepo 會怎麼樣?

  • 方式一: 把所有項目放到一個倉庫裏,創建很多文件夾,分別存放不同的項目,通過路由進行項目隔離。

這樣做的好處是所有代碼都在一起,代碼複用方便,直接 ../ 就行;而且不用創建和維護倉庫,不用配置一堆流水線。

壞處也顯而易見,就是項目會不斷膨脹,本地啓動調試會越來越慢、構建打包越來越慢,包體積越來越大,項目越來越卡,最後用户受不了紛紛棄坑。

  • 方式二: 將項目拆分到不同的代碼倉庫進行維護。

好處是項目之間相互獨立,不容易耦合,維護起來方便。

壞處就是增加了倉庫維護成本、流水線創建成本,並且不方便項目之間複用代碼。

不管是以上哪種方式,後續項目的演進都是麻煩不斷,要麼代碼量膨脹、性能下降,要麼重複勞動、一堆重複代碼。

Monorepo 可以你幫助減少麻煩,快樂工作!

我們一起來看看具體怎麼改造吧!

2 現有工程改造成 Monorepo 的步驟

假如我們已經有了一個 Vite + Vue3 工程,可以通過 npm run dev 本地啓動,npm run build 進行構建。

基本步驟:

  1. 增加 packages 目錄用於存放子包,增加 portal 子包
  2. 把現有工程的 src / public / package.json / vite.config.ts / tsconfig.xx.json / index.html / README.md 等項目啓動和構建相關的目錄和文件全部剪切到 packages/portal 目錄中
  3. 增加 pnpm-workspace.yaml 文件配置多包路徑
  4. 根目錄增加 package.json 文件
  5. 執行 pnpm i 安裝依賴,執行 pnpm -F portal dev 本地啓動
  6. 將本地啓動命令放到根目錄的 packages.json scripts中,方便啓動

2.1 創建子包

第一步就是在根目錄創建 packages 目錄,增加項目子包,比如項目叫:portal

root
├── packages
|  └── portal
|     ├── ... // 項目文件和目錄

2.2 現有項目文件放進子包裏

把現有工程的 src / public / package.json / vite.config.ts / tsconfig.xx.json / index.html / README.md 等項目啓動和構建相關的目錄和文件全部剪切到 packages/portal 目錄中

root
├── packages
|  └── portal
|     ├── index.html
|     ├── package-lock.json
|     ├── package.json
|     ├── public
|     ├── README.md
|     ├── src
|     ├── tsconfig.app.json
|     ├── tsconfig.json
|     ├── tsconfig.node.json
|     └── vite.config.ts

2.3 配置 pnpm-workspace.yaml

根目錄創建 pnpm-workspace.yaml 文件。

packages:
  - packages/**

2.4 配置 package.json

項目原來的 package.json 屬於子包,需要放到 portal 子包中。

項目根目錄需要創建一個新的 package.json 文件。

{
  "name": "root",
  "private": true
}

2.5 改造前後目錄結構對比

image.png

2.6 驗證本地啓動和構建命令

執行 pnpm i 安裝依賴

執行 pnpm -F portal dev 本地啓動

執行 pnpm -F portal build 項目構建

如果以上命令都正常,説明本次 Monorepo 改造成功!

2.7 增加便捷命令

將本地啓動命令放到根目錄的 packages.json scripts 中,方便啓動。

{
  "name": "root",
  "private": true,
+  "scripts": {
+    "dev": "pnpm -F portal dev",
+    "build": "pnpm -F portal build",
+    "preview": "pnpm -F portal preview"
+  }
}

後續啓動項目:pnpm dev

構建項目:pnpm build

3 增加一個新項目 admin

在 packages 目錄下執行 npm create vite admin,選擇 React 框架。

image.png

執行 pnpm i 安裝依賴

執行 pnpm -F admin dev 本地啓動 admin 新項目

執行 pnpm -F admin build 構建 admin 新項目

兩個項目同時啓動了。

image.png

實現了 portal / admin 兩個項目分開啓動分開構建分開管理依賴分開測試,互不影響,而且 portal 是 Vue 技術棧,admin 是 React 技術棧。

可以在根目錄的 package.json scripts 增加對應的便捷命令。

{
  "name": "root",
  "private": true,
  "scripts": {
    "dev": "pnpm -F portal dev",
    "build": "pnpm -F portal build",
    "preview": "pnpm -F portal preview",
+    "dev:admin": "pnpm -F portal dev",
+    "build:admin": "pnpm -F portal build",
+    "preview:admin": "pnpm -F portal preview"
  }
}

改造後的 Monorepo 項目目錄結構,看起來和原來差異不大,就是包了一層 packages,其實整個項目已經脱胎換骨,變成了一個更加讓人“省心”的項目,項目之間的代碼複用更加方便,後續維護和擴展也是非常輕鬆。

root
├── package.json
├── packages
|  ├── admin
|  |  ├── eslint.config.js
|  |  ├── index.html
|  |  ├── package.json
|  |  ├── public
|  |  ├── README.md
|  |  ├── src
|  |  ├── tsconfig.app.json
|  |  ├── tsconfig.json
|  |  ├── tsconfig.node.json
|  |  └── vite.config.ts
|  └── portal
|     ├── index.html
|     ├── package-lock.json
|     ├── package.json
|     ├── public
|     ├── README.md
|     ├── src
|     ├── tsconfig.app.json
|     ├── tsconfig.json
|     ├── tsconfig.node.json
|     └── vite.config.ts
├── pnpm-lock.yaml
└── pnpm-workspace.yaml

如果有些邏輯 portal / admin 都用到了,我們可以新加一個子包:common

然後在 portal / admin 中引入 common。

pnpm -F portal i common
pnpm -F admin i common

安裝之後直接 import 進行使用即可。

4 總結

本文主要給大家分析了 Monorepo 方式組織項目代碼的好處,以及不使用 Monorepo 可能帶來的麻煩;

然後以一個 Vite + Vue3 項目為例,手把手帶大家一起將它改造成 Monorepo 項目;

在此基礎上,如何擴展一個新項目,並且新項目技術棧用的是 React,卻可以和原來的 Vue 項目共同代碼邏輯。

別猶豫了,動手實踐起來吧!

最近我們新開源了一個基於 Quill 2.0 的富文本編輯器:Fluent Editor。

Fluent Editor:一個基於 Quill 2.0 的富文本編輯器,功能強大、開箱即用!

如果你正在尋找一款功能強大、開箱即用、易於擴展的開源富文本,不妨嘗試下!

  • 官網:https://opentiny.github.io/fluent-editor/
  • 源碼:https://github.com/opentiny/fluent-editor/ (歡迎 Star ⭐)
  • Kagol 個人博客:https://kagol.github.io/blogs

關於 OpenTiny

GitHub:https://github.com/opentiny/tiny-vue (歡迎 Star ⭐)

官網:https://opentiny.design/tiny-vue

B站:https://space.bilibili.com/15284299

小助手微信:opentiny-official

公眾號:OpenTiny

user avatar qianduanlangzi_5881b7a7d77f0 頭像 joytime 頭像 shen_5bbe318c912ed 頭像
3 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.