使用 pnpm workspace 管理 monorepo 项目
安装 pnpm
什么是 monorepo
Monorepo 是项目管理代码的方式之一,指的是一个大项目中包含了需要小项目或者模块,大概的样子
├── packages
| ├── pkg1
| | ├── package.json
| ├── pkg2
| | ├── package.json
├── package.json
初始化项目
pnpm init
初始化一个项目,创建 package.json
.
└── package.json
在根目录中创建 pnpm-workspace.yaml
packages:
- 'packages/**'
在根目录中创建 packages
文件夹,并且在 packages
中创建子项目
mkdir packages
mkdir packages/core
mkdir packages/browser
.
├── package.json
└── packages
├── browser
└── core
安装全局依赖
-D 表示安装到开发依赖,即 devDependencies, -w 表示在根目录安装
pnpm install typescript -Dw
.
├── node_modules
│ └── typescript -> .pnpm/typescript@4.7.4/node_modules/typescript
├── package.json
├── packages
│ ├── browser
│ └── core
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
局部依赖
首选在每个子项目中初始化 package.json
.
├── node_modules
│ └── typescript -> .pnpm/typescript@4.7.4/node_modules/typescript
├── package.json
├── packages
│ ├── browser
│ │ └── package.json
│ └── core
│ └── package.json
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
packages/browser 中的 package.json
{
"name": "@test/browser",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
packages/core 中的 package.json
{
"name": "@test/core",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
这里需要给每个子项目指定命名空间和包名,即 @test/core
通过 filter 可以给指定的包安装依赖
pnpm install loadsh -r --filter @test/core
{
"name": "@test/core",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.21"
}
}
两个包之间相互依赖
browser 依赖 core
pnpm i @test/core -r --filter @test/browser
browser 中就依赖上了 core,版本前面有 workspace 字样,表示本地引用,发布的时候就会被剔除掉
{
"name": "@test/browser",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@test/core": "workspace:^1.0.0"
}
}
运行子包命令
根目录 package.json
使用 pnpm -r --filter=@test/* run test
来批量执行子包中的 test 脚本
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "pnpm -r --filter=@test/* run test"
},
"author": "",
"license": "ISC",
"devDependencies": {
"typescript": "^4.7.4"
}
}
@test/browser 中的 package.json
{
"name": "@test/browser",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"test browser\""
},
"author": "",
"license": "ISC",
"dependencies": {
"@test/core": "workspace:^1.0.0"
}
}
@test/core 中的 package.json
{
"name": "@test/core",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"test core\""
},
"author": "",
"license": "ISC",
"dependencies": {
"lodash": "^4.17.21"
}
}
执行 pnpm test
,即可得到输出结果
> pnpm -r --filter=@test/* run test
Scope: 2 of 3 workspace projects
packages/core test$ echo "test core"
│ test core
└─ Done in 13ms
packages/browser test$ echo "test browser"
│ test browser
└─ Done in 8ms