5.4 4pnpm 使用介绍

  • pnpm 官网:https://pnpm.io/   高性能的 Node.js 包管理工具

一、什么是 pnpm?

pnpmPerformant npm)是一个高性能、节省磁盘空间的 Node.js 包管理工具,兼容 npm 生态。它由 Zoltan Kochan 于 2016 年创建,目标是解决 npm 和早期 yarn 在依赖管理中的性能与磁盘占用问题。

pnpm 的核心优势在于其独特的 硬链接 + 内容可寻址存储(Content-Addressable Storage, CAS) 机制,使其在安装速度、磁盘使用和依赖一致性方面表现卓越。


二、pnpm 的核心原理

1. 硬链接(Hard Links)与符号链接(Symlinks)

与 npm/yarn 直接复制依赖包不同,pnpm 使用 硬链接 来引用全局存储中的包,避免重复下载和存储。

  • 全局内容存储(Content Store)
    pnpm 将所有包存储在一个全局目录中(如 ~/.pnpm-store),每个包只保存一份。
  • 项目中使用硬链接
    项目 node_modules 中的依赖通过 硬链接 指向全局存储中的文件,不占用额外磁盘空间。
  • 扁平化结构 + 符号链接
    pnpm 使用 符号链接 构建依赖树,确保依赖可解析,同时避免“幻影依赖”(phantom dependencies)。

2. 内容可寻址存储(CAS)

包文件根据其内容生成唯一哈希值作为存储路径,确保:

  • 相同内容只存储一次
  • 文件完整性高(内容变化则哈希变化)
  • 支持离线安装(若包已存在于 store)

3. 严格的依赖结构(Strict Node Modules)

pnpm 构建的 node_modules扁平且严格的,只包含项目直接依赖和其子依赖的符号链接,不会提升无关包,从而:

  • 防止“幻影依赖”(即项目使用了未声明的依赖)
  • 提高依赖一致性
  • 减少 node_modules 体积

✅ 例如:A 依赖 B,B 依赖 C。pnpm 中 C 只在 B 的 node_modules 下,A 无法直接 require('C'),除非 A 显式声明依赖 C。


三、pnpm vs npm vs yarn:对比分析

特性pnpmnpmyarn (classic)
安装速度⚡️ 极快(硬链接)慢(复制文件)快(缓存)
磁盘占用💾 极小(全局 store)大(重复复制)较大(缓存+复制)
依赖结构✅ 严格、扁平❌ 提升依赖(幻影依赖)❌ 提升依赖
离线安装✅ 支持(store 存在即可)❌ 无缓存则失败✅ 支持
零安装(PnP)❌ 不支持❌ 不支持✅ yarn 2+ 支持
钩子脚本(hooks)✅ 支持 pnpmfile.js
工作区(Workspace)✅ 强大支持✅ npm 7+
兼容性✅ 完全兼容 npm registry

📌 结论:pnpm 在性能、磁盘效率和依赖安全方面全面领先。


四、快速上手:安装与基本使用

1. 安装 pnpm

# 使用 npm 安装(推荐首次安装)
npm install -g pnpm

# 或使用 corepack(Node.js 16.13+ 内置)
corepack enable
corepack prepare pnpm@latest --activate

# 验证安装
pnpm --version

2. 常用命令速查

命令说明
pnpm add <pkg>安装包(--save 默认)
pnpm add -D <pkg>安装为开发依赖
pnpm add -g <pkg>全局安装
pnpm remove <pkg>卸载包
pnpm install安装所有依赖
pnpm update更新依赖
pnpm run <script>运行 package.json 中的脚本
pnpm list查看已安装包
pnpm outdated检查过期依赖
pnpm audit安全漏洞扫描
pnpm doctor检查环境问题

3. 初始化项目

pnpm init
pnpm add vue react lodash  # 安装依赖
pnpm add -D typescript eslint  # 安装开发依赖

五、高级特性详解

1. 工作区(Workspaces)

pnpm 支持多包项目(monorepo),通过 pnpm-workspace.yaml 管理。

# pnpm-workspace.yaml
packages:
  - 'packages/*'
  - 'apps/*'
// packages/shared/package.json
{
  "name": "@myorg/shared",
  "version": "1.0.0"
}
// apps/web/package.json
{
  "dependencies": {
    "@myorg/shared": "workspace:*"
  }
}

使用 workspace:* 可本地链接包,无需发布即可开发调试。

2. 共享依赖存储(Shared Store)

所有项目共享同一个全局 store,默认路径:

  • macOS/Linux: ~/.pnpm-store
  • Windows: %LOCALAPPDATA%\pnpm-store

可通过 .npmrc 配置:

store-dir=/path/to/custom/store
  • 路径
    • macOS / Linux~/.npmrc (即 /Users/你的用户名/.npmrc 或 /home/你的用户名/.npmrc
    • WindowsC:\Users\你的用户名\.npmrc

3. pnpmfile.js:自定义行为

创建 pnpmfile.js 可拦截和修改安装行为(如替换包、重写版本)。

// pnpmfile.js
function readPackage(pkg) {
  // 将 lodash 替换为 lodash-es
  if (pkg.name === 'lodash') {
    pkg.name = 'lodash-es'
  }
  return pkg
}

module.exports = { readPackage }

4. 选择器(Selectors)与过滤器

在工作区中精确操作子包:

# 在所有包中运行构建
pnpm -r build

# 在名为 "web" 的包中安装依赖
pnpm add react --filter web

# 构建依赖图中 web 包及其依赖
pnpm build --filter web...

5. 离线模式与缓存

# 强制使用缓存(离线安装)
pnpm install --offline

# 查看缓存
pnpm store status

# 清理无效包
pnpm store prune

六、最佳实践与注意事项

✅ 推荐做法

  1. 新项目优先使用 pnpm
    • 性能高、节省磁盘、依赖安全。
  2. 启用工作区管理 Monorepo
    • 使用 pnpm-workspace.yaml 统一管理多包。
  3. 使用 pnpm-lock.yaml
    • 锁定依赖版本,确保团队一致性。
  4. 定期清理 store
    pnpm store prune  # 删除未使用的包
  5. 结合 pnpm-ctl 或 changesets 管理版本发布

⚠️ 注意事项

  1. 某些工具不兼容硬链接

    • 如 Docker 构建、CI/CD 中需注意文件系统支持。
    • 解决方案:使用 --shamefully-hoist(不推荐)或调整 CI 配置。
  2. 避免 shamefully-hoist

    • pnpm install --shamefully-hoist 会提升依赖,破坏严格性,仅用于兼容旧工具。
  3. IDE 支持

    • WebStorm、VS Code 均良好支持 pnpm。
    • 确保 TypeScript 路径解析正确。
  4. 迁移现有项目

    # 删除 node_modules 和 lock 文件
    rm -rf node_modules package-lock.json yarn.lock
    # 重新安装
    pnpm install

七、常见问题(FAQ)

Q1: pnpm 为什么更快?

  • 硬链接避免文件复制,CAS 缓存避免重复下载。

Q2: 能否与 npm/yarn 混用?

  • 可以,但不推荐。混用会导致多个 node_modules 和锁文件冲突。

Q3: 如何查看全局安装的包?

pnpm list -g --depth=0

Q4: 如何发布包?

与 npm 相同:

pnpm publish

八、总结

pnpm 是当前最高效、最节省资源的 Node.js 包管理工具,特别适合:

  • 大型项目或 Monorepo
  • 团队协作(依赖一致性高)
  • CI/CD 环境(安装快、缓存友好)
  • 本地开发(节省磁盘空间)

选择 pnpm 的理由:

  • ⚡️ 安装速度极快
  • 💾 磁盘占用极小
  • 🔒 依赖结构严格,避免幻影依赖
  • 🧩 工作区支持强大
  • 🔄 完全兼容 npm 生态

建议:无论是新项目还是老项目迁移,pnpm 都是当前最值得推荐的选择

### 使用 pnpm 包管理器的方法 pnpm 是一种高效的包管理工具,相较于 npm 和 yarn,在磁盘空间占用和性能方面有显著优势。以下是关于如何使用 pnpm 的详细介绍: #### 安装 pnpm 要开始使用 pnpm,首先需要安装它。可以通过以下命令全局安装 pnpm: ```bash npm install -g pnpm ``` 如果已经安装了 Node.js,也可以通过 npx 命令临时运行 pnpm 而无需全局安装: ```bash npx pnpm add <package-name> ``` #### 初始化项目并安装依赖 在一个新的 JavaScript 或 TypeScript 项目中,可以初始化 `package.json` 并安装所需的依赖项。 1. **初始化项目** 运行以下命令来创建一个新的 `package.json` 文件: ```bash pnpm init ``` 2. **安装生产环境依赖** 添加一个生产环境依赖到项目中: ```bash pnpm add <package-name> [^1] ``` 3. **安装开发环境依赖** 如果某些库仅用于开发阶段,则应将其标记为 devDependencies: ```bash pnpm add --dev <package-name> [^1] ``` 4. **安装可选依赖** 对于一些非必需的功能模块,可以选择性地安装它们: ```bash pnpm add --optional <package-name> ``` #### 更新和卸载依赖 随着项目的进展,可能需要更新或移除已有的依赖。 1. **更新依赖** 将指定的依赖升级至最新版本: ```bash pnpm update <package-name> ``` 2. **卸载依赖** 移除不再使用的依赖项: ```bash pnpm remove <package-name> ``` #### 强制使用 pnpm 为了确保团队成员都使用相同的包管理工具,可以在项目根目录下配置脚本以阻止其他工具(如 npm 或 yarn)被误用。具体操作如下: 1. 创建文件 `scripts/preinstall.js`,其内容如下: ```javascript if (!/pnpm/.test(process.env.npm_execpath || '')) { console.warn( '\u001b[33mThis repository must use pnpm as the package manager ' + 'for scripts to work properly.\u001b[39m\n' ); process.exit(1); } ``` 2. 修改 `package.json` 中的 `scripts` 字段,加入 preinstall 生命周期钩子: ```json "scripts": { "preinstall": "node ./scripts/preinstall.js" } ``` 当尝试使用 npm 或 yarn 执行安装时,上述逻辑会被触发,从而中断流程并提示错误消息[^5]。 #### 查看当前依赖树 pnpm 提供了一个清晰查看整个项目依赖关系的方式: ```bash pnpm list ``` 此命令能够帮助开发者理解各个依赖之间的层次结构以及潜在冲突情况。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chxii

小小打赏,大大鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值