DEBUG.WIKI
OnlineSIM:在线接收短信,虚拟号码租用
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →

pnpm add 指定 tag 却装了另一版:比较选择器、保存范围和锁定结果

pnpm 12.15.0 可能先把 tag 解析成保存范围,再按范围选了更高版本。使用审定的精确版本和 save-exact,不能只看 package.json 判断安装结果。

执行 pnpm add 包名@tag,清单里保存的版本看起来合理,锁文件和实际安装却是更高的另一版。若使用 pnpm 12,比较原选择器、写入清单的范围,以及最后锁定的精确版本,三者不一定相同。

pnpm 12.15.0 中有明确的这条回归,12.10.1、12.11.1、12.11.2、12.13.0 也有相同表现。问题不仅限于 tag:带上界的范围可能先解析为一个合格版本,保存成较宽范围后,再安装到原上界之外。

保存的范围丢掉了本次选择意图

例如某个 tag 指向 1.2.3,同系列还有更高的 1.2.9。add 可以把 tag 解析成 1.2.3,再把 ^1.2.3 写进清单;随后的安装若只看这个范围,就可能选中 1.2.9。这些数字说明关系,不表示任何真实包当前的 tag 指向。

已核对的 12.15.0 add 实现会把显式 registry 选择器转成待保存范围,普通 add 没有像对应更新路径一样把本次选定版本完整带入后续安装偏好。已有锁定版本若仍符合保存范围,也可能被保留。不能只凭“下载到了新版本”就归因于 registry 缓存或发布时间策略。

先在项目允许的 registry 核实真实 tag/范围对应的可用版本,再看锁文件与实际包版本。移动 tag 本来可以改变指向,排查记录必须带读取时间,不能把某天的 tag 映射当成永久规则。

必须装指定版本时,临时把清单也锁精确

若项目已经审定了某个精确版本,可通过原安装入口指定它,并使用 --save-exact,例如:

pnpm add example-lib@1.2.3 --save-exact

example-lib 与版本是占位,替换为核实过的包和版本。保留原来的 dependency 类型、过滤器和工作区范围;原来是开发依赖时,不要把它移成生产依赖。保存清单和锁文件,检查变化只覆盖预期包及必要的依赖调整。

这会让后续安装也采用精确约束,改变原先允许范围内更新的策略,因此适合明确需要固定版本的场景。不能一边把所有依赖钉死,一边宣称项目的升级政策完全没变。原本依赖 tag 自动滚动的项目,应在正式修正并通过回归后,再按团队策略恢复范围。

同时核对新增与重新指定版本

检查清单、lockfile importer 和实际包入口的版本一致,并覆盖“此前已锁到更高版本后,再明确指定较低版本”的入口,避免旧 pin 被无意保留。再按原流程完成可重复安装与构建,确认不是只改了清单文本。

这里无需删除整个 store 或锁文件,也不必关闭发布时间限制。采用后续正式版本时,仍用原 tag 和带上界范围做回归;源码修正方向明确,不代表已经安装的 12.15.0 会自动改变选择结果。