源自Babel的多包管理工具:Lerna


編者按:本文做者:劉觀宇,360 奇舞團高級前端工程師、技術經理,W3C CSS 工做組成員。前端

多包合做的煩惱

在開發須要多個密切協做的軟件包時候,咱們每每將獨立的功能塊進行劃分,使得各個功能獨立的模塊分別完成,以減小相互影響,完成有效的多人合做。可是,在模塊協做時,常常會遇到一些問題:vue

  1. 依賴處理繁瑣。node

  2. 依賴的模塊,尚處在開發之中,通行的npm install、yarn等沒法從安裝源中得到。react

  3. 被依賴的模塊版本升級,模塊其餘版本須要手動管理相關的版本。git

  4. 有循環依賴的風險github

對於多個模塊的大型項目的協做管理,通常地有multirepo、monorepo和submodules等多種方式:multirepo是將多個模塊分別分爲多個倉庫,早期的Babel(Babel6之前)使用的就是這種方式;submodules是藉助git的實現,在.gitmodules中寫明引用的倉庫,在主倉庫中只保留必要的索引;monorepo則是將相關的模塊用單一的倉庫統一管理。vue-cli

上述的方式各有優劣。從目前前端工程的代碼管理來看,monorepo被不少超級repo選中。Babel、vue-cli、create-react-app都採用這種模式。npm

Babel的重要貢獻者Jamie Kyle1,在爲 Babel 6 工做的過程當中發現全部東西都拆分紅漂亮的小插件包,但同時也就須要管理數十個軟件包。所以,多包存儲庫管理工具 Lerna 應運而生。爲讓項目更好用,他對項目進行了屢次重寫,試圖讓架構更完善。下圖是Jamie Kyle的靚照@_@json

Lerna也是Babel官方如今使用的多包管理工具。bootstrap

什麼是Lerna

Lerna官網2對此給出了官方的解釋:Lerna是一個管理包含多個軟件包的JavaScript項目的工具。它能夠:

  1. 解決包之間的依賴關係。

  2. 經過git倉庫檢測改動,自動同步。

  3. 根據相關的git提交的commit,生成CHANGELOG。

Lerna是一個命令行工具,能夠將其安裝在系統全局。簡單的命令說明,可使用:lerna -h查看命令幫助。

兩種模式

Lerna分爲兩種模式:fixed模式和independent模式。兩種模式的區別在於:前者強制全部的包都使用在根目錄lerna.json中指定的版本號。然後者各個軟件包,能夠本身指定版本號。

默認的,lerna使用的是fixed模式。筆者認爲,這種模式下,全部的相關軟件包,最好以幾乎一致的發佈週期發佈,如Babel這種。而且軟件內部應該被使用者更多以「黑盒」方式對待。這是fixed模式最適應的方式。

而須要暴露內部包的細節,或者迭代頻率顯著不一致的包,建議採用independent模式。

指定爲independent模式,能夠在lerna init時加入--independent,或者將lerna.json的version字段指定爲independent。

Lerna配置

lerna.json一般位於項目的根目錄下,定義了lerna運行的主要行爲。當在根目錄下運行lerna initlerna init --independent時,會自動生成。如下是一個典型的配置:

{

  "version": "1.1.3",

  "npmClient": "npm",

  "command": {

    "publish": {

      "ignoreChanges": ["ignored-file", "*.md"],

      "message": "chore(release): publish"

    },

    "bootstrap": {

      "ignore": "component-*",

      "npmClientArgs": ["--no-package-lock"]

    }

  },

  "packages": ["packages/*"]

}

上面的配置文件中:

  1. version指定的是全部包的統一版本號;對於independent模式,這個字段請指定爲independent;

  2. npmClient指定的是npm的客戶端。默認的,lerna將使用npm。讀者也可依所需將程序設置爲yarn,甚至cnpm等等。

  3. command字段,能夠對publish和bootstrap命令進行參數傳遞和命令定製。如:command.publish.ignoreChanges,用來設置一些忽略的文件,以免無關文件的提交對於版本號的變動,如README.md等等。command.bootstrap.npmClientArgs指定在bootstrap命令時,傳遞的默認參數,好比咱們會經常使用--no-package-lock來禁止package-lock.json或yarn.lock等等。

  4. packages字段指定包所在的目錄。

Lerna命令

初始一個多包的工程

lerna init

上述命令會初始化一個多包工程。初始化以後會在根目錄生成packages目錄、lerna.json,若是使用independent模式,請使用命令:lerna init --independent

建立子包

lerna create <package> [-y]

在packages所指目錄下建立package包。

添加包

lerna add <package>[@version] [--dev] [--exact] [--scope=module名]

上述命令會添加一個包package指明的軟件包。

指定--dev是添加在devDependencies中。

指定--exact,則將用精確匹配的版本添加包。

指定--scope將只在此指明的模塊中安裝這個軟件包,不然將在全部packages目錄中的包中安裝。

對於packages目錄下的子包,將經過設立systemlink來解決依賴。

對於npm鏡像中存在的包,將安裝鏡像中的包。

運行命令

運行命令分爲兩種:任意命令和npm scripts定義的命令。

對於任意命令使用,lerna exec;對於npm scripts定義的命令使用lerna run

lerna exec爲例:

lerna exec [--concurrency number] [--stream] [--parallel] -- <command> [..args]此命令,在全部包中運行所指定的命令。

特別地,lerna exec -- rm -rf ./node_modules將刪除全部包中的依賴。lerna exec -- npm uninstall <package>將移除全部的package依賴。

lerna execlerna run 如須要每一個子模塊相繼的執行並按順序輸出,能夠指定--concurrency 1。

對於指定了--stream的命令,將把全部子進程的輸出當即回顯此舉可能形成子進程顯示順序交叉,爲了分辨輸出來源,每一個輸出,會帶上包名;指定了--parallel的命令,則會在scope指定的範圍內,並行地執行相關地命令。

lerna run與上述命令不同的狀況在於,lerna run build將在每個包中scripts字段中執行定義的build命令。

安裝全部依賴

lerna bootstrap

上述命令安裝全部的依賴、將全部的相關連接作好,同時在全部的包中運行npm run prepublish。隨後,在全部包中運行npm run prepare。此時,全部的依賴均已完備。

發佈

lerna publish 發佈全部的包。

清理

lerna clean 刪除全部的node_modules

一些優化

合併公共依賴

咱們在開發過程當中,常常發現包依賴相似。這樣,咱們發現運行lerna bootstrap以後,會重複安裝依賴包,這樣會形成空間的浪費和效率的下降。爲此,咱們能夠把一樣的依賴包在根目錄安裝一次便可。此時,可使用lerna bootstrap --hoist命令,則公用的依賴,只會在頂層目錄安裝一次。

發佈帶有scope公有包

帶有scope的包,須要發佈時候,若是是公有的包,須要在npm publish時候使用npm publish --access public。爲了可以成功publish,並使用lerna流程,請在每一個子包的package.json中加入:

"publishConfig": {

    "access": "public"

  }

檢測循環依賴

lerna自己內置了檢測循環依賴的功能,若是出現循環依賴。會在bootstrap時候給出提示:

此時,請依照提示去掉循環依賴,以保證軟件包的正常運行。

文內連接

  1. https://github.com/jamiebuilds

  2. https://lerna.js.org/


若是你喜歡探討技術,或者對本文有任何的意見或建議,很是歡迎加魚頭微信好友一塊兒探討,固然,魚頭也很是但願能跟你一塊兒聊生活,聊愛好,談天說地。魚頭的微信號是:krisChans95 也能夠掃碼關注公衆號,訂閱更多精彩內容。


本文分享自微信公衆號 - 魚頭的Web海洋(krissarea)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索