如果你在前端项目里待过一段时间,一定遇到过这种场景:这个老项目还在用 Node.js 12,那个新项目已经要求 Node.js 20,打开终端敲 npm run dev,先被一个版本兼容报错拦住。还有更尴尬的——系统里明明装了 Node.js,但一查 node -v 发现是别人改过的版本,全局包也全都乱了。我从第一次被 Node 版本折腾到深夜之后,就彻底把 nvm 当成了装机标配。这篇就系统说说怎么用 nvm 管理 node.js,包括安装、全局配置、版本切换,以及我踩过的那些坑。
nvm 是 Node Version Manager 的缩写,专门用来在同一台机器上安装、切换、维护多个 Node.js 版本。它能帮你解决“不同项目需要不同 Node 版本”这个最常见却又最烦人的问题。这篇文章适合刚接触前端开发的学生、一个人维护多个项目的自由开发者,以及被同事吐槽“本地跑得好好的,怎么到你这就报错”的前端打工人。不需要你有太深的基础,只要照着步骤来,就能把本地 Node.js 环境理顺。
1. 搞清楚为什么非要用 nvm,而不是直接装官方包
很多人第一次装 Node.js 都会去官网下载最新安装包,双击安装,一路 Next,完事。这种方式在电脑只用“一个 Node 版本”的情况下确实没问题,可一旦你同时接触多个项目,或者需要跟团队保持完全一致的版本,官方安装包就成了定时炸弹。
1.1 多版本共存是刚需,不是矫情
Node.js 迭代非常快,每年都会有新版本,而一些老项目由于依赖了旧 API,升级 Node 后轻则警告重则直接跑不起来。比如热词里那个错误:The requested module 'node:util' does not provide an export named,这个我印象太深了,当时就是用 Node.js 18 跑一个有历史包袱的项目,某个依赖用了老写法,版本一高就炸。换句话说,你机器上必须保留多个 Node 版本,并且能在不同项目之间自由切换。
官方安装包的设计是“全局覆盖式”,装一个新的,旧的就被替代了。虽然有些系统里你可以手动解压多个 tar 包,然后把 PATH 换来换去,但那样太麻烦,很容易搞乱。nvm 做的事情,就是把各个 Node 版本按目录存放,在 PATH 层面动态切换当前使用的版本,用户只关心一条命令,不需要碰系统环境变量。
1.2 nvm 和 nvm-windows 是两套东西,别搞混
这里必须强调一个常见误区:我们通常说的 nvm 是 GitHub 上 nvm-sh/nvm 这个项目,官方只支持 Linux 和 macOS。Windows 用户用的 nvm-windows 是另一个独立项目(coreybutler/nvm-windows),名字很像,但命令和使用细节有区别。
区别主要体现在三点:
nvm-sh/nvm是 shell 脚本实现,通过修改环境变量和PATH来切换版本。nvm-windows是 Go 语言写的工具,使用nvm.exe管理版本,需要以管理员身份运行部分命令。- Windows 下还有一个类似工具叫
n,我试用过几次,但它的版本管理方式和nvm-windows不同,如果你习惯了nvm命令,直接用nvm-windows更顺畅。
很多教程把两者混为一谈,导致在 Windows 上执行某些 Linux 专属命令时报错,这不奇怪。使用前先确认自己的系统,再选对应工具。
1.3 不依赖 sudo,权限问题少一半
在 Linux 或 macOS 上直接用官方包安装 Node,经常会遇到“全局安装包时提示没有权限”的尴尬。解决办法是加 sudo,但 sudo npm install -g 会把全局包安装到 /usr/lib 或 /usr/local,权限分配混乱,之后无论升级、卸载还是换版本,都容易留下残留垃圾。
用 nvm 后,所有 Node 版本和全局包都安装在你当前用户目录下的 .nvm 文件夹里。权限归属个人用户,不需要 sudo。这一点在多人共用一台开发机时尤其重要,谁都不希望自己的全局命令突然变成别人的版本。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. nvm 安装与环境配置,一步步来
安装过程不算复杂,但有很多细节会直接影响后面能不能正常用。我按 macOS / Linux 和 Windows 两条线来说,大家各取所需。
2.1 macOS / Linux 安装 nvm
官方推荐的脚本安装方式很清楚。注意不要用 sudo 执行,否则它会安装到被管理的目录之外,后面权限又要乱。常见安装命令:
bash复制curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
如果没有 curl,也可以用 wget:
bash复制wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
脚本执行完成后,它会往你当前 shell 的配置文件中写入一段环境变量配置,比如 ~/.bashrc、~/.zshrc 或 ~/.profile。有时候因为终端不是新开的,或者配置没刷新,nvm 命令会找不到。这时重新加载一下配置文件:
bash复制source ~/.zshrc
然后测试:
bash复制nvm --version
如果输出版本号,就成功了。如果提示 nvm: command not found,先检查配置文件里是否真的写入了那段 NVM_DIR 的代码,再检查是不是装到了 /root/.nvm 这类其他用户目录。
这里有个坑:一些较老的 Linux 发行版默认 curl 没有安装,脚本会报错。解决办法是先安装 curl,或者手动克隆仓库到 ~/.nvm,再手动添加那几行配置。手动方式比较折腾,不太适合新手,我一般建议直接补装 curl 后走官方脚本。
2.2 Windows 安装 nvm-windows
Windows 下我推荐直接下载安装包 nvm-setup.exe。流程大概是:
- 先把系统里已安装的 Node.js 卸载干净,避免版本冲突。
- 双击
nvm-setup.exe,选择 nvm 的安装目录,建议放到D:\nvm这种纯英文且没有空格的目录。 - 安装过程中还会让你选择 Node.js 版本的存放目录,也就是
symlink路径,这里要记住,以后nvm use切换版本时,它就是node.exe所在的位置。 - 安装完成后,打开新的 CMD 或 PowerShell,运行
nvm version验证。
需要注意,Windows 下 nvm use 有时候需要管理员权限。因为 nvm-windows 在切换版本时,要修改系统 PATH 或者创建目录软链接,权限不足会出现“切换失败”或“Access Denied”。所以我的习惯是:以管理员身份打开终端,再执行 nvm use。
还有一个容易踩的坑:安装目录不能包含中文或空格。如果装在 C:\Program Files\nvm,虽然也能用,但某些命令包解析路径时会出问题。我用过几台 Windows 机器,最稳妥的方案就是安装到 D:\nvm 或 C:\nvm。
2.3 配置镜像源,解决下载慢的问题
不管在哪个平台,nvm install 都需要从 Node 官网下载对应版本。网络状况好的时候没问题,一旦不稳定,下载经常卡住或者最后校验失败。解决方法是给 nvm 配置镜像源。
Linux/macOS 下,执行安装或更新时,可以临时指定镜像:
bash复制NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node nvm install 18.20.4
Windows 下更简单,打开 nvm 的安装目录,找到 settings.txt,添加或修改一行:
code复制node_mirror: https://npmmirror.com/mirrors/node/
npm_mirror: https://npmmirror.com/mirrors/npm/
这里我多说一句:镜像源的作用只是把下载源换成速度更快的公共镜像,不影响 Node.js 本身的稳定性。如果你的项目要发布到外网环境,还是建议在实际部署环境用官方源重新安装对应版本,保证版本哈希一致。
3. 核心命令实战:安装、切换、全局配置
nvm 的命令不多,但每一条都很有分量。掌握了这几个核心命令,日常开发基本就够用了。
3.1 查看可用版本列表
在安装之前,最好先看一下当前 nvm 能访问到哪些 Node 版本:
bash复制nvm ls available
Linux/macOS 下这个命令会列出远程所有可用的版本,包括 LTS、Current、以及历史版本。Windows 下同样支持,但输出列表可能很长,你可以用 nvm ls available | head -n 20 之类的命令筛选(Windows PowerShell 里可以用 Select-Object -First 20)。
很多人喜欢直接装最新版,这并不总是好主意。如果你的项目里使用了比较老的原生模块,或者依赖了不兼容的新特性,最新版可能反而会让你多花两个小时去排查。我建议先看项目需求:如果项目没有锁定版本,选 LTS 版本最稳。
3.2 安装指定版本 Node.js
安装指定版本非常简单:
bash复制nvm install 18.20.4
这个命令会从镜像源(如果配置了)下载并安装。安装完成后,Linux/macOS 下 nvm 通常会自动把版本切到刚安装的那个;Windows 下需要手动 nvm use 18.20.4。
如果之后需要同时安装多个版本,重复执行 nvm install 即可。它们会各自存放在独立目录,互不影响。比如我本地长期保留了这几个版本:
12.22.12:维护老项目16.20.2:跑一些旧脚手架18.20.4:稳定主力22.14.0:预览新特性
这样做的最大好处是:切换成本极低,只是 PATH 的指向变了,根本不用重装依赖。
3.3 查看已安装版本和当前版本
想看本地装了哪些 Node 版本,直接:
bash复制nvm ls
当前正在使用的版本前面会有一个 *。另一个命令 nvm current 可以直接输出当前版本,适合在脚本中判断。
注意区分这两个命令:
nvm ls是列表,展示所有已安装版本。nvm list与nvm ls相同,只是别名。nvm current是当前激活的版本。
实际使用中,我经常在切换后马上执行 node -v 确认,不依赖 nvm 的输出。因为某些构建工具启动时会缓存 PATH,新开一个终端来运行最保险。
3.4 切换版本
切换版本是 nvm 最核心的用法:
bash复制nvm use 18.20.4
Linux/macOS 下,这个命令会在当前 shell 会话中更新 PATH。Windows 下则需要管理员权限。切换后,执行 node -v 和 npm -v 都会变成对应版本。
如果你发现切换后 npm -v 没有变化,很可能是因为 npm 的全局路径还指向上一个版本的安装目录。解决办法是重新打开一个终端,或者执行 nvm use 后再执行一次 npm cache clean --force(一般不需要,但强迫症患者可以安慰一下自己)。
3.5 设置默认版本
每次新开一个终端,nvm 默认会使用某个版本。如果这个版本不是你想要的,可以通过别名设置:
bash复制nvm alias default 18.20.4
之后每次打开终端,默认的 node 指向的就是 18.20.4。同理,你也可以给常用版本起一个好记的别名:
bash复制nvm alias lts 22.14.0
nvm use lts
不过要提醒一句:nvm alias default 并不是所有平台的新终端都会自动加载。Linux/macOS 下如果配置了 nvm 的 shell 加载脚本,它会自动读取 default;Windows 下如果你打开的是新终端且没有管理员权限,可能需要先执行 nvm use 才能真正切换 symlink。
3.6 卸载不需要的版本
版本装多了会占用磁盘空间。清理方式:
bash复制nvm uninstall 12.22.12
注意不能卸载当前正在使用的版本,否则会报错。可以先 nvm use 18.20.4 切到其他版本,再卸载。
我见过一个新手朋友把整个 .nvm 目录删了,然后重装,结果全局包全没了。正确方式是只删不需要的版本目录,不要动根目录。nvm uninstall 会自动识别并删除对应目录,比较安全。
3.7 全局配置 npm 和全局包
用 nvm 管理 Node 后,npm 的全局包默认也会按 Node 版本隔离存放。这是好事,意味着你在 Node 18 下全局安装的某个 CLI 工具,切到 Node 22 后不会突然无法加载。但副作用是,同样的工具你可能需要在多个版本里各装一遍。
如果你希望某些全局包在所有版本下都能直接用,有两个思路:
- 每个版本都执行一次
npm install -g <package>,简单直接。 - 在系统层面配置
NODE_PATH指向某固定目录,但容易跟 nvm 的目录管理冲突,不推荐。
更常见的做法是使用 npm config set prefix 来指定全局安装目录,然后把它加入 PATH。但是要注意,这会破坏 nvm 的隔离机制,我不建议普通用户这么做。如果确实有需求,更好的办法是使用后续会提到的 .nvmrc 加一个约定,在项目里锁定版本。
npm 本身还有镜像源问题。尤其是安装 Electron、Puppeteer 这类二进制依赖时,默认源会很慢。先给 npm 配置镜像:
bash复制npm config set registry https://registry.npmmirror.com
验证是否生效:
bash复制npm config get registry
这条命令会把当前 registry 输出出来,看到 npmmirror.com 就说明配置成功。个人建议不要在全局随便更换 registry,毕竟很多公司内部源可能不同;如果某个项目需要不同源,可以在项目里加一个 .npmrc 覆盖。
4. 在真实项目中使用 nvm:.nvmrc 与多项目管理
命令学完了,下一步就是在项目里落地。一个好的团队,应该让每个项目都明确告诉你要用哪个 Node 版本,而不是靠成员之间口头相传。
4.1 创建 .nvmrc 锁定版本
nvm 支持你直接在项目根目录放一个 .nvmrc 文件,里面一般只写一个版本号,例如:
code复制18.20.4
然后执行:
bash复制nvm use
Linux/macOS 下,nvm use 会读取当前目录下的 .nvmrc 并自动切换。这个文件还可以配合 .版本管理器 相关的 shell 钩子实现自动切换,不写的话,每次都要手动执行。
Windows 的 nvm-windows 对这个文件的支持比较弱。实测下来,它不会自动读取 .nvmrc。所以我在 Windows 上会在项目 README 里明确写上“先 nvm install,再 nvm use”,并且在项目脚本里加一个 predev 脚本去检查版本,下面会讲。
4.2 检查 Node 版本的脚本
如果你在 Windows 下使用 nvm-windows,或者团队里有人经常忘切换,可以在 package.json 里加一段版本检查脚本。比如用 Node 内置的 process.version 来判断:
json复制{
"scripts": {
"check-node": "node -e \"if (process.version !== 'v18.20.4') { console.error('请先运行 nvm use 18.20.4'); process.exit(1); }\""
}
}
然后在 dev 或 start 脚本前执行它:
json复制"dev": "npm run check-node && vite"
这样即使队友“忘了切换”,终端也会给出明确提示,而不是花半小时排查一个奇怪的报错。
4.3 多项目并行的切换技巧
同时维护 A、B 两个项目,分别要求 Node 16 和 Node 20,如果只是靠记忆切换,很容易搞混。我的做法是给终端分标签页:一个终端永久停在项目 A 的目录,使用 Node 16;另一个终端停在项目 B 目录,使用 Node 20。这样互不干扰,也降低了误切换的概率。
如果这个还不够顺手,可以配合 shell 的自动切换函数。例如在 ~/.zshrc 里加一段:
bash复制autoload -U add-zsh-hook
load-nvmrc() {
local node_version="$(nvm version)"
local nvmrc_path="$(nvm_find_nvmrc)"
if [ -n "$nvmrc_path" ]; then
local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")
if [ "$nvmrc_node_version" != "N/A" ] && [ "$nvmrc_node_version" != "$node_version" ]; then
nvm use
fi
fi
}
add-zsh-hook chpwd load-nvmrc
这段配置的作用是:每次切换目录时,如果检测到 .nvmrc 且当前 Node 版本不匹配,自动执行 nvm use。注意不要把整段代码直接盲目粘贴到生产环境,需要确认你的 nvm 版本支持 nvm_find_nvmrc,否则会报错。
4.4 团队协作时的版本管理约定
一个好的团队应该在初始化项目时就包含 .nvmrc,同时在文档中写明安装依赖的建议步骤。我看到过很多项目因为没有锁定 Node 版本,导致同一个 package-lock.json 在不同人电脑上解析出完全不同的依赖树,最后升级依赖时出现一堆问题。
建议约定如下:
- 项目根目录放
.nvmrc,版本号必须是明确的比如18.20.4,不要写18这种模糊表达。 package.json中的engines字段也要写上:
json复制"engines": {
"node": ">=18.0.0 <19.0.0"
}
这样通过 npm 或 yarn 安装依赖时,工具会提示当前 Node 版本不满足要求。
- 在 CI 脚本里同样使用
nvm use加载版本,确保线上构建和本地一致。
5. 常见问题与排查技巧实录
这部分是我最想分享的。很多朋友用 nvm 时会遇到各种问题,网上搜索到的答案可能只针对某个平台,容易造成误导。我把自己踩过和帮别人排查过的问题整理成了下面这个小表,后面再展开讲。
| 症状 | 可能原因 | 解决办法 |
|---|---|---|
nvm 不是内部或外部命令 |
安装未完成或环境变量未配置 | 重新执行安装脚本,刷新 shell 配置 |
nvm install 很慢或卡死 |
网络源不稳定 | 配置镜像源,如 npmmirror.com |
nvm use 提示需要管理员权限 |
Windows 权限限制 | 以管理员身份打开终端执行 |
切换版本后 node -v 没变 |
当前 shell 未重新加载 PATH | 新开终端,或手动执行 PATH 刷新 |
| 全局包消失了 | nvm 隔离机制导致 | 在目标版本下重新 npm install -g |
项目启动报 node:util 导出错误 |
某些依赖不兼容 Node 18 | 换成项目指定版本或升级依赖 |
npm -v 与 node -v 版本不对应 |
nvm 版本切换不完全 | 检查当前 npm 所在目录,或回退重试 |
5.1 终端找不到 nvm 命令
这个问题在 macOS 和 Linux 上出现频率最高。安装脚本明明执行完,一关终端再开就找不到 nvm。原因多半是 shell 配置文件没有正确加载。检查 ~/.zshrc 或 ~/.bashrc 中是否有类似这样的一段:
bash复制export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
如果没有,手动补上,然后 source 一下。也有可能是你的 shell 用了 fish,不是 bash/zsh,这种情况下需要在 ~/.config/fish/config.fish 里手动加入 nvm 的初始化逻辑,或者使用 fisher 安装 nvm 插件。
Windows 下找不到 nvm,通常是环境变量没生效或者安装路径有问题。打开系统环境变量,确认 NVM_HOME 和 NVM_SYMLINK 都指向正确路径。我有一次帮同事排查,发现他把 nvm 安装到了 C:\Users\张三\AppData\Roaming\nvm,路径里带中文,导致命令时好时坏。后来卸载重装到 C:\nvm,问题消失。
5.2 切换版本后 node 指向不对
Linux/macOS 下执行 nvm use 18.20.4 后,node -v 显示的仍然是旧版本,这种现象多半是终端里存在 node 的别名,或者在 shell 配置文件里有人写死了 /usr/local/bin 路径。使用 which node 看一下当前指向哪里:
bash复制which node
如果路径不是 .nvm/versions/node/v18.20.4/bin/node,说明 PATH 里还有其他 node 可执行文件的优先级更高。可以在 shell 配置里把 nvm 的初始化脚本放到最后一行的前面,确保 nvm 的 PATH 能覆盖系统路径。
Windows 下则要注意 nvm use 是否真的改变了快捷方式。打开资源管理器,看 nvm 设置的 symlink 目录是否指向了对应版本目录。如果没有,右键 CMD 以管理员身份运行后再试。
5.3 Node 18 出现 node:util 导出推荐问题
热词里那个 The requested module 'node:util' does not provide an export named,本质是某些 npm 包内部通过 require('node:util') 或 import { something } from 'node:util',但该包代码只支持旧版本,也就是它要求 Node.js 但实际没有按照新版 API 发布。这个问题不一定是你 nvm 用错了,而是依赖与 Node 版本不匹配。
排查方式:
- 把 Node 切回项目要求版本,通常项目
.nvmrc里写了。 - 如果必须使用 Node 18,升级相关依赖到支持 Node 18 的版本。
- 如果找不到具体哪个包,通过
npm list查看依赖树,定位引用node:util的包。
这个问题的本质是包的兼容性问题,不是 nvm 的 bug。nvm 这时候最大的价值就是让你快速切回旧版本,让业务先跑起来,不用卡在环境上。
5.4 全局包丢失或命令失效
用 nvm 装了很多版本后,你可能会发现某个全局命令在一个版本下有,切到另一个版本后就消失了。这是正常的,因为 nvm 默认按版本隔离全局包。解决办法是,在需要用到该命令的版本里重新安装一次。
如果不想每次重装,也可以尝试使用 npm link 做链接,但考虑到维护成本,我通常不推荐新手这么干。与其折腾全局包的跨版本共享,不如用项目级依赖,把工具装进 devDependencies。这样既能锁定版本,又不怕 nvm 切换,团队协作时也更可复现。
5.5 nvm 下载 Node 版本时校验失败
有时安装版本时提示校验失败,常见原因有:镜像源偶尔同步不完整、本地网络缓存了断点文件、或者网络波动导致文件损坏。解决方式是清掉 nvm 的缓存,比如 Linux/macOS 下删除 ~/.nvm/.cache,Windows 下删除 nvm 安装目录里的临时文件,然后重新安装。
如果换源后仍然失败,可以先到官网确认这个版本是否存在。某些很老的版本在官方归档里会保留,但镜像源可能没有同步,这时需要直接改 NVM_NODEJS_ORG_MIRROR 指向官方源下载。多试几次相信我,之后你就会习惯先配置镜像源再操作。
6. 除了 nvm,还有这些替代方案
不是非要用 nvm 不可,工具的选择取决于使用场景。我身边有些同事会用 Volta,有些用 fnm,它们各有特点。对比一下你就知道为什么 nvm 还是最主流的选择。
| 工具 | 优点 | 缺点 |
|---|---|---|
| nvm | 历史最久、资料多、多平台兼容 | 命令稍显陈旧,自动切换需要额外配置 |
| nvm-windows | 专为 Windows 设计 | 权限要求多,.nvmrc 支持弱 |
| n | 命令简洁,npm 风格 | 只支持 macOS/Linux,不支持 Windows 原生 |
| fnm | 快、支持 Rust 写的二进制 | 配置依赖 shell 插件,有一定学习成本 |
| Volta | 自动切换速度快,内置工具链 | 项目相对年轻,强制 pin 版本可能有额外依赖 |
我的建议是:新手直接学 nvm / nvm-windows,不要一开始就上小众工具。等把版本管理的基本逻辑理解透了,再根据手感和需求去尝试其他工具。工具只是手段,关键是理解“不同项目需要不同运行环境”这件事本身。
在使用 nvm 的这四五年里,我再也没有因为“本地和线上 Node 版本不一致”而抓狂过。说实话,工具本身很简单,难的是遇到问题后能否快速知道是 nvm 配置问题、依赖兼容问题还是环境变量问题。希望这篇分享能让你少走一些弯路,至少遇到报错时,先看一眼 nvm ls 和 which node,再决定要不要折腾环境。最后一个小技巧是:每装一个新版本,记得顺手执行一次 npm install -g npm@latest,这样可以确保 npm 和 Node 版本对齐,避免后续出现各种奇奇怪怪的 npm 行为。
