最近 xxx-admin-ui
和 xxx-admin-service
都用到了lerna
, 记录一下注意点
Need
1. 初始化工程
1 | mkdir temp && cd temp && lerna init |
2. 初始化每个包
- 假设我们有 2 个包, 如 :
1 | packages |
- 分别进入
admin-1
和admin-2
初始化:
1 | cd packages/admin-1 && npm init -y |
- 当然, 每个包都是完整的工程, 可以自由发挥
- 在
admin-1
和admin-2
的package.json
中修改包名和版本
1 | // admin-1 package.json |
@laputaz 为 scope, 所有相同 scope 的包, 安装后会被放在 scope 目录下
- admin-2 同理
3. 每个包添加内容
- 为两个包都增加一个
src/index.js
1 | // admin-1/src/index.js |
-
1 | // admin-2/src/index.js |
- 如果我们不需要对代码打包压缩等操作, 直接指定入口以及需要发布的内容即可:
1 | // in package.json |
- 也可以用
.npmignore
指定不需要发布的内容, 区别如下
1 | .npmignore 该文件指定的内容将不会被发布 |
4. 修改 lerna 配置
在 lerna.json
中, 增加如下配置:
1 | // in lerna.json |
- 建议:
- packages 中我们可以写
packages/*
, 但经常会建立一些不用发布的 demo 等代码文件目录, 所以最好手动指定需要发布的包 - command => bootstrap => hoist 设置为 true, 可以把所有的 node_modules 的内容提升到顶层, 让每个包里的 node_modules 看起来更干净
- version 改为 independent, 让每个包版本号可以不一样
- command => publish => conventionalCommits 设置为 false 把自动生成 changelog 的功能关了, 太鸡肋, 因为生成的 changelog 可读性很差.
- packages 中我们可以写
如果没有依赖关系,或者代码打包压缩等处理, 可以走直接第 6 步发布了.
5. 处理依赖关系
包之间可能存在依赖关系, 这里演示有依赖关系的情况:
- 更新两个包的
src/index.js
, 假设admin-2
依赖admin-1
1 | // admin-1/src/index.js |
&
1 | // admin-2/src/index.js |
- 更新
admin-2
的dependencies
:
1 | // admin-2 package.json |
- 本地调试时, 需要为
admin-1
建立一个软链接, 运行:
1 | lerna bootstrap |
该命令会在 admin-2
的node_modules
下建立指向admin-1
的快捷方式:
可以发现 admin-2/node_modules/@laputa/admin-1
的内容就是 admin-1
的内容
这样不需要先发布admin-1
, 也可以在本地正常调试了.
6. 发布
由于权限限制, 我们不能直接运行lerna publish
发布.
需要分两步操作.
首先保证代码均已 push
到仓库.
- 运行
1 | lerna version [ patch | minor | major | ... ] # 还有其他选项, 但主要使用了这三个 |
该命令会自动更新每个包的版本并打 tag 提交到 git 仓库
- slack deploy channel:
1 | @k fab knpm_lerna_publish:xxxx.git |
xxxx.git
为 git 仓库地址
然后在 npm 上就能看到发布的包了
7. 如果要发布打包后的代码
我们经常需要对代码打包压缩等处理, 然后发布处理后的代码
假设, 我们对 admin-1
打包压缩, 输出文件为 lib/index.common.js
- 首先在
package.json
修改包的入口
1 | { |
- 然后需要在
scripts
增加一个钩子:
1 | { |
我们在 deploy channel
执行发布命令的时候, 会在远端执行 lerna publish
而 lerna publish
中又会执行 npm publish
而 prepublishOnly 这个钩子, 会在npm publish
前执行
prepublishOnly 中就可以写一些譬如: 切换 node 版本/ 执行 npm install && npm run build
等操作
8. 如果需要 changelog
conventionalCommits
生成的changelog
是基于每个commit
的, 难看且鸡肋, 所以决定手动生成.
文件:
1 | 1. changelog.md // 该文件为最终的所有的版本记录 |
每次只修改 current.md
记录当前版本的更改内容
在pulish
之前将 current.md
的内容放到 changelog.md
中, 并清空 current.md
在工程根目录的 package.json
中增加
1 | { |
因为执行version
的时候, package
中的版本号已经被更新了(即可以拿到最新的版本号), 所以可以在version
钩子中操作版本文档的更新, 然后git ad .
9. 后话
2024 不得不说,pnpm
自带的 workspace
更好用