具体值版本范围锁文件推断兜底候选
Node 项目 · 包自身运行要求 Node ≥ 18先确定来源,再排队合并,最后选版本
↘

调用方直接输入

不沿父目录查找

独立包的输入参数

input

01node
02packageManager
完整版本 → 具体值任意 semver 范围

18.20.8 → 单一版本
18 → 18.x
18.20 → 18.20.x

^18.20 · ~18.20
>=18 <21 · *
18 || 20 · 18 - 20

采用 node-semver 的范围语法 ↗;包管理器填写 名称@范围。
由调用方传入一次

调用方把已有配置转换为 node 和 packageManager 传入。包本身只接收这两个值。

最高优先级
直接排在队首
↑

项目文件逐级向上读取

这些来源都与所在目录有关;先读完一层,再进入父目录

查找起点
传了 cwd → 指定目录没有传 cwd → process.cwd()(pwd)
startDir
停止目录从 startDir 定位所属 Git 仓库→gitRoot

读取 startDir → 父目录 → … → gitRoot,包含两端;不越过 gitRoot。Git worktree 的 .git 文件也属于仓库标记。

目录不属于 Git 仓库时,只读取 startDir 并警告,不向文件系统根目录继续查找。

从这里开始当前目录 = startDir层数 = 0
读取本层的 03 → 16文件存在就收集声明
记下目录层数与来源编号
每层都查这些来源
当前目录是
gitRoot 吗?
否 · 继续 ↑进入父目录层数 + 1
是 · 结束 ↓停止收集根目录已读取
gitRoot 的父目录不读取
每层目录,重复读取这一整张表编号只决定同目录内的顺序
具体值 = 单版本范围精确程度不改变来源顺序
实际路径示例
/repo/packages/web↑/repo/packages↑/repo读完即停
startDir · 第 0 层 → 第 1 层 → gitRoot · 第 2 层
↓ 每层的声明按下方顺序进入队列
严格采纳顺序先比较目录,再比较本层编号
调用方输入01 → 02
startDir · 第 0 层03 → 16
父目录 · 第 1 层03 → 16
…
gitRoot · 最后一层03 → 16

本层 .nvmrc 优先于 父层 volta.node,也优先于 父层 packageManager。同目录、同字段的重复项按出现顺序。

每层只读取一次;如果 startDir 就是 gitRoot,目录队列只有第 0 层。

1

加入约束前,带上 Node 要求

包管理器条件 → 候选具体版本

有锁文件时:查随包的冻结安装兼容表 → 得到可用的包管理器具体版本集合或有证据的范围。

查官方包元数据
engines.node
得到每个候选
支持的 Node 范围
包管理器版本与其 Node 要求一起参加合并,沿用原声明的目录层数和来源优先级。查看包版本与 engines.node 的记录 ↗
加入本条后,仍有可运行的
Node + 包管理器组合?
是 ↓保留本条
否 ↓忽略本条 + 警告
↻ 取下一条,直到队列为空

兼容的父层条件继续收窄范围;冲突条件及其推导的 Node 要求一起忽略。没有包管理器类型声明时,默认使用 npm。

2

确定 Node 版本

具体值有保留的具体版本?

有 → 采用该版本

否则 ↓
读取当前 Node 进程当前 Node 版本
这个版本满足保留条件?

是 → 采用当前版本

否则 ↓
范围取满足声明与预发布规则的最大版本

从官方 Node 发行表中筛选,再取最大值。

↓ 选定 Node 版本
3

确定包管理器版本

具体值有保留的具体版本?

有 → 采用该版本

否则 ↓
选 npm 时上一步选定的 Node该 Node 绑定的 npm 版本
选 pnpm / Yarn 时pnpm --version / yarn --version本地安装的具体版本
候选满足范围,且支持选定 Node?

是 → 采用候选版本

否 / 未安装 → 从官方包版本表中,取满足两者的最大版本

✓ Node + 包管理器
↳

完全没有声明:使用当前进程的 Node 和与它绑定的 npm。“最大版本”:从实时获取、符合预发布规则的候选版本中,按 semver 条件取最大值。锁兼容性来自有证据的冻结安装记录,查看数据来源与维护规范。未知兼容性单独警告,不能当作冲突或通过。

预发布版本规则

默认只选择稳定版;用户显式声明允许时,可以采用匹配的预发布版。

预发布许可只对被声明的工具生效。锁文件推断、版本统计和兼容数据维护仍只处理稳定版。

packageManager: "pnpm@>=10.0.0-rc.1 <10.0.0"

这里允许 pnpm 使用匹配的预发布版;推导 Node 时仍只选稳定版,除非 Node 自己的显式声明也允许预发布版。