Daily-It

개발, AI, 인프라, 자동화와 일상 IT 제품 후기를 직접 써보며 정리하는 기술 블로그입니다.

Installing NVM: Managing Node.js Versions on Apple Silicon Mac

Summary

When installing Node.js on Mac for the first time: brew install nodeseems to be sufficient. However, even if there are only two or three projects, problems quickly arise. Some projects require Node 18, while others only work properly on Node 22 or higher.

In this case, you cannot delete and reinstall Node.js every time. Usually, Node versions are divided and managed using NVM. Especially in the Apple Silicon environment, it is not difficult to use as long as you know zsh settings, arm64 support, and issues with Rosetta in older Node versions.

Table of Contents

Background

Node.js version issues come up more often than you might think.

For example, an existing project might run on Node 18, but a new project might require Node 22 or 24. In this state, if only one system node is used, npm installIt works, but the build is broken, or conversely, it builds but certain packages don’t work.

NVM (Node Version Manager) is a tool that allows you to change the Node.js version for each project in this situation.

# 프로젝트 A
nvm use 18

# 프로젝트 B
nvm use 24

In this way, you can change versions and use them.

Sources Checked for This Article

Installation instructions may differ slightly between older blog posts and the current official documentation. So, I re-checked this article based on the data below.

Verified data What we found
nvm official README installation script, zsh configuration, .nvmrc, LTS command
nvm GitHub Releases latest nvm release v0.40.5
Node.js official download page Current LTS and Current version flow
Node.js release policy Active LTS, Maintenance LTS, EOL concepts
Apple Support zsh default shell since macOS Catalina
Homebrew official documentation The Homebrew Path to Apple Silicon /opt/homebrew
Volta/fnm official documentation nvm alternative tools comparison

Details

Step 1. Check current shell and CPU architecture

For Apple Silicon, the default shell is usually zsh. First we check the current shell:

echo $SHELL

In a normal Mac environment, it usually looks like this.

/bin/zsh

Also check your CPU architecture.

uname -m

If it’s Apple Silicon, it usually appears like below.

arm64

If you have checked this far, most of the subsequent configuration files will be ~/.zshrc You can look at it as a standard.

Step 2. NVM installation

Install based on nvm official README. The latest release at the time of writing is v0.40.5no see.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash

wgetIf you are using an environment, the command below is also possible.

wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash

The installation script is usually ~/.nvm Create a directory and add nvm loading code to the shell configuration file.

Step 3. Reopen terminal or load zsh settings

Immediately after installation nvm There are times when you type a command but it doesn’t come out. This doesn’t mean the installation failed, it’s still ~/.zshrcIn many cases, it is not reloaded.

source ~/.zshrc

Alternatively, you can close the terminal completely and reopen it.

Check installation with the command below.

command -v nvm

If it’s normal, it will come out like this.

nvm

Step 4. Check zsh settings

~/.zshrcCheck that the contents below are included.

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

In the nvm official README: $XDG_CONFIG_HOMEWe will also guide you through settings that take this into consideration.

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

If you have a personal Mac development environment, the first approach is often sufficient. If your company manages dotfiles or common shell settings, you can check the second method as well.

Step 5. Install Node.js LTS

For new projects, it is usually safer to install the LTS version first.

nvm install --lts

After installation, check the version.

node -v
npm -v

If you want to use the currently installed version as the default, specify it as follows.

nvm alias default node

If you want to set a specific version as default, you can write the version number.

nvm alias default 24

Step 6. Create project-specific .nvmrc

In practice, this is the most important part. in the project root .nvmrcBy creating a , it becomes easier for team members to use the same Node version.

For example, if your project uses Node 24, .nvmrc Write this in the file:

24

If you want to keep up with the latest version of LTS, you can also write like this:

lts/*

Run the command below in the project folder.

nvm install
nvm use

If you do this, you can easily provide instructions in the README as well.

nvm install
nvm use
npm install

There are more build errors than you might think due to mismatched Node versions. .nvmrc Even just one commit can significantly reduce the differences in environments between team members.

Step 7. Automatically run nvm use when moving a folder

every time nvm useIf you don’t want to bother typing , you can use a zsh hook.

autoload -U add-zsh-hook

load-nvmrc() {
  local node_version="$(nvm version)"
  local nvmrc_path="$(nvm_find_nvmrc)"

  if [ -n "$nvmrc_path" ]; then
    local nvmrc_node_version="$(nvm version "$(cat "$nvmrc_path")")"

    if [ "$nvmrc_node_version" = "N/A" ]; then
      nvm install
    elif [ "$nvmrc_node_version" != "$node_version" ]; then
      nvm use
    fi
  elif [ "$node_version" != "$(nvm version default)" ]; then
    nvm use default
  fi
}

add-zsh-hook chpwd load-nvmrc
load-nvmrc

However, there are likes and dislikes about this setting. Every time you move a folder, you may see output or the terminal may start slightly slower. You can think of it as just trying it out in a personal development environment and removing it if it is inconvenient.

If you need Rosetta on Apple Silicon

If you’re using the latest Node.js LTS, you usually don’t have to worry about Rosetta. According to nvm official documentation, Node.js provides arm64 Darwin binaries for Apple Silicon starting with v16.0.0.

The problem is the old Node version.

Node.js version What it means for Apple Silicon
Node.js 16+ arm64 Darwin binary available
Node.js 14.17 or higher Mention of experimental arm64 support based on source compilation
Old Node.js 14 and below May require Rosetta 2 or x86_64 environment

To check which architecture your Node is currently running, use the command below:

node -p "process.arch"

If an arm64 Node is running on Apple Silicon, it will appear like this.

arm64

Can I install nvm with Homebrew?

In conclusion, I don’t recommend it. nvm’s official README states that Homebrew installation is not supported.

You may see the nvm package in Homebrew. However, when a problem occurs, the official nvm project instructs you to reinstall and check using the official installation script, not the Homebrew installation.

So it is better to install nvm in the following way.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash

Homebrew is convenient for installing other development tools. However, it is less confusing to follow the official installation method for nvm.

Volta compared to fnm

nvm is not the only Node version management tool. If you are in a situation where you are setting a new team standard, Volta or fnm are also worth watching.

equipment Feature Perfect for these cases
nvm The most widely used shell-based Node version manager There is a lot of existing data .nvmrc When Compatibility Matters
Volta Strong in fixing versions of tools such as Node, npm, yarn, and pnpm When you want to strongly match the JS tool version on a team basis
fnm It’s fast because it’s based on Rust .nvmrcalso support Used similarly to nvm, but when speed is important

For a personal development environment, starting with nvm is sufficient. If it is a team unit, README and CI settings must be coordinated regardless of the tool used.

Best Practices

Commit .nvmrc to the project

.nvmrcis small but effective. Especially in front-end projects or Node-based back-end projects, installation errors often occur due to a single Node version.

24

Place this file in the root of your project and commit it to Git.

Write down the execution order in README

It is a good idea to write the following in the README so that anyone who first receives the project can follow it right away.

nvm install
nvm use
npm install
npm run dev

Just this much will help you feel less lost during onboarding.

Match CI and local Node versions

If your local is Node 24 but your CI is Node 20, the results may be different. Node version used in GitHub Actions or Jenkins .nvmrcIt is safer to match .

Old Node versions leave reasons behind

If you need to keep using an older version like Node 14 or 16, it’s a good idea to leave a reason behind it. It will be helpful when upgrading later if you organize whether there are specific package compatibility or operating environment restrictions, rather than simply saying, “I’ve used it this way before.”

Common Mistakes

After installing nvm, command not found appears.

This is the most common case. It’s not that it’s not installed, it’s that the shell settings haven’t been applied yet.

source ~/.zshrc
command -v nvm

If that doesn’t work ~/.zshrcto NVM_DIR Check whether the settings have been entered.

The settings are in a file other than .zshrc.

The nvm installation script is ~/.bashrc, ~/.bash_profile, ~/.zshrc, ~/.profile I’m trying to automatically choose one of the following. Sometimes settings are entered in a file other than what you want.

If you’re using zsh on a Mac, first of all ~/.zshrcCheck out .

cat ~/.zshrc

Homebrew Node and nvm Node are mixed

In the past brew install nodeIf there are any remaining nodes installed with which node Results may not be as expected.

which node
node -v

If you are using nvm Node, usually in the path .nvmThis is included.

/Users/사용자명/.nvm/versions/node/v24.x.x/bin/node

Only create .nvmrc and do not use nvm

.nvmrc Creating a file does not automatically change the version. If you haven’t set up automatic conversion, you’ll need to do it yourself.

nvm use

The Node version is different between VS Code terminal and regular terminal.

There are times when nvm works in a regular terminal, but it doesn’t work in a VS Code terminal. At this time, the default shell of VS Code is zsh, and ~/.zshrcYou need to make sure that it loads properly.

echo $SHELL
command -v nvm
node -v

Failure Cases and Fixes

Case 1. I installed it nvm: command not foundcomes out

This is the most common case. Looking at the official README and Stack Overflow examples, it’s usually not an installation failure, but a problem with the shell settings not being loaded yet.

First, open a new terminal or run the command below.

source ~/.zshrc
command -v nvm

If nothing comes out though ~/.zshrcCheck whether the nvm loading code is entered.

grep NVM_DIR ~/.zshrc

If there are no settings, add the following.

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

Save and reload.

source ~/.zshrc

The important thing here is which nvmsee command -v nvmIt is better to use . This is because nvm is loaded as a shell function rather than a regular executable.

Case 2. nvm does not work only in VS Code terminal

In a normal terminal nvmThis may not work only in the VS Code terminal. In this case, the shell or profile settings that VS Code is opening are likely different from those in a regular terminal.

Check it first in the VS Code terminal.

echo $SHELL
command -v nvm
node -v

Run the same command in a regular terminal and compare the results.

echo $SHELL
command -v nvm
node -v

If the results of the two are different, in VS Code Terminal: Select Default ProfileRun and check that the default terminal is set to zsh. If that doesn’t work, open the VS Code terminal ~/.zshrcYou need to make sure you are reading it correctly.

Case 3. Homebrew Node and nvm Node are mixed

In the past brew install nodeIf you install nvm with Node.js installed, the path may be confusing. At this time node -vJust looking at it is not enough; you need to see which nodes are actually running.

which node
node -v
npm -v

If you are using nvm node, go to the normal path .nvmThis goes in.

/Users/사용자명/.nvm/versions/node/v24.x.x/bin/node

Conversely, when a Homebrew Node is captured, it is usually /opt/homebrew You can see the path.

/opt/homebrew/bin/node

In this case, you need to decide which method to use. If you plan to manage versions for each project using nvm, after initializing the terminal, nvm useFirst, make sure that is applied properly.

nvm use
which node

There is no need to unconditionally delete the Homebrew Node, but if you do not know that the two methods are mixed, npm installThis makes it difficult to track down build errors.

Case 4. .nvmrcThere is, but the Node version does not change automatically.

.nvmrcis not an automatic conversion function, but an indication that “this project uses this version of Node.” If you haven’t set up automatic conversion, you’ll need to do it yourself.

nvm install
nvm use

If you want automatic conversion, you need to add a zsh hook. However, this setting is not necessary for everyone. Some people don’t like having output appear every time they move the terminal, so it’s better to leave it as a personal choice rather than forcing it as a team rule.

Case 5. Apple Silicon problems occur when installing an old Node version

The latest LTS versions usually install well as arm64. The problem is an old Node.js version. According to nvm official documentation, Node.js provides arm64 Darwin binaries for Apple Silicon starting with v16.0.0.

If you need to use Node 14 or lower for an older project, you may need Rosetta or an x86_64 environment. First, check the current architecture.

uname -m
node -p "process.arch"

If possible, it is best to upgrade your project to the LTS version. If you need a really old version of Node, please leave a reason in the README. Later, someone will encounter the same problem again.

Conclusion

Using nvm on Apple Silicon itself is not that difficult anymore. If you’re installing the latest Node.js LTS, you don’t even need to think of Rosetta first.

In fact, the part that often gets stuck is shell settings rather than installation. nvm If the command is not caught, it is not a Node problem. ~/.zshrcIt is often not loaded, or the settings are in a different profile file.

For a personal development environment, starting with nvm is sufficient. If it’s a team project .nvmrcCommit and set the README and CI Node versions together. This little cleanup will save you quite a bit of build errors later on.

References

  • nvm GitHub README — https://github.com/nvm-sh/nvm
  • nvm latest release — https://github.com/nvm-sh/nvm/releases/latest
  • Node.js Downloads — https://nodejs.org/en/download
  • Node.js Releases — https://nodejs.org/en/about/previous-releases
  • Apple Support: Use zsh as the default shell on your Mac — https://support.apple.com/en-us/102360
  • Homebrew Official Site — https://brew.sh/
  • Volta Official Site — https://volta.sh/
  • fnm GitHub README — https://github.com/Schniz/fnm