I had some confusions about
package-lock.json and what is used when but now that I have been “enlightened” I’ll record my new knowledge in this article.
package.json and package-lock.json
package-lock.json is generated by npm.
Often, the versions listed in
package.json are given as ranges. npm uses SemVer, meaning a version scheme in three parts like a.b.c where a,b and c are numbers (also called “major.minor.patch”). “
~a.b.c” means a and b are fixed and the last part can be c or any greater number: “
~4.17.1” means “4.17.x for x>=1”. “^a.b.c” means a is fixed and minor and patch version is variable: “
^4.17.20” means “4.x.y for either (x=17 and y>=20) or x>18”.
package-lock.json contains the exact versions of the project’s dependencies (and their transitive dependencies and so on). When
package-lock.json is generated or updated, the version range in
package.json is resolved to the latest “allowed” version.
Generating and updating package-lock.json
How do you create the lock file? “
npm install” will do it.
How do you update the lock file? “
npm update” will do it, usually. Say
package.json states module A in version “
^3.4.5” and the existing state module A in version “
3.4.20“. Then you run “
npm update A” or “
npm update” and when there is a version “
3.5.2” of A out there, npm will update the lockfile to version “
3.5.2” of module A.
package.json and the lock file are out of sync (the version in
package-lock.json is out of the range specified in
npm install” will correct the
Why committing the lock-file?
The general advice is to commit
package-lock.json to your repository. That way, every developer will be using the same versions: the ones listed in the lock-file (using “
How to upgrade dependencies?
npm outdated” shows outdated dependencies and “
npm update <pkg> --save” updates a package. Commit both files.
Another way is to use tools like dependabot or renovate which check for new versions. If a new version of a module is detected, these tools will create a branch using the new version. CI pipelines are run and pull/merge requests are created or even merged automatically.
There is a special command for CI pipelines: “
npm ci“. It will fail if the lock file is missing or is out of sync with package.json. So the build will fail if “
npm install” would change the lock-file.
npm ci” ensures that your build is always based on a consistent set of dependencies, which is important for reproducibility and stability. It also helps avoid problems that can arise from using different versions of the same package across different stages of the pipeline.
Pinning a dependency means using an exact version in