Dependency management: package.json and package-lock.json explained
Tags: javascript, npm
Published: 2023-04-11 10:37:19

---
title: Dependency management: package.json and package-lock.json explained
published: true
date: 2023-04-11 12:30:46 UTC
tags: javascript, npm
canonical_url: https://on-sw-integration.epischel.de/2023/04/08/package-json-and-package-lock-json-explained/?pk_campaign=feed&pk_kwd=package-json-and-package-lock-json-explained
---

I had some confusion about `package.json` and `package-lock.json` and what is used when. But now that I've been "enlightened", I'll record my new knowledge in this article.

![symbolic image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ga5ump0cg779lcbay142.jpg)

## package.json and package-lock.json

`package.json` lists, among other things, the dependencies you need for your JavaScript project (if you use npm). You'd edit this file manually. In contrast `package-lock.json` is generated by npm.

Example `package.json`:

```
{
  "name": "my-project",
  "version": "1.0.0",
  "dependencies": {
    "express": "^4.17.1",
    "lodash": "^4.17.20"
  },
  "devDependencies": {
    "nodemon": "^2.0.7"
  }
}
```

 

Often, the versions listed in `package.json` are given as ranges. npm uses [SemVer](https://semver.org/), 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”.

In contrast, `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 `package-lock.json` 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.

If `package.json` and the lock file are out of sync (the version in `package-lock.json` is out of the range specified in `package.json`), “`npm install`” will correct the `package-lock.json` file.

## 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 “`npm install`“).

## How to upgrade dependencies?

“`npm outdated`” shows outdated dependencies and “`npm update <pkg> --save`” updates a package as well as `package.json` and the lock file. 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.

## CI pipelines

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 dependencies

Pinning a dependency means using an exact version in `package.json`.