一、什麼是Monorepo
Monorepo是指在一個代碼倉庫中管理多個項目,每個項目可以拆分成不同的模塊,統一的依賴管理,共享代碼和配置等。相比於多個獨立的倉庫,在monorepo中可以更容易地實現代碼復用和協同開發。
在實際應用中,常見的使用Monorepo的場景有:
- 多個相關的項目有共享代碼的需求,例如同一公司或同一部門的多個項目。
- 前端應用拆分成多個模塊或組件,共享依賴。
- 微服務架構中,多個服務共享公共的代碼和配置。
而在monorepo中,一個典型的項目結構通常如下:
root/
├── package.json
├── packages/
│ ├── app/
│ ├── lib/
│ └── common/
└── scripts/
其中,根目錄下的package.json
包含所有項目的相關信息和依賴,packages/
目錄下存放不同的項目或模塊,scripts/
目錄下存放一些腳本和配置文件。
二、Monorepo的優缺點
1. 優點
(1)統一的依賴管理
在Monorepo中,所有的項目和模塊共享同一個package.json
,可以大大簡化依賴管理。例如,對於共同依賴的庫,只需要在package.json
中進行一次安裝即可,而不需要每個項目單獨安裝。
(2)共享代碼
在Monorepo中,多個項目之間可以共享代碼和模塊,避免重複編寫和維護代碼,提高了代碼的復用性和可維護性。此外,共享的代碼也可以更容易地進行版本控制和更新。
(3)容易進行協同開發
由於所有的代碼都在一個倉庫中,可以更容易地進行代碼協同開發,例如可以使用git子模塊、git subtree等技術來讓開發者只克隆需要關注的部分,方便團隊協同開發。
2. 缺點
(1)構建速度慢
由於Monorepo中會有多個項目和模塊的代碼,每次構建都需要對每個模塊進行編譯和構建,如果項目非常龐大,構建速度會明顯變慢。
(2)發布部署複雜
在Monorepo中,不同項目和模塊之間存在依賴關係,如果需要對某個模塊進行修改或升級,需要考慮依賴關係對其他模塊的影響,因此發布和部署可能會更加複雜。
三、使用Monorepo管理項目
在本節中,我們將通過一個簡單的示例來演示如何使用Monorepo管理項目。
1. 初始化項目
首先,我們需要在本地創建一個新的文件夾,例如monorepo-test
,並執行以下命令初始化項目:
mkdir monorepo-test
cd monorepo-test
npm init
在創建package.json
時,可以將Monorepo相關的配置設置成項目的初始化信息:
{
"name": "monorepo-test",
"private": true,
"workspaces": [
"packages/*"
]
}
private: true
表示這是一個私有庫,workspaces: ["packages/*"]
表示我們的工作區設置在packages/
目錄下。
2. 創建項目
現在我們來創建一個新的項目,可以使用lerna
命令來快捷地創建:
npx lerna create app --dependencies=react
你會看到一個新的packages/app
目錄創建出來。
現在,我們需要在app
目錄下添加一個React組件,例如:
// packages/app/src/Hello.js
import React from 'react';
export default function Hello({ name }) {
return Hello, {name}!
;
}
然後,我們需要在packages/app
目錄下創建package.json
,並在其中添加依賴和構建指令:
npm init -y
npm install --save react
// packages/app/package.json
{
"name": "app",
"version": "0.0.1",
"scripts": {
"build": "npm run build:lib",
"build:lib": "rollup -c",
"start": "react-scripts start"
},
"devDependencies": {
"@babel/core": "^7.12.3",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"@rollup/plugin-commonjs": "^16.0.0",
"@rollup/plugin-node-resolve": "^10.0.0",
"rollup": "^2.32.1",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-terser": "^7.0.2"
},
"dependencies": {
"react": "^17.0.1",
"react-dom": "^17.0.1"
}
}
在這裡,我們使用了rollup
進行打包和構建,同時添加了一些常見的依賴和插件。
3. 創建依賴模塊
現在,我們需要創建一個獨立的依賴模塊,用於在不同的項目中共享代碼和邏輯。
我們可以使用lerna
來快速創建一個空的模塊:
npx lerna create common
然後,在packages/common
目錄下,創建一個空的JavaScript文件index.js
,它將作為我們的共享代碼的入口點。
// packages/common/index.js
由於common模塊是一個純JavaScript模塊,因此我們只需要在common/package.json
中添加必要的依賴和構建腳本即可:
// packages/common/package.json
{
"name": "common",
"version": "0.0.1",
"main": "index.js",
"scripts": {
"build": "npm run build:lib",
"build:lib": "babel src --out-dir lib",
"test": "echo \"No tests yet...\""
},
"devDependencies": {
"@babel/core": "^7.12.3",
"@babel/preset-env": "^7.12.1",
"babel-jest": "^26.6.3",
"jest": "^26.6.3"
},
"dependencies": {}
}
在這裡,我們使用了babel
來進行編譯和構建,同時添加了一些常見的依賴和插件。
4. 在app中使用common模塊
現在,我們可以在app模塊中引入common模塊,並使用common模塊中的函數。
首先,我們需要在app/package.json
中添加對common模塊的依賴:
"dependencies": {
"react": "^17.0.1",
"react-dom": "^17.0.1",
"common": "^0.0.1"
}
然後,在app
目錄下的任意JavaScript文件中,可以輕鬆地引入和使用common模塊中的函數:
// packages/app/src/Hello.js
import React from 'react';
import common from 'common';
export default function Hello({ name }) {
return {common.sayHello(name)}
;
}
在這裡,我們使用common.sayHello
來獲取在common模塊中定義的函數,並將結果渲染到頁面中。
5. 構建和測試
現在,我們可以使用lerna
來進行對我們的項目的構建和測試了:
npx lerna run build
這將會使用rollup
和babel
來構建我們的app和common模塊。
npx lerna run test
這將會使用jest
來運行我們的測試用例。
四、總結
Monorepo雖然在一些場景下使用起來會有些複雜,但是其優點同樣非常明顯,特別是在多個項目和模塊之間有共享代碼和統一依賴管理的需求時,使用Monorepo可以顯著提高開發效率和可維護性。
在實際應用中,使用Monorepo需要清晰的項目結構和依賴關係管理,動態調整不同項目和模塊的關係需要仔細考慮,同時需要合理地使用各種工具和技術實現代碼隔離和部署。
原創文章,作者:ZPFBH,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/371976.html