PNPM
pnpm(Performant npm)是一个快速的,节省磁盘空间的包管理工具,用于 JavaScript 和 Node.js 生态系统。它是 npm 和 Yarn 的一个替代品,旨在提供更快、更高效的依赖管理解决方案。pnpm 主要通过使用硬链接和符号链接的方式来存储一个版本的包的单一副本,从而减少磁盘空间的使用和加速安装过程。

查看更多相关内容
pnpm 的 shamefully-hoist 配置是什么?什么时候需要使用?`shamefully-hoist` 是 pnpm 的一个配置选项,用于创建类似 npm/Yarn 的扁平化 node_modules 结构。
**默认行为 vs shamefully-hoist:**
```bash
# 默认 pnpm 结构(严格)
node_modules/
├── .pnpm/
│ └── lodash@4.17.21/
└── lodash -> .pnpm/lodash@4.17.21/node_modules/lodash
# 只能访问声明的依赖
const lodash = require('lodash'); // ✅ 正常
const debug = require('debug'); // ❌ 错误(未声明)
```
```bash
# shamefully-hoist=true 结构(扁平化)
node_modules/
├── .pnpm/
├── lodash/
├── debug/ # 被提升上来
└── ...
# 可以访问所有依赖
const lodash = require('lodash'); // ✅ 正常
const debug = require('debug'); // ✅ 可以访问(幽灵依赖)
```
**配置方法:**
```ini
# .npmrc
shamefully-hoist=true
# 或只提升特定包
shamefully-hoist-pattern[]=webpack
shamefully-hoist-pattern[]=*types*
```
**使用场景:**
1. **遗留项目迁移**
```ini
# 项目依赖幽灵依赖,暂时无法修改
# .npmrc
shamefully-hoist=true
# 迁移完成后应关闭
# shamefully-hoist=false
```
2. **特定工具兼容**
```ini
# 某些工具需要扁平化结构
# 如某些 webpack 插件、IDE 等
shamefully-hoist=true
```
3. **混合使用**
```ini
# 只提升特定包
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=*types*
```
**相关配置对比:**
| 配置 | 作用 | 推荐度 |
|------|------|--------|
| `shamefully-hoist` | 完全扁平化 | ⭐⭐ |
| `public-hoist-pattern` | 部分扁平化 | ⭐⭐⭐⭐⭐ |
| `hoist-pattern` | 内部扁平化 | ⭐⭐⭐⭐ |
**public-hoist-pattern 推荐配置:**
```ini
# .npmrc
# 提升类型定义包
public-hoist-pattern[]=*types*
# 提升构建工具
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=*webpack*
# 提升测试工具
public-hoist-pattern[]=*jest*
public-hoist-pattern[]=*vitest*
```
**为什么不推荐完全扁平化:**
```javascript
// shamefully-hoist=true 的问题
// 1. 幽灵依赖
const someDep = require('some-dep');
// 实际未在 package.json 中声明
// 可能导致 CI/CD 失败
// 2. 版本冲突
// 不同包依赖同一包的不同版本
// 扁平化后只能有一个版本
// 3. 失去 pnpm 的优势
// 磁盘空间节省减少
// 依赖管理不严格
```
**最佳实践:**
```ini
# 推荐配置
# .npmrc
# 默认不扁平化
shamefully-hoist=false
# 只提升必要的包
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=*types*
# 严格模式
strict-peer-dependencies=true
```
**迁移策略:**
```bash
# 1. 先启用 shamefully-hoist 迁移
# .npmrc
shamefully-hoist=true
# 2. 运行项目,检查是否有问题
pnpm install
pnpm build
pnpm test
# 3. 逐步修复幽灵依赖
# 找到所有未声明的依赖
pnpm ls --depth=10
# 4. 添加到 package.json
pnpm add missing-dep
# 5. 关闭 shamefully-hoist
# .npmrc
shamefully-hoist=false
```
**检查幽灵依赖:**
```bash
# 使用 depcheck 检查
cd project
npx depcheck
# 或使用 pnpm 检查
pnpm ls --depth=0
```
**总结:**
- `shamefully-hoist` 是迁移过渡方案
- 长期使用应关闭,保持 pnpm 的严格性
- 使用 `public-hoist-pattern` 替代完全扁平化
- 逐步修复幽灵依赖,回归标准模式
服务端 · 3月7日 12:16
pnpm workspace 如何配置和使用?pnpm workspace 是 pnpm 内置的 monorepo 解决方案,用于管理多个包在一个仓库中。
**基本配置:**
```yaml
# pnpm-workspace.yaml
packages:
- 'packages/*' # 所有 packages 目录下的包
- 'apps/*' # 所有 apps 目录下的应用
- 'shared/*' # 共享模块
```
**项目结构示例:**
```
my-monorepo/
├── pnpm-workspace.yaml
├── package.json
├── pnpm-lock.yaml
├── packages/
│ ├── ui/
│ │ ├── package.json
│ │ └── src/
│ └── utils/
│ ├── package.json
│ └── src/
└── apps/
├── web/
│ ├── package.json
│ └── src/
└── server/
├── package.json
└── src/
```
**包间依赖引用:**
```json
// apps/web/package.json
{
"name": "@my-org/web",
"dependencies": {
"@my-org/ui": "workspace:*", // 使用 workspace 协议
"@my-org/utils": "workspace:^1.0.0"
}
}
```
**workspace 协议类型:**
```json
{
"dependencies": {
"package": "workspace:*", // 使用最新版本
"package": "workspace:^", // 兼容版本
"package": "workspace:~", // 近似版本
"package": "workspace:^1.0.0" // 指定版本范围
}
}
```
**常用命令:**
```bash
# 安装所有依赖
pnpm install
# 在特定包中运行命令
pnpm --filter @my-org/ui build
pnpm -F @my-org/ui build # 简写
# 在所有包中运行命令
pnpm -r build # 递归执行
# 只在有变化的包中运行
pnpm -r --filter "...[origin/main]" build
# 添加包间依赖
pnpm --filter @my-org/web add @my-org/ui
```
**优势对比:**
| 特性 | pnpm workspace | Lerna | Yarn Workspaces |
|------|---------------|-------|-----------------|
| 内置支持 | ✅ | ❌ 需安装 | ✅ |
| 依赖共享 | ✅ 硬链接 | ❌ | ✅ 符号链接 |
| 磁盘效率 | 最高 | 一般 | 中等 |
| 配置复杂度 | 简单 | 复杂 | 简单 |
**最佳实践:**
```bash
# 使用 changesets 管理版本
pnpm add -Dw @changesets/cli
pnpm changeset init
# 发布流程
pnpm changeset # 记录变更
pnpm changeset version # 更新版本
pnpm -r publish # 发布所有包
```
服务端 · 3月6日 23:39
pnpm 如何处理 peer dependencies?与 npm 有什么不同?pnpm 对 peer dependencies 的处理更加严格和正确,这是其重要特性之一。
**什么是 Peer Dependencies:**
```json
// react-dom/package.json
{
"peerDependencies": {
"react": "^18.0.0" // 需要宿主项目提供 react
}
}
```
**npm/Yarn 的问题:**
```bash
# 项目依赖
{
"dependencies": {
"react": "^17.0.0",
"react-dom": "^18.0.0" # 需要 react 18
}
}
# npm/Yarn 可能静默安装,导致版本不匹配
# 运行时才发现问题
```
**pnpm 的严格处理:**
```bash
# 安装时报错
pnpm install
# ERR_PNPM_PEER_DEP_ISSUES Unmet peer dependencies
# react-dom@18.0.0 requires react@^18.0.0 but you have react@17.0.0
```
**解决方案:**
1. **正确安装匹配版本**
```bash
pnpm add react@18 react-dom@18
```
2. **使用 pnpm.overrides**
```json
// package.json
{
"pnpm": {
"overrides": {
"react": "^18.0.0"
}
}
}
```
3. **忽略 peer dependency(不推荐)**
```json
{
"pnpm": {
"peerDependenciesMeta": {
"react": {
"optional": true
}
}
}
}
```
**peerDependencies 的正确使用:**
```json
// 插件包的 package.json
{
"name": "my-react-plugin",
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true // 可选的 peer dependency
}
}
}
```
**monorepo 中的处理:**
```yaml
# pnpm-workspace.yaml
packages:
- 'packages/*'
# packages/plugin/package.json
{
"peerDependencies": {
"react": "^18.0.0"
}
}
# packages/app/package.json
{
"dependencies": {
"react": "^18.0.0",
"@my-org/plugin": "workspace:*"
}
}
# pnpm 会自动将 app 中的 react 提供给 plugin
```
**自动安装 peer dependencies:**
```toml
# .npmrc
auto-install-peers=true # 自动安装 peer dependencies
strict-peer-dependencies=false # 不严格检查
```
**对比总结:**
| 特性 | npm/Yarn | pnpm |
|------|----------|------|
| 检查时机 | 可能延迟到运行时 | 安装时立即检查 |
| 错误提示 | 可能不明显 | 明确的错误信息 |
| 版本冲突 | 可能静默忽略 | 严格报错 |
| monorepo 支持 | 一般 | 优秀 |
服务端 · 3月6日 23:39
pnpm 常用命令有哪些?与 npm 命令有什么区别?pnpm 提供了丰富的 CLI 命令来管理依赖和项目。
**安装命令:**
```bash
# 安装所有依赖
pnpm install
pnpm i
# 安装单个包
pnpm add lodash
pnpm add lodash@4.17.21
# 安装到不同依赖类型
pnpm add lodash --save-prod # dependencies (默认)
pnpm add lodash --save-dev # devDependencies
pnpm add lodash --save-optional # optionalDependencies
pnpm add lodash -D # devDependencies 简写
pnpm add lodash -O # optionalDependencies 简写
# 全局安装
pnpm add -g lodash
pnpm add --global lodash
```
**更新命令:**
```bash
# 更新单个包
pnpm update lodash
pnpm up lodash
# 更新所有依赖
pnpm update
pnpm up
# 更新到最新版本
pnpm update --latest
pnpm up -L
# 交互式更新
pnpm update --interactive
pnpm up -i
```
**删除命令:**
```bash
# 删除包
pnpm remove lodash
pnpm rm lodash
# 删除多个包
pnpm remove lodash express
# 删除全局包
pnpm remove -g lodash
```
**运行脚本:**
```bash
# 运行 package.json 中的脚本
pnpm run build
pnpm run test
# 简写
pnpm build
pnpm test
# 传递参数
pnpm build -- --watch
```
**Monorepo 相关命令:**
```bash
# 在特定包中运行命令
pnpm --filter <package-name> build
pnpm -F <package-name> build
# 在所有包中运行
pnpm -r build
# 并行运行
pnpm -r --parallel build
# 只在有变化的包中运行
pnpm -r --filter "...[origin/main]" build
# 递归执行命令
pnpm -r exec rm -rf node_modules
```
**查询命令:**
```bash
# 查看包信息
pnpm info lodash
pnpm view lodash
# 查看已安装的包
pnpm list
pnpm ls
# 查看全局安装的包
pnpm list -g
# 查看依赖树
pnpm list --depth=2
# 查看过时的包
pnpm outdated
```
**Store 管理命令:**
```bash
# 查看 store 路径
pnpm store path
# 清理 store
pnpm store prune
# 验证 store
pnpm store verify
```
**其他常用命令:**
```bash
# 创建项目
pnpm create react-app my-app
pnpm create vite
# 执行包命令
pnpm dlx create-react-app my-app
# 导入其他锁文件
pnpm import
# 链接本地包
pnpm link ../local-package
# 检查依赖问题
pnpm audit
# 为什么安装了这个包
pnpm why lodash
```
**配置命令:**
```bash
# 查看配置
pnpm config list
# 设置配置
pnpm config set store-dir /path/to/store
# 删除配置
pnpm config delete store-dir
```
**命令对比:**
| npm | yarn | pnpm |
|-----|------|------|
| npm install | yarn | pnpm install |
| npm add lodash | yarn add lodash | pnpm add lodash |
| npm run build | yarn build | pnpm build |
| npm update | yarn upgrade | pnpm update |
| npm remove lodash | yarn remove lodash | pnpm remove lodash |
服务端 · 3月6日 23:39
pnpm 的 overrides 和 resolutions 有什么区别?如何使用?pnpm 提供了强大的依赖覆盖机制,主要通过 `overrides` 和 `resolutions` 来实现。
**pnpm.overrides:**
用于强制覆盖依赖版本,无论原始依赖声明什么版本。
```json
// package.json
{
"pnpm": {
"overrides": {
"lodash": "^4.17.21",
"react": "^18.0.0"
}
}
}
```
**使用场景:**
1. **修复安全漏洞**
```json
{
"pnpm": {
"overrides": {
"minimist@<1.2.6": "^1.2.6"
}
}
}
```
2. **强制统一版本**
```json
{
"pnpm": {
"overrides": {
"typescript": "^5.0.0"
}
}
}
```
3. **替换包**
```json
{
"pnpm": {
"overrides": {
"node-sass": "sass"
}
}
}
```
**路径覆盖:**
```json
{
"pnpm": {
"overrides": {
"react": "$react", // 使用项目中的版本
"webpack>lodash": "^4.17.21" // 只覆盖 webpack 的 lodash
}
}
}
```
**resolutions(Yarn 兼容):**
```json
// package.json
{
"resolutions": {
"lodash": "^4.17.21"
}
}
```
**区别对比:**
| 特性 | pnpm.overrides | resolutions |
|------|----------------|-------------|
| 适用范围 | 所有依赖 | 所有依赖 |
| 优先级 | 高 | 中 |
| Yarn 兼容 | ❌ | ✅ |
| 路径指定 | ✅ | ❌ |
| 版本引用 | ✅ | ❌ |
**实际应用示例:**
```json
// 复杂覆盖场景
{
"dependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0",
"antd": "^5.0.0"
},
"pnpm": {
"overrides": {
// 确保所有包使用相同 React 版本
"react": "$react",
"react-dom": "$react-dom",
// 修复 antd 的某个依赖漏洞
"antd>rc-util": "^5.30.0",
// 替换废弃的包
"request": "axios"
}
}
}
```
**验证覆盖效果:**
```bash
# 查看实际安装的版本
pnpm list react
# 查看依赖树
pnpm list --depth=10
# 查看为什么安装了这个版本
pnpm why lodash
```
**注意事项:**
1. **谨慎使用全局覆盖**
```json
// ❌ 不推荐:全局覆盖可能导致不兼容
{
"pnpm": {
"overrides": {
"react": "^18.0.0"
}
}
}
// ✅ 推荐:路径指定更精确
{
"pnpm": {
"overrides": {
"some-package>react": "^18.0.0"
}
}
}
```
2. **更新锁文件**
```bash
# 修改 overrides 后需要重新安装
pnpm install
# 或强制更新
pnpm install --force
```
服务端 · 3月6日 23:39
什么是 pnpm,它与 npm 和 Yarn 有什么区别?pnpm(Performant npm)是一个快速、节省磁盘空间的 JavaScript 包管理工具。
**核心区别:**
1. **存储机制**
- pnpm:使用内容寻址存储,所有包存储在全局 store,项目中通过硬链接引用
- npm/Yarn:每个项目都会复制一份 node_modules,占用大量磁盘空间
2. **安装速度**
- pnpm:由于硬链接机制,第二次安装时速度极快
- npm/Yarn:每次都需要重新下载或复制文件
3. **依赖结构**
- pnpm:使用非扁平化的 node_modules 结构,通过符号链接创建严格的依赖树
- npm/Yarn:使用扁平化结构,可能导致"幽灵依赖"问题
4. **磁盘空间**
- pnpm:多项目共享同一份包,节省 70% 以上磁盘空间
- npm/Yarn:每个项目独立存储,重复占用空间
**示例对比:**
```bash
# npm 安装
npm install lodash
# node_modules 中包含完整的 lodash 副本
# pnpm 安装
pnpm add lodash
# node_modules 中只是指向全局 store 的硬链接
```
**优势总结:**
- 更快的安装速度
- 更少的磁盘占用
- 更严格的依赖管理,避免幽灵依赖
- 更好的 monorepo 支持
服务端 · 3月6日 23:38
pnpm 如何处理依赖版本冲突?pnpm 通过其独特的 node_modules 结构和依赖解析机制来处理版本冲突。
**版本冲突场景:**
```json
// 项目依赖
{
"dependencies": {
"package-a": "^1.0.0", // 依赖 lodash@^4.17.0
"package-b": "^2.0.0" // 依赖 lodash@^3.10.0
}
}
```
**npm/Yarn 的处理方式(有问题):**
```bash
# 扁平化结构只能有一个版本
node_modules/
├── lodash@4.17.21/ # 只有一个版本
├── package-a/
└── package-b/ # 可能使用错误版本!
```
**pnpm 的处理方式(正确):**
```bash
# 每个包有自己的依赖版本
node_modules/
├── .pnpm/
│ ├── lodash@3.10.1/
│ ├── lodash@4.17.21/
│ ├── package-a@1.0.0/
│ │ └── node_modules/
│ │ ├── package-a/
│ │ └── lodash -> ../../lodash@4.17.21/node_modules/lodash
│ └── package-b@2.0.0/
│ └── node_modules/
│ ├── package-b/
│ └── lodash -> ../../lodash@3.10.1/node_modules/lodash
├── package-a -> .pnpm/package-a@1.0.0/node_modules/package-a
└── package-b -> .pnpm/package-b@2.0.0/node_modules/package-b
```
**pnpm 的依赖解析机制:**
```javascript
// package-a 使用 lodash@4.17.21
const lodash = require('lodash');
// 解析路径:
// node_modules/.pnpm/package-a@1.0.0/node_modules/lodash
// package-b 使用 lodash@3.10.1
const lodash = require('lodash');
// 解析路径:
// node_modules/.pnpm/package-b@2.0.0/node_modules/lodash
```
**查看依赖树:**
```bash
# 查看依赖树
pnpm list
pnpm ls
# 查看特定包的依赖
pnpm why lodash
# 查看详细依赖树
pnpm list --depth=10
# 查看重复依赖
pnpm list --depth=Infinity | grep lodash
```
**解决版本冲突:**
1. **使用 overrides 强制统一版本**
```json
{
"pnpm": {
"overrides": {
"lodash": "^4.17.21"
}
}
}
```
2. **路径指定覆盖**
```json
{
"pnpm": {
"overrides": {
"package-b>lodash": "^4.17.21"
}
}
}
```
3. **使用 resolutions(Yarn 兼容)**
```json
{
"resolutions": {
"lodash": "^4.17.21"
}
}
```
**依赖去重:**
```bash
# pnpm 自动去重
# 如果两个包依赖相同版本的 lodash
# 只会在 store 中存储一份
# 手动检查重复
pnpm list --depth=Infinity | sort | uniq -d
```
**peer dependencies 冲突:**
```json
// package-a
{
"peerDependencies": {
"react": ">=16.8.0"
}
}
// package-b
{
"peerDependencies": {
"react": ">=17.0.0"
}
}
```
```bash
# pnpm 会报错
ERR_PNPM_PEER_DEP_ISSUES
# 解决方案
pnpm add react@18
# 或使用 overrides
{
"pnpm": {
"overrides": {
"react": "^18.0.0"
}
}
}
```
**最佳实践:**
1. **定期检查依赖**
```bash
# 查看过时的包
pnpm outdated
# 更新依赖
pnpm update
```
2. **锁定版本**
```json
{
"dependencies": {
"lodash": "4.17.21" // 精确版本
}
}
```
3. **使用 pnpm-lock.yaml**
```bash
# 确保版本一致性
pnpm install --frozen-lockfile
```
**对比总结:**
| 特性 | npm/Yarn | pnpm |
|------|----------|------|
| 多版本支持 | ❌ 扁平化冲突 | ✅ 独立存储 |
| 自动隔离 | ❌ | ✅ |
| 依赖解析 | 可能错误 | 精确正确 |
| 磁盘占用 | 高(多份) | 低(硬链接) |
服务端 · 3月6日 21:35
pnpm 如何使用硬链接和符号链接来节省磁盘空间?pnpm 通过硬链接和符号链接的组合实现高效的磁盘空间利用:
**硬链接(Hard Links)**
硬链接是指向文件系统中同一文件的多个引用。
```bash
# pnpm 的硬链接机制
# 全局 store 位置
~/.pnpm-store/v3/files/00/abc123... # 实际文件
# 项目中的硬链接
project-a/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash.js
project-b/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash.js
# 两者都指向同一个物理文件,不占用额外空间
```
**特点:**
- 多个硬链接共享同一个 inode
- 删除一个链接不影响其他链接
- 修改会反映到所有链接
**符号链接(Symbolic Links/Soft Links)**
符号链接是指向文件路径的特殊文件。
```bash
# pnpm 的符号链接结构
node_modules/lodash -> .pnpm/lodash@4.17.21/node_modules/lodash
# 这是一个指向相对路径的符号链接
```
**特点:**
- 类似于快捷方式
- 可以跨文件系统
- 原文件删除后链接失效
**pnpm 的组合使用:**
```
项目结构:
node_modules/
├── lodash -> .pnpm/lodash@4.17.21/node_modules/lodash [符号链接]
└── .pnpm/
└── lodash@4.17.21/node_modules/
└── lodash.js [硬链接 → 全局 store]
```
**实际效果:**
```javascript
// 查看 inode 验证硬链接
const fs = require('fs');
const stat1 = fs.statSync('project-a/node_modules/.pnpm/lodash@4.17.21/lodash.js');
const stat2 = fs.statSync('project-b/node_modules/.pnpm/lodash@4.17.21/lodash.js');
console.log(stat1.ino === stat2.ino); // true,同一个 inode
```
**空间节省示例:**
```
# npm 方式:10个项目使用 lodash
10 × 1.4MB = 14MB
# pnpm 方式:10个项目使用 lodash
1 × 1.4MB = 1.4MB(节省 90%)
```
服务端 · 3月6日 21:35
pnpm-lock.yaml 的作用是什么?如何管理锁文件?pnpm-lock.yaml 是 pnpm 生成的锁文件,用于确保依赖版本的一致性。
**锁文件结构:**
```yaml
# pnpm-lock.yaml
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLock: false
importers:
.:
dependencies:
lodash:
specifier: ^4.17.21
version: 4.17.21
packages:
/lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LbbZUZt0P2vK6s4I6F7McA==}
engines: {node: '>=6'}
dev: false
snapshots:
lodash@4.17.21: {}
```
**主要部分解析:**
1. **lockfileVersion**
- 标识锁文件格式版本
- pnpm 8 使用版本 6.0
2. **importers**
- 记录每个包的直接依赖
- 包含 specifier(声明的版本范围)和 version(实际安装的版本)
3. **packages**
- 所有依赖包的元数据
- 包含解析地址、完整性校验、引擎要求等
4. **snapshots**
- 依赖树的快照
- 记录依赖关系
**锁文件的作用:**
```bash
# 开发者 A 安装依赖
pnpm install
# 生成 pnpm-lock.yaml
# 开发者 B 克隆项目
git clone project
pnpm install
# 根据锁文件安装,确保版本一致
```
**版本控制:**
```bash
# 必须提交到版本控制
git add pnpm-lock.yaml
git commit -m "add lockfile"
# CI/CD 中使用冻结安装
pnpm install --frozen-lockfile
# 如果锁文件与 package.json 不匹配,安装失败
```
**常见问题处理:**
1. **更新依赖**
```bash
# 更新单个依赖
pnpm update lodash
# 更新所有依赖
pnpm update
# 更新到最新版本(忽略版本范围)
pnpm update --latest
```
2. **解决冲突**
```bash
# 删除锁文件重新生成
rm pnpm-lock.yaml
pnpm install
```
3. **导入其他锁文件**
```bash
# 从 package-lock.json 导入
pnpm import
# 从 yarn.lock 导入
pnpm import
```
**与 npm/yarn 锁文件对比:**
| 特性 | pnpm-lock.yaml | package-lock.json | yarn.lock |
|------|---------------|-------------------|-----------|
| 格式 | YAML | JSON | 自定义格式 |
| 可读性 | 高 | 中 | 低 |
| 存储方式 | 扁平化 | 扁平化 | 扁平化 |
| 硬链接支持 | ✅ | ❌ | ❌ |
**最佳实践:**
```bash
# 始终提交锁文件
git add pnpm-lock.yaml
# CI 中使用冻结安装
pnpm install --frozen-lockfile
# 定期更新依赖
pnpm update --interactive --latest
```
服务端 · 3月6日 21:35
pnpm 的 .npmrc 配置有哪些常用选项?pnpm 的 `.npmrc` 配置文件提供了丰富的选项来自定义包管理行为。
**基础配置:**
```ini
# .npmrc
# 注册表配置
registry=https://registry.npmjs.org/
# 淘宝镜像(国内加速)
registry=https://registry.npmmirror.com/
# 作用域包注册表
@mycompany:registry=https://npm.mycompany.com/
```
**存储配置:**
```ini
# 全局 store 位置
store-dir=/path/to/custom/store
# 缓存目录
cache-dir=/path/to/custom/cache
# 状态目录
state-dir=/path/to/custom/state
```
**安装行为配置:**
```ini
# 严格模式
strict-peer-dependencies=true
# 自动安装 peer dependencies
auto-install-peers=true
# 扁平化模式(兼容 npm)
shamefully-hoist=true
# 只安装生产依赖
production=true
# 忽略 engines 检查
engine-strict=false
```
**网络配置:**
```ini
# 并发下载数
network-concurrency=16
# 请求超时时间(毫秒)
fetch-timeout=60000
# 重试次数
fetch-retries=3
# 代理设置
proxy=http://proxy.company.com:8080
https-proxy=http://proxy.company.com:8080
# 不使用代理的域名
no-proxy=localhost,127.0.0.1
```
**Workspace 配置:**
```ini
# 递归安装时链接 workspace 包
link-workspace-packages=true
# 优先使用 workspace 版本
prefer-workspace-packages=true
# 保存 workspace 协议
save-workspace-protocol=true
```
**安全与审计:**
```ini
# 忽略审计警告
ignore-workspace-root-check=true
# 允许执行 postinstall 脚本
ignore-scripts=false
# 只读模式(不修改 lock 文件)
frozen-lockfile=true
```
**输出配置:**
```ini
# 日志级别
loglevel=info
# 不显示进度条
reporter=silent
# 使用颜色输出
color=always
```
**常用配置组合:**
```ini
# 开发环境配置
strict-peer-dependencies=false
auto-install-peers=true
shamefully-hoist=false
# CI/CD 配置
frozen-lockfile=true
prefer-offline=true
reporter=silent
# Monorepo 配置
link-workspace-packages=true
prefer-workspace-packages=true
```
**环境变量配置:**
```bash
# 通过环境变量设置
export npm_config_registry=https://registry.npmmirror.com/
export npm_config_store_dir=/custom/store
```
**查看当前配置:**
```bash
# 查看所有配置
pnpm config list
# 查看特定配置
pnpm config get registry
# 设置配置
pnpm config set registry https://registry.npmmirror.com/
# 删除配置
pnpm config delete registry
```
**配置优先级:**
1. 命令行参数
2. 环境变量
3. 项目 `.npmrc`
4. 用户 `~/.npmrc`
5. 全局 `/etc/npmrc`
6. 默认值
**实际应用示例:**
```ini
# 企业环境配置
registry=https://npm.company.com/
@company:registry=https://npm.company.com/
# 使用内部代理
proxy=http://proxy.company.com:8080
https-proxy=http://proxy.company.com:8080
# 严格模式
strict-peer-dependencies=true
engine-strict=true
# 性能优化
network-concurrency=32
fetch-retries=5
```
服务端 · 3月6日 21:35