Node、npm、Homebrew,这三个词放在一起,基本就是一台 Mac 开发机的标准配置。但“标准配置”不等于不会出问题——版本装乱了、环境变量被搞脏了、或者网上那些教程让你装了不该装的东西,最后 node -v、npm -v、brew --version 轮番报错,连卸载个软件都得查半天资料。作为天天跟这套环境打交道的开发者,我太清楚这种“环境越修越乱”的体验了。
这篇文章我直接把三套彻底卸载方案写明白:macOS 上的 Homebrew、macOS 上的 Node/npm、Windows 上的 Node/npm。顺带把很多人卡住的 npm.ps1 执行策略报错、卸载残留、卸载后重装还是旧版本这些“售后问题”一起解决。不管你是老项目跑不起来想重装 node,还是电脑里 Homebrew 残留了一堆没用的包想清干净,这篇都适用。
1. 为什么好好的环境要整个卸载
1.1 三个最典型的卸载场景
很多朋友不是“想卸载”,是“被逼到必须卸载”。根据我在各种社区和群里看到的求助,九成以上属于下面三种情况。
第一种是 Node 版本和项目不匹配。比如老项目用的 Angular 9,官方要求 Node 12/14,结果你电脑上已经升级到 Node 20 甚至 24,一启动就报模块版本不兼容,Google 一堆答案让你卸载重装。这种最冤枉,因为用版本管理器完全可以共存解决,只是大多数人一开始都是官网下载 pkg 安装包直接装的。
第二种是安装方式混乱导致环境变量打架。比如先用 Homebrew 装了一遍 Node,后来又从官网下 pkg 覆盖装了一遍,再后来又装了 nvm,三个套件里都有 node 和 npm,PATH 里谁排在前面谁生效,但全局包又散落在各个目录里,最后 npm 装一个包经常报权限错或者找不到模块。
第三种是全局包装太多,卸载不干净。npm 全局装了一堆工具,有些是你根本不需要的,有些是版本冲突的,还有一些是卸载时把目录权限搞坏了,之后每次 npm install 都要加 sudo。这种环境下与其一个个排查,不如彻底清空重来。
1.2 卸载前的理智判断
我的建议是:动手卸载之前,先花五分钟做个体检,别一上来就 rm -rf。
先跑一遍下面几个命令,把结果截图或者记下来:
node -v npm -v npx -v brew --version which node which npm which npx which brew这几个命令能帮你定位问题到底出在哪。举个例子,如果 node -v 正常、npm -v 报“无法将 npm 项识别为 cmdlet”,这通常不是卸载能解决的,而是 PATH 或者 PowerShell 执行策略的问题,我在第 4 节会专门讲。如果 which node 指向 /usr/local/bin/node 而 which npm 指向 /usr/local/bin/npm 但 node 实际又在 /opt/homebrew/bin 里也有一个,说明环境确实已经乱了,这种才值得走彻底卸载的流程。
1.3 先做一次环境体检
体检不仅仅是看命令能不能跑,更重要的是记录你现在的全局包清单,不然卸载以后想不起来装过什么:
| 命令 | 用途 | 判断标准 |
|---|---|---|
npm ls -g --depth=0 | 列出所有 npm 全局包 | 记录包名和版本,重建时参考 |
npm prefix -g | 查看 npm 全局安装目录 | 判断安装来源,比如 /usr/local 还是 ~/.nvm |
brew list | 列出 Homebrew 安装的所有软件 | 找出哪些依赖 node,哪些可以一起卸载 |
brew deps --tree node | 查看 node 被谁依赖 | 确认卸载后会不会影响其他软件 |
brew bundle dump | 导出当前 brew 安装清单 | 生成 Brewfile 备份,重装时一键恢复 |
这里特别提醒一句:在 Mac 上一定要先跑brew bundle dump。它会把当前 Homebrew 里所有 formula 和 cask 写成一个 Brewfile,以后想恢复环境直接brew bundle install就回来了。很多人卸载完才想起“哦我之前还装过 redis”,但已经晚了,所以备份这步真的不能省。
2. macOS 上的 Homebrew 彻底卸载
2.1 卸载前的备份动作
Homebrew 本身只是一个包管理器,理论上删掉它不影响你电脑上已有的软件,但实际上它的目录里会攒下很多依赖库,这些库可能被其他软件共用。所以卸载前除了备份 brew list,还要留意一下你自己通过 brew 装的业务软件,比如 git、redis、python 这类,卸载 Homebrew 之后它们可能还能用,但升级就没有入口了。
我的习惯是先把 Brewfile 导出来,再把 npm 全局包列表也备一份,然后用brew deps --tree --installed看一眼哪些是孤立依赖。如果某个软件是 brew 从源码编译安装的,删掉 Homebrew 对应目录后这个软件就废了,需要另想办法重装。
2.2 官方卸载脚本与手动兜底
Homebrew 官方提供了一个卸载脚本,这是最省事的路径。在终端执行:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"脚本会先问你确认哪些操作,注意它有一个 dry-run 模式。有些人直接一路 yes 下去,结果连自己不想删的包也删了。正确做法是先跑一次:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)" --dry-run它会列出将要删除的目录和文件清单,仔细看一遍有没有你眼熟的、不想删的。确认没问题再正式执行。
如果官方脚本因为网络中断或者其他原因跑不完,那就手动来。需要扫掉的目录大致是这些:
# Intel Mac 上 Homebrew 默认装在这 sudo rm -rf /usr/local/Homebrew sudo rm -rf /usr/local/Caskroom sudo rm -rf /usr/local/Cellar sudo rm -rf /usr/local/var/homebrew sudo rm -rf /usr/local/etc/homebrew # Apple Silicon Mac 上默认装在这 sudo rm -rf /opt/homebrew2.3 残留目录清理与 shell 配置还原
很多人卸载完 Homebrew 发现brew命令还在,那是因为 shell 配置里还残留着环境变量。去~/.zshrc或者~/.bash_profile里找类似这两行的内容,删掉:
export PATH="/opt/homebrew/bin:$PATH" eval "$(/opt/homebrew/bin/brew shellenv)"同时还要清理 Homebrew 的缓存和辅助目录,这些不删的话会一直占着磁盘空间:
sudo rm -rf /Library/Caches/Homebrew sudo rm -rf ~/Library/Caches/Homebrew sudo rm -rf ~/Library/Application\ Support/Homebrew sudo rm -rf ~/Library/Logs/Homebrew注意:
/usr/local目录下面还可能有其他手动装的软件,千万别整个rm -rf /usr/local,那会把非 Homebrew 的东西也一起删了。我只删上面列出的那几个子目录,这是无数次手滑之后总结出来的教训。
3. macOS 上的 Node 与 npm 彻底卸载
3.1 先搞清楚 Node 是通过什么方式装的
Mac 上安装 Node 的途径实在太多,不同途径卸载方式完全不同,这也是“卸载 node”这个事在网上一搜一堆版本的原因。先通过which node判断:
| 安装方式 | 典型路径 | 卸载方式 |
|---|---|---|
| 官网 pkg 安装包 | /usr/local/bin/node | 手动删文件和目录 |
| Homebrew | /opt/homebrew/bin/node 或 /usr/local/bin/node | brew uninstall node |
| nvm | ~/.nvm/versions/node/vxx.x.x | nvm uninstall <版本> |
| fnm | ~/.local/state/fnm_multishells | fnm uninstall <版本> |
如果which node根本没输出,但node -v还能跑,说明你的 shell 配置里还残留路径,先把 shell 配置修好再说。
3.2 手动删除的完整清单
如果你以前是官网 pkg 装的,或者已经分不清来源,干脆直接手动清理。这块我列一个完整清单,照着扫就行:
# 可执行文件 sudo rm -rf /usr/local/bin/node sudo rm -rf /usr/local/bin/npm sudo rm -rf /usr/local/bin/npx # 全局包目录 sudo rm -rf /usr/local/lib/node_modules # 头文件和相关目录 sudo rm -rf /usr/local/include/node # 用户级缓存和配置 sudo rm -rf ~/.npm sudo rm -rf ~/.npmrc sudo rm -rf ~/.node-gyp sudo rm -rf ~/.node_repl_history sudo rm -rf ~/Library/Caches/node-gyp sudo rm -rf ~/Library/Caches/npm如果你用的是 Apple Silicon Mac,Homebrew 装在 /opt/homebrew 下,那对应的 bin 目录也是 /opt/homebrew/bin,把上面清单里的 /usr/local 替换成 /opt/homebrew 再执行一遍。
3.3 npm 全局包的清理顺序
手动删除前还有一个隐患:如果全局包目录里有大量包,直接删目录没问题,但如果你的 npm 是通过某个 Node 版本管理器装的,正确的卸载姿势应该先用那个管理器卸载,避免把版本管理器的数据弄乱。
比如 nvm 用户,正确操作是先看一眼当前版本:
nvm ls nvm uninstall 20.10.0把 nvm 里所有 node 版本都卸掉之后再删 nvm 本身:
rm -rf ~/.nvm然后检查~/.zshrc里有没有 nvm 相关的三行:
export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"有就删掉。这一步不做,就算 nvm 目录删光了,新开终端也会报 command not found。
3.4 顺手清掉包管理器残留
很多人的 Mac 上不止 npm 一个包管理器,yarn 和 pnpm 也常常存在。既然这次大扫除,就一起处理:
# yarn sudo rm -rf ~/.yarn sudo rm -rf ~/.yarnrc sudo rm -rf ~/.cache/yarn # pnpm sudo rm -rf ~/.pnpm-store sudo rm -rf ~/.pnpm-state sudo rm -rf ~/Library/Caches/pnpm全局命令比如 serve、create-react-app、commitlint 这些,会因为 npm 目录被删而一起消失,这没问题,后面重装 Node 时再挑真正需要的装回来就行。
4. Windows 上的卸载细节:别只看控制面板
4.1 npm.ps1 执行策略报错的真正原因
热搜词里那串“npm : 无法加载文件 d:\program files\nodejs\npm.ps1,因为在此系统上禁止运行脚本”是很多 Windows 开发者的噩梦。这句话不是说你 npm 坏了,而是 PowerShell 的执行策略默认挡住了 .ps1 脚本。
Windows 上 PowerShell 默认执行策略是 Restricted,只允许单个命令,不允许跑脚本文件。npm 是一个 .ps1 的包装脚本,所以你在 PowerShell 里执行 npm 就撞墙了。这跟卸载没关系,很多人以为要卸载重装,其实一句话就能解决。
解决办法是修改当前用户的执行策略:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUserRemoteSigned 的意思是本地脚本可以运行,从网上下载的脚本需要有数字签名。选当前用户范围而不是本机范围,是为了避免影响系统其他账户,这是最稳妥的尺度。
改完之后可以执行Get-ExecutionPolicy验证,应该输出 RemoteSigned。如果你用了终端模拟器比如 VS Code 的终端,改完要重新打开终端窗口才生效。
4.2 控制面板卸载后的深度清理
Windows 上卸载 Node 的常规路径是控制面板里的“程序和功能”,这一步会移除大部分文件,但残留非常严重。装过 node 的 Windows 机器,大概率在下面这些目录里留下尸体:
C:\Program Files\nodejs C:\Users\<你的用户名>\AppData\Roaming\npm C:\Users\<你的用户名>\AppData\Roaming\npm-cache C:\Users\<你的用户名>\AppData\Local\Temp\npm-* C:\Users\<你的用户名>\.npmrc控制面板卸载完,检查一下C:\Program Files\nodejs是否还在,如果还在就手动删除。AppData 下面的 npm 和 npm-cache 文件夹也直接删掉。这里要注意npm-cache是 npm 的全局缓存,里面可能有几百 MB 的临时文件,删掉非常安全,后面重装会自动重建。
我见过一种情况:卸载完 Node 后 npm 命令还能用。这是因为 PATH 里还残留着原来的 npm 路径,而那个路径下的文件并没有被干净删除。处理办法是把 PATH 里残留的 nodejs、npm 路径手动移除,再重启终端。
4.3 PATH 与环境变量的还原
Windows 的环境变量修改入口在“系统属性 → 环境变量”。打开后重点看两个地方:用户变量里的 Path 和系统变量里的 Path。
常见要去掉的条目长这样:
C:\Program Files\nodejs\ C:\Users\<你的用户名>\AppData\Roaming\npm如果之前配过 Node 相关的 NODE_PATH、NODE_ENV,一并删掉。删完记得点确定,然后完全退出终端重新开一个,或者干脆重启一次系统。很多人删完环境变量发现命令还在,其实就是没重启,环境变量不会自动刷新。
4.4 “无法将 npm 项识别为 cmdlet”的排查
这个报错是另一个高频问题,字面意思是系统根本找不到 npm。原因通常是三种:一是 Node 压根没装上;二是装上了但 PATH 没配;三是 PATH 配了但没重启终端。
我的排查顺序比较固定:先检查C:\Program Files\nodejs\npm.cmd存不存在,没有就说明安装有问题;存在就去 PATH 里看有没有路径;路径有但 PowerShell 还是报错,就试一下 cmd 里能不能跑,cmd 能跑说明是 PowerShell 缓存问题,执行Get-Command npm强制刷新一下。
这套流程走下来,99% 的“识别不了”都能定位到具体环节。
5. 卸载之后怎么重建才不会再乱
5.1 macOS 上强烈建议用 nvm 管理 Node
卸载完一大圈,如果最后又回到官网手动下载 pkg 安装 Node,那今天这篇就白看了。macOS 上我唯一的建议是 nvm,它是 Node 版本管理器,可以让你随时切换 Node 版本,老项目要 Node 12,新项目要 Node 20,一键切换互不干扰,再也不用为了兼容性问题卸载重装。
安装非常快:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash装完在~/.zshrc里确认有 nvm 的初始化代码,然后重新打开终端。安装具体版本的 Node:
nvm install 20 nvm install 18 nvm alias default 20alias default是设置默认版本,不然每次新开终端 Node 还是不存在,这个坑我踩过很多次。
5.2 Windows 上用 nvm-windows 或 fnm
Windows 上不能直接装 nvm,要用一个叫 nvm-windows 的独立项目,安装方式也是下载压缩包,然后以管理员身份运行 install。装完可以这样用:
nvm install 20 nvm use 20另外一个现代选择是 fnm,Rust 写成的,安装和切换都快很多,还支持项目级.nvmrc自动切换版本,装完之后在项目根目录写一个.nvmrc文件:
20.0.0然后在 PowerShell 里执行:
fnm env --use-on-cd | Out-String | Invoke-Expression这样进入不同项目目录时 fnm 会自动读.nvmrc并切到对应 Node 版本。对经常维护多个项目的开发者来说,这体验比手动切版本舒服太多了。
5.3 重建之后必须做的三件事
新环境装好,先跑三个验证命令:
node -v npm -v npx -v都输出版本号说明安装成功。接下来是检查 npm 的 registry 配置:
npm config get registry如果显示的不是官方源而是你之前换过的第三方源,自己确认一下是否需要保留。如果你以前为速度快改过淘宝源,那现在依然可以继续用,没必要来回折腾。
第三件事是挑真正需要的全局包重装。我建议少装,越多全局包越容易出问题。比较常用的是这些:
npm install -g commitlint @commitlint/cli @commitlint/config-conventional npm install -g pnpm npm install -g yarn注意 commitlint 对 Node 版本有要求,一般要求 Node >= 18。如果你电脑上 Node 版本是 24,配 commitlint 通常没问题,但如果项目里某些依赖跟 Node 24 八字不合,就换到 20 LTS 版本再装,别硬上最新版。Angular 9 那种老项目,直接 nvm 切到 Node 12 或 14 再单独操作,这才是正路。
5.4 版本共存的核心逻辑
不管 Mac 还是 Windows,核心思维都是一样的:不要让 Node 环境全局只有一个版本,而是让多个版本共存,用工具随时切。Node 生态更新太快,你昨天装的是 18,今天新项目要 20,后天老项目又要 14,如果你只会卸载重装,时间全耗在环境上,项目一点没写,这就是典型的“环境工程师病”。
装上版本管理器之后,卸载 Node、重装 Node 这些操作基本就不需要了,剩下的只有nvm install、nvm use和偶尔的nvm uninstall清理不用的版本。
6. 常见问题排查与我的避坑心得
6.1 卸载时遇到 permission denied
Mac 上删除 /usr/local 或 /opt/homebrew 下的文件经常碰到权限不够的报错。有些人第一反应是sudo rm -rf,但我不建议一开始就上 sudo。先看一下文件属主:
ls -l /usr/local/bin/node如果显示 root 所有,那你确实需要 sudo。但如果是你自己所有,还报 permission denied,很可能是文件被设置了 immutable 标志,需要先解除:
sudo chflags -R nouchg /usr/local/bin/node然后再删。Windows 上遇到“无法删除文件”多半是进程占用,关掉所有 node.exe、npm 相关的终端进程,再用管理员权限删。
6.2 卸载后重装还是旧版本
这个问题太经典了。卸载完之后装新版 Node,结果node -v显示的还是旧版本号。这不是卸载失败,而是 PATH 里旧的 node 执行文件还在,并且排在前面。
解决办法是老规矩,先which node看它的实际路径在哪。如果在 /usr/local/bin 而不是 /opt/homebrew/bin,说明你的 shell 配置里把 /usr/local/bin 排在前面了,而旧文件没删干净。删掉旧文件,或者调整 PATH 顺序,再重开终端就正常了。
6.3 卸载 Homebrew 后 shell 配置里还在报错
Homebrew 卸载完,bash 或 zsh 启动时仍提示 command not found,基本可以断定是~/.zshrc、~/.bash_profile或~/.profile里的 brew shellenv 没清干净。用grep -n brew ~/.zshrc搜一遍,把相关行全部删掉。
6.4 我踩过的几个坑
第一个坑是直接sudo rm -rf /usr/local。有一年我嫌 Homebrew 残留太多,一怒之下把整个 /usr/local 都删了,结果电脑上所有手动编译装的软件全部完蛋,连 git 都只剩一个残废版本。后来花了整整一天把所有东西重新装回来。这个教训我记到今天,卸载动作宁可慢一点,一次只动一个明确的对象。
第二个坑是卸载 nvm 之前没有先卸载 Node 版本。直接rm -rf ~/.nvm虽然也能用,但如果你同时在用其他工具,比如 VS Code 的扩展里有指向旧 Node 路径的配置,新开项目时可能报一串错误。正确顺序是先nvm uninstall清版本再删 nvm。
第三个坑是 Windows 上卸载 Node 后没有重启系统。那次我在控制面板里卸得干干净净,环境变量也改完了,结果新装 Node 后打开终端,npm 还是找不到。最后发现是环境变量变更没生效,Windows 对用户环境变量的广播经常不即时,重启一次就正常了。
6.5 一条自检清单
每次卸载重装完,我都会按下面的清单过一遍,全部通过才算真正干净:
| 检查项 | 命令 | 期望结果 |
|---|---|---|
| 旧 node 是否还存在 | which node | 输出为空或指向新路径 |
| 旧 npm 是否还存在 | which npm | 输出为空或指向新路径 |
| Homebrew 是否清理完 | which brew | 输出为空 |
| 环境变量里有无残留 | echo $PATH | 没有 Homebrew、nodejs 相关路径 |
| npm 全局目录是否干净 | npm prefix -g | 指向当前的版本管理器路径 |
| shell 配置里有无残留 | grep -n node ~/.zshrc | 输出为空或只有干净配置 |
这套流程我帮不少朋友处理过环境问题,基本一次到位。如果你也是那种项目还没写几行、环境先折腾半天的开发者,真心建议从今天这篇开始,把卸载重装这种“治标”的操作彻底换成“版本管理器 + 按需重建”的“治本”方案。以后 Node 生态再出新版本,你只需要nvm install一条命令,整个世界都清净了。