Keep npm dependencies up to date

— 5 minute read

Many developers have been in a situation when their project is stuck because of outdated dependencies. Security vulnerabilities are found in an old dependency. Node.js version is getting out of life, and your project just couldn't compile on the newer version. Many deprecation warnings in the terminal and browser console.

Often forgotten dependencies lead to painful upgrades, more bugs, missed deadlines, and just a very stressful time.

To keep the codebase healthy, dependencies should be kept up to date!

Some pros to keep dependencies always up to date.

  • Getting the latest features and the best developer experience.
  • Fewer bugs and security vulnerabilities.
  • Fewer problems in the future with updates.
  • Sometimes faster and smaller bundles.

There are some cons:

  • Risk of getting new bugs.
  • Risk of getting the bigger bundle.

But the pros outweigh the cons.

Tools permalink

npm outdated/npm update permalink

Built-in npm outdated and npm update provide very basic experience. npm outdated shows dependencies, which has newer version. And it shows highest dependency version, which in semver range specified in package.json.

npm outdated output

npm update updates all dependencies to the highest version, matching the specified semver range (“wanted” column in npm outdated).

npm update output

It is not possible to select only a few dependencies, so it installs everything. Sometimes minor version has bugs, and we don't want to update them just yet. With npm update the only option is to pin the version in package.json, and then unpin it when the dependency is fixed.

After npm update npm outdated shows remaining versions outside the specified semver range. Usually just major versions.

npm update both updates package.json and installs new versions (no need to run npm install).

npm outdated output

npm-check-updates permalink

npm-check-updates provides a much better experience than built-in tools. It shows version differences more clear than npm outdated.

npm-check-updates output

Unlike npm update it updates everything to the latest version ignoring the semver range specified in the package.json.

npm-check-updates has an interactive mode, where it asks whether it should update each dependency:

npm-check-updates interactive mode

It's not possible to end progress with saving progress in the middle of dependency questions. You'll have to answer to every question, even if you want to update only the first few.

npm-check-updates updates only package.json, you need to run npm install after it.

npm-upgrade permalink

npm-upgrade even better experience than npm-check-updates. It shows same version differences list as npm-check-updates (it's because npm-upgrade built on top of it :)). And it provides more functional interactive mode. Interactive mode is main functionality of npm-upgrade.

npm-upgrage interactive mode

Unlike npm-check-updates you could finish answering questions in the middle of the list and still keep the progress (“Finish update process” option).

npm-upgrade provides a quick way to see changelog for each dependency. It tries to find a changelog in the repository, or “Release” page on Github. Sometimes it fails to do so, but at least it will open the repository, and you can find changelog yourself.

npm-upgrade output after finishing update

npm-upgrade updates only package.json, you need to run npm install after it.

npm-check permalink

npm-check has a convenient interactive mode. It groups versions (major, minor, patch, non-semver), and unlike previous tools you can go through the list with arrow keys and select dependencies with a space key.

npm-check interactive mode

npm update both updates package.json and installs new versions (no need to run npm install).

How I update dependencies permalink

Most of the time I use just npm-upgrade because it allows selectively update dependencies and easier access to changelogs. Sometimes I use npm-check.

I prefer to update dependencies every two weeks on Monday. Updating on Monday gives enough time to catch something weird or some regression, and have a calm weekend :) 99% of the time, there are no issues after an update.

Usually, I update dependencies in a few rounds:

  1. All patch versions, and minor versions of devDependencies. It's unlikely something will break.
  2. Then I update minor versions of regular dependencies. I try to group updates. E. g. update Babel and all Babel plugins in a single round. Or ESLint and all it's plugins, etc.
  3. Finally major versions. Usually, one major version at a time, unless major versions have breaking changes, which shouldn't cause any problems for my project (e. g. dependency dropping support for some old Node.js version).

Almost after every round I run tests and check in browser (for client-side projects) areas that could be affected by just updated dependencies.

I commit changes after every round. If new dependencies cause problems, then it would be easier to find the cause, and no need to redo previous rounds.

After updates are done, I run tests again and check all affected areas in the browser, if applicable. Clean Git history by merging all commits into one.