Difference between package.json and package-lock.json

Let's assume that you create a package.json file:

terminal
npm init

After completing the fields, you'll have something like:

JSON
{
  "name": "test",
  "version": "0.0.1",
  "description": "test package",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "erik",
  "license": "ISC",
}

At this point, you install a dependency:

terminal
npm i color-convert@1.9.0

Now package.json is:

JSON
{
  "name": "test",
  "version": "0.0.1",
  "description": "test package",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "erik",
  "license": "ISC",
  "dependencies": {
    "color-convert": "^1.9.0"
  }
}

As color-convert has its own dependencies, a package-lock.json will be generated with the whole tree of dependencies.

A dependency tree is like a photo of the current state of the project. Or, in other words, it shows the dependencies that you are using in a project at a certain point.

In this case, package-lock.json is:

JSON
{
  "name": "test",
  "version": "0.0.1",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "color-convert": {
      "version": "1.9.0",
      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz",
      "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=",
      "requires": {
        "color-name": "^1.1.1"
      }
    },
    "color-name": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
    }
  }
}

Now imagine, that after a few months, you decide to upgrade color-convert:

npm
npm i color-convert@latest

At this point:

JSON
{
  "name": "test",
  "version": "0.0.1",
  "description": "test package",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "erik",
  "license": "ISC",
  "dependencies": {
    "color-convert": "^2.0.1"
  }
}

And package-lock.json is:

JSON
{
  "name": "test",
  "version": "0.0.1",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "color-convert": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
      "requires": {
        "color-name": "~1.1.4"
      }
    },
    "color-name": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
    }
  }
}

Every time you install or upgrade a package, package-lock.json is rewritten with the current state of the project.

Elon and Bill

Now imagine that you work with Elon and Bill. You and your friends want to create a new app:

  • Elon receives package.json and package-lock.json.
  • Bill receives package.json.

Elon runs npm i after two weeks. As he has package-lock.json, he will have an exact copy of the project as yours.

Whereas Bill runs npm i after 2 months... He will get the latest version of color-convert and its dependencies...

So Elon and Bill may be working with different packages at the same time.

Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.