前端包管理方案(二)——lerna多包管理

2,795 阅读4分钟

这是我参与11月更文挑战的第4天,活动详情查看2021最后一次更文挑战

前言

在项目复杂度上升后,代码的各个模块面对着使用多个仓库维护还是放在一个仓库里的问题。Monorepo的思想是将多个项目代码存储在一个仓库里。著名的JS插件Babel即使用了monorepo管理他们的代码。

monorepo的优势

各个包之间的沟通更加的方便,如果multi-package的话,系统内其中一个包修改,需要单独发版,而且引用这个包的其他包都需要发版。使用lerna的话可以自动管理这些包的发版,很方便;一些可以共用的配置,比如eslint,babel,rollup等,可以统一的管理这些开发配置,因为monorepo的结构,所有的子包都会使用这个配置。

lerna简介

安装

为了方便使用lerna首先需要全局安装:npm install lerna -g

工作模式

lerna有两种工作模式:Fixed/Locked Mode和Independent Mode,默认前一种模式(vue babel等都是这个模式)。

初始化时增加命令行参数--independent参数能改成后一种模式,区别是在lerna.json文件中的version是版本号还是"independent"字符串。

如果是后者,那每次publish时都会顺序选择每个已更改包的版本号(是补丁、次要更改还是主要更改)。

lerna.json参数说明

  • version 当前库的版本号,独立模式下,此参数设置为independent
  • npmClient 允许指定命令使用的client, 默认是npm, 可以设置成yarn
  • command.publish.ignoreChanges 可以指定那些目录或者文件的变更不会被publish
  • command.publish.message 指定发布时提交的消息格式
  • command.publish.registry 设置npm包发布的注册地址
  • command.bootstrap.ignore 设置执行lerna bootstrap安装依赖时不受影响的包
  • command.bootstrap.npmClientArgs 指定在执行lerna bootstrap命令时传递给npm install的参数
  • command.bootstrap.scope 指定那些包会受 lerna bootstrap 命令影响
  • packages 指定包所在目录
  • 可以通过添加lerna.json中的参数为lerna项目设置workspace,同一个workspace下的项目可以共享一个node_modules,避免包中node_modules的重复:package.json文件设置private、workspaces参数、lerna.json文件加入useWorkspaces参数(文中还设置了npmClient参数,不确定是否不设置也能生效);

发布

如果需要将npm包发包到外网的话需要登录npm账号然后执行lerna publish,如果只是内网使用的话不需要登录和publish;如果是为了防止其被发布到npm上,可以在其package.json中设置"private"=true;

lerna命令详解

create:

  • npm init -y和lerna create xxx -y分别是npm创建包和lerna创建包,-y是init选项默认全选true,lerna create < name > [loc]有更多可选参数见文档(需要配置workspaces参数);

add:

  • 为lerna中某一个/某些包安装node_module模块;lerna add [@version] [--dev] [--exact]

bootstrap:

  • bootstrap === [cd ${package} && npm run install for package in packages]

list:

  • 列出所有包名,如果没列出来应该是该包下的package.json的name属性没有;

import:

  • 导入本地包,还没有成功过;

run:

  • lerna run xxx === [cd ${package} && npm run xxx for package in packages];可以加--scope参数来控制运行的范围;

exec:

  • lerna run xxx xx === [cd ${package} && xxx xx for package in packages];可以加--scope参数来控制运行的范围;

link:

  • 建立软链接,类似npm link,没有用过;

clean:

  • lerna clean === 删除所有包的node_modules模块,可以加--scope参数来控制运行的范围;

changed:

  • 列出下次发版lerna publish 要更新的包。原理: 需要先git add,git commit 提交。 然后内部会运行git diff --name-only v版本号,搜集改动的包,就是下次要发布的。并不是网上人说的所有包都是同一个版全发布。

version:

  • 分析lerna管理的所有包并更新到下一个版本,根据模式(fixed/independent)的不同有不同行为(好像,不确定);若是fixed的话会统一更新到某个版本,后续参数可提取选或后续有选项,比如patch是更新一个补丁版本;

publish:

  • 会打tag,上传git,上传npm。 如果你的包名是带scope的例如:"name": "@gp0320/gpwebpack", 那需要在packages.json添加"publishConfig": {"access": "public"};(发布package的名字如果是以@开头的,例如@feu/tools,npm默认以为是私人发布,需要使用npm publish --access public发布。但是lerna publish不支持该参数)

其他相关链接

其他关于lerna最佳实践、自动生成日志信息、管理项目依赖和清理环境等的实践:
juejin.cn/post/684490…
juejin.cn/post/684490…
juejin.cn/post/684490…

与其他monorepo方案的比较(统一脚本命令、锁定环境、使用本地npm仓库测试等):
juejin.cn/post/692485…

使用lerna开发和管理UI组件框架的实践:
juejin.cn/post/684490…