基於lerna+yarn workspaces的monorepo專案實踐

Aasd發表於2019-03-22

注: 文章內不會說過多的基礎內容,預設你有搭建開發環境的基礎技能。

我做 re-editor 富文字編輯器 的時候使用了monorepo管理方式,在開發過程中覺得monorepo也是很適合團隊內部組織專案,下面分享下具體做法與大家共同討論

背景

團隊內多專案開發經常會遇到以下幾個問題

  1. 新建專案需要重新配置各種工具,繁瑣,雖然也可以用腳手架生成,但後期涉及到依賴的升級也麻煩
  2. 專案內的依賴互相引用雖然有yarn/npm link,但還是影響開發體驗
  3. babel等配置希望可以多專案共享

為了解決上述問題,決定在專案內使用 lerna + yarn workspaces。

我們使用下面的專案結構模擬團隊內常見的情景,演示專案

  • 兩個毫無關係的web專案
    • www-a,使用antd
    • www-b,使用react-bootstrap
  • 三個元件專案
    • component-a
    • component-b
    • component-c

他們的依賴關係:

  • www-a 依賴 component-a
  • www-b 依賴 component-b
  • component-a 和 component-b 依賴component-c

建立專案

先新建一個資料夾,然後初始化git

# 初始化git
git init 
複製程式碼
# 初始化專案
$ npm init -f 
# 安裝lerna,也可以全域性安裝,非全域性安裝記得在命令前加上npx
$ yarn add lerna --dev
複製程式碼
// 使用workspace需在package.json內增加如下內容
"private": true,
  "workspaces": [
    "packages/*" 
  ],
複製程式碼
# 初始化lerna
$ lerna init
複製程式碼
// 在lerna.json內增加如下內容以在lerna內啟用yarn workspaces
{
  "npmClient": "yarn"
  "useWorkspaces": true
}
複製程式碼

接下來就是建立package了,可以在packages資料夾內手動建立資料夾,或者使用lerna命令:

$ npx lerna create XXX 
複製程式碼

依賴管理

開發中基本會遇到三種依賴安裝情況

  1. package依賴: 也就是某個具體package的依賴,安裝方式有兩種 使用yarn,參照 yarn-workspace
# yarn workspace www add react
$ yarn workspace <workspace_name> <command>
複製程式碼

使用lerna,具體用法參照 lerna add

#  npx lerna add react --scope www 
$ lerna add <package>[@version] [--dev] [--exact]
複製程式碼
  1. workspace依賴: mono repo專案內依賴互相引用
#  npx lerna add component-a --scope www 
$ lerna add <package>[@version] [--dev] [--exact]
複製程式碼
  1. 共用的工具依賴: 比如babel,eslint等工具依賴,需要共享配置
# 注意: 一定要在專案根目錄下
yarn add @babel/core @babel/preset-env --dev -W
複製程式碼

我們現在抽取出可複用的內容:

  • 程式碼編譯,使用babel
  • css預處理,使用postcss
  • eslint,專案使用一致的語法規範
  • commitlint,專案使用一致的commit提交規範

這些工具按照使用習慣正常安裝就行,重點說下babel。

bable配置檔案使用babel.config.js,程式碼編譯配置全域性共享,然後通過overrides進行差異化配置,比如專案www-a使用antd,可以單獨配置按需載入

const presets = [
  "@babel/preset-env",
  "@babel/preset-react"
];

const overrides = [
  {
    test: ["packages/www-a"],
    plugins: [
      ["module-resolver", {
        "alias": { "~": "./src/scripts" }
      }],
      ["import", {
        "libraryName": "antd",
        "libraryDirectory": "es",
        "style": "css"
      }]
    ]
  },
  {
    test: ["packages/www-b"],
    plugins: [
      ["module-resolver", {
        "alias": { "~": "./src/scripts" }
      }]
    ]
  },
]
複製程式碼

npm script

使用lerna管理專案, 每個專案下都寫自己的npm script,比如 start build,然後使用lerna執行,一般將命令寫到根目錄下的npm script,比如:

"scripts": {
   "start:www-a": "lerna run start --parallel --scope www-a --scope component-a --scope component-c"
  },
複製程式碼
# 執行所有packages的build命令
$ lerna run build

# 並行執行所有packages的start命令
$ lerna run start --parallel 

複製程式碼

相關文章