Monorepo 是一种将多个项目存储在一个代码库中的策略,这使得跨项目共享和管理代码变得更加容易。pnpm 是一个高效的包管理器,它通过使用硬链接和符号链接将包存储在共享的内容寻址存储中,从而避免了重复下载和安装。在本文中,我们将探讨如何在 Monorepo 项目中使用 pnpm 进行包管理和工作流程优化。
一、pnpm 简介
pnpm 是一个与 npm 和 Yarn 类似的包管理器,但它有一些独特的优点,特别是在处理 Monorepo 时。pnpm 的主要优势在于其节省磁盘空间和提高安装速度的能力。它通过使用一种称为内容寻址的方式来实现这一点,将所有相同的包版本链接到单个物理位置,从而避免了多个项目中的重复安装。 (pnpm、yarn、npm之间的区别)
二、为什么选择 pnpm
以下是选择 pnpm 的一些原因:
- 磁盘空间和安装速度的优化:通过使用硬链接和符号链接,pnpm 能够显著减少项目的磁盘空间占用和安装时间。
- 更严格的依赖关系管理:pnpm 更严格地遵循包的依赖关系,确保您的应用程序只访问在其
package.json
中声明的依赖项。 - 原生 Monorepo 支持:通过 pnpm workspaces 功能,pnpm 支持原生 Monorepo,使跨项目的包管理变得更加简单。
三、在 Monorepo 中使用 pnpm
1. 安装 pnpm
首先,您需要安装 pnpm。你可以通过运行以下命令来全局安装 pnpm:
npm install -g pnpm
或者,使用以下命令安装到单个项目:
npm install pnpm
2. 配置 pnpm workspaces
要在 Monorepo 中使用 pnpm,请在项目根目录下创建一个名为pnpm-workspace.yaml
的文件,并在其中定义您的工作区:
packages:
- '**'
这个配置指示 pnpm 在名为packages
的文件夹下查找所有的项目。您可以根据实际需求调整此配置。
接下来,在根目录的package.json
文件中启用 workspaces 功能:
{
"name": "my-monorepo",
"private": true,
"workspaces": {
"packages": ["packages/*"]
}
}
3. 创建子项目
在packages
文件夹下创建子项目,并为每个项目创建一个package.json
文件。例如,假设我们有两个子项目:frontend
和backend
。我们将在packages
文件夹下创建这两个文件夹,并在每个文件夹中添加一个package.json
文件。
packages/frontend/package.json
:
{
"name": "frontend",
"version": "1.0.0",
"dependencies": {
"react": "^17.0.0"
}
}
packages/backend/package.json
:
{
"name": "backend",
"version": "1.0.0",
"dependencies": {
"koa": "^2.13.1"
}
}
4. 安装依赖项
在项目根目录下运行pnpm install
,pnpm 将会自动识别 workspaces,并在所有子项目中安装依赖项。您会注意到 pnpm 在项目根目录下创建了一个名为node_modules
的文件夹。这个文件夹中的.pnpm
子文件夹包含了所有已安装的包,而子项目的node_modules
文件夹中包含了指向这些包的链接。
5. 跨项目共享依赖项
在 Monorepo 中,通常希望跨项目共享某些依赖项。您可以在根目录的package.json
文件中添加这些共享依赖项:
{
"name": "my-monorepo",
"private": true,
"workspaces": {
"packages": ["packages/*"]
},
"dependencies": {
"lodash": "^4.17.21"
}
}
现在,您可以在所有子项目中使用lodash
,而不需要在每个子项目的package.json
文件中单独声明它。
6. 跨项目脚本和命令
pnpm 允许您在根目录下运行子项目的脚本。例如,如果您在frontend
项目的package.json
中定义了一个名为start
的脚本,您可以在根目录下运行以下命令来启动该脚本:
pnpm --filter frontend run start
同样,您可以在根目录的package.json
中定义全局脚本,这些脚本可以在所有子项目中运行:
{
"name": "my-monorepo",
"private": true,
"workspaces": {
"packages": ["packages/*"]
},
"scripts": {
"test": "pnpm run test --filter ./packages/*"
}
}
现在,当您在根目录下运行pnpm test
时,pnpm 将会在所有子项目中运行test
脚本。
四、总结
在本文中,我们探讨了如何在 Monorepo 项目中使用 pnpm 进行包管理和工作流程优化。通过使用 pnpm,您可以节省磁盘空间、提高安装速度,并更容易地管理跨项目的依赖关系和脚本。pnpm 的原生 workspaces 功能使得在 Monorepo 中的包管理变得简单且直观。
以下是一些关键点,以便您回顾和实践:
- 安装并配置 pnpm,为项目设置 workspaces。
- 在 Monorepo 中创建子项目,并在每个子项目中添加
package.json
文件。 - 使用
pnpm install
一次性安装所有子项目的依赖项。 - 在根
package.json
文件中添加共享依赖项,以便在所有子项目中使用。 - 使用
pnpm run
命令执行跨项目脚本。
基于 pnpm 的 Monorepo 实践有助于提高项目间的协同开发效率,降低维护成本,并确保项目依赖的一致性。这种方法适用于具有多个相互关联的项目或组件的大型应用程序。如果您正在寻找一个灵活且高效的 Monorepo 解决方案,那么 pnpm 值得一试。