PNPM 是 NPM 的替代产品,相对于 NPM 来说,最大的特点是提供了可靠的 Monorepo
支持
Monorepo 是一种使用单一仓库来统一管理依赖的理念
,使用传统 NPM 时,我们不得不在每个项目目录重复下载安装相同的依赖到 node_modules 下,而支持 Monorepo 的包管理器可通过文件系统链接的方式,将项目需要的依赖链接到本地仓库中已经存在的目录,这样即节省了磁盘空间,也减少了不必要的下载,提高了安装速度
但是,PNPM 并非简单的将 NPM node_moudles 下的依赖进行链接,而是使用了一种称为平坦化依赖
的机制
对于传统 NPM,在 NPM2 时代,不同包的依赖在自己包路径下的 node_modules 中,相同依赖会重复占用,并且造成依赖嵌套很深。NPM3 对 NPM2 进行了优化,即树形依赖扁平化,全部依赖提取到顶层 node_modules 目录,这样也有一些的缺点,如使项目本身的 node_modules 结构不够直观,有些 package.json 中并没有声明但由于被某模块依赖而引入的包也可以在编码时引入使用,造成依赖不安全
PNPM 中所有被声明的依赖存放在 node_modules 下,以软链接
形式链接到到 node_modules/.pnpm/[package_name]@version/node_modules/[package_name]
如图(来源 PNPM 官网),项目使用 express 的 4.17.3 版本,该包的所有依赖都在 .pnpm/express@4.17.3
下
而 .pnpm/express@4.17.3
下的文件是以硬链接
方式链接到 PNPM strore 目录下依赖,避免重复下载和占用
当本机不存在 NPM 环境,可使用命令行直接安装
# windows(powershell)
iwr https://get.pnpm.io/install.ps1 -useb | iex
# linux
curl -fsSL https://get.pnpm.io/install.sh | sh -
Windows 下,此方式安装的 pnpm.exe 默认安装路径一般为
~\AppData\Local\pnpm
中
当本机存在 NPM 环境,可使用 npm 命令安装
npm install -g pnpm
Node 与 PNPM 版本兼容性表
Node.js | pnpm 7 | pnpm 8 | pnpm 9 |
---|---|---|---|
Node.js 12 | ❌ | ❌ | ❌ |
Node.js 14 | ✔️ | ❌ | ❌ |
Node.js 16 | ✔️ | ✔️ | ❌ |
Node.js 18 | ✔️ | ✔️ | ✔️ |
Node.js 20 | ✔️ | ✔️ | ✔️ |
使用 pnpm -v 命令查看版本号,验证是否安装成功
路径相关配置
PNPM 会使用 .npmrc 文件中的配置,同样也有自己全局的配置文件,默认位于
# Windows
~/AppData/Local/pnpm/config/rc
# Linux
~/.config/pnpm/rc
可以在配置文件中通过key=value
方式来配置
# pnpm
global-bin-dir=D:\lib\pnpm-store
global-dir=D:\lib\pnpm-store\global
cache-dir=D:\lib\pnpm-store\cache
state-dir=D:\lib\pnpm-store\state
store-dir=D:\lib\pnpm-store\store
也可以使用命令配置
# 基本目录、可执行文件目录
pnpm config set global-bin-dir=D:\lib\pnpm-store
# 全局包目录
pnpm config set global-dir=D:\lib\pnpm-store\global
# 缓存目录
pnpm config set cache-dir=D:\lib\pnpm-store\cache
# 状态文件目录
pnpm config set state-dir=D:\lib\pnpm-store\state
# 依赖包文件目录
pnpm config set store-dir=D:\lib\pnpm-store\store
环境变量配置
配置PNPM_HOME
,推荐和上面的global-bin-dir
一致
配置PATH
,加入PNPM_HOME
对应的路径
安装
# 默认安装
pnpm i
# 从离线仓库安装
pnpm i --offline
# 安装不更新 lock 文件
pnpm i --frozen-lockfile
# 仅更新 lock 文件
pnpm i --lockfile-only
# 按扁平 node_modules 类似的结构安装
pnpm i --shamefully-hoist
添加
# 保存到 dependencies
pnpm add [package]
# 保存到 devDependencies
pnpm add -D [package]
# 保存到 optionalDependencies
pnpm add -O [package]
# 全局安装
pnpm add -g [package]
# 从 next tag 下安装
pnpm add [package]@next
# 安装指定版本
pnpm add [package]@[version]
更新
# 遵循 package.json 指定的范围更新所有的依赖项
pnpm up
# 更新所有依赖项,此操作会忽略 package.json 指定的范围
pnpm up --latest
# 更新到 version 版本
pnpm up [package]@[version]
# 更新 @babel 范围内的所有依赖项
pnpm up "@babel/*"
删除
pnpm rm [package]
# 从全局删除一个依赖包
pnpm rm [package] --global, -g
# 仅删除开发环境 `devDependencies` 中的依赖项
pnpm rm [package] --save-dev, -D
# 仅移除 `optionalDependencies` 中的依赖项
pnpm rm [package] --save-optional, -O
# 仅从 `dependencies` 中删除相关依赖项
pnpm rm [package] --save-prod, -P
PNPM 提供了pnpm env
命令,用于统一管理 Node 版本
# 安装 Node.js 的 LTS 版本
pnpm env use --global lts
# 安装 Node.js v16
pnpm env use --global 16
# 安装最新版本的 Node.js
pnpm env use --global latest
# 安装指定版本的 Node.js,而不将其激活为当前版本
pnpm env add --global lts 18 20.0.1
# 移除指定版本的 Node.JS
pnpm env remove --global 14.0.0
pnpm env remove --global 14.0.0 16.2.3
# 打印本地安装的版本
pnpm env list
# 打印远程可用的 Node.js 版本
pnpm env list --remote
# 打印远程可用的 Node.js v16 版本
pnpm env list --remote 16
Node 存放在环境变量PNPM_HOME
配置的路径
当前 Node 的链接目录在PNPM_HOME
的nodejs_current
,需要加入到环境变量中
注意调整
nodejs_current
在环境变量中优先顺序,防止系统中本来就存在 Node、NVM 等,由于优先级问题,PNPM 管理的 Node 没有生效