【譯】 Lerna + yarn Workspaces 管理 Monorepo 入門指南

Source: jsilvax. A Beginner's Guide to Lerna with Yarn Workspaces. Oct/6/2018node

當結合在一塊兒時,Lerna和Yarn Workspaces能夠簡化和優化對多包倉庫的管理。 Lerna 經過提供有用的實用命令來處理跨多個包的任務執行,使版本管理和將包發佈到NPM Org中成爲一種輕鬆的體驗。 Yarn Workspaces 管理咱們的依賴關係。它不須要多個node_modules目錄,而是智能地優化了依賴關係,將他們一併安裝,並容許在一個monorepo中交叉連接依賴關係。Yarn Workspaces提供了像Lerna這樣的工具來管理多包倉庫。git

爲了開始,讓咱們啓用Yarn Workspaces吧github

yarn config set workspaces-experimental true
複製代碼

如今咱們能夠經過建立一個模擬項目來講明這些概念了npm

mkdir my-design-system && cd my-design-system
複製代碼

而後,咱們初始化項目json

yarn init
複製代碼

並將Lerna添加爲開發依賴。bootstrap

yarn add lerna --dev
複製代碼

而後你會想要初始化Lerna,這將建立一個lerna.json和一個包目錄緩存

lerna init
複製代碼

爲了設置Lerna開啓Yarn工做空間,咱們須要配置lerna.json。 讓咱們添加yarn做爲咱們的npm客戶端,並指定咱們使用yarn工做空間。在本教程中,咱們將獨立地版本化咱們的包。markdown

// lerna.json
{
  "packages": ["packages/*"],
  "version": "independent",
  "npmClient": "yarn",
  "useWorkspaces": true
}
複製代碼

此時咱們應該只有一個根 package.json。在這個根 package.json中,咱們須要添加workspaces和private爲true。將private設置爲true將阻止根項目被髮布到NPM。併發

// package.json
{
  "name": "my-design-system",
  "private": true,
  "workspaces": [
     "packages/*"
  ]  
}
複製代碼

建立一個新包的流程

須要在包目錄下建立新的包。讓咱們建立一個模擬表單包app

cd packages
複製代碼

一旦咱們進入了正確的目錄,咱們就能夠建立並cd到咱們的新包中了

mkdir my-design-system-form && cd my-design-system-form
複製代碼

而後咱們經過運行 yarn init 來建立一個新的package.json

yarn init
複製代碼

新包的名稱應該遵循咱們的NPM Org scope命名方式,例如:@my-scope-name。 一樣重要的是,新的包要從0.0.0這樣的版本開始,由於一旦咱們使用Lerna進行第一次發佈,它就會發布成0.1.0或1.0.0。

// package.json
{
  "name": "@my-scope-name/my-design-system-form",
  "version" : "0.0.0",
  "main" : "index.js"
}
複製代碼

若是您有一個支持私有包的NPM Org帳戶,您能夠在您的模塊的獨立包.json中添加如下內容。

"publishConfig": {
    "access": "restricted"
}
複製代碼

將本地的兄弟依賴關係添加到特定的包中

如今咱們知道了建立新包的流程,假設說咱們最後的結構是這樣的。

my-design-system/
    packages/
        my-design-system-core/
        my-design-system-form/
        my-design-system-button/
複製代碼

若是咱們想把my-design-system-button做爲依賴關係添加到my-design-system-form中,並讓Lerna將它們進行符號連接,咱們能夠經過cd到該包中來實現。

cd my-design-system-form 
複製代碼

而後運行如下內容。

lerna add @my-scope-name/design-system-button --scope=@my-scope-name/my-design-system-form
複製代碼

這將更新@my-scope-name/my-design-system-form的package.json。 咱們的package.json應該是這樣的。

// package.json
{
  "name": "@my-scope-name/my-design-system-form",
  "version": "1.0.0",
  "main": "index.js",
  "dependencies": {
    "@my-scope-name/my-design-system-button": "^1.0.0"
  }
}
複製代碼

如今,你能夠在index.js中引用這個本地依賴關係,如

import Button from '@my-scope-name/my-design-system-button';
複製代碼

爲全部的包添加一個 "共同 "的依賴關係

作法和前面的命令相似。不過這是針對/packages/* 的。無論你要加的依賴是本地的同級依賴仍是來自NPM的依賴,都不要緊。

lerna add the-dep-name
複製代碼

若是你有常見的開發依賴,最好在 workspace 的 root package.json中指定。例如,能夠是Jest、Husky、Storybook、Eslint、Prettier等依賴項

yarn add husky --dev -W
複製代碼

*添加-W標誌,就能夠明確表示咱們要把依賴關係添加到工做區根目錄。

刪除依賴

若是有一個全部包都使用的依賴,但你想刪除,Lerna有exec命令,能夠在每一個包中運行一個任意命令。有了這些知識,咱們就可使用exec來刪除全部包的依賴關係。

lerna exec -- yarn remove dep-name
複製代碼

運行測試

Lerna提供了run命令,它將在每一個包含了npm腳本的包中運行該腳本。 例如,假設咱們全部的包都遵循my-design-system-form的結構。

my-design-system-form/
    __tests__/
        Form.test.js
複製代碼

在每一個package.json中,咱們都有測試的npm腳本。

"name": "@my-scope-name/my-design-system-form",
"scripts": {
    "test": "jest"
}
複製代碼

而後Lerna能夠經過運行每一個測試腳原本執行。

lerna run test --stream
複製代碼

*-stream 這個flag提供子進程的輸出。

發佈到NPM

手動

首先,你須要確保你已經登陸了。你能夠經過如下操做來驗證你是否已經登陸。

npm whoami // myusername
複製代碼

若是你沒有登陸,請運行如下內容並按照提示操做。

npm login
複製代碼

登陸後,您能夠經過運行Lerna發佈。

lerna publish
複製代碼

Lerna會提示你更新版本號。

自動

Lerna支持使用Conventional Commits Standard在CI環境中自動進行語義版本管理。 這使開發人員可以像下面這樣提交

git commit -m "fix: JIRA-1234 Fixed minor bug in foo"
複製代碼

而後在CI環境中,包的版本能夠根據上面的提交更新併發布到NPM。這能夠經過配置你的CI環境來完成。

lerna publish --conventional-commits --yes 
複製代碼

若是你不想傳遞flag,能夠在你的lerna.json文件中添加如下內容。

"command": {
    "publish": {
       "conventionalCommits": true, 
       "yes": true
    }
}
複製代碼

強制執行 Conventional Commits

若是你想強制執行 Conventional Commits 標準,我建議在項目的ROOT中加入Commitlint。

yarn add @commitlint/cli @commitlint/config-conventional husky cross-env --dev
複製代碼

而後在根package.json中建立一個發佈腳本

"scripts": {
    "release": "cross-env HUSKY_BYPASS=true lerna publish"
}
複製代碼

這個發佈腳本將在CI環境中運行。請注意,咱們在 lerna.json 文件中配置了傳統的提交和 "yes "標誌。因爲這個CI環境將會把版本的變動提交,咱們不但願觸發提交消息的inting。咱們經過添加一個名爲HUSKY_BYPASS的環境變量來實現,咱們將使用cross-env將其設置爲true。 咱們還須要在root package.json中添加進一步的配置。

"husky": {
    "hooks": {
    "commit-msg": "[[ -n $HUSKY_BYPASS ]] || commitlint -E HUSKY_GIT_PARAMS"
    }
},
"commitlint": {
    "extends": ["@commitlint/config-conventional"]
}
複製代碼

對於husky,咱們添加了一個commitlint/config-conventional的commit-msg鉤子,它將檢查咱們在上面添加的HUSKY_BYPASS環境變量,若是這個變量是假的,那麼咱們經過@commitlint/config-conventional來精簡提交消息。

分離版本控制與發佈

若是出於任何緣由,你想徹底掌控版本控制,Lerna有能力將版本控制和發佈分紅兩個命令。 你能夠手動運行。

lerna version
複製代碼

而後按照提示更新各個版本號。 而後你就能夠有一個步驟,讀取最新的標籤(是手動更新的)發佈到NPM。

lerna publish from-git --yes
複製代碼

多貢獻者參與的本地開發

每當有新的貢獻者對你的項目進行git克隆,或者你須要拉取你團隊的最新變化時,你必須運行yarn命令。

yarn
複製代碼

在大多數的Lerna教程中,提倡使用lerna bootstrap命令,然而當啓用yarn工做空間時,這是沒必要要的,也是多餘的

lerna bootstrap when you're using Yarn workspaces is literally redundant? All lerna bootstrap --npm-client yarn --use-workspaces (CLI equivalent of your lerna.json config) does is call yarn install in the root. — Issue 1308
複製代碼

更多信息見github.com/lerna/lerna…

跨項目的本地開發

在咱們的例子中,咱們正在構建一個多包設計系統。若是開發人員想在設計系統中建立一個新的組件,但在發佈以前也要在本地客戶端應用程序中進行測試,他們能夠經過使用yarn的連接命令來實現。

創建本地依賴關係的symlink

假設咱們想在my-client-app中使用咱們本地的my-design-system-core。 咱們先cd到咱們要在另外一個項目中用到的軟件包。

cd ~/path/to/my-design-system/my-design-system-core
複製代碼

而後咱們建立一個symlink

yarn link
複製代碼

你應該看到這樣的輸出

success Registered "@my-scope-name/my-design-system-core".
info You can now run `yarn link "@my-scope/my-design-system-core"` in the projects where you want to use this module and it will be used instead.
複製代碼

如今咱們的包已經有了符號連接,咱們能夠進入my-client-app中使用。

cd ~/path/to/my-client-app 
yarn link @my-scope-name/my-design-system-core
複製代碼

/packages/my-design-system-core 中的任何變化都會反映在my-client-app中。如今,開發人員能夠很容易地在兩個項目上進行本地開發,並看到它的反映。

解除本地依賴關係的連接

當開發者完成後,再也不想使用本地的包時,咱們須要解除連接。 cd到入咱們要解除連接的包中

cd ~/path/to/my-design-system/my-design-system-core
複製代碼

運行unlink刪除本地symlink

yarn unlink
複製代碼

你會看到這樣的輸出

success Unregistered "@my-scope-name/my-design-system-core".
info You can now run `yarn unlink "@my-scope-name/my-design-system-core"` in the projects where you no longer want to use this module.
複製代碼

如今,咱們能夠cd到my-client-app中解除連接。

cd ~/path/to/my-client-app
yarn unlink @my-scope-name/my-design-system-core
複製代碼

總結

Lerna與Yarn Workspaces是一個很好的組合。Lerna 在 Yarn Workspaces 的基礎上增長了實用功能,用於處理多個包。紗線工做空間使得全部的依賴關係能夠一塊兒安裝,使得緩存和安裝速度更快。它讓咱們能夠經過一個命令輕鬆地在NPM上發佈依賴關係,當依賴關係的版本發生變化時,自動更新兄弟依賴關係的package.json,通常來講,安裝、版本管理和發佈都是一種無痛的體驗。

相關文章
相關標籤/搜索