Node.js Dependency Management: A Practical Guide
In this article, I will explain the basics of dependency management and how it works in Node.js and npm and deliver four recommendations that can significantly enhance your dependency hygiene.
Contents
What Is a Software Dependency?
Most software written today relies on the work of other developers. Software projects focus on creating new business logic, and use existing libraries and packages to perform tasks such as logging, authentication, or communication.
These additional libraries, called dependencies, dramatically improve development productivity. However, when dependencies are a large part of the codebase, developers have limited visibility over the code actually running in their application. Also, because each dependency is a software component of its own, they are susceptible to bugs and security vulnerabilities, which are inherited by the software that uses them.
Risks and Challenges of Software Dependencies
The more software dependencies you have, the more pieces you have to manage. Some of the libraries you use could be outdated, which is a security risk. Dependencies can also make it harder to find the cause of bugs and other performance issues. Today most dependencies used in software projects are distributed using open source licenses.
Dependencies, if not properly managed, can have a negative effect on software quality, security, and reliability. In the worst case, you could experience “dependency hell”. This is a term used to describe software that has multiple layers of dependencies, and then starts to malfunction, and it becomes impossible to identify the problem due to the complexity of the dependencies.
Application dependency mapping (ADM) is the process of identifying all the elements of a software ecosystem and understanding how they work together. An automated application dependency mapping tool gives developers a clear picture of the health of the environment and overall application performance. This provides critical visibility, so that when a problem occurs, it is possible to identify the point of failure and find the fastest recovery path.
Dependency Management in Node.js
When developing the front end of a web application, you can use JavaScript dependency management tools to control your dependencies. Typically, dependencies are Node.js modules installed using npm—the default package managing system for Node.js.
npm is packaged with Node.js. After installing Node.js on your local machine, you can start running npm using the command line interface.
How npm manages dependencies
The npm package manager ensures that all dependencies (libraries, packages, modules) that your app depends on are loaded in the correct order. You can also modify, update, delete, and manage packages as your requirements change. Most package managers use a dependency tree to track dependencies.
npm is not only a package manager, it is an open source node package registry. Developers everywhere can upload npm packages, which they can add to their applications with a few commands.
Examples of dependencies
Node.js programs use dependencies for almost anything, from tiny utilities with only a few lines of code to major functionality. Examples of popular Node.js packages are Lodash, which boosts code performance, Axios, which manages HTTP API requests, and Cloudinary, which enables user file uploads and performs media optimization.
The dependency tree and node_modules folder
npm builds the dependency tree outside of your web browser. This means you must add all the application dependencies within the node_modules folder. This folder may contain thousands of files, so npm is often combined with tools like Browserify, which bundles all the dependencies and passes them as static files to the browser.
To enable more efficient package management, npm3 introduces a flat dependency tree that replaces the previous nested tree npm. The new feature reduces verbosity and makes the node_modules folder simpler and cleaner to use.
4 Tips to Properly Manage Your Dependencies in Node.js
1. Review a Package’s Details
Use the following command to get details about a particular package before installing it as a dependency:
npm view <package-name>
Replace <package-name> with the package’s official npm name. The command gives important details like its current version, the license it uses, details about its dependencies, a brief description of its functionality, etc. All this information is returned in JSON, which comes in handy in further steps like the pre-installation process and for automated processing.
You can append the command with the exact detail needed:
npm view <package-name> version
npm view <package-name> license
2. Keep Track of Missing or Unutilized Dependencies
The npm package manager offers the following command to automatically sync dependencies used in code and saved in the package.json configuration file:
npm install -g npm-check
The command helps when a dependency is in use in the codebase but not in package.json and vice versa. When used, the command shows the output that helps track unused dependencies and those missing in package.json:
<package-name-1> 😕 NOTUSED? Still using <package-name-1>?
Depcheck did not find code similar to require(‘<package-name-1> ‘) or import from ‘express’.
…
<package-name-2> 😟 MISSING! Not installed.
😟 PKG ERR! Not in the package.json. Found in: /demo.js
3. Locate and Fix Obsolete Dependencies
Use the following command to retrieve outdated packages that npm can update:
npm outdated
The command will give you all important details of the outdated package like the version currently installed, the most updated one that npm can install according to semantic versioning rules, and the latest available version:
Package Current Wanted Latest Location
<package-name> 3.2.6 3.21.2 4.16.3 example
The command can become a part of the build process, so the user can treat any obsolete dependencies before building the project. There is another command that acts as an alternative to the one above and has the same functionality:
npm-check-updates
4. Review Licenses of Dependencies
Use the following command to install and use a tool that checks all the licenses in your overall dependency tree:
npm install -g license-checker
license-checker –summary
The command can be given parameters to show output in different ways. The –json parameter formats the returned information in JSOn, and the –summary parameter gives an overview:
├─ MIT*: 15
├─ MIT: 3
├─ UNKNOWN: 2
├─ Custom: https://secure.travis-ci.org/shtylman/node-cookie.png: 1
└─ ISC: 1
Conclusion
In this article I explained the basics of dependency management and how it works in Node.js and npm, and provided 4 tips that can significantly improve your dependency hygiene:
- Review a package’s details using npm view to understand what dependencies exist
- Keep track of unutilized dependencies using the npm-check flag
- Locate and fix obsolete dependencies using the npm outdated command
- Review licenses of dependencies using the license-checker flag
I hope this will be useful as you gain more visibility and take control over your Node.js dependencies.
Please refer to the article Building and deploying a Node.JS application to learn more about this subject.