为什么 Gradle 或 Maven 没有依赖项版本锁定文件?

我最近在阅读有关NPM,Yarn,Paket,Cargo等包管理器时,被引入了依赖版本锁定文件的概念。我的理解是,它是一个列出所有直接和可传递依赖项及其确切版本号的文件,因此后续构建可以保证使用一组等效的依赖项。这似乎是一个理想的功能,因为许多包管理器已经或正在采用这个概念。

我的问题是:

  1. 为什么 Maven 或 Gradle 不使用锁定文件?或者,如果他们这样做了,为什么我没有看到它?

  2. 在包管理器的依赖项解析策略中允许版本范围与仅允许精确版本相比,有哪些优点和缺点?


答案 1
  1. Maven没有办法实现你所要求的。即使您为直接依赖项设置了特定版本(您应该这样做),由于看似不相关的更改,您的传递依赖项也很容易无意中更改。例如,在新库上添加依赖项可以为您提供现有可传递依赖项的旧版本。

    您需要的是有一个列出所有直接依赖项和可传递依赖项的部分。您仍然无法检测是否删除或添加了传递依赖项,这是 NPM 提供的功能。缺少的问题在于所有依赖项都不再位于该部分中。要检测这些更改,您可以使用我编写的依赖关系锁定maven插件之类的东西。使用它也会使所有内容都放在一个部分中变得不那么重要,因为将检测到传递依赖项的更改。dependencyManagementdependencyManagementdependencyManagement

    我还建议在构建中 https://maven.apache.org/enforcer/enforcer-rules/requireUpperBoundDeps.html,因为 Maven 选择在树中关闭的传递依赖项版本,而不是如您所期望的那样,选择最高版本。

    我见过许多运行时问题,这些问题是由开发人员意外更改传递依赖项引起的。

    TL;DR:在 Maven 中,你确实需要一个像 lock 文件这样的东西,但由于历史意识形态的原因,它并不存在。

  2. 我不建议使用版本范围,因为它们会使你的构建不可重现。当涉及到传递依赖关系时,它的行为也不如你所相信的那样。


答案 2

依赖关系锁定是 Gradle 5.0 实现一定成熟度的一项功能:https://docs.gradle.org/current/userguide/dependency_locking.html

Gradle的实现灵感来自Nebula插件:https://github.com/nebula-plugins/gradle-dependency-lock-plugin

当用作任何更新锁定机制的输入时,版本范围确实可以很好地工作。因此,对于 Gradle,您实际上可以只针对特定的依赖项,这些依赖项将寻求解析您为其指定的版本范围:

gradle classes --update-locks org.apache.commons:commons-lang3,org.slf4j:slf4j-api

或者,你可以说“去更新我所有的deps”:

gradle dependencies --write-locks

如果您正在研究自动化,指定解决策略也值得一看:https://docs.gradle.org/current/userguide/dependency_resolution.html


推荐