This is the fourth day of my participation in the November Gwen Challenge. See details: The last Gwen Challenge 2021.

In the last post we left a question as to why we sometimes add the insert ^ symbol before our dependency library version:

Dependencies: flutter_bloc: ^ 7.3.3Copy the code

What does this symbol do? How does it relate to the pubspec.lock file?

Flexible dependency library versions

As you can see in the official Dart documentation, there are several different ways to define versions:

  • anyAllows any version, equivalent to an empty version constraint, but more explicitly.althoughanyIt’s allowed, but we don’t recommend it.
  • 1.2.3The version number fixes the dependency library dependency library to only allow thisThe exactVersion. Avoid it as much as possible, as it can lead to version locking for users and make it difficult for them to use your library with other libraries that depend on it.
  • <.>.< =.> =– Allows us to select lower, higher, lower and equal to or higher and equal to the specified version

If we want to have flexibility and stability guaranteed, we should consider using caret syntax, or ^1.2.3.

^version Indicates the range of all versions guaranteed to be backward compatible with the specified version.

Therefore, follow the semantic versioning guide and caret syntax, which means:

  • forThere is no major versionDependency libraries, for example0.1.13andhundreds-> Caret will be found contained in the samesecondaryDependency libraries in the version. so^ 0.1.13Will satisfy> = while < 0.2.0Between all versions.
  • forHaving a major versionDependency libraries, for example7.3.0The caret will look for inclusion in the sameThe mainDependency libraries in the version. so^ 7.3.0Will satisfy> = 7.3.0 < 7.3.3Between all versions.

Now, this raises two different questions:

  1. When will Dart update our dependency library version?
  2. How does it choose the right version for the project?
  3. Where can I find a specific version to use with the project?

To answer these questions, we must understand what a Pubspec.lock file is.

Anatomy of pubspec.lock file

We create a new project, commit it, and add a new dependency library:

Dependencies: flutter_bloc: ^ 7.3.0Copy the code

After that, we run the flutter pub get and view the different contents of the pubspec.lock file:

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"
Copy the code
  • At the top, we have the library name:flutter_bloc
  • And then we havedependencyType,direct: directly depends on the library, and a value istransitive: A dependency library of a dependency library (indirect dependency library).
  • indescriptionAdd some other information about the type of dependency (GIT, local or hosted)
  • sourceTells us how to add a dependency library to a project. In this case, we added it via pub.dev (hosting), but we can also use itpath,git;
  • The lastversionWill tell us exactly what version number we are using.

If we take a closer look at version, we see that although we defined ^7.3.0 in pubspec.yamlversion, the version resolved from the pubspec.lock file is 7.3.3, which means Dart is able to accept and use the latest version of the library.

Why should it be used^

If we only use one dependency, the advantage of using it is simply that we have the latest and greatest version. But ^ is used in our dependency library for another good reason — it allows Dart to be flexible enough to select a version of the dependency library that is consistent with all transient (or dependency libraries of dependency libraries) dependencies.

Imagine the following scenario – you are using the latest version of the library – Bloc: ^6.0.0 in your project. However, you also use the library flutter_bloc, which also relies on Bloc, but uses a newer version: Bloc: 7.2.1.

Flutter_bloc: ^7.3.0 bloc: ^6.0.0Copy the code

If we choose to use the exact version of Bloc bloc: ^6.0.0, Dart will not be able to find a version that satisfies both constraints. So when we run the flutter pub get we will see the following error message:

[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
Copy the code

The only way to solve this problem is to make the two libraries and projects dependent on one version and let them find a version that both satisfy.

If we cannot solve this problem by adding ^ to the dependency library we are using, then we can use dependency_overrides in the project pubspec.yaml file to solve this problem, as described in the -pubspec.yaml structure of the Flutter project.

Upgrade our version

We can see that the flutter pub get file does not change by running the flutter pub get file. This means that the flutter pub get does not update our library. How do we update our dependent libraries?

The answer is to use the Flutter Pub Upgrade

Dependencies: flutter_bloc: ^ 7.0.0Copy the code

If we run flutter pub Upgrade we will see that all dependent libraries will have a higher version that meets the following criteria ^ :

[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 0Copy the code

By seeing the differences above, we can see that these versions have been updated to newer versions.

But what if we don’t want to upgrade all the dependent libraries? What if we only want to upgrade one dependent library? Use flutter pub upgrade .

Let’s test it by using 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 mid-atlantic moved... Changed 1 dependency! 7 packages have newer versions incompatible with dependency constraints. Try `flutter pub outdated` for more information.Copy the code

As we can see, the command line tells us that although there is a newer version available for Flutter_bloc, it has not been upgraded.

Looking at the last line of the flutter pub upgrade command, we see that it mentions the flutter pub upgrade command. If we want pubspec.yaml to update our files directly, we can use this command to see the latest and compatible versions of all our dependent libraries:

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.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.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`.Copy the code

The importance of the pubspec.lock file in your application

If we are developing a project, the Lock file guarantees that everyone with access to the project will be able to run it using the same version of the library we are using. It is the “source of truth” of the real version we use.

This means that even if we use the ^ symbol, we don’t have different parsed versions of the same dependent library on different machines, which makes it easier to develop projects in parallel with other developers.

However, if we look at What Not to Commit in the official Dart documentation, it is not recommended that we commit the pubspec.lock file to the source control server. Because the library should support a range of dependency library versions, the direct dependency library version constraints of the dependency library should be relaxed as much as possible, while still ensuring that the dependency library will be compatible with the version under test.

Lockfile

conclusion

Now we realize the importance of Pubspec. lock: being able to clearly see the dependencies of our project. You also learned why you should consider using the ^ symbol when declaring dependency libraries (it allows us to be more flexible, have fewer dependency library errors, and try newer versions of the libraries we are using).