🚀🚀🚀Lerna通关秘籍🔥🔥🔥

1,077 阅读11分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第2篇文章,点击查看活动详情

简介

Lerna 是一个用于快速管理和发布同一仓库下多个 package 包的管理工具,它基于 gitnpm

初始化lerna工程

首先,我们新建一个目录(yd-lerna-dev),然后初始化项目的 package.json 文件:

npm init -y

接着,安装 lerna

npm i lerna -D

也可以进行全局安装:npm i -g lerna

然后,初始化 lerna

lerna init

执行命令后,会自动创建 packages 目录并生成 lerna.json 文件:

{
  "version": "1.0.0", // 版本号
  "packages": [ // 指定子包所在的目录
    "packages/*"
  ]
}

增加LICENSE文件

初始化完工程后,我们给这个项目增加一个项目许可证,这个是一定要增加的,要不后续发布流程走不通。

在根目录下创建 LICENSE 文件:

MIT License

Copyright (c) 2021 橙某人

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

顺道也增加 .gitignore 文件:

node_modules/

lerna.json

{
  "useWorkspaces": true, // 是否使用 workspaces 的配置; 如果为 true, 将会使用 package.json 文件的 "workspaces" 属性, 而下面的 "packages" 属性将不会生效
  "version": "0.0.0", // 所有子包的版本号; 两种模式: 固定模式(x.x.x)、独立模式(independent)
  "npmClient": "npm", // 指定运行命令的客户端; 可以设置为 npm/cnpm/yarn/pnpm 等等
  "packages": [ // 指定子包所在的目录, 可以指定多个
     "packages/*"
  ],
  "command": { 
    // lerna publish 命令的相关配置
    "publish": { 
      "ignoreChanges": [ // 指定那些目录或者文件的变更不会被publish
        ".gitignore",
        "*.log",
        "*.md"
      ],
      "message": "chore(release): publish", // 执行发布版本更新时的自定义提交消息
      "registry": "https://npm.pkg.github.com" // 设置npm包发布的注册地址
    },
    // lerna bootstrap 命令的相关配置
    "bootstrap": { 
      "ignore": "npm-*",  // 设置执行 lerna bootstrap 安装依赖时不受影响的包
      "npmClientArgs": [ // 指定在执行 lerna bootstrap 命令时传递给 npm install 的参数
        "--no-package-lock"
      ],
      "scope": "" // 指定那些包会受 lerna bootstrap 命令影响
    },
    // lerna version 命令的相关配置
    "version": { 
      "allowBranch": "", // 指定分支
      "conventionalCommits": true
    }
  }
}

Lerna 的配置文件分为两种文件,可以是 lerna.json 或者是 nx.json 文件。传送门

两种版本处理模式

Lerna 对于子包版本号的处理方式有两种模式,分别是固定模式(x.x.x)与独立模式(independent)。

固定模式(x.x.x)

所有子包的版本号都是统一的,每次升级发布,子包的版本都统一更新,不管这个子包内容是否有更改过。

使用这种模式的方式就是在 lerna.json 配置文件中,写死一个固定版本号:

{
  "version": "x.x.x"
}

独立模式(independent)

所有子包的版本号都是独立的,在 lerna publish 发布时,只会更新有变化的子包版本号。

而使用这种模式需要把 version 字段改成 independent

{
  "version": "independent"
}

核心命令

lerna init

该命令用于初始化 Lerna 工程。

此命令可以接收一个参数,让工程使用独立的版本控制模式。

lerna init --independent

// or

lerna init -i

执行后 lerna.json 文件:

{
  "version": "independent",
  "packages": [
    "packages/*"
  ]
}

lerna create

该命令用于在 Lerna 工程中创建一个子包。

我们先给上面初始化的 Lerna 工程增加两个子包,分别执行以下命令:

lerna create button

(不断回车即可)

lerna create icon

执行后的目录结构如下:

image.png

然后修改子包的 package.json 文件:

{
  "name": "@yd-lerna-dev/button",
  ...
}
{
  "name": "@yd-lerna-dev/icon",
  ...
}

主要就是把 name 字段修改一下,这是我们最终要发布到 npm 的名称,为了不引起名称占用的冲突,我们加个了 npm 组织前缀(@yd-lerna-dev/xxx)。

lerna publish

该命令用于把需要发布的包上传到 npm 上。

当然,现在我们还不能把包上传到 npm 上,上传之前我们还需要做一些准备工作。

新建远程仓库

首先,先要创建 git 仓库,开头我们就讲过 Lerna 是基于 git+npm 的,你也可以尝试执行下图中的命令, 会报错,但 Lerna 的提示还是很友好的。

image.png

创建 git 仓库,你可以选择去 github 或者 gitee 等等平台创建,反正最终获取到一个 xxx.git 的仓库地址即可。

然后你需要把代码提交到远程仓库中,你可以借助 vscode 等编辑器工具来提交代码,或者通过以下命令来提交。

git add .
git commit -m "init commit"
git push --set-upstream origin master

git 命令还不熟悉的小伙伴,可以看看小编的另一篇文章,它能帮助你把 git 玩得明明白白(✪ω✪)。

创建npm组织

提交完代码后,我们需要做另外一件事情,就是在 npm 平台上创建自己的组织。

为什么需要做这件事情呢?原因是因为在上面我们修改了每个子包的 package.json 文件的 name 字段,给它们都分别加上了组织前缀(@yd-lerna-dev/xxx)。当然,如果你能给每个子包的名称命名是唯一的,那么你也可以不加组织前缀,也不用创建组织,直接发布包到 npm 上就可以了。(可以跳过这一步骤)

小编还是推荐使用组织前缀,这样子完全不用考虑自己的 npm 包可能会和别人的包命名冲突的问题,而且在下载安装的时候,也会展示成比较可阅读的形式,如下:

"devDependencies": {
  "@yd-lerna-dev/button": "^1.0.0",
  "@yd-lerna-dev/icon": "^1.0.0",
  "@vue/cli-plugin-babel": "^1.0.0",
  "@vue/cli-plugin-eslint": "^1.0.0",
}

那么,我们继续来创建自己的 npm 组织,其实挺简单的。

先登录你的 npm 进到官网,然后点击个人中心里的创建组织按钮。

image.png

输入组织名称,小编这里的组织叫 yd-lerna-dev,然后点击创建。

image.png

很简单就创建成功了。

修改子包package.json

然后我们需要把所有子包都改成公共的属性。

// icon/package.json
{
  "name": "@yd-lerna-dev/icon",
  "publishConfig": {
    "registry": "https://registry.npmjs.org/",
    "access": "public"
  },
  ...
}

主要就是修改子包 package.json 文件中的 publishConfig 字段。

登录npm

在最后上传之前,我们需要让本地的环境登录一下 npm

npm login

执行以上命令,输入账号、密码还有邮箱就可以了,可能还需要邮箱的验证码,可以打开自己的邮箱查看。

image.png image.png 如果你遇到以上错误,可以试试重新登录一下 npm

发布

最后我们回到项目中,执行 lerna publish 命令。

image.png

执行后会提示让你选择版本号,你可以选择想要发布的版本号,也可以自定义版本号。

image.png

在最终发布的时候,也会再次询问你,并列出子包的版本号变化。

当你能看到以下画面,就说明你发布成功了。

image.png

你也可以在 npm 平台上查看你的包。

image.png

102EABDD.jpg

independent模式发布

我们来试试如果使用 independent 模式进行发布又会发生什么呢。

先修改 lerna.json 文件:

{
  "version": "independent",
  "packages": [ 
    "packages/*"
  ]
}

然后我们随便修改一个 packages/icon 子包的内容。

提交代码:

git add .
git commit -m "update icon"
git push

然后执行发布命令:

image.png

选择版本号后,你会看到,这个时候就不是统一更新子包版本号了,只有变更内容的子包才会重新发布。

当然,如果你更改多个子包,那么也会让你一个一个选择,真的是很方便呢(⁎˃ᴗ˂⁎)。

image.png

lerna version

该命令用于给远程仓库最新更改提交的代码打上一个 tag 版本号。

tag 还不了解的小伙伴可以先去了解一下和 git tag 相关的内容。

我们可以去到远程仓库的平台上查看我们每次执行 lerna publish 命令后产生的标签情况。

image.png

通过 lerna publish 命令产生的标签是和你在 npm 上发布的版本号是同步的,因为它俩是同步进行的。

image.png

那么,如果我只想把最新修改提交的代码先打上一个 tag,但又不想它立马就同步发布到 npm 上,那么你就可以使用以下命令。

lerna version 

image.png

执行命令后,你会发现远程仓库会增加相应的标签,但是 npm 上并没有发布新版本。

image.png

可能这里有小伙伴会在想,那它和通过 git tag 直接创建的标签是不是一样的?一半一半,对于远程仓库来说,标签是一样的;但是对于执行命令来讲,又是有点区别的,通过 lerna version 打上 tag 的代码,再次执行 lerna publish 是无法被检测到的. image.pnggit tag 则反之。

lerna add

该命令用于给子包添加依赖。

给所有子包都添加依赖:

lerna add vue

给某个子包单独添加依赖:

lerna add lodash --scope=@yd-lerna-dev/button

默认依赖是安装在 dependencies,也可以添加通过参数配置(--dev/--peer),安装到 devDependencies/peerDependencies 或者 。

lerna add jquery --scope=@yd-lerna-dev/button --dev

lerna clean

该命令用于清除子包的依赖。

清除所有子包的依赖:

lerna clean

需要注意的,这个命令只会把子包里面的 node_modules 删除,但是 package.json 里面的依赖信息还是存在的。

image.png

清除某个子包的依赖:

lerna clean --scope=@yd-lerna-dev/button

lerna bootstrap

该命令用于给子包重新安装依赖。

给所有子包重新安装依赖:

lerna bootstrap

给某个子包单独重新安装依赖:

lerna bootstrap --scope=@yd-lerna-dev/button

lerna link

该命令用于将 Lerna 工程内的子包进行相互引用。

我们来修改子包 @yd-lerna-dev/buttonpackage.json 文件:

{
  "name": "@yd-lerna-dev/button",
  "dependencies": {
    "@yd-lerna-dev/icon": "^0.1.6"
  }
  ...
}

让它依赖另一个子包,然后执行 lerna link 命令。

image.png

你会发现在 @yd-lerna-dev/button 子包的 node_modules 中会多了一个包的引用,你可以在子包内随意使用它。

这里你可能会在想,那我通过 lerna add 一样也能实现子包引用另一个子包吧?

是的。但是 lerna link 的优势在于它是实时的,你在 @yd-lerna-dev/icon 子包中修改的内容,可以实时反应到 @yd-lerna-dev/button 子包的引用中去,不用去发布,这就极大的提高我们的开发效率了。

111.gif

如果对 npm link 熟的小伙伴就会发现它们俩挺类似的。

lerna run

该命令用于执行子包中的 script 命令。

执行所的子包的 script 命令:

lerna run <scriptName>

执行某个子包的 script 命令:

{
  "name": "@yd-lerna-dev/button",
  "scripts": {
    "test": "echo \"Hello Lerna - button\""
  },
  ...
}

随便修改一下 package.json 文件的 script 命令,打印点东西,然后执行以下命令:

lerna run --scope @yd-lerna-button test

image.png

lerna exec

该命令用于在子包中执行任意命令。

在所有子包中执行删除 node_modules 命令:

lerna exec -- rm -rf ./node_modules

image.png

(需要注意 rm -rf 命令并不能直接在 window 系统下执行)

在某个子包中执行删除 node_modules 命令:

lerna exec --scope @yd-lerna-dev/button -- rm -rf ./node_modules

当然,你也可以去执行其他各种有用的命令,还有就它和 lerna run 有点相似,但两者还是有区别的。

lerna diff

该命令用于对比子包更改前后的差异,和 git diff 是一模一样的作用。

展示所有子包的更改差异:

lerna diff

(按 q 退出)

展示某个子包的更改差异:

lerna diff @yd-lerna-dev/button

(注意,没有 --scope 参数哦)

lerna changed

该命令用于检查自上次发布后,最新提交到远程仓库中的代码,有哪些包发生了变化。

image.png

lerna list

该命令用于列出所有子包的信息,可以有几种输出形式。

image.png

lerna info

该命令用于打印本地环境信息。

image.png

lerna ls

列出所有公开的包,private: true 的除外。





至此,本篇文章就写完啦,撒花撒花。

image.png

希望本文对你有所帮助,如有任何疑问,期待你的留言哦。
老样子,点赞+评论=你会了,收藏=你精通了。