npm outdated is less about finding what’s stale and more about understanding the maintenance debt you’ve accumulated.

Let’s see it in action. Imagine you’ve got a project with a few dependencies. You run npm outdated:

$ npm outdated
Package         Current  Wanted  Latest  Location
lodash            4.17.15 4.17.21 4.17.21 my-project
react               16.8.6  17.0.2  18.2.0  my-project
react-dom         16.8.6  17.0.2  18.2.0  my-project
webpack            4.41.2  5.70.0  5.75.0  my-project
webpack-cli        3.3.10  4.9.2   4.10.0  my-project

This output tells us a few things. For lodash, the Current version is 4.17.15. Wanted is the highest version that satisfies the range specified in your package.json (e.g., ^4.17.15 would allow 4.17.21). Latest is the absolute newest version available.

Here, lodash has no major or minor updates within its specified range (Wanted matches Latest). react and react-dom have a Current version from a much older major release line (16.x) than the Wanted and Latest (17.x and 18.x). This is a significant jump, and npm outdated flags it clearly. webpack also shows a gap between Current and Wanted/Latest.

The core problem npm outdated helps you address is dependency drift. Over time, your dependencies evolve. New features are added, bugs are fixed, and security vulnerabilities are patched. Without actively managing these updates, your project can fall behind. This leads to a few common issues:

  • Security Risks: Older versions of libraries might contain known vulnerabilities that attackers can exploit.
  • Bugs: You might be running into bugs that have already been fixed in newer versions.
  • Missing Features: You could be missing out on performance improvements or new functionalities that would make your development easier or your application better.
  • Integration Problems: As your own code evolves, it can become harder to integrate with very old versions of dependencies, leading to complex workarounds.

The system npm outdated uses is straightforward. It consults your package.json to know what versions you want (based on semver ranges like ^, ~, *), then it queries the npm registry for the latest available version of each dependency, and finally, it compares your current installed version (from node_modules and package-lock.json) against these.

The Wanted column is crucial. It represents what npm install (or npm update) would install if you ran it without specifying a version, respecting the semver ranges in your package.json. The Latest column shows the absolute newest version published to the registry, regardless of your package.json constraints.

When you see a discrepancy between Current and Wanted, it means npm update could potentially upgrade that dependency without breaking your specified semver range. When Wanted and Latest differ, it means there’s a newer version available, but it’s outside your current semver range (e.g., a new major version).

To actually update these, you’ll typically use npm update. Running npm update by itself will update all packages to their latest Wanted versions according to your package.json ranges.

For packages where Wanted and Latest are different (like react and react-dom in the example), you’ll need to explicitly tell npm to install the latest version. For instance, to upgrade react and react-dom to their latest versions:

npm install react@latest react-dom@latest

Or, if you want to upgrade webpack to its latest version:

npm install webpack@latest webpack-cli@latest

After running these commands, if you run npm outdated again, you’ll see fewer (or no) entries, indicating your dependencies are more up-to-date.

The "Wanted" column is derived directly from the semver range specified in your package.json. For example, if your package.json has "react": "^16.8.6", npm will consider any version 16.x.y where x >= 8 and y >= 6 to be "wanted" if it’s less than the latest 16.x.y version. However, if the latest version available is 17.0.2, and your range only allows 16.x.y, then Wanted might show 16.8.x (the latest 16.x compatible with your range) while Latest shows 17.0.2. This distinction is key to understanding how to safely update.

The most surprising thing about npm outdated is that it often highlights dependencies that are not updated by a simple npm update. This happens when a dependency has a new major version available, but your package.json specifies a range that excludes it (e.g., ^16.8.6 will not automatically update to 17.0.0). This semver-based safety mechanism, while protecting your project from potentially breaking changes, also means you have to consciously decide to upgrade across major versions, often requiring manual intervention and testing.

Once you’ve addressed all the outdated dependencies, the next thing you’ll likely encounter is the need to understand dependency licensing, especially in larger projects.

Want structured learning?

Take the full Npm course →