Monorepo 項目管理Lerna


一、項目中遇到的問題

      最近在開發小程序的UI庫,組件拆分力度比較細,都是一個個的單獨的package包, 模塊的復用性和靈活性達到最大化,實操的過程中,會遇到以下問題:

     1、維護成本較高,任何的基層 repo 版本變更,將會引發一系列上層封裝版本變動

     2、版本發布npm包,代碼不夠規范,很多都不是發布master

     3、一個包一個repo,每次需要找到對應的倉庫

     4、changelog 梳理異常折騰,有些基本上都沒有changelog

 

基於上面的問題,有沒有一種能解決我們問題的技術呢?

 

二、Monorepo 項目管理

    Monorepo 的全稱是 monolithic repository,即單體式倉庫,與之對應的是 Multirepo(multiple repository),這里的“單”和“多”是指每個倉庫中所管理的模塊數量。

    Multirepo 是比較傳統的做法,即每一個 package 都單獨用一個倉庫來進行管理。例如:Rollup, ...,上面遇到問題的也是采用的這種方式。

    Monorep 是把所有相關的 package 都放在一個倉庫里進行管理,每個 package 獨立發布。例如:React, Angular, Babel, Jest, Umijs, Vue ...

    Multirepo和Monorep優劣勢對比如下:

    

 

三、Monorepo 管理工具Lerna

Lerna 是一個管理多個 npm 模塊的工具,是 Babel 自己用來維護自己的 Monorepo 並開源出的一個項目。優化維護多包的工作流,解決多個包互相依賴,且發布需要手動維護多個包的問題。

Lerna 現在已經被很多著名的項目組織使用,如:Babel, React, Vue, Angular, Ember, Meteor, Jest 。

1、lerna模式

在初始化一個項目之前我們必須要清楚,lerna 對管理 monoRepo 有兩種模式

  • Fixed/Locked mode (default)
  • Independent mode

Fixed/Locked 模式: 官方默認推薦模式,當前 babel 的項目管理模式,在該模式下所有的 packages 都會遵循一個版本號,該版本號維護在 lerna.json 的 version 字段中,當需要版本發布時 lerna publish 時,如果一個模塊和上一次 release 相比有過變更的話,會自動發布一個新版本。

這種模式的問題在於:當有一個 major 變更的時候,所有 packages 都會都會有一個新的 major 版本。

維護團隊認為:版本是一種非常 cheap 的東西,所以不必糾結。

Independent 模式: 在該模式下所有 packages 新版本的生成將會由開發者決定,lerna.json 的 version 字段也會隨之失效。這種模式的弊端非常明顯,開發者必須要非常清晰該發什么版本,事實上在多人協作項目上很難做到這一點。

 2、如何使用lerna

    a、全局安裝lerna

npm i -g lerna

 

    b、初始化項目

mkdir lerna-repo && cd $_
npx lerna init

   初始目錄如下,接着進行開發

 

     c、建立 packages 的依賴關系

lerna bootstrap

     

    這個命令會安裝好所有 packages 的依賴,以及建立好 packages 相互依賴的軟連接

    正式流程為:

  1. 安裝所有 package 的外部依賴.
  2. 對存在相互依賴的 package 創建軟連接.
  3. 在所有已經 bootstrapped 的 package 中執行 npm run prepublish.
  4. 在所有已經 bootstrapped 的 package 中執行 npm run prepare.

       當然我們使用 --hoist 來把每個 package 下的依賴包都提升到工程根目錄,來降低安裝以及管理的成本。

lerna bootstrap --hoist

 

   

   如果以前安裝了依賴,發生改動,可以先清理一下安裝的依賴即可:

lerna clean

 

    d、發布版本

lerna publish

   正式流程為:

  1. 執行 lerna updated 來確定哪些包需要被發布.
  2. 如有必要會升級 lerna.json 的 version 字段。
  3. 對所有需要 update 的 package 進行版本的更新,並寫入他們的 package.json.
  4. 對所有需要 update 的 package 進行依賴申明 specified with a caret (^).
  5. 創建一個 git commit 和 tag
  6. 把包發布至 npm

 

四、生成changelog

     由於本項目后期需要對外,使用基於PR來生成changelog的lerna-changelog,項目建議使用cz-lerna-changelog 。

     1、安裝lerna-changelog

npm install lerna-changelog --save-dev

     

     2、修改 lerna.josn 需要新增相關 lerna-changelog 所需要的配置,此處參考babel配置

"changelog": {
    "repo": "binglingwy/lerna-test-new",
    "cacheDir": ".changelog",
    "labels": {
      "PR: Breaking Change :boom:": ":boom: Breaking Change",
      "PR: New Feature :rocket:": ":rocket: New Feature",
      "PR: Bug Fix :bug:": ":bug: Bug Fix",
      "PR: Docs :memo:": ":memo: Documentation",
      "PR: Internal :house:": ":house: Internal",
      "PR: Performance :running_woman:": ":running_woman: Performance"
    }
  },

     注意:labels 的 key 必須在 github 的倉庫內定義好

     3、設置令牌

export GITHUB_AUTH="..."

GITHUB_AUTH 的 token 字段可以在github 申請 token 獲得。

   4、創建個PR

        a、拉一個新的分支

        b、修改代碼並提交,提交記錄記得關聯issues,例如:

git commit -a -m "module-base: bug fixed, Close #1"

        c、推送代碼,並在github上創建PR

       注意:在創建 pr 時一定要選擇對應的 label ,label需提前在github建好,跟lerna.josn一致

        d、合並pr到主干,切換到本地master,生成changelog

node_modules/.bin/lerna-changelog

      e、一旦 publish 后我們便可以創建 release note,效果如下

     

 當然也可以在生成文件CHANGELOG.md,在lerna.json中添加conventionalCommits配置:

"command": {
    "publish": {
      "allowBranch": "master",
      "conventionalCommits": true
    }
  }

配置后,當我們執行lerna publish后會在項目根目錄以及每個packages包下,生成CHANGELOG.md

注意: 只有符合約定commit提交才能正確生成CHANGELOG.md文件。

 

參考文章

Lerna 官網:https://github.com/lerna/lerna/blob/master/README.md

lerna-changelog:https://github.com/lerna/lerna-changelog

手摸手教你玩轉 Lerna: http://www.uedlinker.com/2018/08/17/lerna-trainning/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM