lerna
最近在看vue-cli的原始碼部分,注意到這一個倉庫下維護了多個package,很好奇他是如何在一個repo中管理這些package的。
我們組現在也在使用元件庫的方式維護專案間共用的業務程式碼。有兩個元件庫,存在依賴的關係,目前聯調是通過npm link
的方式,效能並不好,時常出現卡頓的問題。加上前一段時間組內分享vue3也提到了lerna,於是便決定仔細的調研一下這個工具,為接下里的元件庫優化助力。
lerna的文件還是很詳細的,因為全是英文的,考慮到閱讀問題,這裡我先是自己跑了幾個demo,然後做了中文翻譯。後續我會出一篇專門的lerna實戰篇
lerna 是幹什麼的?
Lerna 是一個工具,它優化了使用 git 和 npm 管理多包儲存庫的工作流。
背景
1.將一個大的 package 分割成一些小的 packcage 便於分享,除錯
2.在多個 git 倉庫中更改容易變得混亂且難以跟蹤
3.在多個 git 倉庫中維護測試繁瑣
兩種工作模式
Fixed/Locked mode (default)
vue,babel 都是用這種,在 publish 的時候,所有的包版本都會更新,並且包的版本都是一致的,版本號維護在 lerna.jon 的 version 中
Independent mode
lerna init --independent
獨立模式,每個 package 都可以有自己的版本號。版本號維護在各自 package.json 的 version 中。每次釋出前都會提示已經更改的包,以及建議的版本號或者自定義版本號。這種方式相對第一種來說,更靈活
初始化專案
npm install -g lerna // 這裡是全域性安裝,也可以安裝為專案開發依賴,使用全域性方便後期使用命令列
mkdir lerna-repo
cd lerna-repo
lerna init // 初始化一個lerna專案結構,如果希望各個包使用單獨版本號可以加 -i | --independent
標準的 lerna 目錄結構
- 每個單獨的包下都有一個 package.json 檔案
- 如果包名是帶 scope 的,例如@test/lerna,package.json 中,必須配置"publishConfig": {"access": "public"}
my-lerna-repo/
package.json
lerna.json
LICENSE
packages/
package-1/
package.json
package-2/
package.json
啟用 yarn Workspaces (強烈建議)
Workspaces can only be enabled in private projects.
預設是 npm, 每個子 package 下都有自己的 node_modules,通過這樣設定後,會把所有的依賴提升到頂層的 node_modules 中,並且在 node_modules 中連結本地的 package,便於除錯
注意:必須是 private 專案才可以開啟 workspaces
// package.json
"private": true,
"workspaces": [
"packages/*"
],
// lerna.json
"useWorkspaces": true,
"npmClient": "yarn",
hoist: 提取公共的依賴到根目錄的node_moduels
,可以自定義指定。其餘依賴安裝的package/node_modeles
中,可執行檔案必須安裝在package/node_modeles
。
workspaces: 所有依賴全部在跟目錄的node_moduels
,除了可執行檔案
常用命令
lerna init
初始化 lerna 專案
- -i, --independent 獨立版本模式
[lerna create <name> [loc]](https://github.com/lerna/lern...
建立一個 packcage
--access
當使用scope package
時(@qinzhiwei/lerna),需要設定此選項 可選值: "public", "restricted"--bin
建立可執行檔案--bin
--description
描述 [字串]--dependencies
依賴,用逗號分隔 [陣列]--es-module
初始化一個轉化的Es Module [布林]--homepage
原始碼地址 [字串]--keywords
關鍵字數 [陣列]--license
協議 字串--private
是否私有倉庫 [布林]--registry
源 [字串]--tag
釋出的標籤 [字串]-y, --yes
跳過所有的提示,使用預設配置 [布林]
lerna add
為匹配的 package 新增本地或者遠端依賴,一次只能新增一個依賴
$ lerna add <package>[@version] [--dev] [--exact] [--peer]
執行該命令時做的事情:
- 為匹配到的 package 新增依賴
- 更改每個 package 下的 package.json 中的依賴項屬性
Command Options
以下幾個選項的含義和npm install
時一致
--dev
--exact
--peer
同級依賴,使用該package需要在專案中同時安裝的依賴--registry
--no-bootstrap
跳過lerna bootstrap
,只在更改對應的 package 的 package.json 中的屬性
Examples
# Adds the module-1 package to the packages in the 'prefix-' prefixed folders
lerna add module-1 packages/prefix-*
# Install module-1 to module-2
lerna add module-1 --scope=module-2
# Install module-1 to module-2 in devDependencies
lerna add module-1 --scope=module-2 --dev
# Install module-1 to module-2 in peerDependencies
lerna add module-1 --scope=module-2 --peer
# Install module-1 in all modules except module-1
lerna add module-1
# Install babel-core in all modules
lerna add babel-core
lerna bootstrap
將本地 package 連結在一起並安裝依賴
執行該命令式做了一下四件事:
1.為每個 package 安裝依賴
2.連結相互依賴的庫到具體的目錄,例如:如果 lerna1 依賴 lerna2,且版本剛好為本地版本,那麼會在 node_modules 中連結本地專案,如果版本不滿足,需按正常依賴安裝
3.在 bootstraped packages 中 執行
npm run prepublish
4.在 bootstraped packages 中 執行
npm run prepare
Command Options
--hoist
匹配 [glob] 依賴 提升到根目錄 [預設值: '**'], 包含可執行二進位制檔案的依賴項還是必須安裝在當前 package 的 node_modules 下,以確保 npm 指令碼的執行--nohoist
和上面剛好相反 [字串]--ignore-prepublish
在 bootstraped packages 中不再執行 prepublish 生命週期中的指令碼 [布林]--ignore-scripts
在 bootstraped packages 中不再執行任何生命週期中的指令碼 [布林]--npm-client
使用的 npm 客戶端(npm, yarn, pnpm, ...) [字串]--registry
源 [字串]--strict
在 bootstrap 的過程中不允許發出警告,避免花銷更長的時間或者導致其他問題 [布林]--use-workspaces
啟用 yarn 的 workspaces 模式 [布林]--force-local
無論版本範圍是否匹配,強制本地同級連結 [布林]--contents
子目錄用作任何連結的源。必須適用於所有包 字串
lerna link
將本地相互依賴的 package 相互連線。例如 lerna1 依賴 lerna2,且版本號剛好為本地的 lerna2,那麼會在 lerna1 下 node_modules 中建立軟連指向 lerna2
Command Options
- --force-local 無論本地 package 是否滿足版本需求,都連結本地的
// 指定軟鏈到package的特定目錄
"publishConfig": {
"directory": "dist" // bootstrap的時候軟鏈package下的dist目錄 package-1/dist => node_modules/package-1
}
lerna list
list 子命令
lerna ls
: 等同於lerna list
本身,輸出專案下所有的 packagelerna ll
: 輸出專案下所有 package 名稱、當前版本、所在位置lerna la
: 輸出專案下所有 package 名稱、當前版本、所在位置,包括 private package
Command Options
--json
以 json 形式展示
$ lerna ls --json
[
{
"name": "package-1",
"version": "1.0.0",
"private": false,
"location": "/path/to/packages/pkg-1"
},
{
"name": "package-2",
"version": "1.0.0",
"private": false,
"location": "/path/to/packages/pkg-2"
}
]
--ndjson
$ lerna ls --ndjson
{"name":"package-1","version":"1.0.0","private":false,"location":"/path/to/packages/pkg-1"}
{"name":"package-2","version":"1.0.0","private":false,"location":"/path/to/packages/pkg-2"}
--all
Alias: -a
顯示預設隱藏的 private package
$ lerna ls --all
package-1
package-2
package-3 (private)
--long
Alias: -l
顯示包的版本、位置、名稱
$ lerna ls --long
package-1 v1.0.1 packages/pkg-1
package-2 v1.0.2 packages/pkg-2
$ lerna ls -la
package-1 v1.0.1 packages/pkg-1
package-2 v1.0.2 packages/pkg-2
package-3 v1.0.3 packages/pkg-3 (private)
--parseable
Alias: -p
顯示包的絕對路徑
In --long
output, each line is a :
-separated list: ::[:flags..]
$ lerna ls --parseable
/path/to/packages/pkg-1
/path/to/packages/pkg-2
$ lerna ls -pl
/path/to/packages/pkg-1:package-1:1.0.1
/path/to/packages/pkg-2:package-2:1.0.2
$ lerna ls -pla
/path/to/packages/pkg-1:package-1:1.0.1
/path/to/packages/pkg-2:package-2:1.0.2
/path/to/packages/pkg-3:package-3:1.0.3:PRIVATE
--toposort
按照拓撲順序(dependencies before dependents)對包進行排序,而不是按目錄對包進行詞法排序。
$ json dependencies <packages/pkg-1/package.json
{
"pkg-2": "file:../pkg-2"
}
$ lerna ls --toposort
package-2
package-1
--graph
將依賴關係圖顯示為 JSON 格式的鄰接表 adjacency list.
$ lerna ls --graph
{
"pkg-1": [
"pkg-2"
],
"pkg-2": []
}
$ lerna ls --graph --all
{
"pkg-1": [
"pkg-2"
],
"pkg-2": [
"pkg-3"
],
"pkg-3": [
"pkg-2"
]
}
lerna changed
列出自上次釋出(打 tag)以來本地發生變化的 package
注意: lerna publish
和lerna version
的lerna.json
配置同樣影響lerna changed
。 例如 command.publish.ignoreChanges
.
Command Options
lerna changed
支援 lerna ls
的所有標記:
lerna 不支援過濾選項, 因為lerna version
or lerna publish
不支援過濾選項.
lerna changed
支援 lerna version
(the others are irrelevant)的過濾選項:
lerna import
lerna import
將現有的 package 匯入到 lerna 專案中。可以保留之前的原始提交作者,日期和訊息將保留。
注意:如果要在一個新的 lerna 中引入,必須至少有個 commit
Command Options
--flatten
處理合並衝突--dest
指定引入包的目錄--preserve-commit
保持引入專案原有的提交者資訊
lerna clean
lerna clean
移除所有 packages 下的 node_modules,並不會移除根目錄下的
lerna diff
檢視自上次釋出(打 tag)以來某個 package 或者所有 package 的變化
$ lerna diff [package]
$ lerna diff
# diff a specific package
$ lerna diff package-name
Similar tolerna changed
. This command runsgit diff
.
lerna exec
在每個 package 中執行任意命令,用波折號(--
)分割命令語句
使用方式
$ lerna exec -- <command> [..args] # runs the command in all packages
$ lerna exec -- rm -rf ./node_modules
$ lerna exec -- protractor conf.js
可以通過LERNA_PACKAGE_NAME
變數獲取當前 package 名稱:
$ lerna exec -- npm view $LERNA_PACKAGE_NAME
也可以通過LERNA_ROOT_PATH
獲取根目錄絕對路徑:
$ lerna exec -- node $LERNA_ROOT_PATH/scripts/some-script.js
Command Options
$ lerna exec --scope my-component -- ls -la
- --concurrenty
使用給定的數量進行併發執行(除非指定了
--parallel
)。
輸出是經過管道過濾,存在不確定性。
如果你希望命令一個接著一個執行,可以使用如下方式:
$ lerna exec --concurrency 1 -- ls -la
--stream
從子程式立即輸出,字首是包的名稱。該方式允許交叉輸出:
$ lerna exec --stream -- babel src -d lib
![lerna exec --stream -- babel src -d lib]()
--parallel
和--stream
很像。但是完全忽略了併發性和排序,立即在所有匹配的包中執行給定的命令或指令碼。適合長時間執行的程式。例如處於監聽狀態的babel src -d lib -w
$ lerna exec --parallel -- babel src -d lib -w
注意:
建議使用命令式控制包的範圍。
因為過多的程式可能會損害
shell
的穩定。例如最大檔案描述符限制
--no-bail
# Run a command, ignoring non-zero (error) exit codes
$ lerna exec --no-bail <command>
預設情況下,如果一但出現命令報錯就會退費程式。使用該命令會禁止此行為,跳過改報錯行為,繼續執行其他命令
--no-prefix
在輸出中不顯示 package 的名稱
--profile
生成一個 json 檔案,可以在 chrome 瀏覽器(devtools://devtools/bundled/devtools_app.html
)檢視效能分析。通過配置--concurrenty
可以開啟固定數量的子程式數量
![lerna exec --stream -- babel src -d lib]()
$ lerna exec --profile -- <command>
注意: 僅在啟用拓撲排序時分析。不能和--parallel
and--no-sort
一同使用。
--profile-location
設定分析檔案存放位置
$ lerna exec --profile --profile-location=logs/profile/ -- <command>
lerna run
在每個 package 中執行 npm 指令碼
使用方法
$ lerna run <script> -- [..args] # runs npm run my-script in all packages that have it
$ lerna run test
$ lerna run build
# watch all packages and transpile on change, streaming prefixed output
$ lerna run --parallel watch
Command Options
--npm-client
設定npm
客戶端,預設是npm
$ lerna run build --npm-client=yarn
也可以在lerna.json
配置:
{
"command": {
"run": {
"npmClient": "yarn"
}
}
}
- 其餘同
lerna exec
lerna version
生成新的唯一版本號
bumm version:在使用類似 github 程式時,升級版本號到一個新的唯一值
使用方法
lerna version 1.0.1 # 顯示指定
lerna version patch # 語義關鍵字
lerna version # 從提示中選擇
當執行時,該命令做了一下事情:
1.識別從上次打標記釋出以來發生變更的 package 2.版本提示 3.修改 package 的後設資料反映新的版本,在根目錄和每個 package 中適當執行lifecycle scripts 4.在 git 上提交改變並對該次提交打標記(git commit
& git tag
) 5.提交到遠端倉庫(git push
)
![lerna version]()
Positionals
semver bump
lerna version [major | minor | patch | premajor | preminor | prepatch | prerelease]
# uses the next semantic version(s) value and this skips `Select a new version for...` prompt
When this positional parameter is passed, lerna version
will skip the version selection prompt and increment the version by that keyword.
You must still use the --yes
flag to avoid all prompts.
Prerelease
如果某些 package 是預釋出版本(e.g. 2.0.0-beta.3
),當你執行lerna version
配合語義化版本時(major
, minor
, patch
),它將釋出之前的預釋出版本和自上次釋出以來改變過的 packcage。
對於使用常規提交的專案,可以使用如下標記管理預釋出版本:
--conventional-prerelease
: 釋出當前變更為預釋出版本(即便採用的是固定模式,也會單獨升級該 package)--conventional-graduate
: 升級預釋出版本為穩定版(即便採用的是固定模式,也會單獨升級該 package)
當一個 package 為預發版本時,不使用上述標記,使用lerna version --conventional-commits
,也會按照預發版本升級繼續升級當前 package。
Command Options
--allow-branch
--amend
--changelog-preset
--conventional-commits
--conventional-graduate
--conventional-prerelease
--create-release
--exact
--force-publish
--git-remote
--ignore-changes
--ignore-scripts
--include-merged-tags
--message
--no-changelog
--no-commit-hooks
--no-git-tag-version
--no-granular-pathspec
--no-private
--no-push
--preid
--sign-git-commit
--sign-git-tag
--force-git-tag
--tag-version-prefix
--yes
--allow-branch
A whitelist of globs that match git branches where lerna version
is enabled.
It is easiest (and recommended) to configure in lerna.json
, but it is possible to pass as a CLI option as well.
設定可以呼叫lerna version
命令的分支白名單,也可以在lerna.json
中設定
{
"command": {
"version": {
"allowBranch": ["master", "beta/*", "feature/*"]
}
}
}
--amend
lerna version --amend
# commit message is retained, and `git push` is skipped.
預設情況下如果暫存區有未提交的內容,lerna version
會失敗,需要提前儲存本地內容。使用該標記可以較少 commit 的次數,將當前變更內容隨著本次版本變化一次 commit。並且不會git push
--changelog-preset
lerna version --conventional-commits --changelog-preset angular-bitbucket
預設情況下,changelog 預設設定為angular
。在某些情況下,您可能需要使用另一個預置或自定義。
--conventional-commits
lerna version --conventional-commits
當使用這個標誌執行時,lerna 版本將使用傳統的提交規範/Conventional Commits Specification來確定版本並生成CHANGELOG.md。
傳入 --no-changelog
將阻止生成或者更新CHANGELOG.md
.
--conventional-graduate
lerna version --conventional-commits --conventional-graduate=package-2,package-4
# force all prerelease packages to be graduated
lerna version --conventional-commits --conventional-graduate
但使用該標記時,lerna vesion
將升級指定的 package(用逗號分隔)或者使用*
指定全部 package。和--force-publish
很像,無論當前的 HEAD 是否釋出,該命令都會起作用,任何沒有預釋出的 package 將會被忽略。如果未指定的包(如果指定了包)或未預先發布的包發生了更改,那麼這些包將按照它們通常使用的--conventional-commits
進行版本控制。
"升級"一個包意味著將一個預釋出的包升級為釋出版本,例如package-1@1.0.0-alpha.0 => package-1@1.0.0
。
注意: 當指定包時,指定包的依賴項將被釋放,但不會被“升級”。必須和--conventional-commits
一起使用
--conventional-prerelease
lerna version --conventional-commits --conventional-prerelease=package-2,package-4
# force all changed packages to be prereleased
lerna version --conventional-commits --conventional-prerelease
當使用該標記時,lerna version
將會以預釋出的版本釋出指定的 package(用逗號分隔)或者使用*
指定全部 package。
--create-release
lerna version --conventional-commits --create-release github
lerna version --conventional-commits --create-release gitlab
當使用此標誌時,lerna version
會基於改變的 package 建立一個官方正式的 GitHub 或 GitLab 版本記錄。需要傳遞--conventional-commits
去建立 changlog。
GithuB 認證,以下環境變數需要被定義。
GH_TOKEN
(required) - Your GitHub authentication token (under Settings > Developer settings > Personal access tokens).GHE_API_URL
- When using GitHub Enterprise, an absolute URL to the API.GHE_VERSION
- When using GitHub Enterprise, the currently installed GHE version. Supports the following versions.
GitLab 認證,以下環境變數需要被定義。
GL_TOKEN
(required) - Your GitLab authentication token (under User Settings > Access Tokens).GL_API_URL
- An absolute URL to the API, including the version. (Default: https://gitlab.com/api/v4)
注意: 不允許和--no-changelog
一起使用
這個選項也可以在lerna.json
中配置:
{
"changelogPreset": "angular"
}
If the preset exports a builder function (e.g. conventional-changelog-conventionalcommits
), you can specify the preset configuration too:
{
"changelogPreset": {
"name": "conventionalcommits",
"issueUrlFormat": "{{host}}/{{owner}}/{{repository}}/issues/{{id}}"
}
}
![lerna version --conventional-commits --create-release github]()
--exact
lerna version --exact
--force-publish
lerna version --force-publish=package-2,package-4
# force all packages to be versioned
lerna version --force-publish
強制更新版本
這個操作將跳過lerna changed
檢查,即便 package 沒有做任何變更也會更新版本
--git-remote
lerna version --git-remote upstream
將本地commit
push 到指定的遠端殘酷,預設是origin
--ignore-changes
變更檢測時忽略的檔案
lerna version --ignore-changes '**/*.md' '**/__tests__/**'
建議在根目錄lerna.json
中配置:
{
"ignoreChanges": ["**/__fixtures__/**", "**/__tests__/**", "**/*.md"]
}
--no-ignore-changes
禁止任何現有的忽略配置:
--ignore-scripts
--include-merged-tags
lerna version --include-merged-tags
--message
-m`別名,等價於`git commit -m
lerna version -m "chore(release): publish %s"
# commit message = "chore(release): publish v1.0.0"
lerna version -m "chore(release): publish %v"
# commit message = "chore(release): publish 1.0.0"
# When versioning packages independently, no placeholders are replaced
lerna version -m "chore(release): publish"
# commit message = "chore(release): publish
#
# - package-1@3.0.1
# - package-2@1.5.4"
也可以在lerna.json
配置:
{
"command": {
"version": {
"message": "chore(release): publish %s"
}
}
}
--no-changelog
lerna version --conventional-commits --no-changelog
不生成CHANGELOG.md
。
注意:不可以和--create-release
一起使用
--no-commit-hooks
預設情況下,lerna version
會執行git commit hooks
。使用該標記,阻止git commit hooks
執行。
--no-git-tag-version
預設情況下,lerna version
會提交變更到package.json
檔案,並打標籤。使用該標記會阻止該預設行為。
--no-granular-pathspec
預設情況下,在建立版本的過程中,會執行git add -- packages/*/package.json
操作。
也可以更改預設行為,提交除了package.json
以外的資訊,前提是必須做好敏感資料的保護。
// leran.json
{
"version": "independent",
"granularPathspec": false
}
--no-private
排除private:true
的 package
--no-push
By default, lerna version
will push the committed and tagged changes to the configured git remote.
Pass --no-push
to disable this behavior.
--preid
lerna version prerelease
# uses the next semantic prerelease version, e.g.
# 1.0.0 => 1.0.1-alpha.0
lerna version prepatch --preid next
# uses the next semantic prerelease version with a specific prerelease identifier, e.g.
# 1.0.0 => 1.0.1-next.0
版本語義化
--sign-git-commit
npm version
option
--sign-git-tag
npm version
option
--force-git-tag
取代已存在的tag
--tag-version-prefix
自定義版本字首。預設為v
# locally
lerna version --tag-version-prefix=''
# on ci
lerna publish from-git --tag-version-prefix=''
--yes
lerna version --yes
# skips `Are you sure you want to publish these packages?`
跳過所有提示
生成更新日誌CHANGELOG.md
如果你在使用多包儲存一段時間後,開始使用--conventional-commits
標籤,你也可以使用conventional-changelog-cli
和 lerna exec
為之前的版本建立 changelog:
# Lerna does not actually use conventional-changelog-cli, so you need to install it temporarily
npm i -D conventional-changelog-cli
# Documentation: `npx conventional-changelog --help`
# fixed versioning (default)
# run in root, then leaves
npx conventional-changelog --preset angular --release-count 0 --outfile ./CHANGELOG.md --verbose
npx lerna exec --concurrency 1 --stream -- 'conventional-changelog --preset angular --release-count 0 --commit-path $PWD --pkg $PWD/package.json --outfile $PWD/CHANGELOG.md --verbose'
# independent versioning
# (no root changelog)
npx lerna exec --concurrency 1 --stream -- 'conventional-changelog --preset angular --release-count 0 --commit-path $PWD --pkg $PWD/package.json --outfile $PWD/CHANGELOG.md --verbose --lerna-package $LERNA_PACKAGE_NAME'
If you use a custom --changelog-preset
, you should change --preset
value accordingly in the example above.
Lifecycle Scripts
// preversion: Run BEFORE bumping the package version.
// version: Run AFTER bumping the package version, but BEFORE commit.
// postversion: Run AFTER bumping the package version, and AFTER commit.
Lerna will run npm lifecycle scripts during lerna version
in the following order:
- Detect changed packages, choose version bump(s)
- Run
preversion
lifecycle in root - For each changed package, in topological order (all dependencies before dependents):
- Run
preversion
lifecycle - Update version in package.json
- Run
version
lifecycle - Run
version
lifecycle in root - Add changed files to index, if enabled
- Create commit and tag(s), if enabled
- For each changed package, in lexical order (alphabetical according to directory structure):
- Run
postversion
lifecycle - Run
postversion
lifecycle in root - Push commit and tag(s) to remote, if enabled
- Create release, if enabled
lerna publish
lerna publish # 釋出自上次發版依賴更新的packages
lerna publish from-git # 顯示的釋出在當前提交中打了tag的packages
lerna publish from-package # 顯示的釋出當前版本在登錄檔中(registry)不存在的packages(之前沒有釋出到npm上)
執行時,該命令執行以下操作之一:
- 釋出自上次發版依賴更新的 packages(背後呼叫
lerna version
判斷) - 這是 2.x 版本遺留的表現
- 顯示的釋出在當前提交中打了 tag 的 packages
- 顯示的釋出在最新的提交中當前版本在登錄檔中(registry)不存在的 packages(之前沒有釋出到 npm 上)
- 釋出在之前提交中未版本化的進行過金絲雀部署的 packages(
canary release
)
Lerna 無法釋出私有的 packcage("private":true
)
在所有釋出操作期間,適當的生命週期指令碼(lifecycle scripts
)在根目錄和每個包中被呼叫(除非被--ignore-scripts
禁用)。
Positionals
- bump
from-git
除了lerna version
支援的 semver 關鍵字之外,lerna publish
還支援from-git
關鍵字。這將識別lerna version
標記的包,並將它們釋出到 npm。這在 CI 場景中非常有用,在這種場景中,您希望手動增加版本,但要通過自動化過程一致地釋出包內容本身
- bump
from-package
與from-git
關鍵字相似,除了要釋出的軟體包列表是通過檢查每個package.json
並確定登錄檔中是否沒有任何軟體包版本來確定的。 登錄檔中不存在的任何版本都將被髮布。 當先前的lerna publish
未能將所有程式包釋出到登錄檔時,此功能很有用。
Command Options
lerna publish
除了支援一下選項外,還支援lerna version
的所有選項:
--canary
--contents
--dist-tag
--git-head
--graph-type
--ignore-scripts
--ignore-prepublish
--legacy-auth
--no-git-reset
--no-granular-pathspec
--no-verify-access
--otp
--preid
--pre-dist-tag
--registry
--tag-version-prefix
--temp-tag
--yes
--canary
lerna publish --canary
# 1.0.0 => 1.0.1-alpha.0+${SHA} of packages changed since the previous commit
# a subsequent canary publish will yield 1.0.1-alpha.1+${SHA}, etc
lerna publish --canary --preid beta
# 1.0.0 => 1.0.1-beta.0+${SHA}
# The following are equivalent:
lerna publish --canary minor
lerna publish --canary preminor
# 1.0.0 => 1.1.0-alpha.0+${SHA}
針對最近一次提交發生改變的 package,做更精細的版本控制。類似於金絲雀部署,構建生產環境的容錯測試。如果是統一的版本控制,其他 package 版本號不做升級,只針對變更的 package 做精準除錯。
--contents
子目錄釋出。子目錄中必須包含 package.json。
lerna publish --contents dist
# publish the "dist" subfolder of every Lerna-managed leaf package
--dist-tag
lerna publish --dist-tag custom-tag
自定義 npm釋出標籤。預設是latest
該選項可以用來定義prerelease
或者 beta
版本
注意
:
npm install my-package
預設安裝的是
latest
版本.
安裝其他版本
npm install my-package@prerelease
.
--git-head
只可以和from-package
配合使用,根據指定的git
釋出
lerna publish from-package --git-head ${CODEBUILD_RESOLVED_SOURCE_VERSION}
--graph-type
npm`上構建`package dependencies`所採用的方式,預設是`dependencies`,只列出`dependencies`。`all`會列出`dependencies` 和 `devDependencies
lerna publish --graph-type all
也可以通過lerna.json
配置:
{
"command": {
"publish": {
"graphType": "all"
}
}
}
--ignore-scripts
關閉npm指令碼生命週期事件
的觸發
--ignore-prepublish
近關閉npm指令碼生命週期 prepublish事件
的觸發
--legacy-auth
釋出前的身份驗證
lerna publish --legacy-auth aGk6bW9t
--no-git-reset
預設情況下,lerna publish
會把暫存區內容全部提交。即lerna publish
釋出時更改了本地 package 中的 version,也一併提交到 git。
未避免上述情況發生,可以使用--no-git-reset
。這對作為管道配置--canary
使用時非常有用。例如,已經改變的package.json
的版本號可能會在下一步操作所用到(例如 Docker builds)。
lerna publish --no-git-reset
--no-granular-pathspec
By default, lerna publish
will attempt (if enabled) to git checkout
only the leaf package manifests that are temporarily modified during the publishing process. This yields the equivalent of git checkout -- packages/*/package.json
, but tailored to exactly what changed.
If you know you need different behavior, you'll understand: Pass --no-granular-pathspec
to make the git command literally git checkout -- .
. By opting into this pathspec, you must have all intentionally unversioned content properly ignored.
This option makes the most sense configured in lerna.json, as you really don't want to mess it up:
{
"version": "independent",
"granularPathspec": false
}
The root-level configuration is intentional, as this also covers the identically-named option in lerna version
.
--no-verify-access
預設情況下lerna
會驗證已登入使用者對即將釋出的 package 的許可權。使用此標記將會阻止該預設行為。
如果你正在使用第三方的不支援npm access ls-packages
的 npm 庫,需要使用該標記。或者在lerna.json
中設定command.publish.verifyAccess
為false
。
謹慎使用
--otp
當釋出需要雙重認證的 package 時,需要指定一次性密碼
lerna publish --otp 123456
當開啟npm 雙重認證後,可以通過配置對 account 和 npm 操作的進行二次驗證。需要 npm 版本大於5.5.0
密碼的有效時長為 30s,過期後需要重新輸入驗證
--preid
Unlike the lerna version
option of the same name, this option only applies to --canary
version calculation.
和 --canary
配合使用,指定語義化版本
lerna publish --canary
# uses the next semantic prerelease version, e.g.
# 1.0.0 => 1.0.1-alpha.0
lerna publish --canary --preid next
# uses the next semantic prerelease version with a specific prerelease identifier, e.g.
# 1.0.0 => 1.0.1-next.0
當使用該標記時,lerna publish --canary
將增量改變 premajor
, preminor
, prepatch
, 或者 prerelease
的語義化版本。
--pre-dist-tag
lerna publish --pre-dist-tag next
效果和--dist-tag
一樣。只適用於釋出的預釋出版本。
--registry
--tag-version-prefix
更改標籤字首
如果分割lerna version
和lerna publish
,需要都設定一遍:
# locally
lerna version --tag-version-prefix=''
# on ci
lerna publish from-git --tag-version-prefix=''
也可以在lerna.json
中配置該屬性,效果等同於上面兩條命令:
{
"tagVersionPrefix": "",
"packages": ["packages/*"],
"version": "independent"
}
--temp-tag
當傳遞時,這個標誌將改變預設的釋出過程,首先將所有更改過的包釋出到一個臨時的 dis tag (' lerna-temp ')中,然後將新版本移動到'--dist-tag '(預設為' latest ')配置的 dist-tag 中。
這通常是沒有必要的,因為 Lerna 在預設情況下會按照拓撲順序(所有依賴先於依賴)釋出包
--yes
lerna publish --canary --yes
# skips `Are you sure you want to publish the above changes?`
跳過所有的確認提示
在Continuous integration (CI)很有用,自動回答釋出時的確認提示
每個 package 的配置
每個 package 可以通過更改publishConfig
,來改變釋出時的一些行為。
publishConfig.access
當釋出一個scope
的 package(e.g., @mycompany/rocks
)時,必須設定access
:
"publishConfig": {
"access": "public"
}
- 如果在沒有使用 scope 的 package 中使用該屬性,將失敗
- 如果你希望保持一個 scope 的 package 為私有(i.e.,
"restricted"
),那麼就不需要設定
注意,這與在包中設定"private":true
不一樣;如果設定了private
欄位,那麼在任何情況下都不會發布該包。
publishConfig.registry
"publishConfig": {
"registry": "http://my-awesome-registry.com/"
}
- 也可以通過
--registry
或者在 lerna.json 中設定command.publish.registry
進行全域性控制
publishConfig.tag
自定義該包釋出時的標籤tag
:
"publishConfig": {
"tag": "flippin-sweet"
}
--dist-tag
將覆蓋每個 package 中的值- 在使用[--canary]時該值將被忽略
publishConfig.directory
非標準欄位,自定義釋出的檔案
"publishConfig": {
"directory": "dist"
}
npm 指令碼生命週期
// prepublish: Run BEFORE the package is packed and published.
// prepare: Run BEFORE the package is packed and published, AFTER prepublish, BEFORE prepublishOnly.
// prepublishOnly: Run BEFORE the package is packed and published, ONLY on npm publish.
// prepack: Run BEFORE a tarball is packed.
// postpack: Run AFTER the tarball has been generated and moved to its final destination.
// publish: Run AFTER the package is published.
// postpublish: Run AFTER the package is published.
lerna publish
執行時,按如下順序呼叫npm 指令碼生命週期:
- 如果採用隱式版本管理,則執行所有 version lifecycle scripts。
- Run
prepublish
lifecycle in root, if enabled - Run
prepare
lifecycle in root - Run
prepublishOnly
lifecycle in root - Run
prepack
lifecycle in root - For each changed package, in topological order (all dependencies before dependents):
- Run
prepublish
lifecycle, if enabled - Run
prepare
lifecycle - Run
prepublishOnly
lifecycle - Run
prepack
lifecycle - Create package tarball in temp directory via JS API
- Run
postpack
lifecycle - Run
postpack
lifecycle in root - For each changed package, in topological order (all dependencies before dependents):
- Publish package to configured registry via JS API
- Run
publish
lifecycle - Run
postpublish
lifecycle - Run
publish
lifecycle in root
- To avoid recursive calls, don't use this root lifecycle to run
lerna publish
- Run
postpublish
lifecycle in root - Update temporary dist-tag to latest, if enabled
過濾選項
--scope
為匹配到的 package 安裝依賴 [字串]--ignore
和上面正相反 [字串]--no-private
排除 private 的 packcage--since
包含從指定的[ref]依賴改變的 packages,如果沒有[ref],預設是最近的 tag--exclude-dependents
當使用—since 執行命令時,排除所有傳遞依賴項,覆蓋預設的“changed”演算法 [布林]--include-dependents
啟動命令式包含所有傳遞的依賴項,無視 --scope, --ignore, or --since [布林]--include-dependencies
啟動命令式包含所有傳遞的依賴項,無視 --scope, --ignore, or --since [布林]--include-merged-tags
在使用—since 執行命令時,包含來自合併分支的標記 [布林]
全域性選項
--loglevel
列印日誌的級別 [字串] 預設值: info--concurrency
並行任務時啟動的程式數目 [數字] [預設值: 4]--reject-cycles
如果 package 之間相互依賴,則失敗 [布林]--no-progress
關閉程式進度條 [布林]--no-sort
不遵循拓撲排序 [布林]--max-buffer
設定子命令執行的 buffer(以位元組為單位) [數字]-h, --help
顯示幫助資訊-v, --version
顯示版本資訊
Concept
lerna.json
{
"version": "1.1.3", // 版本
"npmClient": "npm", // npm客戶端
"command": {
"publish": {
"ignoreChanges": ["ignored-file", "*.md"], // 釋出檢測時忽略的檔案
"message": "chore(release): publish", // 釋出時 tag標記的版本資訊
"registry": "https://npm.pkg.github.com" // 源
},
"bootstrap": {
"ignore": "component-*", // bootstrap時忽略的檔案
"npmClientArgs": ["--no-package-lock"], // 命令列引數
},
"version": {
"allowBranch": [ // 允許執行lerna version的分支
"master",
"feature/*"
],
"message": "chore(release): publish %s" // 建立版本時 tag標記的版本資訊
}
},
"ignoreChanges": [
"**/__fixtures__/**",
"**/__tests__/**",
"**/*.md"
],
"packages": ["packages/*"],// package位置
}
Wizard
這裡推薦一個新手引導工具lerna-wizard