要点速览
- 只要保留 package.json 和锁文件,删除 node_modules 就是安全的;npm ci 或 pnpm install 会装回完全相同的版本。
- 带 -prune 的 find 命令可以列出个人文件夹中的每个 node_modules 文件夹及其大小,且不会深入嵌套的文件夹。
- npx npkill 让你以交互方式浏览并删除 node_modules 文件夹,但它会立即删除,不经过废纸篓。
- 使用 pnpm 时,node_modules 中的文件是共享存储的克隆或硬链接,所以在运行 pnpm store prune 之前,删除它们释放不了多少空间。
- .next、.turbo、.nuxt、.svelte-kit 和 .parcel-cache 等构建文件夹会自动重建,同样可以放心移除。
如何在 Mac 上查找并清理 node_modules 文件夹
- 列出 node_modules 文件夹及其大小. 对个人文件夹运行 find 命令,跳过 ~/Library 和废纸篓,在每个顶层 node_modules 处停止,再把结果交给 du -sh。
- 挑出你目前没有在做的项目. 确认每个项目都有 package.json 和锁文件,例如 package-lock.json、pnpm-lock.yaml、yarn.lock 或 bun.lock。保留这些文件。
- 删除它们的 node_modules 文件夹. 在访达中把每个 node_modules 文件夹移到废纸篓,或用 npx npkill 以交互方式删除;后者会永久删除。
- 清理包管理器缓存. 根据你使用的包管理器,运行 npm cache clean --force、pnpm store prune、yarn cache clean 或 bun pm cache rm。
- 回到项目时重新安装. 在项目文件夹中运行 npm ci、pnpm install、yarn install 或 bun install,按锁文件恢复 node_modules。
node_modules 文件夹保存着为某个 JavaScript 或 TypeScript 项目安装的依赖,一个典型的 node_modules 有几百 MB。旧项目一多,它们很容易累积到几十 GB。只要保留 package.json 和锁文件,它们就可以放心删除:当你回到项目时,包管理器会重新安装相同的版本。
找出每个 node_modules 文件夹及其大小
这条命令会搜索你的个人文件夹,跳过 ~/Library 和废纸篓,列出每个 node_modules 文件夹及其大小,最大的排在最后:
find ~ \( -path "$HOME/Library" -o -path "$HOME/.Trash" \) -prune -o -type d -name node_modules -prune -print0 2>/dev/null | xargs -0 du -sh 2>/dev/null | sort -h
原理是这样的:第一个 -prune 跳过两个排除的文件夹,-type d -name node_modules 匹配目标文件夹,第二个 -prune 阻止 find 深入其中,因此嵌套的 node_modules 只会在其上层文件夹中计算一次。du -sh 测量每个文件夹的大小,sort -h 给列表排序。这条命令只读取。个人文件夹很大时,可能需要几分钟,“终端”也可能请求访问“文稿”、“桌面”或“下载”。
位于 ~/.nvm、~/.vscode 或 ~/.cursor 等工具文件夹中的结果可以忽略。它们属于已安装的工具和编辑器扩展,而不是你的项目。
如果你的项目使用 pnpm,显示的大小会比实际能收回的空间大。原因见下文。
删除不需要的文件夹
删除之前,打开项目文件夹,确认其中有锁文件:package-lock.json(npm)、pnpm-lock.yaml(pnpm)、yarn.lock(Yarn)或 bun.lock / bun.lockb(Bun)。保留它,也保留 package.json。
最安全的删除方法是在访达中把 node_modules 拖到废纸篓。在清倒废纸篓之前,你仍然可以反悔。小文件很多时,移到废纸篓需要一点时间。
在“终端”中,进入某个项目文件夹后:
cd ~/Projects/old-app
rm -rf node_modules
rm -rf 会永久删除,不经过废纸篓。请先用 pwd 确认当前所在的文件夹,并且绝不要搭配通配符或空变量运行它。
npkill:交互式的替代方案
npkill 会列出 node_modules 文件夹及其大小,让你按一下键就删除一个:
npx npkill -d ~/Projects
-d 用于设置搜索的起点;不加的话,npkill 从当前文件夹开始。用方向键移动,按空格键或 Del 键删除所选文件夹。npkill 会立即删除,不经过废纸篓。它会用 ⚠️ 标出 App 运行所需的文件夹,这些应当保持原样。如果想先试试,可以用 --dry-run 模拟删除。
回到项目时重新安装
使用严格按照锁文件安装的命令:
| 包管理器 | 锁文件 | 重新安装 |
|---|---|---|
| npm | package-lock.json |
npm ci |
| pnpm | pnpm-lock.yaml |
pnpm install --frozen-lockfile |
| Yarn(Berry) | yarn.lock |
yarn install --immutable |
| Yarn Classic | yarn.lock |
yarn install --frozen-lockfile |
| Bun | bun.lock |
bun install --frozen-lockfile |
npm ci 要求有锁文件,会先移除已有的 node_modules,并且从不更改 package.json 或锁文件。普通的 npm install 也可以,但可能会更新锁文件。
其他会自动重建的文件夹
框架和构建工具会在 node_modules 旁边存放缓存和输出。在你没有运行的项目中,这些文件夹可以放心删除;下一次构建或启动开发服务器时会重新创建。
| 文件夹 | 创建者 |
|---|---|
.next |
Next.js |
.nuxt |
Nuxt |
.svelte-kit |
SvelteKit |
.turbo |
Turborepo |
.parcel-cache |
Parcel |
.angular |
Angular CLI |
dist 和 build 通常也是构建输出,但名称太常见。有些项目会把文件提交到这里,或另作他用,所以删除前请先看看里面的内容。
列出某个项目文件夹中的框架缓存:
find ~/Projects -type d \( -name .next -o -name .nuxt -o -name .svelte-kit -o -name .turbo -o -name .parcel-cache \) -prune -print0 | xargs -0 du -sh | sort -h
清理全局包缓存
每个包管理器还有一个由所有项目共享的下载缓存。清除它是永久性的,但没有坏处:需要时包会重新下载。
npm cache clean --force
pnpm store prune
yarn cache clean
bun pm cache rm
- npm 的缓存位于
~/.npm/_cacache。npm 缓存文档解释了为什么clean需要--force,并指出npm cache verify可以做垃圾回收而不清空全部内容。npx获取的包位于~/.npm/_npx。 - pnpm 在 macOS 上把存储放在
~/Library/pnpm/store(pnpm store path会显示你的位置)。pnpm store prune只移除没有任何项目引用的包,pnpm 文档建议偶尔运行,而不是频繁运行。 - Yarn Classic 的缓存位于
~/Library/Caches/Yarn。对于 Yarn Berry,yarn cache clean --mirror会清空~/.yarn/berry/cache中的全局缓存。 - Bun 的缓存位于
~/.bun/install/cache;bun pm cache rm会把它清空。
用 nvm 安装的旧版 Node.js 也会在 ~/.nvm/versions/node 中累积;nvm uninstall <version> 可以移除不再需要的版本。
为什么 pnpm 释放的空间比 du 显示的少
npm 和 Yarn Classic 会把每个包拷贝到每个项目的 node_modules 中。pnpm 则把每个包只在内容寻址存储中保存一份,再把文件链接到每个使用它的项目中。在 macOS 上,pnpm 默认的 packageImportMethod 会先尝试 APFS 克隆,再尝试硬链接。
无论哪种方式,数据都是共享的。du 仍会在每个项目中计入完整大小,所以删除 pnpm 项目的 node_modules,释放的空间通常远少于报告的数字。等到 pnpm store prune 移除剩余项目都不再使用的包时,空间才会回来。要做到这一点,存储必须和项目位于同一个磁盘上;外置驱动器上的项目会在那里拥有自己的存储。
MoreRoom 能帮你做什么
MoreRoom 免费版会找出有锁文件且 30 天未改动的项目中的 node_modules 文件夹,以及 .next 和 .turbo 等框架缓存,并标注为“可安全移除”。它会跳过 ~/Library 以及 ~/.nvm、~/.vscode 这类工具文件夹。你可以逐项把它们移到废纸篓,并且可以撤销。对于 npm 缓存和 pnpm 存储,MoreRoom 会运行 npm cache clean --force 和 pnpm store prune;这些命令是永久性的,并会明确标注。
MoreRoom Pro 还提供项目休眠:不活跃的项目会丢弃 node_modules 和构建输出等可重建的文件夹,回到项目时点一下即可唤醒。Pro 还包括“收集器”和目标模式。
常见问题
删除 node_modules 安全吗?
安全。它只包含已安装的依赖,包管理器可以根据 package.json 和锁文件重新安装。只删除你当前没有在运行的项目中的 node_modules,并保留锁文件。
package-lock.json 也要删除吗?
不要。锁文件记录了可以正常运行的确切版本。保留它,以后 npm ci、pnpm install 或 yarn install 才能重建出相同的 node_modules。
为什么删除 pnpm 项目的 node_modules 释放的空间这么少?
pnpm 在共享存储中为每个包只保留一份,再把这些文件克隆或硬链接到每个项目中。删除某个项目的 node_modules 只会移除链接;之后运行 pnpm store prune,才会删除没有任何项目使用的包。
npm cache clean --force 安全吗?
安全。它会清空 ~/.npm/_cacache 中的 npm 下载缓存,需要时 npm 会重新下载包。npm 文档指出,清除缓存唯一的用处就是回收磁盘空间。
npkill 会把文件夹移到废纸篓吗?
不会。npkill 会立即删除所选文件夹。可以先用它的 --dry-run 选项演练一遍;如果想要废纸篓这层保障,请使用访达。