前端必备:NVM管理Node版本不翻车,新手老手都能用
- 前端必备:NVM管理Node版本不翻车,新手老手都能用
- 先说个扎心的事儿
- NVM到底是个什么鬼
- 为啥非得用这玩意儿不可
- 安装过程其实没那么复杂
- Mac用户看这里
- Windows用户看这里
- Linux用户看这里
- 常见安装坑
- 常用命令给你捋一遍
- 查看和安装版本
- 切换和使用版本
- 设置别名和默认版本
- 卸载和维护
- Windows版的一些差异
- 实际项目里怎么玩转
- 项目根下建个
.nvm文件夹,里面给每个Node版本都搞个独立的小房间。当你
nvmuse
18的房间门打开,把路径指向那里;当你
nvmuse
14的时候,又切换到另一个房间。
各个版本之间井水不犯河水,全局安装的包也是分开存放的,互不干扰。
这里有个细节可能有人没注意:NVM管理的Node版本,和你去nodejs.org官网下载的.pkg或.msi安装包安装的Node,在系统里是两码事。
如果你之前手动装过Node,最好先把那个卸载干净,再让NVM接管,不然容易打架。
为啥非得用这玩意儿不可
你想想啊,现在前端生态更新这么快,Node几乎年年大版本迭代,LTS长期支持版本都赶趟儿似的。
2023年Node
22又来了,这谁顶得住?
老项目依赖旧版本,可能是因为某个古老的依赖包还没适配新API;新项目要用新特性,比如Node
Runner;测试还得覆盖多个版本,确保你的库在Node
14到Node
20都能跑。
没有NVM的话,你每次切换都得手动卸载安装,npm全局包全得重装,耗时耗力还容易出错。
更现实的问题是团队协作。
你电脑上是Node
14,同样的代码在不同机器上表现可能完全不一样。
最常见的就是
package-lock.json冲突,Node版本不同生成的lock文件结构都有差异,合并代码时简直噩梦。有了NVM,一条命令秒切版本,效率直接拉满。
而且配合
.nvmrc文件,可以做到项目级别的版本锁定,从根本上解决"在我电脑上能跑"的经典难题。安装过程其实没那么复杂
Mac用户看这里
Mac用户最爽,直接用Homebrew一条龙服务:
#先确保你有Homebrew,没有的话去brew.sh装一个
brewinstallnvm装完之后,别急着用,还得告诉shell怎么加载它。
打开你的shell配置文件,如果是zsh(Mac
Catalina之后默认就是这个)就编辑
~/.zshrc,如果是bash就编辑~/.bash_profile或~/.bashrc:#在文件末尾加上这两行
exportNVM_DIR="$HOME/.nvm"[-s"/opt/homebrew/opt/nvm/nvm.sh"]&&\."/opt/homebrew/opt/nvm/nvm.sh"#This
nvm
[-s"/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm"]&&\."/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm"#This
bash_completion
注意啊,M1/M2/M3芯片的Mac,Homebrew路径可能在
/opt/homebrew,Intel芯片的在/usr/local/opt/nvm,上面那段配置要对应修改。我之前就栽过这个坑,复制粘贴网上的配置发现不生效,后来才发现路径不对。
加完配置后,记得source一下或者重启终端:
source~/.zshrc#验证安装
nvm的版本号
Windows用户看这里
Windows用户去GitHub搜
nvm-windows,找coreybutler维护的那个项目,下载最新的nvm-setup.exe安装包。安装过程一路下一步就行,但有个地方要注意:安装路径最好别带空格和中文,比如别装在
C:\ProgramFiles\nvm,容易出各种玄学问题。
我习惯装在
C:\nvm或者D:\nvm。装完之后,新开一个PowerShell或者CMD窗口(注意一定要新开,旧的缓存了环境变量),输入:
nvmversion#
1.1.12
Windows版有个小差异,它用
nvmlist
available查看可安装版本,而Mac/Linux版是
nvmls-remote。
这个后面会细说。
Linux用户看这里
Linux用户通常用curl或wget下载安装脚本执行:
#用curl
curl-o-https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh|bash#
或者用wgetwget-qO-
https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh|bash
脚本会自动往你的
~/.bashrc、~/.zshrc或~/.profile里追加配置。装完同样要source一下或者重新登录。
source~/.bashrcnvm
--version
常见安装坑
这里有个
universal
的坑,不管你什么系统都可能遇到:装完记得完全重启终端,甚至重启电脑。
有时候环境变量已经写进去了,但当前终端会话没加载,你输入
nvm就提示commandnot
found,其实并不是没装好,只是需要刷新一下。
还有一个权限问题,特别是在公司电脑或者有IT管控的机器上。
Mac/Linux如果遇到
Permissiondenied,检查下
.nvm,而不是系统放.nvmrc这是最重要的一个习惯。
每个项目根创建.nvmrcecho"18.19.0">.nvmrc#
或者写大版本号,自动用最新的18.xecho"18">.nvmrc#
也可以用别名echo"lts/*">.nvmrc
同事拉下代码后,只需要在项目下的
.nvmrc文件并切换到对应版本。如果本地没装这个版本,会提示你先
nvminstall。
配合package.json的engines字段
.nvmrc是给NVM看的,package.json里的engines字段是给npm看的,双保险:{"name":"my-awesome-project","version":"1.0.0","engines":{"node":">=18.0.0<19.0.0"
,"npm":">=10.0.0"}}这样如果用户用了错误的Node版本运行
npminstall,npm会发出警告。
配合一些CI工具,还可以强制检查。
加个npm脚本检测版本
有时候
.nvmrc容易被忽略,可以在package.json里加个前置脚本:{"scripts":{"preinstall":"node\"const
}\""
,"start":"react-scriptsstart"
,"build":"react-scriptsbuild"
}}这样每次
npminstall前都会检查Node版本,不对就报错退出,从源头避免版本问题。
CI/CD流水线配置
GitHub
Actions、GitLab
Actions为例:
#.github/workflows/ci.yml
name:CIon:[push,pull_request]jobs:build:runs-on:ubuntu-lateststeps:-uses:actions/checkout@v4#安装NVM并读取.nvmrc
-name:SetupNode.jsuses:actions/setup-node@v4with:node-version-file:'.nvmrc'#
自动读取.nvmrccache:'npm'-run:npm
ci-run:npm
run
build-run:npm
test
这样保证构建环境和开发环境完全一致,再也不怕"我本地能构建,CI却挂了"的尴尬。
团队多人协作规范
我们团队内部有个不成文的规定:
- 每个项目必须有
.nvmrc文件,代码审查时检查 - 新人入职文档里专门有一节"安装NVM并运行项目"
- 项目README里第一段就是环境要求,加粗提示
- 定期(比如每季度)评估升级Node版本,统一迁移
这些习惯能省掉一堆沟通成本。
以前经常有同事在群里问"我这个报错是为什么",后来发现八成是Node版本不对。
现在有了
.nvmrc,这类问题基本绝迹。这玩意儿有啥优缺点
优点很明显
切换快:一条命令秒切,比手动卸载重装快多了。
特别是需要同时维护多个项目时,效率提升巨大。
隔离好:每个版本的Node和全局包都是独立的。
你在Node
18全局装了
pnpm,切换到Node16时看不到它,互不干扰。
这避免了版本间的污染问题。
不污染系统环境:NVM把一切都放在用户存在不
- 每个项目必须有
- 检查shell配置文件里有没有加载NVM的脚本(前面安装部分的那两行)
- 检查路径对不对,特别是M1
Mac的Homebrew路径
- 执行
source(或对应的配置文件)刷新当前终端~/.zshrc
- 如果都不行,试试重启终端或重启电脑
- 检查当前shell会话是不是开了很久,环境变量可能没刷新。
关掉重开终端最简单。
- 检查是否有系统级的Node路径优先级更高。
执行
whichnode,如果显示的是
/usr/local/bin/node而不是~/.nvm/versions/...,说明系统PATH优先级问题。需要调整shell配置文件,把NVM的加载放在后面(这样它的路径会prepend到PATH前面)。
- 检查是否有其他Node版本管理工具冲突,比如之前装过
n或者手动安装的Node。
切换了版本但node
-v没变
现象:执行了
nvmuse
-v还是显示旧的版本
排查步骤:
全局包不见了
现象:切换Node版本后,之前全局安装的
vue、create-react-app等命令找不到了原因:NVM的每个Node版本有独立的全局包时,会自动读取
.nvmrc并切换版本,完全无感知。和同类工具比咋样
NVM不是唯一的Node版本管理工具,市面上还有几个竞争者,各有各的适用场景。
nvm-fish
如果你用Fish
shell而不是zsh/bash,原生NVM支持不好,可以用
nvm-fish。它是专门为Fish
shell封装的,命令一样,但底层适配了Fish的语法。
fnm
(Fast
Manager)
用Rust写的,主打一个快。
安装和切换版本的速度确实比NVM快不少,特别是Windows上。
它还支持
.node-version文件(和.nvmrc类似),以及跨shell的自动切换。#fnm的安装
curl-fsSLhttps://fnm.vercel.app/install|bash#
命令和NVM很像fnminstall18fnm
default18
缺点是生态没NVM成熟,遇到问题Stack
Overflow上的答案少,适合喜欢折腾和追求速度的玩家。
Volta
另一个Rust写的工具,理念更现代。
它会自动读取
package.json里的engines字段,自动安装和切换版本,不需要手动use。还支持全局包的版本锁定,比如你可以指定
yarn用1.22版本,而不管当前Node版本。#Volta安装
curlhttps://get.volta.sh|bash#安装Node
voltainstallnode@18#安装全局包并锁定版本
voltainstallyarn@1.22.19Volta的问题是还在快速发展中,有些边缘场景支持不完善,而且和NVM的
.nvmrc不兼容。如果你的团队已经统一用NVM,迁移成本较高。
怎么选?
- 新手/团队协作者:选NVM,文档多,社区大,遇到问题好解决
- 追求速度的个人玩家:试试fnm
- 喜欢全自动管理:试试Volta
- Fish
shell用户
:nvm-fish或fnm
但说实话,NVM社区最活跃,Stack
Overflow上的问题也最多,对于需要稳定性的工作场景,NVM仍然是首选。
一些掏心窝子的建议
用了这么多年NVM,最后分享几个血泪教训:
别在项目里写死绝对路径
有些配置文件的坑位喜欢写死Node的绝对路径,比如
#!/usr/bin/envnode这种shebang是好的,但写成
#!/Users/yourname/.nvm/versions/node/v16.20.2/bin/node就完蛋了。NVM管理后路径会变,一旦升级Node版本,这些硬编码路径就失效。
团队内部统一工具链
如果团队用NVM,就统一写进新人手册;如果有人用fnm有人用Volta,最好统一一下,不然
.nvmrc、.node-version、package.json里的配置打架,反而增加混乱。定期更新NVM本身
NVM也在迭代,新版本会修bug、支持新特性。
偶尔执行一下:
#upgrade
或者手动更新
cd"$NVM_DIR"&&gitfetchorigin&&gitcheckout$(gitdescribe
--abbrev=0--tags)
重要项目锁定版本,别盲目追新
Node的新版本固然香,但生产环境稳定压倒一切。
我们有个习惯:线上跑的项目,Node版本至少落后LTS最新版一个大版本。
比如Node
20是LTS了,我们生产环境可能还在18,等20成熟稳定了再迁移。
迁移前先在测试环境跑几周,确认没问题再上生产。
备份你的.nvmrc和配置
虽然
.nvmrc是提交到git的,但你的NVM别名、默认版本设置这些在个人环境里。重装系统前记得备份:
#list>~/nvm-backup.txt#
导出别名
nvmalias>~/nvm-aliases.txt恢复时就照着列表重新install一遍。
最后
NVM不是什么高科技,但它解决的是前端开发中最常见也最烦人的问题。
配置好它,相当于给你的开发环境打了个坚实的基础,后面跑项目、切分支、协作开发都会顺畅很多。
别小看这些工具链的投入,前期花半小时配置好,后期能省下数不清的调试时间和沟通成本。
毕竟,我们的精力应该花在实现业务逻辑上,而不是跟环境较劲,对吧?
好了,今天就聊到这。
去装个NVM,建个
.nvmrc,享受版本切换的自由吧!
- 项目根下建个


