Lerna 给我们工程带来了什么

1,334 阅读4分钟

前言

最近在公司搭建脚手架,使用最近市面上🔥的Monorepo模式进行包管理。原因以下几点:

  • 借鉴Vue Cli和CRA
  • Cli主要包含base-create、server、utils、plugin几个模块,通过Monorepo,使模块容易拆分、集中管理。
  • 开发方便,通过yarn workspace 使模块间的相互引用变得更容易

repo

这里先介绍两种项目代码管理方式(monorepo、multirepo)。

Monorepo 就是将多个项目放在一个仓库中进行管理

monorepo所带来的就是代码集中化管理,各个模块间的相互依赖变得简单、清晰。对于一个大型项目来说,模块的拆分尤为重要,所以我认为对于模块耦合性较高的、或者说多个模块为一个项目服务的情况下,从管理和维护来讲,这个方案是一个不错的选择。当然它也有repo的体积变得很大、权限也不好分配等缺点。

Mutirepo 则相反是放在多个仓库中进行维护

mutirepo带来的就是代码的多元化管理,降低了各个项目或团队的耦合性,每个团队单独作战,维护各自唯一的package,对于独立的项目,也许是不错的管理方式,但也需要考虑重复性工作、团队沟通成本、repo管理成本等影响

借鉴网上的一张图很容易发现两者区别

两种方案各有千秋,需要考虑自己项目、团队的实际情况来进行选择,相信总有一款适合你

lerna

而monorepo的解决方案就是lerna 目前很多开源项目采用lerna来进行项目管理(Babel、vue-cli、create-react-app。。。)

模式

lerna提供两种模式

  1. Fixed/Locked(默认)

固定模式,项目维护一个版本号,也就是在lerna.json文件中,当运行lerna publish,如果某个模块在上次发布版本之后有了更新,那么他将会更新到新发布的版本,也就意味着你只能在你确定需要更新时才能发布一个新的版本(不能随便发啦!!!)

{
  "packages": [
    "packages/*"
  ],
  "version": "0.0.0"
}
  1. Independent 独立模式,它允许Lerna中每个模块独立维护自己的版本号,也将导致你每次发布时,会有一个提示,针对本次更改的包指定他是patch、minor、major或者custom change
{
  "packages": [
    "packages/*"
  ],
  "version": "independent"
}

命令

这里只介绍几种常用命令,详细请参考官方README。安装就不说了,全局安一下就完了

初始化

lerna init --independent // 模式参数,默认Fixed/Locked

创建子项目

lerna create <name>

顾名思义,该命令是在packages下创建一个新的package。

需要注意的一点是创建的目录是在lerna.json中配置,例子

"packages": [
  "packages/@vue/*"
]

添加依赖

$ lerna add <package>[@version] [--dev] [--exact] [--peer]

安装本地或远程依赖包,需要注意的是,一次只能添加一个包(与yarn add 和 npm install不同)

当运行这个命令,lerna到底干了啥

  1. 会给每一个package返回内的应用安装依赖
  2. 修改每个应用的package.json文件
参数说明
参数说明
--dev开发环境依赖包
--scope安装范围,当你想在某个应用安装时,应该需要它
举个🌰

给packages目录下所有前缀为prefix-的应用安装module-1依赖

$ lerna add module-1 packages/prefix-*

给module-2安装module-1

$ lerna add module-1 --scope=module-2

给所有应用安装module-1

$ lerna add module-1

发布

$ lerna publish

根据提示选择相应发布版本就OK

yarn

yarn相比npm优点

  • 速度(并行安装、离线模式)
  • 简洁(输出信息更加简洁,结合emoji增加趣味性)
  • 更好的语义化 (add/remove)

yarn workspace

yarn workspace允许我们使用Monorepo的形式管理项目,在安装 node_modules 的时候它不会安装到每个子项目的 node_modules 里面,而是直接安装到根目录下面,这样每个子项目都可以读取到根目录的 node_modules。整个项目只有根目录下面会有一份yarn.lock文件。子项目也会被 link 到 node_modules 里面,这样就允许我们就可以直接用 import 导入对应的项目

  • 注意 当我们开发node应用 或者不需要对项目进行打包操作,要慎用全局依赖,因为当我们使用lerna publish对项目进行发布时,是将每个子项目单独发布到npm上(也就是最终的依赖以子项目的package.json为准)

开启workspace

{
  "name": "root",
  "private": true, // 私有的,用来管理整个项目,不会被发布到npm
  "workspaces": [
    "packages/*"
  ],
  "devDependencies": {
    "lerna": "^3.22.1"
  }
}