fnm vs nvm

共同点:都用来管理多套 Node.js,都识别 .nvmrc / .node‑version,命令用法大体相似,可以做到几乎无缝迁移。

核心对比表

对比项 nvm fnm
实现 Bash Shell 脚本 Rust 编译二进制单文件
启动速度 慢,每次开终端加载脚本,200‑400ms 极快,毫秒级,几乎无延迟
Windows 原生不支持;要用独立项目 nvm‑windows,两套代码逻辑不一致 原生完整支持 Windows/macOS/Linux,一套工具全平台统一
自动切换 需要手动写 shell 钩子实现 cd 自动切版本 内置 --use‑on‑cd,开箱即用目录自动切换版本
安装方式 git clone + shell 注入配置 单二进制,winget/homebrew/curl 一键安装
社区生态 老牌,教程、问题案例极多 较新,功能齐全,资料略少但够用
全局包 每个 Node 版本独立一套全局包,fnm 同样如此 每个 Node 版本独立一套全局包
CI 使用 脚本安装,初始化慢 单二进制下载,CI 速度快
镜像配置 需要手动改下载源环境变量 支持 FNM_NODE_DIST_MIRROR 环境变量配置镜像地址

底层原理差异

  1. nvm:shell 脚本,每次打开终端修改 PATH 环境变量来切换版本;新开终端会重新执行脚本,带来启动开销;shell 环境复杂时容易出现版本错乱问题。
  2. fnm:Rust 二进制,靠符号链接做版本切换,shell 只注入一小段环境逻辑;绝大部分逻辑在二进制程序内部执行,终端启动开销极小。

命令对照(迁移参考)

nvm fnm
nvm ls fnm list / fnm ls
nvm ls‑remote fnm list‑remote
nvm install lts/* fnm install --lts
nvm use 22 fnm use 22
nvm alias default 22 fnm default 22
nvm uninstall 22 fnm uninstall 22

fnm 额外好用:fnm exec --using=20 -- node xxx.js不改变当前 shell 环境,临时用指定版本跑一条命令,CI、脚本非常方便。

怎么选

选 fnm,如果:

  • 你同时用 Windows + Mac/Linux,想要一套统一工具
  • 受不了打开终端卡顿、shell 启动慢
  • 想要 cd 进项目自动切换版本,不想写复杂钩子
  • CI/自动化脚本场景,追求快速安装

选 nvm,如果:

  • 只使用 macOS / Linux,习惯老生态,大量旧项目文档都是 nvm
  • 遇到疑难问题,优先搜网上海量 nvm 排错案例

迁移注意

不要同时加载两者的 shell 配置,会互相干扰 PATH。
如果你从 nvm 迁移 fnm:注释掉 nvm 的 shell 加载代码,再配置 fnm 的 eval "$(fnm env --use-on-cd)"
fnm 支持导入 nvm 已经下载好的 node:fnm install --from‑nvm

小坑:fnm 不会复用 nvm 的全局 npm 包,每个 node 版本包完全隔离,和 nvm 行为一致。