老规矩,技术方案对比直接先明示一下,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 命令
lerna init 将一个仓库初始化为 lerna 仓库(默认固定模式)。支持参数(--independent/-i – 使用独立的版本控制模式)
lerna create 「package」创建一个 package 到项目工程的 packages 下。
lerna add 「module」为每个 package 都安装指定依赖:
lerna add 「module」--socpe=「package」 为指定的 package 安装特定依赖。包括子依赖。
lerna publish 用于 npm 包版本发布。
lerna bootstrap 将 packages 链接在一起(前提是相互依赖的库),并安装 package 下的依赖到 package/node_modules。
lerna clean 删除各个包下的 node_modules(不会删除根目录 node_modules)。
lerna ls 列出当前 Lerna 仓库中的所有公共软件包(public packages)。
lerna run 「script」运行每个包下面的 script(如果某个包没有此 script,将会报错)
lerna run 「script」--socpe=「package」运行某个包下面的 script
lerna exec 「shell」 允许去执行 shell 脚本
lerna changed 检查自上次发布以来哪些软件包被修改过。
lerna link 链接互相引用的库,当 pakcage/package.json 内明确了 packages 下的包时,才会将相关包链接到 package/node_modules 中。
lerna info 查看 lerna 及运行环境的信息。
Lerna 配置文件
version: 当前仓库的版本,Independent mode 请设置为 independent;
packages: 指定包所在的目录,支持指定多个目录;
npmClient: 允许指定命令使用的client, 默认是 npm, 可以设置成 yarn;
command.bootstrap.npmClientArgs: 指定默认传给 lerna bootstrap 命令的参数;
command.publish.ignoreChanges: 指定那些目录或者文件的变更不用触发 package 版本的变更;
command.publish.message: 执行发布版本更新时的生成的 commit message;
command.publish.registry: 指定发布到的 registry url,比如可以发布到指定私服,默认是 npmjs.org;
command.publish.conventionalCommits: lerna version 将生成 CHANGELOG.md files(如果设置了这个,lerna 管理模式将直接使用固定模式,version = independent 的配置将失效)。
更多操作还请去官网查看