pnpm
yuhuo2023-09-21JavaScriptNodeJs
参考链接
前言
pnpm 主要解决 npm 和 yarn 遗留的问题:
- 幽灵依赖:A 依赖 B,B 依赖 C,A 没有直接依赖 C 却可以引用 C;
- 依赖分身:A 依赖 B@1、C 和 D,同时 C 和 D 依赖 B@2,那 B@2 就会在 C 和 D 的模块下重复安装;
pnpm 引入了另一套依赖管理策略:内容寻址存储。
该策略会将包安装在系统的全局 store 中,依赖的每个版本只会在系统中安装一次。
在引用项目 node_modules 的依赖时,会通过硬链接与符号链接在全局 store 中找到这个文件。为了实现此过程,node_modules 下会多出 .pnpm
目录,而且是非扁平化结构。
node_modules
├── .pnpm
│ ├── A@1.0.0
│ │ └── node_modules
│ │ ├── A => <store>/A@1.0.0
│ │ └── B => ../../B@1.0.0
│ ├── B@1.0.0
│ │ └── node_modules
│ │ └── B => <store>/B@1.0.0
│ ├── B@2.0.0
│ │ └── node_modules
│ │ └── B => <store>/B@2.0.0
│ └── C@1.0.0
│ └── node_modules
│ ├── C => <store>/C@1.0.0
│ └── B => ../../B@2.0.0
│
├── A => .pnpm/A@1.0.0/node_modules/A
└── C => .pnpm/C@1.0.0/node_modules/C
pnpm 也存在一些弊端:
- 在不支持软链接的环境中,无法使用 pnpm,比如 Electron 应用;
- 不同项目的依赖是硬链接到同一份文件,如果在调试时修改了文件,有可能会无意中影响到其他项目;
安装
npm install yarn -g
-v
# 查看 pnpm 版本
pnpm -v
config
# 配置 pnpm 全局包目录
pnpm config set global-dir "D:\Software\NodeJs\pnpm\global"
# 配置 pnpm 全局包的 bin 目录(还需要将该目录添加到环境变量 Path 中)
pnpm config set global-bin-dir "D:\Software\NodeJs\pnpm\global_bin"
# 配置 pnpm 全局存储目录(项目包的实际存储位置)
pnpm config set store-dir "D:\Software\NodeJs\pnpm\store"
# 配置 pnpm 缓存目录
pnpm config set cache-dir "D:\Software\NodeJs\pnpm\cache"
# pnpm-state.json文件目录
pnpm config set state-dir "D:\Software\NodeJs\pnpm\state"
# 配置仓库路径
# 默认仓库 https://registry.npmjs.org 下载缓慢,可以改为淘宝镜像仓库
npm config set registry https://registry.npmmirror.com
# 查看当前配置
npm config list
# 查看指定配置
npm config get <configName>
# 删除指定配置
npm config delete <configName>
init
# 直接创建默认 package.json
pnpm init
run
# 查看 pakage.json 下的所有 scripts 脚本
pnpm run
# 运行指定 scripts 脚本
pnpm run <task-name>
# run 可以直接省略
pnpm <task-name>
install
# 全局包,安装至全局包目录下的 node_modules,可全局使用对应命令行
pnpm install <name> -global
# npm 也可以安装不同版本 npm
pnpm install npm -global
# (注:项目包,统一安装至当前目录下的 node_modules 文件夹)
# 安装 package.json 里的指定版本的所有包,生成 workspaces 字段指定的子包软链接
pnpm install
# (注:安装时已存在不同版本会覆盖,相同版本不处理)
# 运行依赖包安装,写入 package.json 的 dependencies 字段
pnpm install <name>
pnpm install <name> --save
# 开发依赖包安装,写入 devDependencies 字段
pnpm install <name> --save-dev
# 安装无标签最高版本的包
pnpm install <name>
# 安装指定版本的包
pnpm install <name>@<version>
# 安装指定标签最高版本的包
pnpm install <name>@<tag>
简写
install
=>i
--global
=>-g
--save
=>-S
--save-dev
=>-D
uninstall
# 卸载指定包
yarn uninstall <name>
list
# 查看当前项目包依赖
npm list
# 查看全局包依赖
npm list -g
# 查看指定包
npm list <name>
简写
list
=>ls
--global
=>-g
info / view / show
查看 npm 仓库包
# 查看详细信息
pnpm info <name>
pnpm view <name>
pnpm show <name>
# 查看最新版本
pnpm info <name> version
pnpm view <name> version
pnpm show <name> version
# 查看历史版本
pnpm info <name> versions
pnpm view <name> versions
pnpm show <name> versions
简写
view
=>v
outdated / update
# 查看需要更新的包
pnpm outdated
# 更新所有需要更新的包
pnpm update
# 更新指定包
pnpm update <name>
publish / unpublish
# 发布包
pnpm publish
# 发布带自定义标签名的包
pnpm publish --tag beta
# 发布 @name/package 类型的包,默认是私有包,需要指定为公开包
pnpm publish --access public
# 卸载当前项目version字段指定版本的发布包
pnpm unpublish --force
// package.json
{
// commonjs模块类型的入口文件,被 require('moduleName') 时加载
"main": "dist/index.js",
// module模块类型的入口文件,被 import xx from 'moduleName' 时加载
"module": "dist/index.js",
// npm发布的文件白名单
"files": [
"dist"
],
}
store
# 从存储中删除未被引用的包
pnpm store prune
# 查看存储中被过修改的包
pnpm store status
# 查看存储的路径
pnpm store path
# 往存储中添加一个包
pnpm store add <name>
monorepo
在根目录下配置 pnpm-workspace.yaml
文件,标志当前项目为 monorepo 项目。
packages:
- "packages/*"
在 A 子包中引用了 B 子包,也需要在 A 子包中像对其他第三方包一样安装和引用 B 子包。此时 A 子包的 node_modules
中就会出现 B 子包的软链接。
同时在引用时,TS 会报路径错误,需要配置一下 tsconfig.json
文件:
{
"compilerOptions": {
"paths": {
// 假设子包都是 @yho-vue/ 开头,
// 引用到子包时,则映射到对应文件夹 src 目录
"@yho-vue/*": ["./packages/*/src"]
}
},
}
安装命令
# 在根目录安装依赖包
pnpm install <name> --workspace-root
# 指定子包安装依赖包(或者直接进入子包中,正常安装无须参数)
pnpm install <name> --filter <son-package>
# 在所有子包安装依赖
pnpm install <name> --filter *
# 其他操作(如 uninstall)也是相同参数,不再列举
简写
--filter
=>-F
--workspace-root
=>-w