5.3 语义化版本、范围与冲突
前置知识:Maven 基础
预计时间:15 分钟
完成标志:能解释 SemVer,并避免把 npm 范围语法套到其他生态
清单终于写好了,但 ^1.2.3、~=1.4.2 和 [1.0,2.0) 看起来都像“允许某个范围”。先停一下:版本号的含义与解析器的范围语法是两层规则,不能凭长相互换。
SemVer 描述公共 API 变化
在发布者遵守 Semantic Versioning 2.0.0 的前提下:
| 版本段 | 何时增加 |
|---|---|
| MAJOR | 公共 API 出现不兼容变化 |
| MINOR | 增加向后兼容功能,或标记公共 API 为废弃 |
| PATCH | 修复向后兼容的错误 |
0.y.z 用于初始开发,公共 API 不应视为稳定。预发布版本低于对应正式版;+build 元数据不参与优先级比较。版本号表达的是发布者承诺,不能代替变更说明和测试。
npm 的 caret 和 tilde
json
{
"dependencies": {
"stable-api": "^1.2.3",
"zero-minor-api": "^0.2.3",
"patch-line": "~1.2.3"
}
}| 写法 | npm 范围 |
|---|---|
^1.2.3 | >=1.2.3 <2.0.0 |
^0.2.3 | >=0.2.3 <0.3.0 |
^0.0.3 | >=0.0.3 <0.0.4 |
~1.2.3 | >=1.2.3 <1.3.0 |
1.2.3 | 精确匹配 |
表格按普通正式版描述范围;预发布版本还有额外的匹配规则,并非只比较上下界就会自动纳入。上面的包名仅为配置示意,不要求安装,参见 node-semver 的范围与预发布规则。
caret 范围在 0.x 下更窄:^0.2.3 的上界是 0.3.0,^0.0.3 的上界是 0.0.4,均不包含上界。确定范围时,要检查最左侧的非零版本分量。
Python 使用 PEP 440 说明符,如 >=1.2,<2、~=1.4.2;Maven 范围写作 [1.0,2.0)。三套语法不能互换。
冲突并不都靠“装两份”解决
- Maven 通常使用最近定义;同深度时先声明者优先。
dependencyManagement能管理版本,但不会自动引入依赖。 - npm 可以在依赖树不同位置保留多个版本,peer dependency 仍可能冲突。
- pip 在一个虚拟环境中通常只能为某个分发包安装一个版本,约束无解时应失败。
- Gradle 的选择受 configuration、约束、平台、规则和锁定设置影响。
查看原因:
bash
npm explain PACKAGE_NAME
npm ls --all
./mvnw dependency:tree
./gradlew dependencyInsight --dependency NAME --configuration runtimeClasspath
python -m pip check排除传递依赖前,先确认最终运行时 classpath 和兼容要求。exclusion 可能把必需类一并移走。
离开这一页前
看到 ^0.2.3,先写出上界 <0.3.0;看到两个 Maven 路径选中不同版本,再检查深度、声明顺序和 dependencyManagement。最后给候选升级补上兼容性测试。lock 固定的是解析结果,无法替你检验行为。
→ 下一步:综合实验