关于npm:Lerna-多包存储管理工具一

4次阅读

共计 23115 个字符,预计需要花费 58 分钟才能阅读完成。

lerna

最近在看 vue-cli 的源码局部,留神到这一个仓库下保护了多个 package,很好奇他是如何在一个 repo 中治理这些 package 的。

咱们组当初也在应用组件库的形式保护我的项目间共用的业务代码。有两个组件库,存在依赖的关系,目前联调是通过 npm link 的形式,性能并不好,时常呈现卡顿的问题。加上前一段时间组内分享 vue3 也提到了 lerna,于是便决定认真的调研一下这个工具,为接下里的组件库优化助力。

lerna 的文档还是很具体的, 因为全是英文的,思考到浏览问题,这里我先是本人跑了几个 demo,而后做了中文翻译。后续我会出一篇专门的lerna 实战篇

demo

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 <executableName>
  • --description 形容 [字符串]
  • --dependencies 依赖,用逗号分隔 [数组]
  • --es-module 初始化一个转化的 Es Module [布尔]
  • --homepage 源码地址 [字符串]
  • --keywords 要害字数 [数组]
  • --license 协定 字符串
  • --private 是否公有仓库 [布尔]
  • --registry 源 [字符串]
  • --tag 公布的标签 [字符串]
  • -y, --yes 跳过所有的提醒,应用默认配置 [布尔]

lerna add

为匹配的 package 增加本地或者近程依赖,一次只能增加一个依赖


$ lerna add <package>[@version] [--dev] [--exact] [--peer]

运行该命令时做的事件:

  1. 为匹配到的 package 增加依赖
  2. 更改每个 package 下的 package.json 中的依赖项属性

Command Options

以下几个选项的含意和 npm install 时统一

  • --dev
  • --exact
  • --peer 同级依赖,应用该 package 须要在我的项目中同时装置的依赖
  • --registry <url>
  • --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自身,输入我的项目下所有的 package
  • lerna ll: 输入我的项目下所有 package 名称、以后版本、所在位置
  • lerna la: 输入我的项目下所有 package 名称、以后版本、所在位置,包含 private package

Command Options

  • --json
  • --ndjson
  • -a, --all
  • -l, --long
  • -p, --parseable
  • --toposort
  • --graph

所有的过滤选项都反对

--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

以 newline-delimited JSON 展现信息


$ 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: <fullpath>:<name>:<version>[: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 publishlerna versionlerna.json配置同样影响lerna changed。例如 command.publish.ignoreChanges.

Command Options

lerna changed 反对 lerna ls的所有标记:

  • --json
  • --ndjson
  • -a, --all
  • -l, --long
  • -p, --parseable
  • --toposort
  • --graph

lerna 不反对过滤选项, 因为 lerna version or lerna publish 不反对过滤选项.

lerna changed 反对 lerna version (the others are irrelevant)的过滤选项:

  • --conventional-graduate.
  • --force-publish.
  • --ignore-changes.
  • --include-merged-tags.

lerna import

lerna import <path-to-external-repository>

将现有的 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 to lerna changed. This command runs git 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

  • --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 --profile -- <command>

留神: 仅在启用拓扑排序时剖析。不能和 --parallel and --no-sort一起应用。

  • --profile-location <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 <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)

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 <glob>

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 <type>

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}}"

    }

}

--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 <name>

lerna version --git-remote upstream

将本地commitpush 到指定的近程残暴,默认是origin

--ignore-changes

变更检测时疏忽的文件


lerna version --ignore-changes '**/*.md' '**/__tests__/**'

倡议在根目录 lerna.json 中配置:


{"ignoreChanges": ["**/__fixtures__/**", "**/__tests__/**", "**/*.md"]

}

--no-ignore-changes 禁止任何现有的疏忽配置:

--ignore-scripts

禁止 lifecycle scripts

--include-merged-tags

lerna version --include-merged-tags
--message <msg>

-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-clilerna 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:

  1. Detect changed packages, choose version bump(s)
  2. Run preversion lifecycle in root
  3. For each changed package, in topological order (all dependencies before dependents):
  4. Run preversion lifecycle
  5. Update version in package.json
  6. Run version lifecycle
  7. Run version lifecycle in root
  8. Add changed files to index, if enabled
  9. Create commit and tag(s), if enabled
  10. For each changed package, in lexical order (alphabetical according to directory structure):
  11. Run postversion lifecycle
  12. Run postversion lifecycle in root
  13. Push commit and tag(s) to remote, if enabled
  14. 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 <dir>
  • --dist-tag <tag>
  • --git-head <sha>
  • --graph-type <all|dependencies>
  • --ignore-scripts
  • --ignore-prepublish
  • --legacy-auth
  • --no-git-reset
  • --no-granular-pathspec
  • --no-verify-access
  • --otp
  • --preid
  • --pre-dist-tag <tag>
  • --registry <url>
  • --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 <dir>

子目录公布。子目录中必须蕴含 package.json。


lerna publish --contents dist

# publish the "dist" subfolder of every Lerna-managed leaf package
--dist-tag <tag>

lerna publish --dist-tag custom-tag

自定义 npm 公布标签。默认是latest

该选项能够用来定义prerelease 或者 beta 版本

留神 : npm install my-package 默认装置的是latest 版本.

装置其余版本 npm install my-package@prerelease.

--git-head <sha>

只能够和 from-package 配合应用,依据指定的 git <sha> 公布

也能够应用环境变量指定


lerna publish from-package --git-head ${CODEBUILD_RESOLVED_SOURCE_VERSION}
--graph-type <all|dependencies>

npm上构建 package dependencies 所采纳的形式,默认是 dependencies,只列出dependenciesall 会列出dependenciesdevDependencies


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.verifyAccessfalse

审慎应用

--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 的语义化版本。

语义化版本(prerelease identifier)

--pre-dist-tag <tag>

lerna publish --pre-dist-tag next

成果和 --dist-tag 一样。只实用于公布的预公布版本。

--registry <url>
--tag-version-prefix

更改标签前缀

如果宰割 lerna versionlerna 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 脚本生命周期:

  1. 如果采纳隐式版本治理,则运行所有 version lifecycle scripts。
  2. Run prepublish lifecycle in root, if enabled
  3. Run prepare lifecycle in root
  4. Run prepublishOnly lifecycle in root
  5. Run prepack lifecycle in root
  6. For each changed package, in topological order (all dependencies before dependents):
  7. Run prepublish lifecycle, if enabled
  8. Run prepare lifecycle
  9. Run prepublishOnly lifecycle
  10. Run prepack lifecycle
  11. Create package tarball in temp directory via JS API
  12. Run postpack lifecycle
  13. Run postpack lifecycle in root
  14. For each changed package, in topological order (all dependencies before dependents):
  15. Publish package to configured registry via JS API
  16. Run publish lifecycle
  17. Run postpublish lifecycle
  18. Run publish lifecycle in root
  • To avoid recursive calls, don’t use this root lifecycle to run lerna publish
  1. Run postpublish lifecycle in root
  2. 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

正文完
 0