pnpm 实现 Monorepo 项目的简单实践

1,095 阅读3分钟

本文将说明如何使用 pnpm 搭建 monorepo 仓库。

项目初始化

mkdir mono-app && cd mono-app && pnpm init && pnpm install

定义工作空间

创建 pnpm-workspace.yaml 文件,用于定义工作空间

touch pnpm-workspace.yaml
# pnpm-workspace.yaml 配置文件
packages:
  # 指定工作空间中的包路径
  - 'packages/**'

目录结构及文件创建

# 创建项目目录结构,包含不同类型的包和组件
mkdir -p packages/apps/react-demo      # 创建 React 应用包目录
mkdir -p packages/apps/vue-demo        # 创建 Vue 应用包目录
mkdir -p packages/components/react-components  # 创建 React 组件包目录
mkdir -p packages/components/vue-components    # 创建 Vue 组件包目录
mkdir -p packages/libs/cli             # 创建 CLI 库目录
mkdir -p packages/libs/logs            # 创建 日志库目录
mkdir -p packages/libs/utils           # 创建 工具库目录
├── package.json              # 项目根目录的配置文件,定义依赖、脚本和基础信息
├── packages                  # 主项目文件夹,包含所有子模块
│   ├── apps                  # 存放独立的应用程序
│   │   ├── react-demo        # 基于 React 的示例应用
│   │   └── vue-demo          # 基于 Vue 的示例应用
│   ├── components            # 存放可复用的组件库
│   │   ├── react-components  # 基于 React 的组件集合
│   │   └── vue-components    # 基于 Vue 的组件集合
│   └── libs                  # 工具库和核心逻辑模块
│       ├── cli               # 项目脚手架相关代码
│       ├── logs              # 日志处理库
│       └── utils             # 通用工具函数库
├── pnpm-lock.yaml            # pnpm 生成的锁定文件,记录依赖的具体版本
└── pnpm-workspace.yaml       # pnpm 工作区配置文件,用于管理 Monorepo

安装依赖的方法

全局安装

monorepo 项目全局安装依赖

pnpm i <package> -w

局部安装

子项目单独安装依赖

pnpm add <lib-package-name> --filter <子项目包名>

内部安装

子项目之间互相引用。

pnpm add <子项目包名> --filter <子项目包名>

[!TIP]

在子项目之间互相引用的时候会存在一些问题下面是一些行之有效的解决方案。

配置 .npmrc

当设置为 true 时,pnpm 会优先使用工作区中的包(packages 文件夹下的模块)作为依赖,而不是从注册表下载它们的版本。

link-workspace-packages=true

顺便补充一个 dedupe-peer-dependents

当设置为 false 时,不会尝试对 peerDependencies 的依赖项去重

  • 默认情况下,pnpm 会将多个相同的依赖提升到共享目录,减少重复安装。但是对于 peerDependencies,去重可能导致版本不匹配问题。
  • 设置为 false,确保 peerDependencies 的依赖保留在各自的模块目录中,从而避免潜在的兼容性问题。
  • 适用场景: 如果你的项目中存在对 peerDependencies 版本严格依赖的情况(例如某些插件与主包必须匹配特定版本),可以设置为 false 来避免冲突。
dedupe-peer-dependents=false

手动安装子项目

在 package.json 中的 dependi 中手动添加

 "子项目包名": "workspace:^",

然后 pnpm install。

通过上面的步骤一个 monorepo 项目的基本结构已经搭建好了。下面是一些搭建过程中的个人偏好。


个人偏好

锁定版本

因为我是使用 volta 来管理 node 和 pnpm 版本的, 所以我一般会在 pnpm init 之后先进行版本锁定。

volta pin node@23.2.0

npm 源

# https://registry.npmmirror.com/
registry=https://registry.npm.taobao.org

用于在自签名证书、抓包调试或旧版 Node.js 不支持现代 TLS 协议等场景下,暂时禁用 npm 的严格 SSL 校验以解决连接问题。当出现: Error: self signed certificate in certificate chain 错误时使用。

npm config set strict-ssl false