Dependency Pinning in Node.js

Learn how to manage dependencies effectively in Node.js with package-lock.json and semantic versioning.

Arun K R
Bits and Pieces

--

Photo by AbsolutVision on Unsplash

There are more than 1.3 million libraries available in the NPM registry. We don’t have to start from scratch. Just install the right library, and it’s a piece of cake.

Have you ever wondered how these libraries are installed and managed in projects?

When you install a library from npm in Node.js, npm will download the package and its dependencies and store them in a local node_modules directory in your project. This directory will contain a sub-directory for each installed package, along with any dependencies that the package requires.

It’s imperative to note that when you install a package from npm, you are also installing any dependencies that the package requires. These dependencies can themselves have additional dependencies, leading to a complex tree of packages that can be difficult to manage. That’s why it’s critical to use dependency management tools like npm and the package-lock.json file to ensure that all dependencies are properly tracked and managed.

What is package-lock.json?

The file that is automatically generated by npm whenever a package is installed or updated. Your project uses this file to keep track of what version of packages and dependencies it uses. Your project’s dependency tree is recorded here as a record of its exact state. As a result, everyone working on your project will use the same package version.

What is semantic versioning?

The package-lock.json file and Node.js packages have a concept called semantic versioning that is important to understand. A semantic versioning system, or SemVer, helps users understand how a package has evolved over time by using a system of versioning.

SemVer version number is divided into three parts: a major version, a minor version, and a patch version. The version number of a package is incremented when it is updated depending on what kind of change has been made.

The major version is increased if the package’s API is modified in a way that is backwards-incompatible. (npm version major)

The minor version is increased if the package has new functionality that is backwards compatible. (npm version minor)

The patch version is increased if the package contains bug fixes that are backwards compatible. (npm version patch)

The new version of a package, for instance, will be 2.2.0 if its current version is 2.1.4 and it receives an upgrade that adds a new feature while maintaining backward compatibility. The new version will be 3.0.0 unless the modification renders backward compatibility unusable.

Meet caret (^) & tilde (~)

The caret (^) and the tilde (~) are two additional versioning operators that are frequently used in Node.js packages in addition to semantic versioning.

To upgrade packages to the most recent minor or major version while preserving backward compatibility with the first release, use the caret () operator. For instance, running npm update on a package with a version number of 2.1.4 will update it to the most recent version within the 2.x.x range but not to version 3.x.x.

To update packages to the most recent patch version inside the same minor version, use the tilde () operator. For instance, running npm update on a package with a version number of 2.1.4 will update it to the most recent version available within the 2.1.x range but not to version 2.2.0.

💡 The process of managing dependencies becomes infinitely more streamlined if you use a platform like Bit for your projects. Within a Bit Workspace, you don’t need to tell npm, pnpm, or yarn which component dependencies need to be installed to, nor if it’s a dev or prod dependency. Bit dynamically generates package.json files for each, and can handle this for you painlessly.

Learn more here:

Additional tip

When working with various environments, I generally do this in my projects to obtain the deployed version of my backend application.
Simply put, I’ll develop a ping API to determine whether the backend services are available and return the backend application’s version.

const { version } = require('../package.json');

router.get('/ping', (_req, res) => {
res.send(`API Endpoint is working. Version - ${version}`);
});

Build Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--

I am a self-taught developer, learning from mistakes and turning them into my content.