likes
comments
collection
share

Flutter 项目结构篇之- pubspec.lock

作者站长头像
站长
· 阅读数 2

上一篇我们留下一个问题:为什么我们有时会添加插入^符号在我们的依赖库版本之前:

dependencies:
    flutter_bloc: ^7.3.3

^这个符号有什么作用?它与pubspec.lock文件有什么关系?

灵活的依赖库版本

正如Dart官方文档中所见,有几种不同的方式来定义的版本:

  • any 允许任何版本,相当于一个空版本约束,但更明确。虽然any是允许的,但我们不推荐它。
  • 1.2.3 具体版本号将依赖库依赖库固定为仅允许该 确切版本。尽可能避免使用它,因为它会导致用户的版本锁定,并使他们难以将您的库与其他依赖它的库一起使用。
  • <><=>=- 允许我们选择更低、更高、更低且等于或更高且等于规定版本的版本

如果我们想要有灵活性和稳定性的保证,我们应该考虑使用使用插入符号语法, 或^1.2.3

^version  表示保证向后兼容指定版本的所有版本的范围。

因此,遵循语义版本指南插入符号语法,这意味着:

  • 对于没有主要版本的依赖库,例如0.1.130.0.2-> 插入符号将找到包含在同一次要版本中的依赖库。所以^0.1.13会满足>= 0.1.1 < 0.2.0之间的所有版本。
  • 对于具有主要版本的依赖库,例如7.3.0,插入符号将查找包含在同一主要版本中的依赖库。所以^7.3.0会满足>=7.3.0 <7.3.3之间的所有版本。

现在,这引出了两个不同的问题:

  1. Dart 什么时候更新我们的依赖库版本?
  2. 它如何为项目选择合适的版本?
  3. 在哪里可以找到与项目一起使用的特定版本?

要回答这些问题,我们必须了解什么是pubspec.lock文件。

pubspec.lock 文件的剖析

我们创建一个新项目,提交它,然后添加一个新的依赖库:

dependencies:
  flutter_bloc: ^7.3.0

之后,我们运行flutter pub get并查看pubspec.lock文件的差异内容:

flutter_bloc:
    dependency: "direct main"
    description:
      name: flutter_bloc
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "7.3.3"
bloc:
    dependency: transitive
    description:
      name: bloc
      url: "https://pub.flutter-io.cn"
    source: hosted
    version: "7.2.1"
  • 在顶部,我们有库名称:flutter_bloc
  • 接下来,我们有dependency类型,direct:直接依赖库,还有一个值是transitive:依赖库的依赖库(间接依赖库)。
  • description将相关的依赖性的类型的其他一些信息(GIT,本地或托管)
  • source告诉我们如何将依赖库添加到项目中。在本例中,我们通过 pub.dev(托管)添加了它,但我们也可以使用pathgit;
  • 最后version将告诉我们正在使用的具体版本号是多少。

如果我们仔细查看version,我们会看到,虽然我们在pubspec.yamlversion 中定义的是^7.3.0但从pubspec.lock文件中解析出来的版本是7.3.3,这意味着 Dart 能够接受并使用最新版本的库。

为什应该使用 ^

如果我们只使用一个依赖,使用的好处^只是让我们拥有最新最好的版本。但是,^在我们的依赖库中使用还有另一个很好的理由——它允许 Dart 足够灵活地选择一个与所有瞬态(或依赖库的依赖库)依赖库一致的依赖库版本。

想象一下以下场景 - 您在项目中使用最新版本的库 - bloc: ^6.0.0. 但是,您还使用了 flutter_bloc 的库,它也依赖于bloc,但它使用的是更新的版本:bloc: 7.2.1.

dependencies:
  flutter_bloc: ^7.3.0
  bloc: ^6.0.0

如果我们选择使用bloc确切的版本bloc: ^6.0.0,此时Dart 将无法找到同时满足这两个约束的版本。因此当我们运行flutter pub get我们将看到以下错误消息:

[new_test] flutter pub get

Running "flutter pub get" in new_test...

Because new_app depends on flutter_bloc ^7.3.0 which depends on bloc ^7.2.0, bloc ^7.2.0 is required.

So, because new_app depends on bloc ^6.0.0, version solving failed.

pub get failed (1; So, because new_app depends on bloc ^6.0.0, version solving failed.)

exit code 1

解决这个问题的唯一办法就是让这两个库和项目依赖于一个^版本,让他们找到一个版本,同时满足。

升级我们的版本

我们可以看到通过运行flutter pub getpubspec.lock文件并没有发生改变,说明flutter pub get对我们的库没有进行任何更新,那么我们如何更新我们的依赖库呢?

答案是使用flutter pub upgrade

dependencies:
  flutter_bloc: ^7.0.0

如果我们运行,flutter pub upgrade我们会看到所有依赖库都将具有更高版本,符合以下标准^

[new_test] flutter pub upgrade

Resolving dependencies...

bloc 7.2.1

> flutter_bloc 7.3.3 (was 7.0.0)

> provider 6.0.1 (was 5.0.0)

sky_engine 0.0.99 from sdk flutter
....

Changed 2 dependencies!

5 packages have newer versions incompatible with dependency constraints.

Try `flutter pub outdated` for more information.

exit code 0

通过看到上面的差异,我们可以看到这些版本已更新到较新的版本。

但是如果我们不想升级所有的依赖库呢?如果我们只想的升级某一个依赖库呢? 那我们使用flutter pub upgrade <package_name>.

让我们通过使用来测试它flutter pub upgrade shared_preferences

Resolving dependencies...
  ....
  flutter_bloc 7.0.0 (7.3.3 available)
  ....
> shared_preferences 2.0.8 (was 2.0.0)
 .....
Downloading shared_preferences 2.0.8...
Changed 1 dependency!
7 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.

正如我们所看到的,命令行告诉我们:虽然有一个更新的版本可用于flutter_bloc,但它没有被升级。

查看flutter pub upgrade命令的最后一行,我们看到它提到了该flutter pub outdated命令。如果我们希望pubspec.yaml直接更新我们的文件,可以用此命令查看我们所有的依赖库最新和兼容版本:

flutter pub outdated

Showing outdated packages.
[*] indicates versions that are not the latest available.

Package Name  Current   Upgradable  Resolvable  Latest   

direct dependencies:
flutter_bloc  *7.0.0    *7.0.0      7.3.3       7.3.3    

dev_dependencies: all up-to-date.

transitive dependencies:
characters    *1.1.0    *1.1.0      *1.1.0      1.2.0    
provider      *5.0.0    *5.0.0      6.0.1       6.0.1    
vector_math   *2.1.0    *2.1.0      *2.1.0      2.1.1    

transitive dev_dependencies:
async         *2.8.1    *2.8.1      *2.8.1      2.8.2    
matcher       *0.12.10  *0.12.10    *0.12.10    0.12.11  
test_api      *0.4.2    *0.4.2      *0.4.2      0.4.7    

2  dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `flutter pub upgrade --major-versions`.

pubspec.lock文件在应用中的重要性

如果我们正在开发一个项目,该lock文件保证每个有权访问该项目的人都能够使用我们正在使用的相同版本的库来运行它。它是我们使用的真实版本的“真相来源”。

这意味着即使我们使用^符号,我们也不会在不同机器上有相同依赖库的不同解析版本,这使得与其他开发人员并行开发项目变得更加容易。

但是我们查看 Dart 官方文档中的What not to commit会发现官方不建议我们提交pubspec.lock文件的源代码管理服务器中。因为库应该支持一系列依赖库版本,依赖库的 直接依赖库的 版本约束 应尽可能放宽,同时仍确保依赖库将与测试的版本兼容性。

Lockfile

结论

现在我们认识到pubspec.lock的重要性:能够明确的来看到我们的项目的依赖关系。 并且也知道了为什么在声明依赖库时应该考虑使用^符号(它使我们更加灵活,具有更少的依赖库错误,并尝试我们正在使用的库的更新版本)。