从 nvm 到 fnm:更快、更省心的 Node.js 版本管理器迁移指南
如果你受够了每次开终端都要等上好几秒、
nvm use在新 shell 里"失忆"、Windows 上还得装nvm-windows这个另起炉灶的分支——那么fnm(Fast Node Manager)值得你花十分钟迁移过来。
一、为什么需要 Node.js 版本管理器
前端生态迭代极快:一个老项目可能锁死在 Node 16,新项目却要用 Node 22 的原生 ESM 与测试运行器。手动装/卸 Node 版本既痛苦又容易污染全局。版本管理器的价值在于:
- 一键切换:
nvm use 18/fnm use 18秒切版本 - 目录自动切换:进入项目目录自动读取
.nvmrc/.node-version,无需手动 - 隔离全局依赖:每个 Node 版本有独立的全局
node_modules,互不干扰
二、nvm:经典但显老
nvm(Node Version Manager)是社区最老牌的方案,GitHub 仓库nvm-sh/nvm累计~81k stars。
优点:
- 生态最成熟,几乎所有教程都默认你用 nvm
- 纯 Bash/Zsh 脚本实现,零额外依赖
痛点:
- 慢:每次启动 shell 都要
source nvm.sh,这段脚本会同步加载所有版本元数据,冷启动开销大(普遍几百毫秒到数秒) - Windows 不官方支持:必须改用第三方分支
coreybutler/nvm-windows,命令和实现都和 macOS/Linux 版不一样 - 自动切换靠手搓 hook:需要自己在
.bashrc里写cd钩子才能根据.nvmrc自动切版本 - 单线程 shell 脚本:下载、解压、读元数据都没有并行优化
三、fnm:用 Rust 重写的现代替代品
fnm(Fast Node Manager)由 Gal Schlezinger 开源,仓库地址Schniz/fnm,目前26.4k stars,用Rust编写,单一二进制文件。
核心优势:
| 特性 | nvm | fnm |
|---|---|---|
| 实现语言 | Bash/Zsh 脚本 | Rust 编译二进制 |
| 安装包体积 | 脚本(KB 级) | 单二进制(~5MB) |
| Shell 启动开销 | 较大(source 脚本) | 极小(仅注入一个 shell 函数) |
| 版本切换速度 | 慢(同步解析) | 快(并行下载 + 缓存) |
| Windows 原生支持 | ❌ 需 nvm-windows 分支 | ✅ 原生支持 |
.nvmrc自动切换 | 需手写 cd 钩子 | ✅ 内置--use-on-cd |
.node-version支持 | ❌ | ✅ |
| 多架构(arm64 等) | 支持 | 支持 |
简单说:fnm 把 nvm 做的事,用 Rust 重新做了一遍,而且做得更快、更跨平台、开箱即用。
四、安装 fnm
macOS / Linux(推荐 Homebrew 或脚本)
# 方式一:Homebrew(macOS / Linuxbrew)brewinstallfnm# 方式二:官方安装脚本(curl)curl-fsSLhttps://fnm.vercel.app/install|bashWindows
# 方式一:Scoopscoop install fnm# 方式二:Wingetwinget install Schniz.fnm# 方式三:Chocolateychoco install fnm配置 Shell 集成(关键一步)
安装后必须把 fnm 的 shell 钩子加到你的启动脚本里,并开启自动切换:
Bash(~/.bashrc):
eval"$(fnmenv--use-on-cd--shellbash)"Zsh(~/.zshrc):
eval "$(fnm env --use-on-cd --shell zsh)"PowerShell($PROFILE):
fnm env--use-on-cd--shell powershell|Out-String|Invoke-ExpressionFish(~/.config/fish/config.fish):
fnm env --use-on-cd --shell fish | source💡
--use-on-cd是 fnm 的杀手锏:进入任何含.nvmrc或.node-version的目录时,自动切换到对应 Node 版本;离开时自动切回默认版本。nvm 需要你手写钩子才能实现。
配置完成后重启终端,验证安装:
fnm--version五、命令对照表(nvm → fnm 迁移速查)
这是迁移过程中最常查的部分,建议收藏:
| 操作 | nvm 命令 | fnm 命令 |
|---|---|---|
| 安装指定版本 | nvm install 18 | fnm install 18 |
| 安装最新 LTS | nvm install --lts | fnm install --lts |
| 使用某版本(当前 shell) | nvm use 18 | fnm use 18 |
| 设默认版本 | nvm alias default 18 | fnm default 18 |
| 列出已装版本 | nvm ls | fnm list |
| 列出远程可装版本 | nvm ls-remote | fnm list-remote |
| 卸载某版本 | nvm uninstall 18 | fnm uninstall 18 |
| 查看当前版本 | nvm current | fnm current |
| 执行指定版本的命令 | nvm exec 18 node app.js | fnm exec --using=18 node app.js |
| 跑一次性命令 | nvm run 18 --version | fnm run --using=18 --version |
可以看到,命令几乎是一一对应的,记忆成本极低。
六、完整迁移流程(nvm → fnm)
Step 1:记录当前 nvm 管理的版本
迁移前先摸清家底,避免遗漏:
nvmls记下你实际在用的版本(比如 16.20.2、18.20.4、20.18.0),以及默认版本。
Step 2:安装 fnm
按上一节的步骤安装并配置好 shell 集成,确认fnm --version正常输出。
Step 3:用 fnm 重新安装所需版本
# 安装你记录下来的版本(支持模糊匹配,自动装该大版本最新)fnminstall16fnminstall18fnminstall20# 安装最新 LTS 版本fnminstall--lts# 设置默认版本(相当于 nvm alias default)fnm default20fnm 的版本号支持模糊匹配:
fnm install 18会自动装 18.x 的最新版;--lts则安装当前最新的 LTS 版本。
Step 4:迁移.nvmrc习惯
好消息:fnm 完全兼容.nvmrc,你项目里现有的.nvmrc文件无需任何修改。
只要开启了--use-on-cd,cd进项目目录就会自动fnm use对应版本。你也可以手动触发:
fnm use# 读取当前目录的 .nvmrc / .node-versionfnminstall# 读取 .nvmrc 并安装对应版本(首次进入新项目时很方便)Step 5:确认全局 npm 包
注意:fnm 和 nvm 的版本目录结构不同,全局包不会自动继承。迁移后需要在每个版本下重装你依赖的全局工具(如pnpm、yarn、tsx、nodemon等):
fnm use20npminstall-gpnpmyarntsx如果你全局包很多,建议先在 nvm 下导出清单:
nvm use20npmls-g--depth=0>global-packages.txt再用脚本批量重装。
Step 6:卸载 nvm(可选)
确认 fnm 一切正常后,可以清理 nvm:
1. 从 shell 启动脚本中移除 nvm 配置
编辑~/.bashrc/~/.zshrc,删除或注释掉以下类似行:
# export NVM_DIR="$HOME/.nvm"# [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"# [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"2. 删除 nvm 目录
rm-rf"$NVM_DIR"# 通常是rm-rf~/.nvmWindows(nvm-windows):通过"添加或删除程序"卸载,再删除%NVM_HOME%与%NVM_SYMLINK%指向的目录,并清理环境变量NVM_HOME、NVM_SYMLINK。
Step 7:验证迁移成功
# 确认 fnm 生效、node 来源正确whichnode# 应指向 fnm 管理的路径(如 ~/.fnm/...)node-vfnm current fnm list# 测试自动切换:进入一个有 .nvmrc 的项目cdyour-project/ fnm current# 应自动切到 .nvmrc 指定的版本七、迁移决策建议
一句话总结:
- 如果你在 Windows 上,或受够了 shell 启动慢 / 自动切换难用,迁移到 fnm 收益巨大,且
.nvmrc零成本兼容。 - 如果你深度依赖 nvm 的某些边缘特性、或团队强制统一,fnm 也能和平共处(两者可并存,只要 shell 启动脚本里只
eval一个)。
八、常见坑与 FAQ
Q1:迁移后node命令找不到了?
A:99% 是 shell 集成没配好。确认启动脚本里有eval "$(fnm env --use-on-cd)",并重启终端。用which node检查路径是否在~/.fnm下。
Q2:fnm 和 nvm 能同时装吗?
A:能装,但同一个 shell 会话里只应激活一个。如果node路径混乱,检查启动脚本里是否同时source了 nvm 和eval了 fnm,注释掉其一即可。
Q3:--use-on-cd没生效?
A:确认配置时带了--use-on-cd参数(不是只写fnm env)。另外,离开目录时 fnm 默认切回fnm default设的版本,记得先fnm default 20设一个默认值。
Q4:CI 环境怎么用 fnm?
A:GitHub Actions 官方有Schniz/fnmaction,或用fnm install && fnm use两行搞定,比 nvm 快很多。
Q5:fnm 安装包从哪下载?会不会很慢?
A:fnm 从 Node 官方源下载 Node 二进制。国内可通过设置镜像加速:
exportNODE_DIST_URL=https://npmmirror.com/mirrors/node fnminstall20九、参考链接
- fnm 官方仓库:https://github.com/Schniz/fnm
- fnm 官方文档:https://fnm.vercel.app
- nvm 官方仓库:https://github.com/nvm-sh/nvm
- nvm-windows:https://github.com/coreybutler/nvm-windows
写在最后:版本管理器是开发体验里"基础设施级"的工具,换一个更快的,每天能省下的等待时间是复利。fnm 用 Rust 把这件事做到了近乎完美——跨平台、快、兼容.nvmrc,迁移成本远小于你想象。如果你还在用 nvm,不妨今晚就试试。