Managing multiple Node.js installs with nvm

Date
Node.js

Whether you’re a full-stack, backend, or frontend JavaScript developer, there will likely come a time when the projects on your system will require different versions of Node.js to function properly. Unless you’re running projects in a sandboxed environment (such as a VM), a system-wide Node installation is going to cause you issues because the version installed may be incompatible with some of your projects.

I’ve been using Node Version Manager to switch between multiple Node versions on my system for quite some time, and so far it has worked out great for me on macOS (and Linux1).

This post will walk you through installing nvm (on macOS), usage, and how to make sure each nvm instance’s npm version is up-to-date.

Installing nvm

If you’re on macOS, you’ll first want to install Homebrew and install nvm with the following command:

brew install nvm

Afterwards, you’ll want to verify some lines were added to your .zshrc (or .bashrc) file located at $HOME/.zshrc. If you don’t see them, be sure to add them (the last line is optional):

export NVM_DIR="$HOME/.nvm"
[ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh"  # This loads nvm
[ -s "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" ] && \. "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm"  # This loads nvm bash_completion

Restart any open terminals (or run source ~/.zshrc) and nvm will be ready to use. You can verify with the following command (you should see a version number printed, not an error):

nvm --version

If you’re on Linux or Windows, see the official installation instructions.

Setting the system default

To install a specific Node version, run the following in a Terminal, replacing the number with the version you want to use:

nvm install 20.10.0

To set it as the default version on your system:

nvm alias default 20.10.0
nvm use default

In your current session, and when you launch new Terminal sessions, the node command will now use the version you set as default2.

NPM and global packages

Whenever you install a new version of Node with nvm, it’s a good idea to make sure you also have the latest Node Package Manager (npm) installed as well. Normally you would use npm to upgrade itself, but for an nvm install you need to run the following command instead:

nvm install --latest-npm

Next you’ll need to install any global packages you want available. For example, to install yarn globally:

npm install --global yarn

Since every new version installed with nvm is a clean install, you’ll need to re-install any global packages you want for that specific version of Node.

Per-project versions

Being able to use separate versions of Node for different projects on your system is the primary benefit of nvm, and this can be configured by saving an .nvmrc file at the root3 of your project with the Node version number:

18.16.1

In your Terminal (make sure the current directory is your project’s), run:

nvm install
nvm use

This will pick up the .nvmrc file at the current working directory and install the version specified there. Next time, you’ll only need to run nvm use to switch to the correct Node version. Note that when you switch to a different version (without the default command), only that current Terminal session is affected. So if you have two tabs (or windows) open and you only ran nvm use in one of them, the other tab will still have the default Node version in its PATH.

Default same as project

What if the current project you’re working on uses the same version as the default on your system? In this case you don’t need to run either of the above commands since your session will already be using the correct Node version. I still recommend adding an .nvmrc to your project in case you want to upgrade or change the default Node version on your system without affecting your project.

It’s also a good idea to check the .nvmrc file into source control (ie. git) so that others working on the same project are on the same version of Node as everyone else. Even if it’s a solo project, your future self will thank you for specifying the Node version if it’s been a while.


  1. I spent a large amount of 2023 daily-driving Linux (EndeavourOS + KDE) and have since switched back to using macOS full-time, but that’s a topic for another time↩︎

  2. This is what the commands you added to .zshrc do whenever you start a new Terminal session. ↩︎

  3. The top-level folder of your project ↩︎