What are lockfiles?

Packages are an important part of a project. They enable us to use various frameworks and libraries in our project. But packages are also constantly being developed, fixed and improved. In the worst case scenario, the packages may produce errors in our application, after an update. To avoid this, we want to save the correct working package versions. This is where lockfiles come into play.

Package versions in the package.json

The package.json file is the central configuration file of a project.

All important project information is stored here: the name, version, authors, etc.
In addition, all packages used in the project and the desired minimum version number are stored in the package.json too.

{
    "dependencies": {
        "axios": "^1.2.3",
        "next": "14.2.5",
        "nextjs-routes": "^2.2.1",
        "react": "~18.3.1",
        "react-dom": "^18.3.1"
    }
}

Each package manager (for example npm or yarn) installs the latest versions of the packages defined under dependencies . This can be controlled by using the version prefixes ~ and ^ or by specifying the exact version number:

  • If the exact version number is specified, e.g. "next": "14.2.5" , version 14.2.5 is installed each time npm install is executed.
  • ^ automatically updates the package to the next minor version. If available, npm install would automatically install version 1.3.0 of the axios package. However, it will never update to the next main version 2.0.0 .
  • ~ automatically updates the package to the next patch version. React would therefore be updated to version 18.3.2 at most with npm install. The highest version that would be installed would be 18.3.9. So it will never be updated to the next minor version 18.4.0.

Depending on the package manager used, the lockfiles may have a different name or a slightly different structure. Essentially, they all contain the same information.

The exact definition of the version numbers is important to understand what distinguishes package.json from the other lockfiles, such as the npm lockfile: package-lock.json

Differences between package.json and lockfiles

As already mentioned, the versions defined in the package.json do not have to match the installed versions. The defined package.json versions are called version ranges. Due to this version range, different versions of the packages may be loaded each time the packages are installed.

In order to always be able to load the same versions of a package, the exact version number must be saved. The lockfile is used for this purpose. All exact version numbers of the installed packages and their subpackages are saved here. This ensures that all required packages are always installed in the version desired by the developer and used in the development of the project.

It is important to note that the defined package versions only apply to the main package. The respective packages naturally have their own package dependencies, which are also defined with version ranges. This can lead to different versions of the sub-packages being installed than before when the packages are installed. This in turn can lead to errors. The versions of the sub-packages are therefore also saved in the lockfiles. You can find more informations about how to safely update a package to the next version in our blog post on how to update dependencies correctly .

Why my lockfile is also important for other developers

If all packages defined in package.json are to be installed (e.g. npm install, yarn install) and there is no lockfile in the project folder, the latest versions (depending on the version ranges) are installed. However, if there is a lockfile in the project folder, the packages are installed in the version stored in the look file.

It is important to push the lockfile to the project repository! This has decisive advantages:

  1. This ensures that all developers work with the same package versions. This prevents the app from behaving differently due to different package version
  2. Changes to the package versions are made clear directly in the pull request and during the code review
  3. There is always a clear history that shows which package version was changed by wich pull request
  4. This also ensures that the project runs in the production environment in exactly the same way as during local development or in the test environment.

Lockfiles therefore primarily ensure that every developer works with the correct and identical package versions at all times.