锁定项目的 Node 版本

Node.js 大版本之间的 API、默认 OpenSSL、模块解析并不完全兼容。仓库没有标明该用哪一版时,有人用 18、有人用 24,故障会表现为「我这机能跑」。把版本写进仓库,再让安装在不对的版本上直接失败,比事后对 node -v 省事。

做法分三层,可以叠用:

  • 告诉版本管理器装哪一版.nvmrc.node-version
  • 告诉包管理器允许哪一档package.jsonengines,必要时 engine-strict=true
  • CI 读同一份声明,避免流水线和笔记本各用各的。

.nvmrc

nvm(node version manager)在 Unix、WSL、Git Bash 里切换 Node 版本。它和 n 一类工具解决的是「本机并排安装多个 Node」。

安装以 nvm 仓库 README 为准,现行脚本示例:

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

装完重开终端(或 source 一次配置文件)。

项目根目录.nvmrc,一行一个 nvm 能识别的版本字符串,末尾换行。不要用 JSON,也不要写成 14.* 这种 npm semver 通配(nvm 不按那套解析)。

22.14.0

也可以写主版本、LTS 别名或 node(最新 Current),详见 nvm --help 里对 <version> 的说明:

22
lts/*
node

不带版本参数时,下列命令会读最近的 .nvmrc(会往上找父目录):

  • nvm use
  • nvm install
  • nvm exec
  • nvm run
  • nvm which

本地没有该版本时,nvm install 会按 .nvmrc 下载。nvm use 只切换已安装的版本。nvm execnvm run 在既没有参数也找不到 .nvmrc 时,会退回到当前已激活的 Node,脚本里不要依赖这个回退。

nvm 不会cd 进目录时自动切换,除非你自己加了 shell 钩子(README 里有 cd 后自动 nvm use 的例子)。zsh 也可用 zsh-nvmNVM_AUTO_USE

nvm-windows 不读 .nvmrc 它和 nvm-sh 不是同一个项目。Windows 原生更省事的是 fnm、Volta;或在 WSL 里用 nvm-sh。

engines

package.jsonengines 声明本包适用的 Node(以及可选的 npm)范围,语法是 semver,不是 .nvmrc 那种单行别名:

{
  "engines": {
    "node": ">=22.0.0 <25"
  }
}

范围按项目真实支持来写:只测过 22 就不要写成 *

默认情况下,npm install 只警告、不失败,因为 npm 的 engine-strict 默认是 false。Yarn 1 会检查 engines,不匹配就退出,这才是多数人想要的。

要让 npm 也不匹配就失败,在项目根目录加 .npmrc 并提交进仓库:

engine-strict=true

版本不对时大致是:

npm ERR! engine Unsupported engine
npm ERR! engine Not compatible with your version of node/npm: ant-design-pro@1.0.0
npm ERR! notsup Required: {"node":">=14.0.0 < 15.0.0"}
npm ERR! notsup Actual:   {"npm":"9.5.1","node":"v18.16.0"}

pnpm 同样认 .npmrc 里的 engine-strict。这只挡住 安装,已经装好依赖、只是换了 Node 再直接 node app.js,不会再走一遍检查。

较新的 npm 还有 devEngines,用来约束「正在开发这份源码」的人用哪套 runtime,和面向安装你这个包的用户的 engines 不是同一字段。

用脚本再挡一层

engines 管的是 install。若还要在 npm run、或别人没开 engine-strict 时拦住,可以在仓库里放一个检查脚本。适合 应用仓库;发到 registry 的库不要用 postinstall 把消费者的安装直接 exit 1,声明 engines 即可。

开发依赖装 semver:

npm i -D semver

checkver.js

const semver = require('semver');
const { engines } = require('./package.json');
const range = engines.node;

if (!semver.satisfies(process.version, range)) {
  console.error('Required node version ' + range + ', got: ' + process.version);
  process.exit(1);
}

package.json

{
  "scripts": {
    "postinstall": "node ./checkver.js"
  }
}

postinstall 在本地 npm install 之后跑。也可以改成 prestartpretest,只在启动和测试时检查。

CI 对齐

GitHub Actions 的 actions/setup-node 可以用同一份文件,避免 CI 写死一个和 .nvmrc 不同的号:

- uses: actions/setup-node@v6
  with:
    node-version-file: '.nvmrc'

node-version-file 也认 .node-version.tool-versionspackage.json(会依次看 volta.nodedevEngines.runtimeengines.node)。本地声明和流水线读同一处,版本才算锁住。

常用 Node 版本管理工具

  • nvm(nvm-sh):命令行安装、切换多个 Node。适用于 macOS、Linux、WSL、Git Bash。读 .nvmrc。Windows 原生请改用下面几项,或 nvm-windows(命令相近,不读 .nvmrc)。nodist、nvs 也是 Windows 上的替代。
  • n:交互式切换,几乎没有配置文件。适用于 macOS、Linux,不适用于 Windows。较新版本可用 n auto.nvmrc.node-version
  • fnm:Rust 写的,启动快。macOS、Windows、Linux 都能用。读 .nvmrc.node-version,可配置 cd 进目录后自动切换。
  • Volta:也跨平台。不靠 .nvmrc,用 volta pin node@22.14.0 把版本写进 package.jsonvolta 字段;之后在该仓库里跑 nodenpm 会走钉住的版本。团队若要「进目录即正确版本」,Volta 比「记得敲 nvm use」更硬。

asdf、mise 一类通用版本管理器用 .tool-versions(如 nodejs 22.14.0),不读 .nvmrc,除非另做插件映射。

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-09-02 01:19:40

results matching ""

    No results matching ""