工具

Turborepo

Rush

Nx

Lerna

Pnpm Workspace

依赖管理

版本管理

增量构建

插件扩展

云端缓存

Stars

25.5K

5.7K

22.6K

35.5K

28.4K

老规矩,技术方案对比直接先明示一下,Rush的我已经写过入门了,大家可以移步这里

然后我们既然看了最好的方案,然后再看一下最流行的方案,岂不美哉。

Lerna + pnpm workspace就是目前最流行的方案。

名称解释

这里俩个东西其实要分开看。因为不是一个连贯的东西。

pnpm:大家都用过,它会缓存安装过的包,因此再次安装时不必再去下载了,直接简简单单地创建一个软连接就好了。所以pnpm很能省空间。

workspace:是 npm v7.x 后在npm-cli中新增的功能,该功能支持从顶级根目录中管理本地文件系统中的多个包。

lerna:一个管理工具,用于管理包含多个软件包的JavaScript项目,是 Babel 自己用来维护自己的 Monorepo 并开源出的一个项目。是业界当中使用规模最多的repo管理工具。

起步搭建

安装lerna,然后初始化一个项目

npm i -g lerna && mkdir packages && lerna init

在lerna.json文件中,增加 "useWorkspaces": true 和 "npmClient": "pnpm"。

  "npmClient": "pnpm"

新建 pnpm-workspace.yaml,内容如下

packages:
   - "packages/*"

此时,项目目录结构如下:

packages
├─ .gitignore
├─ lerna.json
├─ package.json
├─ packages
└─ pnpm-workspace.yaml

由于默认使用pnpm,我们删除packages-lock.json,执行

pnpm i

增加子项目

我们继续执行

lerna create @monorepo/demo

我们在packages根目录执行

lerna ls

就可以看到如下输出

lerna notice cli v8.1.6
@monorepo/demo
lerna success found 1 package

packages/demo文件夹下新建index.js文件,然后作为库的入口文件。然后,新建index.d.ts,作为入口类型文件。

// index.js
export const sum = (a, b) => a + b

// index.d.ts
export declare function sum (a: number, b: number): number;

可以看到默认创建的子项目有自己的出入口,我们可以根据项目需求修改。

我们再整一个VUE项目

pnpm create vite

然后修改名字为@monorepo/vite-project,去掉"private": true,

再跑

lerna ls

就发现

info cli using local version of lerna
lerna notice cli v8.1.6
@monorepo/demo
@monorepo/vite-project
lerna success found 2 packages

然后我们在最外面执行

pnpm i

我们的包(包括子项目)就装好了

运行也就是正常运行。

相互依赖

我们直接在packages.json 里面修改dependencies

  "dependencies": {
    "vue": "^3.4.29",
    "@monorepo/demo": "^1.0.0"
  },

然后引入重新跑

pnpm i

或者直接这样

pnpm -F @@monorepo/vite-project add @monorepo/demo

也可以实现引用

Lerna 命令

  1. lerna init 将一个仓库初始化为 lerna 仓库(默认固定模式)。支持参数(--independent/-i – 使用独立的版本控制模式)

  2. lerna create 「package」创建一个 package 到项目工程的 packages 下。

  3. lerna add 「module」为每个 package 都安装指定依赖:

  4. lerna add 「module」--socpe=「package」 为指定的 package 安装特定依赖。包括子依赖。

  5. lerna publish 用于 npm 包版本发布。

  6. lerna bootstrap 将 packages 链接在一起(前提是相互依赖的库),并安装 package 下的依赖到 package/node_modules。

  7. lerna clean 删除各个包下的 node_modules(不会删除根目录 node_modules)。

  8. lerna ls 列出当前 Lerna 仓库中的所有公共软件包(public packages)。

  9. lerna run 「script」运行每个包下面的 script(如果某个包没有此 script,将会报错)

  10. lerna run 「script」--socpe=「package」运行某个包下面的 script

  11. lerna exec 「shell」 允许去执行 shell 脚本

  12. lerna changed 检查自上次发布以来哪些软件包被修改过。

  13. lerna link 链接互相引用的库,当 pakcage/package.json 内明确了 packages 下的包时,才会将相关包链接到 package/node_modules 中。

  14. lerna info 查看 lerna 及运行环境的信息。

Lerna 配置文件

  1. version: 当前仓库的版本,Independent mode 请设置为 independent;

  2. packages: 指定包所在的目录,支持指定多个目录;

  3. npmClient: 允许指定命令使用的client, 默认是 npm, 可以设置成 yarn;

  4. command.bootstrap.npmClientArgs: 指定默认传给 lerna bootstrap 命令的参数;

  5. command.publish.ignoreChanges: 指定那些目录或者文件的变更不用触发 package 版本的变更;

  6. command.publish.message: 执行发布版本更新时的生成的 commit message;

  7. command.publish.registry: 指定发布到的 registry url,比如可以发布到指定私服,默认是 npmjs.org;

  8. command.publish.conventionalCommits: lerna version 将生成 CHANGELOG.md files(如果设置了这个,lerna 管理模式将直接使用固定模式,version = independent 的配置将失效)。

更多操作还请去官网查看

未曾清贫难成人,不经打击老天真。 自古英雄出炼狱,从来富贵入凡尘。 醉生梦死谁成气,拓马长枪定乾坤。 挥军千里山河在,立名扬威传后人。