☰
nvm安装与Node多版本管理:macOS、Windows分平台配置指南
2026/11/4 14:25:39 网站建设 项目流程

上个月帮同事配环境,他照着某篇教程把命令敲完,终端里nvm死活认不出来,回头一看——他在 Windows 的 PowerShell 里,完整走了一遍 macOS 的安装步骤。这种事故我见过不止一次,根子上是搜"nvm 安装"出来的内容把两套完全不同的东西混成了一锅:macOS 上叫 nvm 的是一个 shell 脚本项目,Windows 上叫 nvm 的是一个编译好的 exe 程序,它们的下载地址、安装方式、配置文件、甚至命令参数都不一样。这份指南就按"分平台落地"的思路,把 nvm 的下载、安装、配置、验证、排错整条链路拆开讲清楚。如果你是刚接手多版本 Node 项目的新人,或者手上有一台要重新配环境的新机器,跟着走一遍基本不会踩空;如果你已经装过但总在某些项目里切不过去,第五章的排查顺序应该能帮你定位到具体环节。

1. 名字都叫 nvm,但两个平台装的根本不是同一个项目

1.1 一个是靠 shell 脚本改环境变量,一个是编译好的可执行文件

先把最容易被忽略的事实摆出来:macOS(以及各类 Linux 发行版)上用的 nvm,主体是一堆 bash 脚本,安装过程本质上是把仓库克隆到用户主目录下的.nvm文件夹,然后往你的 shell 配置文件里追加几行启动代码。它切换版本的方式是修改PATH变量,让node这个命令指向不同版本目录下的可执行文件。整个过程没有二进制安装包,没有注册表,也没有系统级的卸载程序。

Windows 上用的 nvm 则是另一套实现,通常被人叫做 nvm-windows,它是一个用 Go 写的程序,安装完成后你会得到一个nvm.exe。它的工作方式和 macOS 版完全不同:先建一个固定的软链接目录(安装向导里默认是C:\Program Files\nodejs),切换版本时把这个软链接指向不同版本的安装文件夹。也就是说,Windows 上永远只有一个"看起来像 Node 安装目录"的路径,实际内容被软链接替换掉了。

理解这个底层差异,后面很多"为什么命令不一样""为什么这里要管理员权限"就有了答案。很多人装完发现命令对不上,不是操作错了,而是照着另一个平台的文档在操作。

1.2 命令长得像,参数和副作用差得远

两个项目的命令名高度重合,这也是混淆的主要来源。下面这张表是我自己整理的高频对照,建议收藏:

操作意图macOS / Linux 版Windows 版关键差异
安装指定版本nvm install 20nvm install 20.11.0Windows 版对完整版本号更友好
安装最新 LTSnvm install --ltsnvm install lts参数写法不同
切换到某版本nvm use 20nvm use 20.11.0Windows 需管理员权限
查看已安装nvm lsnvm list别名不同
查看可安装nvm ls-remotenvm list available一个查远程仓库,一个查内置清单
设置默认版本nvm alias default 20切换后自动记住Windows 没有 alias 机制
卸载某版本nvm uninstall 20nvm uninstall 20.11.0都要求该版本未被使用
查看当前版本nvm currentnvm current这个倒是通用

注意nvm ls-remote和nvm list available的区别不是命名随意,而是实现机制不同。macOS 版会实时去拉取远程的版本索引,所以能列出全部历史版本;Windows 版查的是程序内置的一份可用版本清单,遇到刚发布的新版本可能需要更新 nvm 本身才能看到。这一点在你想装某个刚出的版本却"列表里没有"时会很有用。

还有一个隐性差异:Windows 版的nvm use是会写盘的操作,它要删除并重建软链接,所以经常会弹出权限错误或者被占用错误;macOS 版的nvm use只是改内存里的环境变量,速度快、无副作用,但在当前终端之外不生效。这两个体感差异经常让人误以为其中一个"坏了"。

1.3 在 WSL 里装的那个 nvm,管不到 Windows 侧的编辑器

这条单独拎出来讲,因为踩坑的人特别多。WSL 是一个完整的类 Linux 环境,你在里面装的 nvm 和 Node 都是 Linux 版本的二进制文件,跟 Windows 侧完全隔离。你的终端里node -v显示 20,但编辑器或者某个 Windows 桌面工具调用的是另一个路径下的 Node,版本可能还是 16。

判断方法很直接:在 Windows 的 PowerShell 里执行where node,和在 WSL 里执行which node,如果两个结果里的路径风格完全不同(一个是C:\...,一个是/home/...),那就说明你同时维护着两套运行环境。这种状态下最忌讳的是两个环境都装 nvm、都改版本,最后自己都记不清哪个项目跑在哪个环境里。

我的建议是明确分工:如果项目主要在 WSL 里跑,就把 WSL 里的 nvm 当作唯一入口,Windows 侧不装 Node;如果项目要在 Windows 原生环境跑(比如某些桌面端构建工具),那就装 Windows 版的 nvm,WSL 里保持干净。不要两边都折腾,收益低、排查成本高。

2. macOS 上的落地流程:从执行脚本到 shell 真正认到命令

2.1 动手前先做三行体检,能省掉一半返工

很多人直接跳过检查就开始装,结果装完发现系统里有两个 node,which node指向的还是老的。装之前先在终端里跑这三条:

echo $SHELL which -a node ls -la ~/.nvm

第一条确认你当前用的是哪个 shell。近年版本的 macOS 默认是 zsh,配置文件是~/.zshrc;老系统或者手动改过的可能是 bash,对应~/.bash_profile或~/.bashrc。这一条决定了后面安装脚本往哪个文件里写配置,如果搞错了,脚本写进~/.bash_profile,而你天天用的是 zsh,那命令当然出不来。

第二条列出所有能找到的 node 路径。如果输出里出现了/usr/local/bin/node或者/usr/local/lib/node_modules这类系统级路径,说明你之前用官方安装包装过 Node,需要先清理掉。清理方式是按顺序删掉这几个位置的可执行文件和模块目录,再确认which node已经没有任何输出。

第三条看.nvm目录是否已经存在。如果存在,说明你以前装过,可能是配置没生效或者版本太老,这时候建议先按卸载流程处理干净再重装,而不是在旧目录上覆盖,避免残留的旧版本目录干扰。

2.2 脚本执行时究竟对你的系统做了什么

从官方仓库拿到install.sh的当前地址后执行,脚本做的事情其实很朴素:把仓库克隆到~/.nvm,然后往你的 shell 配置文件末尾追加一段启动代码。如果你想让 nvm 装到别的目录(比如磁盘空间紧张,想放到外挂盘),可以在执行前先设置NVM_DIR环境变量指向目标路径,脚本会尊重这个变量。

提示:脚本里的版本号会随项目迭代变化,不要照抄几年前教程里的固定版本链接。正确的做法是打开项目官方说明页,复制当前给出的那条安装命令,这样能避免拉到已经不再维护的旧脚本。

安装完成后脚本通常会打印一句提示,让你重新打开终端或者手动 source 一下配置文件。多数人就是在这里出问题的——他们既没重开终端,也没 source,直接就开始敲nvm -v,当然报错。这不是安装失败,只是当前这个终端进程还没有读到新写入的配置。

2.3 shell 配置文件里那三行,每一行都有明确职责

安装脚本追加的配置大致是这样几行:

export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

第一行把 nvm 的根目录声明成一个环境变量,后续脚本都依赖这个变量定位文件。第二行是一个条件判断加加载动作:-s判断文件存在且大小非零,成立才执行后面的.(等价于source)。用一个判断包住,是为了避免文件缺失时每次开终端都弹出一堆报错。第三行加载命令补全脚本,让你敲nvm ins按 Tab 能自动补全,属于体验优化,删掉不影响功能。

第二行的加载动作是整件事的核心。nvm 的版本切换靠的是在 shell 里注入一个函数,而不是简单改PATH,所以必须通过source把这个函数加载进当前会话。这也解释了一个常见现象:你在 A 终端里nvm use 18,切到 B 终端发现还是老版本,因为每个终端进程都有独立的环境变量副本,nvm use只影响自己所在的那个进程。

如果你手动改过配置,或者从别的机器拷了一份.zshrc过来,一定要确认这几行在你实际使用的那个配置文件里,而不是在~/.bash_profile里躺着。检查方法很简单:grep nvm ~/.zshrc,有输出就说明写对了。

2.4 验收要跑完整链路,别只看一个版本号

装完之后,按这个顺序验收,任何一步不符合预期就停下来查:

nvm -v nvm install --lts node -v npm -v nvm ls

第一步nvm -v能出版本号,说明脚本加载成功。第二步安装最新 LTS,正常会经历下载、解压、安装几个阶段,最后提示已经切换到该版本。第三步第四步确认 node 和 npm 都能正常响应。第五步列出已安装列表,你会看到当前版本前面有个箭头标记。

这里有个细节值得说:nvm install --lts装完之后会自动把当前 shell 切到新装的那个版本,但仅仅是当前 shell。如果你重开终端发现又变回别的版本,说明你没设默认版本,去执行一次nvm alias default lts/*,把默认版本钉住。这个 alias 的名字可以自定义,default只是最常用的一个,开新终端时会自动应用这个别名指向的版本。

另外,nvm ls的输出里除了已装版本,还会显示system这一项,代表系统自带的那个 node。如果你在装 nvm 之前清理干净了,这一项通常显示为N/A,属于正常状态,不用管它。

3. Windows 上的落地流程:卸载残留、选对目录、改好配置

3.1 装之前必须把旧的 Node 清干净,否则一定冲突

Windows 上这一步的重要性远高于 macOS,因为 nvm-windows 要占用一个nodejs目录作为软链接目标,而官方 Node 安装包默认也会建一个同名目录,两者直接撞车。清理步骤如下:

  1. 在"应用和功能"里找到 Node.js,正常卸载。
  2. 手动检查并删除残留目录:C:\Program Files\nodejs、C:\Users\你的用户名\AppData\Roaming\npm、C:\Users\你的用户名\AppData\Roaming\npm-cache。前一个是程序目录,后两个是全局安装的包和缓存。
  3. 打开系统环境变量,在用户变量和系统变量的Path里逐条检查,把所有指向nodejs的条目删掉。这一步最容易漏,因为安装包写入的不一定在哪个位置,有人卸载后没清Path,导致新装的 nvm 一直找不到正确的 node。
  4. 重新打开一个命令行窗口,执行where node,确认已经没有任何输出。

清理完再做下一步。很多"装完 nvm 之后 node -v 报错"的问题,根子都在这里没做干净。

3.2 安装向导里那两个路径,含义完全不同,别随手改

nvm-windows 有安装版和免安装压缩包两种形式。安装版双击运行后会问两个路径:

第一个是 nvm 自己的安装目录,用来存放各版本的 Node,默认在用户目录下的AppData\Roaming\nvm。这个路径建议保持默认,或者至少保证不含中文、不含空格。原因不复杂——nvm 执行命令时会拼接路径作为参数,路径里有空格就得加引号,而某些内部调用没处理好引号,就会报"找不到文件"这类看起来莫名其妙的错误。

第二个是软链接目录,默认是C:\Program Files\nodejs。这个路径是最终对外暴露的 Node 安装位置,PATH环境变量指向的就是它。强烈建议保持默认,因为不少工具、脚本、构建配置会硬编码去找这个位置,改了之后你可能会遇到一些很难解释的工具报错。

免安装压缩包则适合不想动系统目录的场景。解压后需要手动设置两个环境变量:NVM_HOME指向解压目录,NVM_SYMLINK指向软链接目录,再把这两个变量加进Path。这种方式灵活,但配置环节多一步出错的机会,对新手不太友好。

3.3 settings.txt 里改几个字段,下载速度和可用性完全不一样

nvm 安装目录下有一个settings.txt,这是 Windows 版的核心配置文件,内容大致包含root(版本存放目录)、path(软链接目录)、node_mirror(Node 下载源)、npm_mirror(npm 下载源)四项。前两项由安装向导写入,一般不用动;后两项是控制下载地址的,可以根据你的网络情况换成访问更顺畅的镜像地址。

改的时候有个规矩必须遵守:改完保存,然后关掉所有已经打开的命令行窗口重新打开。原因是 nvm 在启动时读取这个文件,已经运行中的进程读的还是旧配置。有人改完在原来的窗口里反复试,一直不生效,最后发现只是没重开窗口。

注意:settings.txt里的root和path必须和实际安装位置完全一致。如果你后来手动移动过安装目录,一定要同步改这两行,否则nvm use会报软链接创建失败,而且报错信息不会直接告诉你路径不一致,只会给你一个权限相关的错误,很容易误判。

3.4 为什么 Windows 上切换版本总要管理员权限

nvm use这个操作在 Windows 上要做两件事:删掉现有的nodejs软链接,再新建一个指向目标版本的软链接。而默认的软链接目录在C:\Program Files\下面,这是受系统保护的路径,普通权限改不了。所以你会看到"拒绝访问"或者"创建符号链接失败"。

解决办法有三个,按推荐程度排序:第一,用管理员身份打开终端再执行切换,这是最省事的做法,缺点是每次切版本都得记得提权;第二,安装时把软链接目录设到用户目录下(比如C:\Users\你的用户名\nodejs),同时把Path里的旧路径替换掉,之后就再也不需要提权了,代价是要改环境变量、且个别工具可能找不到默认位置;第三,只在项目初始化时切一次版本,之后长期不动,规避频繁提权。

我自己的习惯是第一种,因为切换频率其实没那么高,而把软链接目录挪到用户目录后,偶尔会遇到某个工具的安装脚本去找C:\Program Files\nodejs然后报错,排查起来反而更烦。

4. 装完只是开始:版本切换策略、项目锁定与全局包处理

4.1 高频命令的实操细节,比命令表更重要的是副作用

命令本身不难记,难的是知道每条命令会带来什么副作用。举几个例子:

nvm install 18在 macOS 上,如果 18 系列有多个小版本,它会装当前最新的那个 18.x,并且自动切换过去;如果你只是想在多台机器上对齐版本,应该在项目里写清完整版本号,而不是只写大版本。

nvm uninstall 18在两边都要求目标版本当前没有被使用。macOS 上如果你正处于该版本,会直接拒绝;Windows 上会提示版本正在使用中。正确顺序是先nvm use切到另一个版本,再执行卸载。

nvm ls和nvm list的输出里,那个箭头指向的是当前 shell 正在用的版本,而default别名指向的是新开终端会用的版本。这两个可以不一样,理解这一点能解释很多"我明明切了,怎么重开终端又回去了"的疑惑。

nvm which 18在 macOS 上能直接告诉你该版本的 node 可执行文件绝对路径,排查"到底在用哪个 node"时非常有用。Windows 上没有这个命令,替代做法是看where node的输出,再看软链接指向的实际目录。

4.2 用 .nvmrc 把项目钉在某个版本上

团队协作里最有效的做法不是口头约定版本,而是在项目根目录放一个.nvmrc文件,内容就一行版本号,比如20.11.0。这个文件的约定很简单:谁进到这个目录,就按里面的版本切换。

macOS 上的体验比较顺:在项目目录里直接执行nvm use,它会自动往上找.nvmrc,读到版本号就切过去。如果该版本没装,会提示你先 install。

Windows 上的行为要保守看待,部分版本不会自动读取这个文件,稳妥做法是先看一眼内容再显式指定:

type .nvmrc nvm use 20.11.0

这个差异导致的典型翻车场景是:Windows 同事执行nvm use,命令没报错,但版本根本没变,他以为切过去了,结果构建出来一堆版本相关的报错。所以在跨平台团队里,我一般会在 README 里写明 Windows 需要显式指定版本,并且把.nvmrc里的版本号写成完整的三段式,避免大版本匹配到不同小版本。

配合这个文件,还可以在项目的package.json里加上engines字段声明支持的 Node 范围。两者一个管"用哪个",一个管"至少得是哪个",校验逻辑交给包管理器。

4.3 切完版本全局工具就消失了,这是设计如此

这是新手最常问的问题之一:装了pnpm、typescript、某个脚手架,切个 Node 版本就全没了。原因很直白——全局安装的包是装在各个 Node 版本自己的目录下的,不同版本的全局包目录互相独立,切换版本等于换了一个全新的全局环境。

macOS 上有个补救命令:nvm reinstall-packages <旧版本号>,它会把旧版本下全局安装的包在新版本里重装一遍。用法是先nvm use到新版本,再执行nvm reinstall-packages 18。注意它迁移的是"包清单",二进制文件会重新下载,网络不好的时候会等一会儿。

Windows 上没有这个命令,只能手动重装。所以我在 Windows 上的策略是尽量少用全局包,能用项目本地依赖就用本地的,能用npx临时跑就用npx。真正需要全局的只有那么一两个包管理器,重装成本可以接受。

另一个思路是统一 npm 的全局前缀,让所有版本共用一个全局目录。做法是设置npm config set prefix <统一路径>并把该路径下的可执行目录加进PATH。好处是切版本不用重装,坏处是不同版本可能对同一个包的兼容性不一致,遇到原生模块编译的场景容易出问题。我个人只在纯工具类包(比如代码格式化工具)上用这个方案,涉及编译的不碰。

4.4 默认版本怎么设才不会每天重设

macOS 上的做法是设置别名:nvm alias default 20.11.0。这条命令写进~/.nvm/alias/default文件,之后每开一个新终端,nvm 加载时自动切到这个版本。想改成跟踪最新 LTS 也可以,用nvm alias default lts/*,这样以后 LTS 更新了你重开终端就能拿到新版,代价是版本会不知不觉变化,对需要严格复现的项目不友好。

Windows 上不需要显式设默认,因为nvm use会把目标版本写进配置,下次开终端自动沿用。这也意味着如果你上次切到了一个很老的版本忘了切回来,下次开机还是那个老版本,容易让人困惑。养成习惯:切完版本在项目文档里记一笔,或者干脆靠.nvmrc显式声明。

5. 装完不顺手的几种情况,按这个顺序查

5.1 命令找不到:先确认配置文件有没有被真正加载

macOS 上报command not found: nvm,排查顺序是这样的:

先执行echo $SHELL确认 shell 类型,再看对应的配置文件里有没有那三行 nvm 配置。用grep nvm ~/.zshrc(bash 用户换成对应文件名)检查,没有就手动补上,有就手动source ~/.zshrc再试。

如果 source 之后还不行,执行ls -la ~/.nvm/nvm.sh看文件在不在、大小是不是零。文件不存在说明当初克隆失败了,多半是网络中断,重新跑一遍安装脚本即可。文件存在但大小为 0,通常是下载过程中断留下的残骸,删掉整个.nvm目录重装。

还有一种隐蔽情况:你的配置文件里前面某一行有语法错误,导致 shell 加载到那里就中断了,后面的 nvm 配置根本没执行到。判断方法是新开终端看有没有报错信息,或者用bash -x ~/.bash_profile之类的方式看加载过程。这种情况在手工改过配置文件的机器上不算少见。

Windows 上报"'nvm' 不是内部或外部命令",排查顺序是:先确认安装目录下确实有nvm.exe;再打开环境变量看Path里有没有 nvm 安装目录和软链接目录;最后关掉所有终端重新打开。Windows 的环境变量修改对已经打开的终端不生效,这一点和配置文件的加载逻辑是一样的道理。

5.2 安装 Node 卡在下载阶段

表现是执行安装命令后长时间没有进展,或者报连接超时。这不是 nvm 的问题,是下载源的可达性问题。

macOS 上的 nvm 没有配置文件式的镜像设置,要靠环境变量:在执行安装前先export NVM_NODEJS_ORG_MIRROR=<可用的镜像地址>,或者把这行写进 shell 配置文件长期生效。npm 自己的下载源是另一回事,需要用npm config set registry <地址>单独配置,两者互不影响,不要以为改了一个另一个也会跟着变。

Windows 上就是改settings.txt里的node_mirror和npm_mirror两行,改完记得重开终端。如果改完还是慢,可以先在浏览器里直接访问那个镜像地址,确认能打开再回来试,避免配置了一个本身就不通的地址浪费排查时间。

提示:镜像源不是越多越好,也不是随便找一个就行。优先用你已经确认可访问、且更新及时的源。装完版本之后,可以用node -v和npm -v双重确认版本号符合预期,避免下到残缺包。

5.3 Windows 切换版本报权限或软链接错误

前面提过管理员权限这条,但实际排查还要多看两层。如果已经用管理员终端还是失败,检查这三处:

一是软链接目录是否被杀毒软件或安全软件锁着。有些安全软件会监控Program Files下的目录变更,切换版本时正在重建软链接,被拦截后就会报权限错误。临时关掉防护或者把该目录加入白名单可以验证这个猜测。

二是目录是否被进程占用。如果你开着编辑器、终端、某个本地服务,它们可能正持有nodejs目录下的文件句柄,导致软链接删不掉。关掉这些程序再试,或者干脆重启一次。

三是settings.txt里的path和实际目录是否一致。路径不一致时报错信息往往指向权限,实际原因是找不到目标路径。打开文件对照一下,花不了几秒钟。

5.4 卸载重装的正确顺序

有时候环境已经被折腾得很乱,最快的办法是推倒重来。macOS 上的顺序:先用nvm uninstall把各个版本卸掉(可选),然后删掉~/.nvm整个目录,再从配置文件里删掉那三行 nvm 配置,最后重开终端确认nvm已经不存在,再重新走安装流程。注意别只删目录不删配置,否则新终端会加载一个指向不存在路径的脚本,每次开窗口都报错。

Windows 上的顺序:先用nvm uninstall卸掉所有已安装版本(这一步会清掉版本目录),然后从"应用和功能"里卸载 nvm 程序本身,再手动删掉残留的安装目录和软链接目录,最后清理环境变量里的相关条目。顺序反了的话,卸载程序可能因为目录里有版本文件而失败。

我在实际配置中沉淀下来的几个习惯

折腾过十几台机器之后,有几个做法已经变成肌肉记忆了。第一台机器上我不会只装一个最新 LTS,而是固定保留一个较低的大版本(比如 18 和 20 各一个),因为总有老项目锁在旧版本上,临时装一次要等下载,不如常备。第二,.nvmrc里的版本号我坚持写完整三段式,见过太多次"大版本匹配到了不同小版本导致构建结果不一致"的事故。第三,Windows 机器上我会把settings.txt备份一份到项目目录里,换机器时直接覆盖,省去逐项配置的功夫。

最后一个不太起眼但很省事的技巧:装完之后立刻执行一次nvm ls并把输出记下来,包括当前版本、默认版本、已装版本列表。等哪天环境出问题,第一件事是再跑一次nvm ls对比,能在一分钟内判断出是"版本被改了"还是"根本没加载上",比从头排查快得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询