Lerna 篇
回顾
在上一篇文章中我们可以使用 lerna init
来初始化我们的工程。上一篇文章忘了放 源代码。
lerna
允许我们使用两种模块来管理我们的模块:Fixed
模式和 Independent
模式。
-
fixed/locked (默认)
固定模式,也就是我们初始化时默认采用的模式。该模式为单版本号,在根目录
lerna.json
中设置,该模式你可以理解为 ‘全量发布’,即任何一个模块更新了,当你在执行lerna publish
发布时,所有的模块都会统一更新版本号。Babel
目前就是采用该模式。 -
independent
lerna init --independent
独立模式,在这种模式下你可以单独更新某个包的版本, 你可以理解为 ‘增量发布’。在每次发布时,会针对每个包的改动的提示,配合
git
检查文件变动,只发布有变动的包。独立模式允许开发者更新指定
package
的版本,只需将lerna.json
中的version
键改成independent
即可启用independent
模式。
配置
在根目录的 lerna.json
中设置 lerna
相关的配置
{
"npmClient": "yarn",
"useWorkspaces": true,
"version": "0.4.0",
"packages": [
"packages/@ramda/*"
],
"changelog": {
"repo": "essencemike/ramda-ts",
"labels": {
"PR: New Feature": ":rocket: New Features",
"PR: Breaking Change": ":boom: Breaking Changes",
"PR: Bug Fix": ":bug: Bug Fix",
"PR: Documentation": ":memo: Documentation",
"PR: Internal": ":house: Internal",
"PR: Underlying Tools": ":hammer: Underlying Tools"
},
"cacheDir": ".changelog"
}
}
其他配置都是字面意思,这里重点想说一下 useWorkspaces
, 它可以很好的和 yarn
的 workspaces
很好的结合在一起,前者负责 版本管理与发布
,后者负责 依赖管理
。
在 lerna
中启用 workspaces
不仅要在 lerna.json
中配置 useWorkspaces
,还需要在根目录 package.json
中配置:
{
...
"private": true,
"workspaces": [
"packages/*"
],
...
}
注意: private
是必须的,开启 workspace
工作区必须设置成 private
, 保证工作区不会被发布出去。
创建模块
lerna create a
lerna create b
执行上面的命令会在 packages
中创建模块,并根据交互提示在每个模块中生成 package.json
.
├── lerna.json
├── package.json
└── packages
└── a
├── __tests__
│ └── a.test.js
├── lib
│ └── a.js
├── package.json
└── README.md
└── b
├── __tests__
│ └── b.test.js
├── lib
│ └── b.js
├── package.json
└── README.md
依赖管理与 npm scripts
依赖的安装与移除
-
安装所有依赖
lerna bootstrap
使用
bootstrap
命令,会下载所有定义在package.json
中的依赖包。相当于执行npm install
,并且会链接所有依赖包。 -
给所有 package 添加依赖
lerna add lodash
给所有的 package 包添加 lodash 依赖。
-
给指定的 package 添加依赖
# 给a, b 包中加入 Lodash,会同时改变 a, b 模块中 packages.json 文件 lerna add lodash packages/a packages/b # 你也可以使用通配符, 下面这命令,会往所有 re 开头的模块包中加入依赖 lerna add lodash packages/re-* # 指定特定的范围,要使用 --scope 参数,如下:给 b 包安装 lodash 模块 lerna add lodash --scope=b
-
packages 中的包相互添加依赖
# 指定特定的范围,要使用 --scope 参数,如下:给 b 包安装 a 模块 lerna add a --scope=b
-
移除所有 package 的依赖
lerna exec -- yarn remove lodash
把所有 package 包中的
lodash
依赖删除。 -
移除指定 package 包中的依赖
目前
lerna
中没有remove
命名,需要在对应的 package 中的package.json
中删除对应的依赖,然后执行lerna bootstrap
命令即可。
执行 npm scripts
- 执行所有 package 中的 scripts 命令
使用
lerna run
命令可以执行 package 中的scripts
命令,前提是需要先在 package 中写好scripts
命令。比如每个 package 中都有如下命令:
即可使用如下命令在每个 package 中执行测试、构建了:... "scripts": { "test:coverage": "jest --coverage", "test:dev": "jest --watch --coverage", "test:unit": "jest", "clean": "rm -rf lib/*", "build": "npm run clean && rollup -c ../../../rollup.config.js --name F" }, ...
lerna run test:unit lerna run build
- 执行指定 package 中的
scripts
命令# 执行 a 包中的 build 命令 lerna exec --scope a -- yarn run build
发布模块
使用 lerna publish
命令可以将我们的包发布到 npm
仓库中。
这里可能会失败, 如下图
lerna info execute Skipping releases
lerna info git Pushing tags...
lerna info publish Publishing packages to npm...
lerna info Verifying npm credentials
lerna http fetch GET 200 https://registry.npmjs.org/-/npm/v1/user 6266ms
lerna http fetch GET 200 https://registry.npmjs.org/-/org/emike/package?format=cli 1671ms
lerna info Checking two-factor auth mode
lerna http fetch GET 200 https://registry.npmjs.org/-/npm/v1/user 1197ms
lerna http fetch PUT 404 https://registry.npmjs.org/@ramda%2ff 1962ms
lerna ERR! E404 Not found
{ Error: Command failed with exit code 1 (EPERM): /Users/imike/code/github/ramda-ts/node_modules/lerna/cli.js publish 0.4.1 --dist-tag latest
at makeError (/Users/imike/code/github/ramda-ts/node_modules/execa/lib/error.js:58:11)
at handlePromise (/Users/imike/code/github/ramda-ts/node_modules/execa/index.js:112:26)
at process._tickCallback (internal/process/next_tick.js:68:7)
command:
'/Users/imike/code/github/ramda-ts/node_modules/lerna/cli.js publish 0.4.1 --dist-tag latest',
exitCode: 1,
exitCodeName: 'EPERM',
stdout: undefined,
stderr: undefined,
failed: true,
timedOut: false,
isCanceled: false,
killed: false,
signal: undefined }
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @ release: `npm run build && node scripts/release.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the @ release script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/imike/.npm/_logs/2019-09-18T14_16_39_196Z-debug.log
可以看到我们的包名是 @ramda/f
, 当我们以这种方式命令包名时,就可能会出现问题,那是什么原因呢?
其实当我们执行 lerna publish
的时候,本质上还是执行 npm publish
。那么我们首先就需要现在 npm
仓库上注册用户, 并登录。
$ npm adduser
username:
password:
email:
... 等等信息
注意点:
-
npm publish
默认发布私有包,想要发布公共包必须使用npm publish --acsess=public
也可以在
package.json
中配置... "publishConfig": { "access": "public" }, ...
-
组织包(scope packages)需要先创建团队(团队删除了,包就没有了~)
其实上面我们所说的 @ramda/f
就是组织包的形式,这里的 scope
就是 @ramda
。
如何你想一直在这个 scope
中发布 npm
包, 可以运行全局的 npm
配置命令进行设置
npm config set scope @ramda
在这里有两种方式效果看起来是一样的。
-
使用非组织包方式,那么你的包名必须以
npm
账户名为前缀。$ npm adduser Username: @ramda Password:
如何不是的话就会报我们上面提到的错误。
-
使用组织包方式发布,直接
publish
也是不行的,需要- 在
npm
仓库中创建团队 - 将自己的账号添加到该团队中
- 在
更多命令
lerna
的更多命令这里不再详细罗列,详情请参考 lerna。
总结
本文学习了如何使用 lerna
管理并发布我们的模块,下一篇文章我们将学习如何使用 rollup
结合 babel
、typescript
来编译我们的代码,以及如何使用 jest
来进行单元测试。