Understanding package.json and package-lock.json

Understanding package.json and package-lock.json

If you have worked on or seen any Node.js project on GitHub, you might have seen these two files. And, just like me you probably would have been confused on what do these files do or what's there purpose?

Let's look into them one by one.

package.json

package.json in simple terms is a manifest file that stores metadata about the project. The package.json file is the heart of any Node.js project. It is created as soon as you create a Node.js project. You can create a node.js project by running the command npm init. It would ask you information regarding the project name, project description, license, etc. If you don't want to explicitly provide all of this information, you can type the command npm init --y.

A typical package.json file looks like this:

{
  "name": "test_project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "nodemon app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  }
}

If you notice carefully, it is an object with key value pairs. Let's look into these keys, one by one:

  • name: It is the name of the project.
  • version: It is the version of the project. We can create different versions, for different updates.
  • main: It is the entry point of our project.
  • scripts: It further includes keys like start and test.
    • start: It defines the command that is needed to run our project. In this case it's nodemon app.js. Nodemon is a package that is used to run .js files and it keeps updating the result with new changes in code. It's helpful as there is no need to run the project again and again.
    • test: Command under it runs whenever we type npm test. It is important when integrating with CI/CD pipeline deployment tools like Jenkins.
  • keywords: It is an array of strings, that helps our package/project to be discovered.
  • author: It refers to the person who has created the project.
  • license: It defines on how the project is intended to be used and what are the restrictions on it.
  • dependencies: These are all the modules that are needed for our project to run. All the modules are written as key: value pair, where key is the name of the module and value is the version of the module.

There is a reason why dependencies are defined like this. It's because usually the size of these npm modules is too large to be uploaded on GitHub. Thus they are defined in package.json, so that anyone who is interested on making the project work on his local machine, can install the required npm modules just by running the command npm i.

Note: To avoid pushing node modules with your project on GitHub, there is a special file called .gitignore. This file includes all the names of those files and folders that are not needed to be pushed to GitHub. We include /npm_modules in it, to avoid pushing it to GitHub.


package-lock.json

This file is generated when we type the command npm i. It describes the exact tree that was generated to allow subsequent installs to build an identical dependency tree. It records the exact version of each installed package, that allows you to reinstall them.

A typical package-lock.json looks like this:

{
  "name": "test_project",
  "version": "1.0.0",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "": {
      "name": "test_project",
      "version": "1.0.0",
      "license": "ISC",
      "dependencies": {
        "express": "^4.17.1"
      }
    },
    "node_modules/accepts": {
      "version": "1.3.8",
      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
}
}

Let's look into each key one by one:

  • name: It refers to the project name.
  • version: It refers to the version of the project.
  • lockfileversion: It is an integer value that starts at 1, and combined with the current version of the project, defines the sematics that were used while generating this package-lock.json.
    • No version provided: an "ancient" shrinkwrap file from a version of npm prior to npm v5.
    • 1: lockfile version used by npm v5 and v6.
    • 2: lockfile version used by npm v7 and is backwards compatible to version 1.
    • 3: lockfile version used by npm v7 but is not backwards compatible.
  • requires: It tracks which modules a given module requires. It has been added since v5.1.0, you can read about it further on github.com/npm/npm/pull/17508
  • dependencies: It defines all the modules that are needed with their respective versions.
  • Then we have information regarding all the node-modules, that were installed. Let's dive a bit deeper.
    • version: It defines the version of the module.
    • resolved: It defines the place from where the package was actually resolved from.
    • integrity: The official npm documentation defines it as

      A sha512 or sha1 Standard Subresource Integrity string for the artifact that was unpacked in this location.

Standard Subresource Integrity defines a mechanism by which user agents may verify that a fetched resource has been delivered without unexpected manipulation.

We have various such node modules defined in package-lock.json file.


There you have a detailed insight into package.json and package-lock.json files. You can reach out to me on:

  1. Twitter
  2. Showwcase

Did you find this article valuable?

Support Swapnil Pant by becoming a sponsor. Any amount is appreciated!