一文搞懂pnpm、npm、yarn、npx

1,173 阅读7分钟

在现代 JavaScript 开发中,包管理器(Package Manager)是不可或缺的工具,它们用于管理项目的依赖、包的安装和执行命令等。常见的包管理工具包括 npmyarnpnpm,以及 npx(一个命令行工具)。

一、npm(Node Package Manager)

1.1 npm 概述

npm 是 Node.js 的官方包管理器,也是全球使用最广泛的 JavaScript 包管理工具。它用于管理 JavaScript 项目的依赖包,可以通过命令行来安装、更新、卸载依赖包。

  • 默认情况下,npm 通过 package.json 文件管理项目的依赖,node_modules 目录存放实际的依赖包。
  • npm 支持语义化版本控制(semver),确保项目依赖版本的兼容性。
  • npm 是 Node.js 的默认包管理工具,几乎每个 Node.js 项目都可以用 npm 来管理依赖。

1.2 npm 的优缺点

优点:

  • 广泛使用:是 Node.js 官方推荐的包管理工具,支持全球最大的 JavaScript 包生态。
  • 易于使用npm 命令简单直观,开发者易于上手。
  • 持续更新npm 社区活跃,定期发布新版本,提供新的功能和修复。

缺点:

  • 性能问题:在处理大量依赖时,npm 的安装速度较慢,尤其是依赖树过深时。
  • 冗余依赖npm 默认会安装很多重复的依赖包,导致磁盘空间浪费。

1.3 npm 使用示例

# 安装所有依赖
npm install

# 安装某个包
npm install <package-name>

# 安装某个包的特定版本
npm install <package-name>@<version>

# 删除某个依赖包
npm uninstall <package-name>

# 运行项目中的脚本命令
npm run <script-name>

二、yarn

2.1 yarn 概述

yarn 是由 Facebook 发起的包管理工具,目的是解决 npm 的一些性能和依赖管理问题。yarn 在安装速度、离线安装和一致性方面做了显著优化。

  • yarn 提供了更高效的依赖安装方式,采用并行安装并且支持缓存,能显著提升安装速度。
  • yarn.lock 文件确保所有团队成员安装的依赖版本一致,避免版本冲突。
  • 支持离线安装,在没有网络的情况下仍然能够安装已经缓存的依赖。

2.2 yarn 的优缺点

优点:

  • 安装速度快:通过并行下载和离线缓存,yarn 提供了比 npm 更快的安装速度。
  • 一致性好yarn.lock 锁定所有包的确切版本,确保跨环境一致性。
  • 离线缓存:依赖包下载后会缓存,可以在无网络环境下再次使用。
  • 多仓库支持:支持 Monorepo(多个包的仓库管理),适用于管理大型项目。

缺点:

  • 与 npm 的兼容性问题:虽然大多数功能兼容,但在某些情况下,npmyarn 的行为有所不同。
  • 较新的工具:虽然已经被广泛使用,但相比 npmyarn 的社区和文档支持稍显不足。

2.3 yarn 使用示例

# 安装所有依赖
yarn install

# 安装某个包
yarn add <package-name>

# 安装某个包的特定版本
yarn add <package-name>@<version>

# 删除某个依赖包
yarn remove <package-name>

# 更新依赖包
yarn upgrade

三、pnpm

3.1 pnpm 概述

pnpm 是一个高效的 JavaScript 包管理器,旨在解决 npmyarn 在磁盘空间使用和依赖安装方面的问题。pnpm 引入了硬链接技术,通过避免重复安装相同的依赖包,显著节省了磁盘空间。

  • pnpm 使用硬链接来共享依赖,在多个项目中共用同一个版本的依赖,减少了磁盘空间浪费。
  • pnpm 强制每个包只能访问其直接依赖,避免了隐式依赖问题。

3.2 pnpm 的优缺点

优点:

  • 磁盘空间优化:通过硬链接共享依赖,显著节省了磁盘空间。
  • 高效的依赖管理:依赖安装速度快,尤其是在多个项目共享依赖时表现优秀。
  • 强制封闭依赖:避免隐式依赖,提高了依赖管理的可靠性。

缺点:

  • 学习曲线较陡:由于其依赖管理方式不同,可能需要时间适应。
  • 生态相对较小:相比 npmyarnpnpm 的社区较小,某些第三方工具的兼容性可能较差。

3.3 pnpm 使用示例

# 安装所有依赖
pnpm install

# 安装某个包
pnpm add <package-name>

# 安装某个包的特定版本
pnpm add <package-name>@<version>

# 删除某个依赖包
pnpm remove <package-name>

# 更新依赖包
pnpm update

四、npx

4.1 npx 概述

npx 是一个由 npm 提供的工具,用于直接运行 node_modules/.bin 中的可执行文件,而不必在全局安装依赖。npx 实际上是 npm 5.2+ 版本中新增的命令行工具,允许开发者运行任何命令而无需显式安装。

  • npx 可以临时运行安装在项目中的命令(即便这些命令没有全局安装),也可以运行 GitHub 上的命令或者从 npm 注册表中直接运行包。
  • npx 可以用来快速执行脚本,如运行项目中的构建工具、脚本命令等。

4.2 npx 的优缺点

优点:

  • 无需全局安装包:使用 npx,可以临时运行包中的命令,而无需在全局安装包。
  • 减少依赖冗余:避免全局安装大量工具,保持环境清洁。
  • 方便快捷npx 直接执行命令,无需额外配置。

缺点:

  • 需要较新的 npm 版本npx 仅在 npm 5.2+ 版本中可用。
  • 命令可能复杂:如果没有很好地理解 npx 的工作原理,可能会误用。

4.3 npx 使用示例

# 运行一个本地安装的包的命令
npx <package-name>

# 运行特定版本的包
npx <package-name>@<version>

# 直接运行 GitHub 上的脚本
npx github:<owner>/<repo>

五、npmyarnpnpmnpx 对比总结

特性npmyarnpnpmnpx
安装方式使用 npm install 安装依赖使用 yarn install 安装依赖使用 pnpm install 安装依赖临时执行包中的命令,不需要安装全局依赖
安装速度较慢,依赖树较深时效率较低快,支持并行安装和缓存非常快,使用硬链接和共享依赖运行时自动下载依赖,不需要安装
磁盘空间使用重复依赖,占用较多磁盘空间缓存依赖,但依赖安装较多时仍会占用一定磁盘空间通过硬链接减少重复安装,节省磁盘空间不占用磁盘空间,仅临时运行命令
锁定依赖版本使用 package-lock.json 锁定版本使用 yarn.lock 锁定版本使用 pnpm-lock.yaml 锁定版本不锁定版本,运行时临时安装和执行命令
依赖管理默认安装多份重复依赖(有冗余)安装时尽量避免冗余依赖强制封闭依赖,避免隐式依赖无依赖管理,直接执行命令
兼容性与大部分工具和社区兼容npm 兼容,但存在部分差异npmyarn 不完全兼容,特别是在依赖管理方式上依赖于 npm,通过 npx 直接执行命令
离线支持不完全支持离线安装支持离线安装,缓存安装过的包完全支持离线安装,依赖缓存共享不需要离线安装,运行时自动下载依赖
适用场景适用于大部分 Node.js 项目适合需要高性能和一致性保证的项目适合需要优化磁盘空间和性能的大型项目快速执行单次命令,无需全局安装依赖
社区和支持最大的社区支持,生态最广泛被许多大公司采用,尤其适合 Monorepo 管理生态较小,但专注于性能和空间优化npm 的一部分,功能简单实用

主要差异总结:

  • npm:广泛使用且成熟,适合大部分项目,但安装速度和磁盘空间管理较差。
  • yarn:性能优于 npm,尤其在并行安装和离线支持方面,适合需要版本一致性的团队协作项目。
  • pnpm:通过硬链接节省磁盘空间,优化了安装速度,特别适合大型项目或多个项目共享依赖的情况。
  • npx:用于临时执行命令或包,不需要全局安装,适用于单次执行而不需要管理依赖的场景。