If you work in web development, you likely use NPM (Node PM or New PM) all the time. It is a free public software registry – the largest in the world that is accessible at the type of npm install in your command prompt so long as you have node.js installed already.
Whenever we try to create a new project we will see a package.json file will be created. Whenever we install any packages package-lock.json file and node_modules folder will be created. In this blog post, we will see on SemVer, the purpose of package.json and package-lock.json and the internal functioning of npm install.
What is versioning?
The Node.js ecosystem uses SemVer, which is not mandatory but is strongly encouraged. This feature isn’t necessary for an unpublished package. Maintaining the version field of a package used as a dependency is critical to ensuring that others use the correct version of a package.
There are three elements to a version:
- major (significant changes in the version)
- minor (adding new features )
- patch (a bug fix)

There also two prefix symbols present in the semver. It’s the deciding factor what release to be updated ( either patch, minor ).
- Caret (^) – Allow npm to upgrade minor and patch versions if they are available.
- Tilde (~) – Allow npm to upgrade only patch versions if they are available.
For Example,
Consider the package express, with version-> ^4.17.1 -> If there are any minor versions available say 4.18.0 then npm is allowed to update to 4.18.0.

But in the case of ~, even if the 4.18.0 version is available, npm won’t upgrade to 4.18.0.

Now let’s come to our topic package.json and package-lock.json.
Package.json
package.json is an important file, which is been used to install the packages required for the node projects.
How it is created?
package.json is a file that gets generated when we are initializing the npm project (npm init -y)

It contains,
{
"name": "node-projects",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.1"
}
}
- Package.json is a list of all the dependencies of a project. This includes version info (with upgradation feasibility caret ^ and tilde ~ ) for what needs to be downloaded.
- It keeps the minimum version an application needs.
- It also contains details on project properties, description, author & license information, scripts to run via npm, etc.
Properties inside package.json
1. name property: Name of the module.
2. version property: Current version of the module.
3. license property: Licence of the project (eg. MIT, GPL-3.0, BSD-3).
4. description property: Description of the module given by the developer.
5. keywords property: Related keywords of the module.
6. main property: specify the direction to the entry point to the module package.json is describing.
7. repository property (optional): Details about the cloud repository (eg: git)
8. scripts property: It takes an object with as many key (category)/value (commands) pairs.
9. dependencies property: The other modules that this module uses – are defined. The dependencies property takes an object that has the name and version at which each dependency should be used. Do note that you’ll frequently find carets (^) and tildes (~) included with package versions. (It’s for production).
10. devDependencies property: Used to define dependencies to run in development.
package-lock.json (Exact version of the installed package)
package-lock.json is an auto-generated document during installation. It looks a lot like the package.json dependencies but with more information when you open it.

package-lock.json describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.
As you can see in the below image, package-lock.json won’t contain ^ or ~. It will have the exact version of the installed package. While package.json will have the minimum version needed to run the project.

How it is created?
package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree or package.json. Eg. during npm install.

What it contains?
Let’s take a look,

- package-lock.json is used to avoid differences in installed dependencies on different environments and generate the same results in every environment.
- NPM installs exact versions of the package as saved in package-lock.json and ignores the symbol ^ and ~ from package.json so as to avoid installing the latest/updated version of the package which might break the application if the application codebase is not compatible with the updated version of packages.
- It contains other meta information of packages to save the time of fetching that data from npm when installing any package using npm install.
- It allows npm to skip repeated metadata resolutions for previously installed packages and hence optimizes the installation process.
Properties inside package-lock.json
1. name property: name of the module. It will match the name property in package.json.
2. version property: The version of the package this is a package-lock for. This will match what’s in package.json.
3. lockfileVersion property: It’s an integer value. Either 1, 2, or 3.
- 1: The lockfile version used by npm v5 and v6.
- 2: The lockfile version used by npm v7, which is backward compatible with v1 lock files.
- 3: The lockfile version used by npm v7, without backward compatibility affordances. This is used for the hidden lockfile at node_modules/.package-lock.json, and will likely be used in a future version of npm, once support for npm v6 is no longer relevant.
4. packages property: It is an object that maps package locations to an object containing the information about that package.
Eg:
"node_modules/etag": {
"version": "1.8.1",
"resolved": "registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"engines": {
"node": ">= 0.6"
}
},
5. dependencies property: Its a mapping of package names to dependency objects