实用pnpm的资料整理
缘起
之前做项目,对于打包工具并没有特别的讲究,也没空认真去研究它们的优劣。
总体上就是yarn用得多点,npm用得少一点,因为React是主力生态的缘故吧,好像还瞄到一篇文章说meta(当年Facebook)团队在研发过程中受不了低效的npm,于是开发了yarn的故事,后来当然就一致以yarn为主了。
后来Expo成熟了,我开发ReactNative的也开始首选Expo,这货的动不动就建议用npx,npx expo install
变成了主要的安装手段,倒也挺方便,此时我也没在意它其实是npm的执行工具。而且这货居然没有提供卸载的命令,于是在卸载包时又顺手yarn remove
。
这样,一个项目时间够久,变得够复杂的时候,往往什么工具都用了,反正电脑上至少有npm和yarn,碰到谁用谁(好多时候直接copy文档的你懂)。
近期看各种视频发现老外特别喜欢用pnpm
,看名字以为它无非是个变种的npm,开始没在意。直到今天想试试3.0后的nextra(之前版本确实稀烂,不摆了),虽然官方文档还是大量用yarn,但github README(上月更新)有这么一句:
The Nextra repository uses [PNPM Workspaces](https://pnpm.io/workspaces) and [Turborepo](https://github.com/vercel/turborepo). To install dependencies, run `pnpm install` in the project root directory.
我觉得确实要了解一下这个pnpm
了。
问AI
pnpm是什么,和yarn比有什么不同和优势?是否现在比较热门?
AI回答
pnpm (performant npm) 是一个现代的包管理器,在2024年确实非常热门。以下是主要特点和与yarn的对比:
主要优势:
- 磁盘空间利用
- pnpm: 使用硬链接和内容寻址存储,所有版本的依赖包只会在硬盘上存储一次
- yarn: 每个项目都会复制依赖包到自己的node_modules
- 安装速度
- pnpm: 通常比yarn和npm快2-3倍
- yarn: 比npm快,但不如pnpm
- 依赖管理:
- pnpm: 使用符号链接创建非扁平的node_modules结构,更严格的依赖管理
- yarn: 使用扁平化的依赖树,可能导致"幽灵依赖"问题
- 性能对比:
操作 pnpm yarn npm
初次安装 31s 42s 55s
重复安装 3s 7s 12s
磁盘占用 0.8GB 1.3GB 1.3GB
- 特色功能:
- 内置monorepo支持
- 更快的依赖解析
- 更好的安全性
- 支持side-effects标记
- 工作空间协议支持
使用趋势:
2022: 14% 使用率
2023: 28% 使用率
2024: 35%+ 使用率(预计)
基本命令对比:
# 安装依赖
pnpm install
yarn install
# 添加包
pnpm add [包名]
yarn add [包名]
# 删除包
pnpm remove [包名]
yarn remove [包名]
# 运行脚本
pnpm [脚本名]
yarn [脚本名]
选择建议:
- 新项目建议使用pnpm
- 现有项目若无特殊需求可继续使用yarn
- monorepo项目强烈推荐pnpm
- 对磁盘空间要求高的场景选pnpm
总的来说,pnpm正在成为前端工程化的首选包管理器,特别适合现代前端开发需求。
***以上回答,除了说明这个工具性能很高外,重点还 省空间(每个项目的node_modules都是黑洞啊)。使用符号链接创建非扁平的node_modules结构真的太重要了,我macbook可怜的512G硬盘...😭。
在中国大陆,pnpm是否也需要镜像包设置?
这个问题很实用,我帮大家问了。
AI回答
是的,在中国使用pnpm也需要设置镜像源以提升下载速度。以下是常用的设置方法:
- 临时使用镜像
pnpm install package-name --registry=https://registry.npmmirror.com
- 永久设置镜像(推荐)
# 设置淘宝镜像
pnpm config set registry https://registry.npmmirror.com
# 查看当前镜像
pnpm config get registry
- .npmrc 文件配置(项目级别)
registry=https://registry.npmmirror.com
常用的国内镜像源:
淘宝:https://registry.npmmirror.com
腾讯:https://mirrors.cloud.tencent.com/npm/
华为:https://mirrors.huaweicloud.com/repository/npm/
- 使用工具切换源
# 安装 nrm
pnpm install -g nrm
# 查看可用源
nrm ls
# 切换到淘宝源
nrm use taobao
# 测试速度
nrm test
- 对于私有包可以设置作用域
@company:registry=http://your-private-registry.com
registry=https://registry.npmmirror.com
注意事项:
- 建议团队统一使用相同的镜像源
- CI/CD环境也需要配置镜像
- 私有包和公共包可以使用不同的源
- 某些包可能需要使用原始npm源
***这其实和其他包管理工具原理一样。
如果我的mac上已经安装了npm, yarn,现在要用pnpm是否需要把这些工具卸载,并清理之前的库、缓存?
明知故问的傻问题,可见我有多迫不及待了😂。
AI回答
不需要卸载npm和yarn,它们可以共存。但建议清理一下缓存以节省空间。以下是具体步骤:
- 安装pnpm
# 使用npm安装
npm install -g pnpm
# 或使用官方推荐的安装脚本
curl -fsSL https://get.pnpm.io/install.sh | sh -
# 验证安装
pnpm --version
- 清理旧缓存(可选)
# 清理npm缓存
npm cache clean --force
# 清理yarn缓存
yarn cache clean
# 清理pnpm缓存
pnpm store prune
- 查看全局包(可选迁移)
# 查看npm全局包
npm list -g --depth=0
# 查看yarn全局包
yarn global list
# 用pnpm重新安装需要的全局包
pnpm add -g package-name
- 常见目录位置
# npm全局包位置
~/node_modules
/usr/local/lib/node_modules
# yarn全局缓存
~/.yarn
# pnpm存储位置
~/.pnpm-store
建议操作:
- 保留npm(因为它是Node.js自带的)
- 按项目使用包管理器:
- 新项目使用pnpm
- 已有项目保持原有的包管理器
- 在package.json中添加限制(可选):
{
"scripts": {
"preinstall": "npx only-allow pnpm"
}
}
不建议的操作:
- 强制卸载npm(可能影响Node.js运行)
- 在同一项目中混用不同的包管理器
- 手动删除node_modules目录(使用清理命令更安全)
省空间啊,强迫症啊😆
如果是一个旧项目,之前用npm和yarn,现在想用pnpm怎么做?
我还想拯救一下之前的...
AI回答
这里删除n个字 大致上就是迁移,很麻烦的,算了。
还是新项目再说,老的不照顾了。
用pnpm是否就没有node-modules目录了?
我知道这又一个傻问题,其实前面都说过 。
AI回答
使用 pnpm 时仍然会有 node_modules 目录,但其结构和工作方式与 npm/yarn 有很大不同:
- 结构差异:
- pnpm 创建的 node_modules 是符号链接(symlinks)的集合
- 实际的依赖包存储在全局内容寻址存储中(通常在 ~/.pnpm-store)
- node_modules 中的包是扁平化的,但使用符号链接保持了正确的依赖树结构
- 主要优势:
- 节省磁盘空间:相同的依赖包只会在全局存储中保存一次
- 更快的安装速度:复用已经下载的包
- 避免依赖地狱:严格的依赖树结构
- 实际目录结构示例:
node_modules
├── .pnpm/ (包含实际的依赖包)
├── your-project-deps -> .pnpm/your-project-deps/
└── package -> .pnpm/package@version/node_modules/package
所以总结:pnpm 确实有 node_modules 目录,但它是以符号链接方式组织的,更加高效且节省空间。
用最新的expo sdk52新建一个项目,如何保证这个项目完全采用pnpm安装依赖
我觉得这是个好问题,涉及到管理思路。
AI回答
要使用 pnpm 创建和管理 Expo SDK 52 项目,可以按以下步骤操作:
- 首先创建项目,使用
pnpm dlx
替代npx
:
bash
複製
pnpm dlx create-expo-app@latest my-app
- 进入项目目录:
bash
複製
cd my-app
- 创建
.npmrc
文件确保只使用 pnpm:
bash
複製
echo "engine-strict=true" > .npmrc
echo "auto-install-peers=true" >> .npmrc
- 修改 package.json,添加 engines 限制:
json
複製
{
"engines": {
"node": ">=18.0.0",
"pnpm": ">=8.0.0"
},
"packageManager": "pnpm@8.x"
}
- 创建
.gitignore
(如果还没有):
bash
複製
echo "node_modules
.pnpm-store
.expo/
dist/
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
.DS_Store" > .gitignore
- 安装依赖:
bash
複製
pnpm install
- 使用 pnpm 运行脚本:
bash
複製
pnpm start
# 或
pnpm android
# 或
pnpm ios
- 后续添加新依赖时:
bash
複製
pnpm add package-name # 添加生产依赖
pnpm add -D package-name # 添加开发依赖
这样设置后,项目就会强制使用 pnpm,其他人克隆项目后也只能使用 pnpm 安装依赖。
追问:以后安装组件,是否不能再用npx expo install?
AI
正确。使用 pnpm 管理项目时,应该替换所有的 npx
命令为 pnpm dlx
。对于 Expo 项目,安装组件的命令应该这样使用:
- 替代
npx expo install
,使用:
bash
複製
pnpm add [package-name]
例如安装 react-navigation:
bash
複製
pnpm add @react-navigation/native @react-navigation/native-stack
- 对于 Expo 特定的包,同样使用
pnpm add
:
bash
複製
pnpm add expo-camera
pnpm add expo-location
pnpm add expo-sensors
- 运行 Expo 命令时:
bash
複製
pnpm dlx expo start
pnpm dlx expo doctor
pnpm dlx expo install
建议:
- 将常用的 Expo 命令添加到 package.json 的 scripts 中,这样可以直接使用
pnpm
运行:
json
複製
{
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
}
}
然后就可以用 pnpm start
, pnpm android
等命令运行项目。
接着问:用其他npx命令也不行吗?比如:npx expo start
虽然 npx expo start
技术上可以运行,但在使用 pnpm 管理的项目中不推荐使用 npx,原因如下:
- 混合使用包管理器可能导致:
- 依赖树不一致
- 缓存冲突
- node_modules 结构混乱
- 项目行为不可预测
- 正确的做法:
直接使用项目中定义的 scripts:
pnpm start # 如果在 package.json 中定义了 scripts
或使用 pnpm dlx:
pnpm dlx expo start
- 最佳实践是在 package.json 中定义所有需要的命令:
{
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"doctor": "expo doctor",
"prebuild": "expo prebuild"
}
}
这样团队成员都会使用统一的命令,保持项目的一致性。如果一定要使用 npx,最好在项目文档中说明原因,避免混淆。
看来我要改变习惯了。
npx这个工具,是否expo官方建议?其本质和npm/yarn有关系吗?
结果AI的回答升华了。
npx 是 npm 的一部分,以下是详细解释:
- npx 的本质:
- npx 是 npm 5.2+ 版本后自带的工具
- 它是 npm 的一个包执行器
- 主要用于执行一次性命令或本地未安装的包
- 与包管理器的关系:
- npm:npx 是 npm 的官方工具
- yarn:有自己的执行器
yarn dlx
- pnpm:有自己的执行器
pnpm dlx
- Expo 官方立场:
- Expo 文档中大量使用 npx 是因为 npm 是最广泛使用的包管理器
- Expo 实际上支持所有主流包管理器(npm、yarn、pnpm)
- 在文档中使用 npx 主要是为了简化说明
- 各包管理器的命令对比:
# npm 生态
npx expo start
# yarn 生态
yarn dlx expo start
# pnpm 生态
pnpm dlx expo start
- 建议做法:
- 选定一个包管理器后就坚持使用它的生态系统
- 使用 pnpm 就始终使用
pnpm dlx
- 使用 yarn 就始终使用
yarn dlx
- 使用 npm 就始终使用
npx
所以 npx 不是 Expo 特有的工具,而是 npm 生态系统的一部分。Expo 官方文档使用 npx 主要是因为它的普及度最高。
这里讲到的从一而终,是本文要点之一👍
bun和pnpm区别,各自优劣?expo项目用哪个好?
AI
以下是 Bun 和 pnpm 的主要区别和比较:
优势对比:
Bun:
- 性能极快,包安装和项目启动速度远超 npm/yarn/pnpm
- 内置了运行时环境,可直接运行 JavaScript/TypeScript
- 内置了打包器、测试运行器等开发工具
- 内存占用更少
- 目前仍处于发展阶段,生态不够成熟
pnpm:
- 采用硬链接机制节省磁盘空间
- 更严格的依赖管理,避免幽灵依赖
- 生态成熟,兼容性好
- monorepo 项目支持优秀
- 社区验证充分,稳定性好
对于 Expo 项目的选择建议:
目前推荐使用 pnpm,原因是 :
- Expo 生态主要基于 Node.js,pnpm 与其完全兼容
- Expo 项目依赖较多,pnpm 的依赖管理更可靠
- Bun 对某些原生模块支持还不够完善
- pnpm 的稳定性更有保障
如果你特别在意开发环境的速度,可以尝试 Bun,但要注意可能遇到兼容性问题。
如用npx create expo项目,对以后本项目的pnpm包管理会不会有负面影响?
因为pnpm create expo@latest my-app总是失败(网络问题),故问。
AI
使用 npx create-expo-app@latest 创建项目不会对后续使用 pnpm 管理项目造成负面影响,原因是:
- 项目创建工具(create-expo-app)和包管理器(pnpm)是相互独立的
- 创建完项目后,你可以:
# 删除原有的 package-lock.json 或 yarn.lock(如果有)
rm -f package-lock.json yarn.lock
# 创建 .npmrc 确保兼容性
echo "node-linker=hoisted" > .npmrc
# 用 pnpm 重新安装所有依赖
pnpm install
之后就可以正常使用 pnpm:
pnpm add
添加依赖pnpm remove
删除依赖pnpm start
启动项目pnpm run xxx
运行脚本
注意事项:
- 确保 package.json 中的 scripts 部分使用的是通用命令
- 如果发现任何异常,可以删除 node_modules 后重新
pnpm install