I'm available for challenging remote roles. Let's get in touch.

How to install and run Node.js with nvm on macOS

Learn how to install and run multiple Node.js versions effortlessly using nvm.

Flavio Silva
Flavio SilvaJune 26, 2023
How to install and run Node.js with nvm on macOS
Image by jcomp on Freepik

I last tested these instructions on macOS Ventura 13.3.1.

Head to my Introduction to Node.js if you want to know more about it.

Introduction

In this step-by-step guide, you'll learn what nvm is, how to install it, and how to install, run and manage multiple Node.js versions effortlessly, including how to use .nvmrc files for project-based Node.js versions, and how to install and set up an nvm plugin for Zsh to switch Node.js versions automatically for you.

What is nvm, and why should we use it?

When you work with Node on several projects, each one will be set up with a different version of Node, so you need a way to install, manage and run different Node versions. You need a way to run project-based Node versions efficiently and to do that, you need a tool to manage Node versions, as Node itself cannot do that. That's what nvm does.

nvm is a version manager for Node, allowing us to install and use different Node versions quickly.

With nvm, we can create a simple .nvmrc text file in the root of our project dir, defining a specific Node version for that project. Then, all we have to do besides installing such a Node version is run $ nvm use in that root project dir to switch our current Node version to the one wanted. And there are ways even to avoid manually running $ nvm use, which is great, and we'll see them moving forward.

In short, nvm makes using multiple Node versions on different projects a breeze.

Prerequisite: Have a ~/.zshrc file

You can skip to the next section if you already have a ~/.zshrc file.

Zsh automatically reads some files at certain moments. The ~/.zshrc file is one of them, and Zsh evaluates it every time it starts. We should use such files to add our custom configurations to Zsh, like what we will do with Antigen.

To check if you have your ~/.zshrc file, run the following two commands:


$ cd ~/


$ ls -lah

And look for that file. You should see it listed after a file named .zsh_sessions.

If you don't have it, create it by running the following command:


$ touch ~/.zshrc

You can read more about those files and how to use them in this StackExchange topic.

Step 1. Make sure you don't have nvm installed already

Before proceeding, make sure you don't have nvm installed already by running the following command:


$ nvm --version

If you see something like 0.39.3, you already have it installed! So you can head to Step 4. Install a Node version with nvm.

Otherwise, you should see something like the following:


zsh: command not found: nvm

In that case, let's get it installed.

Step 2. Install nvm on macOS

You only need to run a single command from the official installation guide to install nvm. But that command contains the specific nvm version you'll install. If I add it here, it'll be outdated shortly after I publish this guide.

To make sure you install the latest nvm version, copy the command from the official installation instructions (the one starting with curl -o-), run it in your Terminal, and get right back here to follow on.

That command will download and run the official nvm installation script.

You should see a bunch of output, including the following:


=> Downloading nvm from git to '/Users/your_user_name/.nvm'
=> Cloning into '/Users/your_user_name/.nvm'...

That means the installation script could run and clone the nvm Git repo into the expected dir, i.e., ~/.nvm.

You should also see the following:


=> Appending nvm source string to /Users/your_user_name/.zshrc
=> Appending bash_completion source string to /Users/your_user_name/.zshrc

That means the installation script could find and add the required configuration to your ~/.zshrc file. It adds the following three lines to the bottom of your ~/.zshrc file:


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

You can let it as is for now, as we'll remove those lines after installing the nvm plugin for Zsh.

Step 3. Make Zsh read your updated ~/.zshrc file

Now, even though nvm is installed, trying to run any nvm command, for example, nvm --version, will result in the following error:


zsh: command not found: nvm

That's because we need to open a new Terminal window or tab so Zsh can read our updated ~/.zshrc file and apply the changes we made to it.

Alternatively, you can run the following command to reload your current shell, making it read your ~/.zshrc file:


$ exec zsh

You must do either step above every time you change your ~/.zshrc file.

Now you should be able to run any nvm command. Try the following:


$ nvm --version

You should see an output like this: 0.39.3.

Awesome, nvm is installed and set up.

Step 4. Install a Node version with nvm

Now that we have nvm up and running let's install a Node version with it. The first version we install using nvm becomes nvm's default Node version, i.e., if we don't tell nvm to use a specific Node version, like right after opening a new shell instance, it uses the default one.

To install a specific Node version, we run a command like the following:


$ nvm install <node_version>

For example:


$ nvm install 14.7.0

If we want to install the latest version, we don't have to open Node's official website to check what that version is. nvm provides the node alias to install the latest Node version. So let's do that by running the following command:


$ nvm install node

You should see an output containing the following:


Downloading and installing node v20.2.0...
...
Now using node v20.2.0 (npm v9.6.6)
Creating default alias: default -> node (-> v20.2.0)

Nice. Now, if you run the following:


$ node --version

You should see an output like v20.2.0 (or the version you've got installed).

That means you now have not only nvm working but a Node version installed with it working as well! Yay! 🎉

Step 5. Set specific Node versions for your projects using a .nvmrc file

Quickly installing, managing, and switching multiple Node.js versions is the most helpful feature of nvm.

The second most helpful feature is the .nvmrc file.

In any project's root directory, you can create a .nvmrc text file with only a node version number like 14.7.0. Then, when you're in that root dir, you can run $ nvm use, and nvm will start using the Node version specified in that .nvmrc file.

That's how you set up project-based Node.js versions with nvm, and that's very helpful when you work on multiple Node.js projects because they'll rarely use the same version.

After that, anything you do Node-related will use that Node version. That way, you can easily switch between projects using different Node versions.

If you want to install a Node version set in a .nvmrc file, all you have to do is $ cd into the dir with the .nvmrc file and run $ nvm install without passing any arguments to it.

Now, what's even better than just having to run $ nvm use to switch between project-based Node versions? Not having to run it at all!

There are a few ways to accomplish this. Next, we'll see one of them.

See the official documentation about .nvmrc for more information.

What is the nvm plugin for Zsh, and why should we use it?

The nvm plugin for Zsh adds some features to Zsh related to nvm. For example, it adds autocompletion for nvm commands and makes it easy to load .nvmrc files for you automatically, so you don't ever have to run $ nvm use.

We'll use Antigen, a plugin manager for Zsh, to install the nvm plugin for Zsh.

If you still need to install Antigen or need clarification, head to my guide on How to install and use Antigen and Oh My Zsh on macOS, then get back here to proceed.

Install and set up the nvm plugin for Zsh using Antigen

Open your ~/.zshrc file and add the following to it:


...
# nvm plugin: lazy startup config
zstyle ':omz:plugins:nvm' lazy yes
# nvm plugin: auto load node version when it finds a .nvmrc file
zstyle ':omz:plugins:nvm' autoload yes
...
# Load oh-my-zsh library
...
# oh-my-zsh plugins
...
antigen bundle nvm
...

Note: Do not add the ... you see above. That's an indication that those places could have more config lines.

We must add the nvm plugin config before loading Oh My Zsh.

We add two configurations for the nvm plugin.

The first, lazy yes, avoid loading nvm right after opening a new Zsh instance, speeding up its startup time. In this case, nvm will only be loaded when we run an nvm or node command.

The second, autoload yes, sets up the plugin to automatically load a Node version when it finds a .nvmrc file in the current directory. And what is even better: if you don't have such a Node version installed, it'll install it for you! How cool is that? Well, you have to see it in action to understand it! 😉

That way, you have the best of both worlds: you don't have nvm starting automatically every time you open a new Zsh instance. At the same time, you have it automatically loaded and running the desired Node version specified in your current .nvmrc file. So you can freely browser your projects, and when you cd into a project containing a .nvmrc file, you know you're good to go and use Node.

If you followed my guide on How to install and use Antigen and Oh My Zsh on macOS and added everything I added there, nothing more, nothing less, then your ~/.zshrc file should look like the following after adding the nvm plugin config above:


# Make Antigen always available to Zsh
# Change this path if you didn't install Antigen with Homebrew
source /opt/homebrew/share/antigen/antigen.zsh
# Defaults
MAGIC_ENTER_GIT_COMMAND='git status'
MAGIC_ENTER_OTHER_COMMAND='ls -lah .'
# History management settings
setopt hist_ignore_all_dups
setopt hist_ignore_space
HISTSIZE=9999
# nvm plugin: lazy startup config
zstyle ':omz:plugins:nvm' lazy yes
# nvm plugin: auto load node version when it finds a .nvmrc file
zstyle ':omz:plugins:nvm' autoload yes
# Load oh-my-zsh library
antigen use oh-my-zsh
# Non oh-my-zsh plugins
antigen bundle unixorn/autoupdate-antigen.zshplugin
antigen bundle zsh-users/zsh-autosuggestions
antigen bundle zsh-users/zsh-completions
antigen bundle zsh-users/zsh-syntax-highlighting
# oh-my-zsh plugins
antigen bundle command-not-found # depends on Homebrew
antigen bundle git
antigen bundle history-substring-search
antigen bundle magic-enter
antigen bundle nvm
# Load a syntax highlighting theme
antigen theme robbyrussell
# Tell Antigen you're done
antigen apply
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion

Reload Zsh to apply your changes to the ~/.zshrc file

Now, you need to open a new Terminal window or tab so Zsh can read your ~/.zshrc file and apply your changes, installing the nvm plugin. Alternatively, you can run the following command to reload your current shell, making it read your ~/.zshrc file:


$ exec zsh

You must do either step above every time you change your ~/.zshrc file.

You should see an output like the following:


load-nvmrc:2: command not found: nvm_find_nvmrc

That's fine, I couldn't get rid of it, but everything works as expected. At the time of this writing, this message appears whenever I cd into dirs that don't result in a change of Node version by nvm (e.g., cd back and forth into projects using the same Node version) and when opening new Terminal windows. That's weird, but it doesn't affect its functionality. It seems to be a bug in the nvm plugin, but it could be something I did wrong in the installation or setup. But as I said, everything works as expected. Let me know if I did something wrong that's causing that problem.

Now, open your ~/.zshrc file again and delete those three lines that the nvm installation script added to its bottom. We don't need them anymore now that we have the nvm plugin for Zsh up and running, as it runs nvm for us.

Then, reload your Zsh instance:


$ exec zsh

You should get that same output again.

Using ~/.nvmrc files in your projects

If you have Node projects with .nvmrc files in their root dirs, you can now cd into them and see the magic happens. Go ahead, test it. Go to their dirs, then run $ node --version to see that it switches Node versions automatically for you and even automatically installs those you don't have installed!

If you don't have such projects set up but want to see it working, create the following dir structure:


- project-a
.nvmrc
- project-b
.nvmrc

You can have the following inside project-a/.nvmrc:


18.16.0

And the following inside project-b/.nvmrc:


16.20.0

Go back and forth into each of those dirs, and every time you get into a project dir, run the following:


$ node --version

You should see the correct Node version for each project! Nice, huh?

Every time you cd into a dir that contains a .nvmrc file, you'll also see a message like the following:


Found '<path to your .nvmrc>' with version <node_version>
Now using node <node_version> (npm <npm_version>)

Now that we have that awesome setup working let's learn the most common nvm commands.

The most common nvm commands


$ nvm install <node_version>

Installs a specific Node version.


$ nvm uninstall <node_version>

Uninstalls a specific Node version.


$ nvm ls

Outputs all installed Node versions (-> points to the active version).


$ nvm ls-remote

Outputs all available Node versions for you to install.


$ nvm current

Outputs the active version. That's the same as running $ node --version.


$ nvm alias default <version>

Sets a default (global) version of Node to use in all shells.


$ nvm use

Sets the active Node version to the one in the .nvmrc, if available. Otherwise, it outputs the following error:


No .nvmrc file found


$ nvm use <version>

Sets the active Node version to the one specified in <version>.

How to update nvm

If you followed this guide and installed nvm running their official installation script, you run the same command to update it. That's why the official documentation calls it Install & Update Script.

How to uninstall nvm

To uninstall nvm manually, run the following command:


$ rm -rf "$NVM_DIR"

Then, open your ~/.zshrc file and delete those three lines that were added by nvm when we installed it. They should look like the ones below:


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

If you're using the nvm plugin for Zsh, you already removed those lines from your ~/.zshrc file, so you don't have to do it.

And that's it. nvm should be uninstalled. You can make sure by running the following command:


$ nvm --version

You should see an output like the following:


zsh: command not found: nvm

For more information about uninstalling nvm, visit the official instructions.

How to uninstall the nvm plugin for Zsh

If you want to keep nvm but want to uninstall the nvm plugin for Zsh, run the following command:


$ antigen purge nvm --force

You should see an output like the following:


Done. Please open a new shell to see the changes.

That removes the nvm plugin from your filesystem.

But you must also manually delete all configuration lines for the nvm plugin from your ~/.zshrc file, especially the following one:


antigen bundle nvm

Otherwise, Antigen will install the nvm plugin again the next time you open a shell.

After that, you can reload your Zsh instance by running the following:


$ exec zsh

And that's it. The nvm plugin should be uninstalled.

Conclusion

And that's it for this guide. I hope you enjoyed it!

Thank you for reading, and let me know if you have any issues or suggestions in the comments below.




I incorporated generative AI tools into my workflow, and I love them. But I use them carefully to brainstorm, research information faster, and express myself clearly. It's not copy/paste in any way.



Introduction to Node.js
How to set up your Mac for software development
How to install and use Homebrew on macOS
How to install Git with Homebrew on macOS
How to install and use Antigen and Oh My Zsh on macOS
How to install Command Line Developer Tools on macOS
How to generate and use SSH keys on macOS
How to sign Git commits with SSH keys on macOS

How to install and run Node.js with nvm on macOS by Flavio Silva is licensed under a Creative Commons Attribution 4.0 International License.

Leave a comment using your GitHub account

© 2024 Flavio Silva