Skip to content

Node 版本管理:Windows 用 fnm,macOS 用 nvm

多项目、多机器协作时,Node 版本不一致很容易踩坑。最终方案很简单:

系统工具说明
Windowsfnm原生支持 Windows,速度快,读 .nvmrc
macOSnvm生态成熟,同样读 .nvmrc

项目默认版本统一用根目录的 .nvmrc 锁定,两边都能识别。

早期用过 n,Windows 上也试过 nvm-windows;现在跨平台协作更推荐上面这一套:文件格式统一、命令习惯接近、和 CI(node-version-file: .nvmrc)也好对齐。


为什么 Windows 不推荐 nvm?

这里说的「nvm」在 Windows 上通常指 nvm-windows,它和 macOS/Linux 上的 nvm-sh/nvm 不是同一个东西

核心差异在于:切版本时影响的范围

nvm-windows:改的是全局 Node

nvm-windows 会在系统 PATH 里放一个全局唯一的符号链接(例如指向 C:\Program Files\nodejs)。执行 nvm use 18 时,它改的是这个全局链接的目标目录。

结果是:

  • 一切开着的终端、IDE、脚本立刻都变成新版本
  • 项目 A 切到 18、项目 B 需要 22 时,两边会互相踩
  • 切换往往还要管理员权限(创建/修改系统级 symlink)

也就是说,它更像「整机换一套 Node」,而不是「当前这个项目/这个终端用哪套」。

fnm:按终端用软链接隔离

fnm 同样用软链接,但是每个 shell 会话各自一份(multishell):打开终端时,把当前会话的 PATH 指到一个临时软链接,再由这个链接指向具体的 Node 安装目录。

因此:

  • fnm use / 进目录自动切换,只影响当前终端
  • 可以一边开着 Node 18 的窗口,一边开着 Node 22 的窗口
  • 配合 --use-on-cd.nvmrc,按项目切版本,不会把整机全局版本拧来拧去
nvm-windowsfnm
机制系统 PATH 上的全局 symlink每个 shell 一份 multishell 软链接
use 影响范围整机、所有窗口一起变仅当前终端
多项目并行容易互相覆盖互不影响
.nvmrc支持弱、习惯偏手动全局切原生友好,可进目录自动切

所以 Windows 上最终选 fnm:同样是软链接思路,但作用域是「会话 / 项目」,而不是「改全局 Node」。

macOS 继续用 nvm 没问题——那边的 nvm 是改当前 shell 的环境变量,本身就是会话级的,和 Windows 上 nvm-windows 的全局行为不是一回事。


一、用 .nvmrc 锁定项目版本

在项目根目录创建:

bash
echo "22.12.0" > .nvmrc

内容只写版本号即可,例如:

22.12.0

建议同时在 package.json 里声明:

json
{
  "engines": {
    "node": "22.12.0"
  }
}

GitHub Actions 可直接读 .nvmrc,避免文档、本地、CI 各写一份版本号:

yaml
- uses: actions/setup-node@v4
  with:
    node-version-file: ".nvmrc"

二、Windows:fnm

安装

powershell
# winget(推荐)
winget install Schniz.fnm

# 或 scoop
scoop install fnm

配置 PowerShell

安装后需要把 fnm 接到当前 shell。编辑配置文件:

powershell
notepad $PROFILE

若提示文件不存在,先创建:

powershell
if (!(Test-Path -Path $PROFILE)) { New-Item -ItemType File -Path $PROFILE -Force }
notepad $PROFILE

写入:

powershell
fnm env --use-on-cd --shell powershell | Out-String | Invoke-Expression

保存后重新打开终端。--use-on-cd 表示 cd 进带 .nvmrc 的目录时自动切版本。

常用命令

powershell
fnm install          # 按当前目录 .nvmrc 安装
fnm install 22.12.0  # 安装指定版本
fnm use              # 切换到 .nvmrc 版本
fnm use 22.12.0      # 切换到指定版本
fnm default 22.12.0  # 设置全局默认
fnm list             # 已安装版本
fnm uninstall 18.20.4
node -v              # 确认当前版本

进项目后的最短路径:

powershell
fnm install
fnm use
node -v

三、macOS:nvm

安装

bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash

按脚本提示写入 ~/.zshrc(或 ~/.bashrc),重新打开终端。也可手动确认有类似内容:

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

常用命令

bash
nvm install          # 按当前目录 .nvmrc 安装
nvm install 22.12.0  # 安装指定版本
nvm use              # 切换到 .nvmrc 版本
nvm use 22.12.0      # 切换到指定版本
nvm alias default 22.12.0
nvm ls
nvm ls-remote
nvm uninstall 18.20.4
node -v

进项目后的最短路径:

bash
nvm install
nvm use
node -v

需要 cd 自动切换时,可参考 nvm Deeper Shell Integration


四、日常协作流程

  1. 仓库根目录提交 .nvmrc(版本号与团队约定一致)。
  2. Windows:fnm install && fnm use;macOS:nvm install && nvm use
  3. node -v.nvmrc 一致后再 npm install / 跑脚本。
  4. 升级项目 Node 时:改 .nvmrc(以及 engines.node)→ 本地重新 install + use → CI 自动吃到新版本。
场景建议
团队协作只认 .nvmrc,不要口头约定版本
构建结果不一致先看 node -v 是否和 .nvmrc 一致
多项目频繁切换Windows 开 fnm 的 --use-on-cd;macOS 配 nvm 的目录集成

五、参考链接

旧方案备忘

若机器上还装着 nnvm-windows,可以逐步迁到 fnm / nvm。旧命令大意如下,仅作对照,新项目不必再跟:

bash
# 曾经的 n(偏 macOS / Linux)
sudo npm install -g n
sudo n 22.12.0
n   # 交互选择已安装版本
最近更新