Lerna学习与理解

适用范围

不会用到的情况

  • 业务项目(xxx系统之类的):不会用到lerna,平时开发的项目,只需一个git仓库下放一个项目,根目录下只有一个package.json文件。
  • 单包项目:不会用到lerna,比如开发一个npm包,里面包含了一些功能,也只需一个git仓库下放一个项目。

会用到的情况

  • 多包项目:如果你想开发一个组件库、或大型工具库。这种项目弄成一个npm包就很不合适,需要拆分成多个npm包,这时候就是一个git仓库下,管理多个npm包。这时候用lerna就派上用场了。

多包项目

  • 拿组件库举例子,如果将所有组件都放在一个git仓库下,发布到一个npm包里,用户想使用这个组件库里的某一个组件,也只能整体安装我们的组件库。但如果每个组件单独发包,比如有一个用户只用了这个组件库的button组件,用户就可以只安装button组件(npm install @my-ui/button),更灵活了。另一个好处是,我们更改另一个toast组件的代码,单包项目就得再发一次版,用户更新新包,但他使用的button却没有任何改变,就很没必要。换做多包项目,我们改了toast组件的代码,重新发toast包和整体的包。但是不用重新发button组件包(button组件包的版本号不会变),就很合适。
  • 拿babel库举例子。babel库也是个典型的多包git仓库。我们去babel的github仓库看看,packages文件夹下一堆npm包,babel-cli、babel-core、babel-preset-env等等。我们作为使用者,安装自己项目需要的包即可。babel也是用lerna来管理的。
  • 另一个方面,如果将这些npm包完全分开管理,一个git仓库下一个npm包,维护起来挺麻烦,包之间关联很强。还是放在一个git仓库下,用lerna进行管理比较好。

Lerna定义

Lerna是帮助我们在一个git仓库下管理多个npm包的工具。

// 初始化一个lerna管理的项目
npm i -g lerna
lerna init --independent // 关于independent下面解释
复制代码

固定模式 vs 独立模式

在初始化一个lerna管理的项目时,有固定(默认)和独立(lerna init时加–independent参数)两种模式。这两种模式关键区别是,怎样管理子包们的版本。

  • 固定模式:版本号使用项目根目录下lerna.json文件中的version属性。执行lerna publish时,如果代码有更新,会自动更新此版本号的值,其他有改动子包也自动更新版本号,没改动的子包不更新版本号。也就是所有包的版本号都跟根目录下lerna.json文件中的version是有关系的。Babel库是用的这种模式。
  • 独立模式:子包们的版本号独自维护,和根目录的配置没关系。每次publish时,得为每个更改的子包设置版本。

我觉得可能是这样的,对于子包之间关联性比较大的,如babel,使用固定模式合适,如组件库这种子包之间关联性不大等,使用独立模式,版本维护更自由一点。

Lerna管理的项目结构

my-ui/
  package.json
  lerna.json
  packages/
    Button/
      src/
      package.json
    Toast/
      src/
      package.json
  ...
复制代码

Button、Toast都是独立的npm包,你也可以用vscode等编辑器只打开Button文件夹,进行该组件的开发。当然这么做也没啥必要,只是为了说明Button文件夹是个独立的子项目。我们可以在Button文件夹下执行npm install vue webpack babel等,会在Button文件夹下安装依赖包,生成node_modules文件夹 。 那么问题来了,在Toast文件夹下同样用npm install来安装包,同样有vue webpack babel等,这就比较浪费磁盘。lerna为我们提供了lerna bootstrap命令解决此问题。

Lerna Hoisting

Lerna Hoisting就是指将子包下的node_modules都提升到根目录的node_modules里,统一管理,节省磁盘。

做如下配置,Lerna Hoisting就会生效。

// 配置 lerna.json:
{
  ...
  "npmClient": "yarn",
  "useWorkspaces": true
}

// package.json配置
{
  "private": true,
  ...
  "workspaces": [
    "packages/*"
  ],
}
复制代码

命令

lerna bootstrap

既然Button、Toast有很多公共的依赖包,那将这些依赖都放到my-ui文件夹下的node_modules,清空Button、Toast下的node_modules,就达到节省磁盘等目的了。

要实现这个,就用到lerna bootstrap,相当于为packages下所有子项目都npm install了一下,但是依赖包都安装在了my-ui文件夹下的node_modules,统一管理依赖。

lerna publish

在上面介绍固定模式、独立模式时提到了lerna publish。包开发完了,要发布到npm源上。用lerna publish命令就是发布到npm源上。根据固定模式、独立模式不同,使用不同的版本号更新策略。

配置 lerna.json:
"command": {
  "publish": {
    "registry": "https://registry.npmjs.org"
  }
},
"ignoreChanges": [
  "ignored-file",
  "**/__tests__/**",
  "**/*.md"
]
复制代码
  • 设置 command.publish.registry:发布地址
  • 设置 ignoreChanges:告诉lerna,这些文件更改,不需升级版本。

lerna add

假如我想为我的组件库下的所有子包,都安装lodash。传统做法是,到每个子包文件夹下npm install lodash。但是使用lerna,我们可以在根目录下执行命令lerna add lodash,你会看到所有等子包的package.json中dependencies字段下都有了lodash。

npm install lodash
复制代码

这里再次点明主旨,lerna方便我们管理多包项目。这种需要为所有子包安装同一个依赖的情况,使用lerna add简化了操作。

同样如果你只想给Button组件安装lodash,可以执行

lerna add lodash --scope=@my-ui/Button
复制代码

区别于直接在Button文件夹下npm i lodash,是将依赖装在了根目录的node_modules。

lerna create

如果你想新建一个lerna子包,使用

lerna create @my-ui/Input 
复制代码

会在packages文件夹下生成Input文件夹,一个子项目。

my-ui/
  package.json
  packages/
    Button/
      src/
      package.json
    Input/
      src/
      package.json
    Toast/
      src/
      package.json
  ...
复制代码

额外的,如果你想搞一套组件库,还可以新建一个主包,一个工具包

lerna create @my-ui/my-ui
lerna create @my-ui/Utils

my-ui/
  package.json
  packages/
    Button/
      src/
      package.json
    Input/
      src/
      package.json
    Toast/
      src/
      package.json
    Utils/
      src/
      package.json
    my-ui/
      src/
      package.json
  ...
复制代码

Utils子包用来放一些工具函数,供其他组件使用,my-ui子包引用所有其他组件包,供想全部使用我们组件库的用户安装的包。

lerna add @my-ui/Utils --scope @my-ui/Button
lerna add @my-ui/Utils --scope @my-ui/Input
lerna add @my-ui/Utils --scope @my-ui/Toast

lerna add @my-ui/Button --scope my-ui
lerna add @my-ui/Input --scope my-ui
lerna add @my-ui/Toast --scope my-ui
复制代码

执行上面这样的命令,就可以完成子包间的引用。

总结

  • 从使用场景上,如果我们开发多包项目,就适合用lerna。
  • lerna是非常多明星库的选择,我们看babel、react、element-ui等等都能看到lerna。
  • 你可以根据自己点需要选择固定模式或独立模式
  • 包提升(Lerna Hoisting)是lerna一个非常有用的特性。
  • Lerna的命令都是服务于我们方便管理多包项目,管理它们的依赖,发版时的版本号维护。

本篇文章希望能帮助您了解lerna使用场景,和它的基本使用。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享