lerna 4 to 6

582 阅读5分钟

简介:本篇主要介绍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错误

具体的错误详情如下所示

测试用例无法正常跑通

测试用例无法正常跑通,提示找不到子包内的依赖 image.png

CI场景-ERR_PNPM_OUTDATED_LOCKFILE错误

CI场景执行pnpm install的时候出现ERR_PNPM_OUTDATED_LOCKFILE错误 image.png 原因:是因为包之间有依赖关系的话,子包在lerna修改版本号的时候,package.json是变化了的,所以package.jsonpnpm.lock文件对不上,报错是正常的

CI场景- EUNCOMMIT working tree has uncommitted changes

CI场景执行lerna publish的时候出现EUNCOMMIT working tree has uncommitted changes错误 image.png 加上pnpm install --no-frozen-lockfileinstall是正常了,但是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的命令替换lernabootstrap, link, and add 命令,如下所示

注意在lerna6中直接使用bootstrapaddlink命令,会报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文件 image.png

再看CI场景正常 image.png

lerna中使用yarn与pnpm命令对比

场景/包管理工具yarnpnpm
首次安装依赖lerna bootstrap | yarn installpnpm install
根目录下安装依赖yarn add md5 -wpnpm install md5 -w
某个子包安装依赖lerna add md5 --scope=child1
lerna add md5 --scope= @xxx/lerna-demo-corepnpm add md5 --filter child1
pnpm add md5 --filter @xxx/lerna-demo-core
所有子包安装依赖lerna add md5pnpm add md5 --filter "child*"
pnpm add qs --filter '@xxx/*'

除了上面的区别,lerna6相对lerna4还有一个比较大的变动点就是通过nx提供了更强的调度模型与缓存方式,可以在lerna.json内通过"useNx": false,参数来进行关闭

CI场景-lerna ERR! EUNCOMMIT M pnpm-lock.yaml

image.png 原因:pnpm不同版本之间,生成的pnpm-lock.yml文件有差异feat!: lockfile format v6 image.png 解决:将本地的pnpm版本与CI场景的pnpm版本保持一致

借助CI场景发布npm包

获取npm token

第一步:进入npm官网 第二步:进入Access Tokens页面-选择Claasic Token image.png

第三步:选择Automation-点击Generate Token image.png 第四步:保留创建好的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配置 image.png

点击添加secret变量 image.png

填写keyvaluevalue就是在npm通过Claasic Token获取到的token image.png 添加成功之后,就能看到对应的key image.png

总结

上面提供的示例或者碰到的错误,并不一定覆盖了所有场景,只是列出来自己升级过程中碰到的问题,具体的问题还需要具体分析,最后提供了一个lerna-demo项目,可以直接查看