Better Node.js management with ASDF

Short practical guide to Node.js version management

· 4 min

For a long time I've relied on NVM to manage my Node.js versions. Later onc I switched to fnm. FNM is similar to NVM, but written in Rust. Both of them are good at what they do - managing Node.js versions, but that's about it. They are specialized tools.

Recently I gave asdf a try and I don't think I will ever go back to other Node.js managers. Asdf is not only a Node.js manager. It's a tools manager. It can manage many different tools and programming languages that you probably already use in your daily work. Why use specialized tools when you can use one tool to rule them all?

I've written some notes on now to get started with asdf to manage Node.js. Mostly for myself, but hopefully you will find them useful too. Maybe I can at least awaken your curiosity so you can give it a try!

Installing ASDFpermalink

To install Asdf git clone it into .asdf directory in your home folder or some other location. You are free to choose the location, but I strongly recommend sticking to Asdf's recommendation.

$ git clone ~/.asdf

I am using Zsh as my main shell. To make asdf command and autocompletion available in the shell I had to add the following to my ~/.zshrc.

# ~/.zshrc
source $HOME/.asdf/

# add asdf completion
fpath=(${ASDF_DIR}/completions $fpath)
autoload -Uz compinit

If you source your Zsh config the asdf command should be available to you. I am on Linux, so make sure to check installation instructions for your distro or operating system by reading Asdf's excellent documentation.

Asdf is useless on its own. To install a tool or programming language you first have to install a plugin for it in asdf. Maybe a best way is to view asdf as a plugin manager. You first install a specific plugin and then you install specific versions of tools or languages using that plugin.

Asdf has a well thought-out design. You keep everything self-contained and isolated and use asdf top level command to orchestrate everything. Its design also enables modularity and easy plugin authoring. Everything is kept in one local directory - $HOME/.asdf. No chmod or sudo commands required!

You can view all your installed plugins by running asdf plugin list all command. To see all available Asdf plugins you can run asdf plugin list all or visit Asdf's plugin page.

Installing Node.js ASDF pluginpermalink

You can install many tools and programming languages with Asdf. Here is how to install Node.js using Asdf.

# add nodejs asdf plugin
$ asdf plugin add nodejs

The command may fail if you don't have all plugin's requirements installed on your computer. Often plugins rely on a few specific system packages to be installed. For example Node.js plugin relies on dirmngr, GnuPG, curl and awk to be present.

Installing Node.jspermalink

After you have a working Node plugin installation you can proceed to install a specific version Node.js, but first you have to know versions are available.

# list all node versions
$ asdf list all nodejs

The command will print out a couple of pages of Node.js versions with latest and greatest version at the bottom of the list.

If you want to install the latest version of Node you don't have to specify the version, just use latest.

$ asdf install nodejs latest

% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4009 0 4009 0 0 16430 0 --:--:-- --:--:-- --:--:-- 16430
gpg: key D7062848A1AB005C: public key "Beth Griggs " imported
gpg: Total number processed: 1
gpg: imported: 1
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 31.8M 100 31.8M 0 0 3369k 0 0:00:09 0:00:09 --:--:-- 3553k
node-v16.3.0-linux-x64.tar.gz: OK

Same goes for Node LTS. Just use lts instead of latest. To see what versions you currently have installed run asdf list nodejs command.

Installing global NPM packagespermalink

I rely on a few global NPM packages in my daily work. Luckily Asdf's Node.js plugin can install global packages for us automatically if we specify them in ~/.default-npm⁠-⁠packages file.

$ cat ~/.default-npm-packages

If you don't want auto NPM installs after installing new Node.js version you can install the packages manually. A common gotcha is to forget to reshim after installation.

$ asdf reshim nodejs

If you forget to run the reshim command the globally install NPM package will not be available in your path.

Different projects, different versionspermalink

Asdf lets you specify specific tool versions per project. For that it relies on the .tool⁠-⁠versions file for switching between versions. If you are coming from NVM you can have asdf read an existing .nvmrc or .node⁠-⁠version file. To do this, add the following line to $HOME/.asdfrc.

legacy_version_file = yes

To use a specific version of Node.js in your project run asdf local node <version> command. Just make sure that node version is installed first otherwise the command will fail. If everything went fine Asdf will write to a .tool⁠-⁠versions file in the project folder. Next time you come back to that folder asdf will use the project-local node version.

Global versionspermalink

You can specify system-wide (global) version of the tool by running asdf global node 16.3.0 command. This will add it to the ~/.tool⁠-⁠versions file and that version will be use if no local version is specified. Here is my global versions file.

$ cat ~/.tool-versions
bat 0.18.0
erlang 24.0.1
elixir 1.12.1-otp-24
neovim nightly
nodejs 16.3.0

It's a short list for now as I am currently in the tool migration phase.

Every day ASDF commandspermalink

  • asdf list <plugin> - show locally installed tool versions
  • asdf list all <plugin> - show all available tool versions
  • asdf plugin add <plugin> - install asdf plugin
  • asdf install <plugin> <version> - install specific tool version
  • asdf uninstall <plugin> <version> - remove specific tool version
  • asdf global <plugin> <version> - set global tool version
  • asdf local <plugin> <version> - set project-specific tool version
  • asdf reshim <plugin> - refresh plugin state
  • asdf help - probably the only command you need to know

Bonus: Installing Neovimpermalink

I've recently switched to Neovim where some features are only available in the nightly build. Just for the reference, and to demonstrate now to use Asdf to install something else, here is how I installed Neovim using Asdf.

$ asdf plugin add neovim
$ asdf install neovim nightly
$ asdf global neovim nightly
$ asdf uninstall neovim nightly && asdf install neovim nightly

Side note: A Vim user? I encourage you to give Neovim nightly (upcoming v0.5) a try!

In summarypermalink

Why use many specialized package managers when you can have one manager to rule them all? Of course, it's not always smooth sailing. Asdf can be a bit quirky to set it up if you are unlucky.

Although Asdf supports many tools I have some personal threshold. For example, I would not install Postgres with it. For that I would either use Docker or install it using native OS package manager. For everything else I will probably use Asdf in the near future.

If you liked what you read, it would make me really happy if you could share it on Twitter.