Node.js 包版本约束与依赖类型
· 4 min read
package.json 里的版本号不是装饰——它决定下游装你的包时会拿到什么。
- SemVer 三段式:major.minor.patch,递增规则:破坏性变更 / 新功能 / bugfix
- 范围符号核心:4 个最常用 ——
^~*>= - 0.x.x 陷阱:
^0.6.6实际只升 patch,不升 minor - 5 种依赖类型:dependencies / devDeps / peerDeps / optionalDeps / bundledDeps
- peerDeps 行为变化:npm 7+ 默认自动安装(npm 3-6 还会警告)
- 现代替代:
overrides(npm)/resolutions(Yarn)取代 bundledDeps
SemVer 不是"三个数字"
Node.js 全套包管理工具都遵循 SemVer 2.0.0 三段式:major.minor.patch。
递增规则(递增时把后面段归零):
- major:破坏性变更,不兼容老版本
- minor:新功能,向后兼容
- patch:bugfix,向后兼容
例:2.6.6 的下一个 minor 是 2.7.0(minor +1,patch 归零)。规范本身不难,下面这些 范围符号 才是真正用错的坑。
范围符号:^ ~ * >=
| 符号 | 语义 | 例子 | 实际匹配范围 |
|---|---|---|---|
^ | 升 minor + patch(npm/yarn 默认) | ^2.6.6 | >=2.6.6 <3.0.0 |
~ | 升 patch | ~2.6.6 | >=2.6.6 <2.7.0 |
* | 任意版本 | * | >=0.0.0 |
>= | 大于等于 | >=2.6.6 | >=2.6.6 |
< > <= 也支持,但粗粒度控制用得不多,所有版本约束都能用裸数字(如 "lodash": "2.6.6" 锁死单个版本)。
0.x.x 的特殊约定
关键陷阱
0.y.z 阶段被认为不稳定,所以 ^ 在这里不升 minor。
^0.6.6实际范围:>=0.6.6 <0.7.0(只升 patch)^0.6实际范围:>=0.6.0 <0.7.0
原因是 0.x 的 minor 通常会破 API,跟成熟版本里 minor 等于"向后兼容新功能"的语义不一样。维护 0.x 包要时刻记着这条,否则用户装了不会拿到你期望的更新范围。