如何利用lerna來管理模塊

當前端項目變得越來越大的時候,我們通常會將公共代碼拆分出來,成爲一個個獨立的npm包進行維護。但是這樣一來,各種包之間的依賴管理就十分讓人頭疼。爲了解決這種問題,我們可以將不同的npm包項目都放在同一個項目來管理。這樣的項目開發策略也稱作monorepo。Lerna就是這樣一個你更好地進行這項工作的工具。本文將詳細介紹如何使用Lerna來輔助我們的包依賴管理。

什麼是Lerna

根據官網上的定義,Lerna是一個使用git和npm來處理多包依賴管理的工具,利用它能夠自動幫助我們管理各種模塊包之間的版本依賴關係。目前,已經有很多公共庫都使用Lerna作爲它們的模塊依賴管理工具了,如:babel, create-react-app, react-router, jest等。

常用命令

bootstrap

使用bootstrap命令,會下載所有定義在package.json中的依賴包。相當於執行npm install,並且鏈接所有依賴包。

publish

當你完成某個包的更新後,就可以使用lerna publish命令來發布新版本的包。執行這條命令的時候,你可以指定版本號,然後lerna就會自動給你加更新版本號,加tag並提交到git倉庫上去。

add

假設你想往你的開發項目中特定包中加入依賴,你就可以使用add命令輕鬆實現:

# 給a, b 包中加入Lodash,會同時改變a,b模塊中packages.json文件
lerna add lodash packages/a packages/b 
# 給a 包中加入jquery, 使用--dev參數是使依賴加入到devDependencies中
lerna add jquery packages/a --dev
# 你也可以使用通配符, 下面這命令,會往所有re開頭的模塊包中加入依賴
lerna add jquery packages/re-* 
# 指定特定的範圍,要使用--scope參數,如下:給b包安裝a模塊
lerna add a --scope=b

clean

執行clean命令,用來刪除所有模塊下node_modules中的npm包。

import

你可以使用import命令導入已有的模塊,並且會保留所有的git commit記錄。

list

列出項目中所有的模塊。

run

在每個包含該腳本的模塊中運行npm腳本。

動手實戰

說了那麼多,我們寫個例子實操一下。

初始化項目

首先,先建一個新項目,接着我們全局安裝lerna,並執行初始化操作,再上傳到git倉庫上。:

npm intall lerna -g
mkdir lerna-demo && cd $_
lerna init
git init
git add .
git commit -m "Initial Commit"
git remote add origin http://github.com/scq000/lerna-demo.git
git push -u origin master
ls

執行完上述命令後,就會在當前目錄下生成以下幾個文件:

packages/
package.json
lerna.json

其中: packages目錄用來存放我們需要拆分的各種公共代碼庫。lerna.json文件裏面記錄了lerna的相關配置信息:

{
  "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/*"]
}

分別介紹每個配置項的功能:

  • version: 記錄當前項目的版本號
  • npmClient: 你可以指定使用npm, cnpm或yarn來執行命令
  • command.publish.ignoreChanges: 忽略特定的項
  • command.publish.npmClientArgs: 當執行lerna bootstrap命令時,傳給npm install的參數
  • command.publish.message: 發佈模塊的時候,填寫的commit信息
  • packages: 模塊包默認所在的地址

你可以根據需要自己更改相應的配置。

新建兩個模塊

爲了演示方便,我們新建兩個模塊, moduleA和moduleB, 並讓moduleA依賴moduleB:

lerna create module-a
lerna create module-b
# 將本地包鏈接起來,可以直接引用
lerna link

修改module-b 的入口文件:

export const sayHello() {
    return "hello world";
};

修改module-a 的入口文件:

const moduleB = require('module-b');

const moduleA = function() {
    console.log(moduleB.sayHello());
}

export default moduleA;

發佈新模塊

完成修改後,我們可以直接發佈新的模塊

lerna publish

然後,根據提示輸入版本號等,lerna就會自動幫我們給包加上tag,並上傳到對應的倉庫中去。

希望這個簡單的例子可以能讓大家熟悉簡單的操作流程。

兩種模式

lerna允許我們使用兩種模塊來管理我們的模塊:Fixed 模式和Independent模式。

Fixed/Locked mode

這個模式也是我們初始化項目的時候默認採用的模式。在這種模式下, 你可以理解爲"全量發佈"。也就是當我們一旦有某個模塊的主版本更新了,那麼所有包都會擁有一個新的版本號。而主版本號,是管理在項目根目錄的lerna.json文件中。

Independent mode

如果你不喜歡上面這種模式,你也可以使用Independent模式來管理項目中的模塊。你只需要在初始化項目的使用指定--independent參數就可以了:

lerna init --independent

在這種模式下,我們可以獨立地更新某個包的版本號,你可以理解爲"增量發佈"。

可能遇到的問題及解決方案

打包太慢

在使用過程中,最經常遇到的問題是,執行lerna bootstrap的時候奇慢無比。這種情況通常是因爲在每個獨立包中都重複安裝了公共依賴。在這時候,我們可以將所有公共使用的包,如react,lodash之類的移到根目錄的package.json中去,並使用lerna bootstrap --hoist命令進行安裝。使用hoist選項後,所有公共的依賴都只會安裝在根目錄的node_modules目錄中去,而不會在每個包目錄下的node_modules中都保留各自的依賴包。

這樣一來,lerna bootstrap的執行效率就大大增加了。

多個包版本依賴不一致

另一個可能常遇到的問題就是多個安裝包之間版本不一致,比如,A包需要依賴1.0的lodash, 而B包則需要依賴2.0的lodash。這樣就會導致在打包過程中多了許多重複代碼。而且在同一項目下保留不同版本的npm包也難以管理。對於這個問題,在大多數情況下,我們可以嘗試使用npm包管理器提供的peerDependencies選項來固定一個版本號。既可以避免很多重複的代碼,也可以解決不同版本號所帶來的衝突問題。

參考資料

https://github.com/lerna/lerna

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章