Editor’s note: This article was last updated by Rosario De Chiara on 22 April 2024 to update code blocks based on Node.js v22, provide an overview of the asdf plugins ecosystem, and feature a few alternative package management tools like nvm and Volta.
When working with several projects at a time, you may need different versions of the programming language you are using. This leads to uninstalling and reinstalling the correct version of each language, which wastes time.
Fortunately, switching between different versions can be easy with version managers like Node Version Manager, rbenv for Ruby, or pyenv for Python.
These are a great help, but if you need to manage and install multiple tools for your multi-language project, it can be cumbersome. Instead, you can use asdf to manage multiple runtime versions, managing all of the language versions you’re using with a single CLI tool. asdf is an extendible version manager that supports multiple languages, including Ruby, Node.js, Elixir, Erlang, Python, and more, all at once. You can switch between multiple versions of languages globally and on a per-directory basis.
In this article, we will learn everything you need to work with asdf and Node, including how to set up and update asdf on your local machine, and install, update, and remove the Node plugin.
To begin using asdf, we need to first install some dependencies like coreutils
, curl
, and git
. asdf uses these dependencies to install different languages.
Execute the following installation commands:
brew install coreutils curl git # on macOS with Homebrew sudo apt install curl git # on Linux
asdf documentation recommends cloning from the Git repo, like so:
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0
To install asdf, add it to your shell. You can check out other installation methods in the documentation.
I’ll be using the Bash and Homebrew (macOS) method. But before moving on to the real action, let’s look at the overlap between asdf and brew (and other package managers).
Asdf and brew (or choco, for example) are package management tools, but they serve slightly different purposes: they enable the installation and management of software packages. asdf specializes in managing runtime versions of various programming languages and frameworks, while brew (short for Homebrew) is a general package manager for macOS and Linux. The same task is covered by choco under Windows.
Add asdf.sh
to your ~/.bash_profile
with the following:
echo -e "\\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ~/.bash_profile
Then, set up Bash completion:
echo -e "\\n. $(brew --prefix asdf)/etc/bash_completion.d/asdf.bash" >> ~/.bash_profile
You can see your ~/.bash_profile
like so:
cat ~/.bash_profile
asdf also supports Zsh
and Fish
shells.
Now, close the terminal, and start a new terminal. Let’s make sure asdf is installed by typing asdf
in the command line.
In asdf, each language is supported by a plugin. They offer hundreds of plugins, but if you don’t see what you need, you can also create your own.
Plugins include more than just languages; asdf also supports databases, expanding the possibilities with the tool. We describe the plugin ecosystem here to scratch the surface of what can be achieved.
First, the extensive list of plugins demonstrates that, no matter how esoteric your framework or language is, asdf likely covers it. And, if you want, there is a solid framework to develop new plugins to accommodate your needs. The plugins can be classified into two families: those provided directly by the asdf team and those developed by the community. In the first category, named First Party Plugins, you can find Elixir, Erlang, Ruby, and Node.js, which is the focus of this article.
Plugins are installed with the following command:
asdf plugin add <name>
Before installing the Node plugin, we first have to install GnuPG to verify the authenticity of the package. There are different requirements for every plugin, which you can find on each plugin’s GitHub repo.
Once installed, you can see a list of installed plugins like so:
asdf plugin list
asdf lists all available versions of each programming language; as of writing this article, there are a total of 735 versions of Node that we can install.
You can view a list of Node versions with the following:
asdf list all nodejs | wc -l # prints 735
To install a specific version of Node, run this:
asdf install nodejs 22.1.0
If you come across some errors while installing a version of Node, try this command:
asdf reshim nodejs
You may get an error here about reshim
. Without running the reshim
command, the npm package will not be available in your path:
Unknown command: `asdf reshim nodejs 22.1.0` /usr/local/Cellar/asdf/0.14.0_1/libexec/bin/asdf: line 82: /Users/<your-username>/.asdf/lib/commands/command-help.bash: No such file or directory
You can see which versions you have installed by running the following:
asdf list all nodejs
To install the latest version of Node, run:
asdf install nodejs latest
We can also install the latest Node version that begins with a given string:
# asdf install <name> latest:<version> asdf install nodejs latest:16
Programming language versions can be set on three levels: global, in the current shell, or locally.
You can set a default global version of Node so that it will persist in any new shell. This will add or update a line in the .tool-versions
file under the Home
directory.
To set a global or default version of Node, run the following:
# asdf global <name> <version> [<version>...] asdf global nodejs 22.1.0 asdf global nodejs latest
Now, you can verify the current version of asdf with asdf current
command. In my case, it’s showing the latest Node version, 22.1.0:
(base) âžś ~ asdf current nodejs 22.1.0 /home/<your-username>/.tool-versions
If you don’t have a version listed for a tool execution, it will return an error. With this command, we can see the tool and version resolution, or the absence of it, from the current directory.
Global defaults are managed in $HOME/.tool-versions
. You can see its contents by running the following:
cat $HOME/.tool-versions
I have set the global Node version to the latest, which I can verify by running this:
(base) âžś ~ node -v v22.1.0
If you want to use the Node version only in the current shell, run the following:
# asdf shell <name> <version> [<version>...] asdf shell nodejs 14.17.6 asdf shell nodejs latest
This version of Node will only run in the current shell session, so when you close the session, this version will not be available.
Under the hood, shell
sets the version to an environment variable named ASDF_${LANG}_VERSION
for the current shell session only:
ASDF_NODEJS_VERSION=14.17.6 node --version
You can also run a specific version of Node based on a single project by setting up the version locally:
asdf local <name> <version> [<version>...] asdf local nodejs 14.17.6 asdf local nodejs latest
local
writes the version to $PWD/.tool-versions
.
You can verify the Node version for local and shell environments by running node -v
. To set up a local version based on a single project, first, install the version you want to use with asdf install nodejs
and run asdf local nodejs
. This will create a .tool-versions
file with the Node version you chose.
Uninstalling a version
To uninstall a version, use this command:
# asdf uninstall <name> <version> asdf uninstall nodejs 14.17.6 asdf uninstall nodejs latest
Adopting a new version manager can take time within teams, which is why asdf lets you fall back to legacy version files. You can still use your preferred version manager, if you’d like.
To enable legacy support, add an .asdfrc
file to the home directory ($HOME/.asdfrc
) and add the following configuration setting:
legacy_version_file = yes # .asdfrc file
By setting legacy version files to yes
, asdf will be able to read other version manager files like .nvmrc
, .node-versions
, or .ruby-versions
.
At some point, you may need to update the plugins. You can do so by running this command:
asdf plugin update --all
Up until this point, we have relied on asdf to manage multiple development environments. To keep up with the asdf
version, run the following command:
asdf update # via git brew upgrade asdf # via homebrew
If you want to uninstall asdf, you can follow along with the docs.
The subject of this article is asdf, of course, but it helps to have a list of alternatives that solve (more or less) the same problems as asdf. Here, we briefly summarize a few of them:
These tools offer different features, but they all allow you to install, manage, and switch between different versions of Node.js. Your preference will depend on your environment and needs.
For example, NVM is widely used and well-supported, n is known for its simplicity and speed, fnm is lightweight, and Volta offers additional features like managing npm and Yarn versions. If you need to manage multiple languages within a single tool, asdf is a great choice. But if you’re focused on a particular language, you might find specialized tools more suitable.
The scenario where asdf particularly excels is the one where you want to use different programming languages and handle their version by using a unique interface. In this case, asdf is the tool of choice, offering a single command to juggle versions and frameworks.
asdf is a great tool for polyglot programmers. It enables a concern-free installation and easy switching between multiple language versions, saving time for what matters — don’t forget to read the Ballad of asdf!
Now, you can install as many languages as you want to work with. Instead of using many different package managers, you can give asdf a try to rule them all.
What about you? Do you use asdf? How has your experience been with it?
Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third-party services are successful, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens while a user interacts with your app. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.
LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. Start monitoring for free.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowEfficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.
Design React Native UIs that look great on any device by using adaptive layouts, responsive scaling, and platform-specific tools.
Angular’s two-way data binding has evolved with signals, offering improved performance, simpler syntax, and better type inference.
Fix sticky positioning issues in CSS, from missing offsets to overflow conflicts in flex, grid, and container height constraints.