What is pubspec.lock and why should flutter devs care?

What is pubspec.lock and why should flutter devs care?

Understand *.lock file in general.

Introduction

As Flutter developers, we’re all familiar with the pubspec files. But as soon as we do flutter pub get a random large file gets generated and we simply overlook the importance of that file. This file is called the pubspec.lock , and it is a critical component of dependency management in Flutter projects. It is essential for us as developers to understand why the file exists and what role it plays in our development process. So, let’s uncover the mystery surrounding the pubspec.lock file and explore why it matters.

PS: This concept will work for all other *.lock files not just pubspec.lock eg package.lock in npm or yarn.lock.

pubspec.yaml

As Flutter developers, we all are aware of this file. This is the required file in every flutter/dart project or package. Here we can define the dependencies of our project. Also in a flutter, we can define assets like images, fonts, etc. More detail about pubspec.yaml may deserve a separate article but for now, let's focus on the pubspec.lock file.

dependencies:
  flutter:
    sdk: flutter
  awesome_package: ^8.1.2

Before going through the next topic I would like to pause here and have a slight discussion on Semantic versioning and how it works.

Semantic versioning

Semantic versioning is the widely-used versioning convention which is a standardized way to define and manage version numbers for a software project. It consists of 3 part Major:Minor:Patch = 8.1.2

  1. Major → updating this indicates significant changes in the software that may not be backward-compatible.

  2. Minor → updating this indicates new functionality or features that are backward-compatible.

  3. Patch → updating this indicates bug fixes or minor changes that are backward-compatible.

Let's take an example of awesome_package dependency from above with version 8.1.2. 8 is the Major, 1 is Minor and 2 is the Patch version.

Version Range

awesome_package: ^8.1.2

The initial look might seem that it will install awesome_package with version 8.1.2 but the “^” symbol will change the whole story. Apart from “^” we have different other symbols, let's learn them quickly:

  1. ~8.1.2 → will install any version of the package that has the same major and minor version numbers as 8.1.2 but can include any patch version number 8.1.2 ≤ version < 8.2.0 i.e 8.1.2, 8.1.3, …. 8.1.9 but not 8.2.0.

  2. ^8.1.2 → can install any version of the package that is compatible with version 8.1.2, up to but not including version 9.0.0. This allows for minor version updates, but not major version updates8.1.2 ≤ version < 9.0.0i.e 8.1.2, 8.1.3, … , 8.2.0 but not 9.0.0.

  3. 8.1.2 → it will only install version 8.1.2 of the package. This is an exact version number.

Let's say two of your friend installed the same package at different time intervals and the chance is that the package got a minor update in between.

So from ^8.1.2 it may install 8.2.0 or 8.3.1 or anything within the compatible range i.e two different versions on both of you.Ideally📌 it should not cause issues because the increase of minor and patch versions are backward compatible.

But we are not in a perfect world. What if the developer didn’t follow the semantic versioning convention and released version 8.3.1 of the package with a major breaking change, the same project that was previously working smoothly on one friend’s device might not run on the other friend’s device.

Here comes the role of pubspec.lock file or any .lock file in general.

Spoiler 😉

The *.lock file locks the specific versions of dependencies, ensuring that everyone working on the project uses the exact same versions.

pubsepc.lock

When you run flutter pub get in a Flutter project, it searches for pubspec.yaml to fetch and download all the dependencies listed in it.

Once it downloads the dependencies, it creates a pubspec.lock file, which is essentially a snapshot of all the dependencies, their versions, and their transitive dependencies at a specific time.
(Transitive dependencies mean dependencies of dependencies. For e.g., awesome_package may depend on cool_package so its important to take version snapshot of that as well.)

Next time when a developer runs flutter pub get on their machine, Flutter checks the pubspec.lock file to ensure that the exact same version of each dependency is installed, rather than simply using the latest available version.

So from its name, *.lock file locks the versions of dependencies to ensure everyone working on the project uses the exact same version. This helps avoid compatibility issues and ensures that everyone works with the same codebase.

Managing the pubspec.lock file

Version Control

Always add and commit the latest pubspec.lock file in your version control system so all the team uses the same dependency.

Don’t edit on your own

Why would someone do it 😅, anyway please don’t.