简介:本篇主要介绍lerna 4如何升级到lerna 6,以及lerna 6与lerna 4中存在的一些差异,最后介绍了lerna结合CI场景去发布多包项目
背景
多包项目一直用的是lerna 4版本,但是最近在lerna 4中直接使用pnpm在本地没有什么大问题,但是在CI场景发布的时候,无法正常publish包,会报错,于是,我们进行了排查,并记录了这个过程以及最终结果。
lerna 4与6 中使用pnpm
lerna 4使用 pnpm 抛错
当我们直接在lerna 4中使用pnpm可能会碰到如下错误
- 测试用例无法正常跑通
- CI场景出现
ERR_PNPM_OUTDATED_LOCKFILE错误 - CI场景出现
EUNCOMMIT working tree has uncommitted changes错误
具体的错误详情如下所示
测试用例无法正常跑通
测试用例无法正常跑通,提示找不到子包内的依赖
CI场景-ERR_PNPM_OUTDATED_LOCKFILE错误
CI场景执行pnpm install的时候出现ERR_PNPM_OUTDATED_LOCKFILE错误
原因:是因为包之间有依赖关系的话,子包在
lerna修改版本号的时候,package.json是变化了的,所以package.json与pnpm.lock文件对不上,报错是正常的
CI场景- EUNCOMMIT working tree has uncommitted changes
CI场景执行lerna publish的时候出现EUNCOMMIT working tree has uncommitted changes错误
加上
pnpm install --no-frozen-lockfile,install是正常了,但是publish的时候,还是会抛错,提示working tree有未提交的文件,所以发布还是不成功,原因是install的时候,因为子package的版本号变了,install之后lock文件发生了更新,所以git tree又有未提交文件
然后去lerna项目内找了相关issues,发现lerna 4确实不支持pnpm,相关的issuesQuestion: moving from yarn to npm,可以从pnpm support看到相关进度在2022年的时候正式支持
lerna 6使用 pnpm 正常
lerna 4迁移到lerna 6
步骤如下
第一步:在根目录下添加pnpm-workspace.yaml内容如下所示
packages:
- packages/* # 这里写自己的多包文件目录
第二步:lerna.json内将useWorkspaces: true
第三步:将package.json内的lerna版本升至6.x
第三步:使用pnpm的命令替换lerna的bootstrap, link, and add 命令,如下所示
注意在lerna6中直接使用bootstrap、add、link命令,会报pnpm is not supported错误,如下所示
lerna bootstrap
lerna notice cli v6.6.1
lerna ERR! EWORKSPACES Bootstrapping with pnpm is not supported. Use pnpm directly to manage dependencies: https://pnpm.io/cli/install
lerna add md5 --scope=@xxx/lerna-demo-core
lerna notice cli v6.6.1
lerna ERR! EPNPMNOTSUPPORTED Add is not supported when using `pnpm` workspaces. Use `pnpm` directly to add dependencies to packages: https://pnpm.io/cli/add
原因是
block usage of bootstrap, link, and add commands. Instead, you should use pnpm commands directly to manage dependencies (pnpm.io/cli/install).
直接使用pnpm的相关的命令即可,不在使用bootstrap等命令
注意通过pnpm add 添加依赖看到的是workspace:xxx 这种写法,这个是正常的,最终publish的时候会替换成对应的版本号
"dependencies": {
"@xxx/lerna-demo-utils": "workspace:0.1.0-beta.17",
"@xxx/uid": "^0.0.1-beta.2",
"axios": "^0.26.0",
"fetch": "^1.1.0",
"qs": "^6.11.1"
},
在看下使用lerna version之后提交的commit内,发现commit内主动更新了pnpm.lock文件
再看CI场景正常
lerna中使用yarn与pnpm命令对比
| 场景/包管理工具 | yarn | pnpm |
|---|---|---|
| 首次安装依赖 | lerna bootstrap | yarn install | pnpm install |
| 根目录下安装依赖 | yarn add md5 -w | pnpm install md5 -w |
| 某个子包安装依赖 | lerna add md5 --scope=child1 | |
lerna add md5 --scope= @xxx/lerna-demo-core | pnpm add md5 --filter child1 | |
pnpm add md5 --filter @xxx/lerna-demo-core | ||
| 所有子包安装依赖 | lerna add md5 | pnpm add md5 --filter "child*" |
pnpm add qs --filter '@xxx/*' |
除了上面的区别,lerna6相对lerna4还有一个比较大的变动点就是通过nx提供了更强的调度模型与缓存方式,可以在lerna.json内通过"useNx": false,参数来进行关闭
CI场景-lerna ERR! EUNCOMMIT M pnpm-lock.yaml
原因:
pnpm不同版本之间,生成的pnpm-lock.yml文件有差异feat!: lockfile format v6
解决:将本地的
pnpm版本与CI场景的pnpm版本保持一致
借助CI场景发布npm包
获取npm token
第一步:进入npm官网
第二步:进入Access Tokens页面-选择Claasic Token
第三步:选择Automation-点击Generate Token
第四步:保留创建好的
token,留到后面的步骤用
不同的CI工具结合lerna发布npm包
gitlab CI中结合lerna发布npm包
第一步:新增.gitlab-ci.yml文件
第二步:配置.gitlab-ci.yml文件
stages:
- publish
publish:
stage: publish
image: node:v16.13.1
script:
- echo -e $NPM_AUTH_CONTENT >> ~/.npmrc # 注入 token
- pnpm install --frozen-lockfile --registry=https://registry.npmmirror.com # 安装依赖
- yarn build # 构建
- yarn publish-all # 发布
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
changes:
- package.json
- lerna.json
- packages/**/package.json
when: always
publish-beta:
stage: publish
image: node:v16.13.1
script:
- echo -e $NPM_AUTH_CONTENT >> ~/.npmrc # 注入 token
- pnpm install --frozen-lockfile --registry=https://registry.npmmirror.com # 安装依赖
- yarn build # 构建
- yarn publish-all --pre-dist-tag=beta # 发布 beta 版本
rules:
- if: '$CI_COMMIT_BRANCH == "beta"'
changes:
- package.json
- lerna.json
- packages/**/package.json
when: always
第三步:在gitlab界面配置环境变量,注入token
github action结合lerna发布npm包
第一步:新增.github/workflows/npm-publish.yml文件
第二步:配置npm-publish.yml文件
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
name: Node.js Package
# 可以自己根据条件自定义触发action的条件
on:
push:
paths:
- '**/package*.json'
workflow_dispatch:
jobs:
publish-npm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # 一定要设置,不然获取不到tag,无法正常publish
- uses: actions/setup-node@v3
with:
node-version: 16
registry-url: https://registry.npmjs.org/
- run: npm install pnpm -g
- run: pnpm install --registry=https://registry.npmmirror.com
- run: npm run build
- run: npm run publish-all
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} # 注入的npm token
第四步:在github setting配置npm token
进入项目setting配置
点击添加secret变量
填写key与value,value就是在npm通过Claasic Token获取到的token
添加成功之后,就能看到对应的key
总结
上面提供的示例或者碰到的错误,并不一定覆盖了所有场景,只是列出来自己升级过程中碰到的问题,具体的问题还需要具体分析,最后提供了一个lerna-demo项目,可以直接查看