Have you ever been in this situation where you are working on multiple projects and have to deal with multiple versions of Java, NodeJS or Postgres? In this article, we’ll discover how to switch between different runtime versions automatically depending on the current folder, and therefore the project. 📁
As a freelance developer working on different projects for different clients, you have probably already found yourself in this situation: project A runs with Java 8, project B runs with Java 11, and project C runs with Java 17. To easily switch between these versions, you might have used the
sudo update-alternatives --config java
This works pretty fine, but there is a drawback to this approach: you have to manually run this command every time you have to switch to another version, which can quickly get cumbersome. Also, this command does not work with all tools, such as
One way to solve this problem is to use Docker. Indeed, the purpose of Docker is to create an image that contains all the correct versions for the current project. However, not everyone knows Docker, and not every project has a Dockerfile to build this setup. Also, not all teams have the time to build a Dockerfile: depending on the project size, it can easily get complicated to create one quickly.
Another solution would be to have something like a magic wand that automatically switches between Java 8 in the
project-A folder and Java 11 in the
project-B folder, and so on.
Actually, this magic wand exists, and is called asdf. 🪄
So what really is
asdf? It is a CLI tool that automatically switches between your runtime versions (Java, NPM, Node, Postgres, PHP, and even more) depending on your current folder. To do so, it relies on a file named
.tool-versions (located in the folders where you need to use it) to know which version to use for each tool. This file simply contains a mapping list of each tool with the correct version to use.
java openjdk-17 nodejs 17.3.0 postgres 13.5
When your current folder does not contain a
asdf will just look in the parent folders to find the first one containing such a file. As a result, you need to define a default version for each tool, so that
asdf can use this default version if no
.tool-versions file was found in the parent folders. The default versions are stored in your home directory:
Something really interesting is that you can commit this
.tool-versions file to your git repository so that your colleagues can also have the correct versions of the different tools, as long as they are using
Let’s say your default
node version is 17.3.0, but one of the projects you are working on is a bit old and uses version 12.13.0. If you start a terminal and run the command to get the
node version, it will display your current one.
$ node --version v17.3.0
This command will produce the same output if you are in the
project-A folder. However, if you tell
asdf that it should use the version 12.13.0 of
node in this project, the output will change.
$ asdf local nodejs 12.13.0 $ node --version v12.13.0
And if you change to another directory, the
node version will magically change back to your default one.
$ cd .. $ node --version v17.3.0
Totally crazy, right? 🤯 Let’s now see how to set-up
asdf (spoiler alert: it is ridiculously easy).
In the first place, you will need to download
asdf (available on Linux and MacOS, but unfortunately
not on Windows). To do so, just clone the git repository to your home folder.
git clone https://github.com/asdf-vm/asdf.git ~/.asdf
If you are on MacOS, you can simply use
brew install asdf
Once done, you will need to add these two lines to your
. $HOME/.asdf/asdf.sh . $HOME/.asdf/completions/asdf.bash
And that’s it, you’ve successfully installed
asdf, you will first need to add the plugins you need. A plugin corresponds to a tool: for instance, you will need to add the
java plugin to switch between java versions, the
nodejs plugin to switch between NodeJS versions, and so on. To add a plugin, simply run the following command:
asdf plugin add [plugin]
In this example, we will continue with
nodejs, so we will install this plugin.
asdf plugin add nodejs
💡 You can list all the available plugins with the
asdf plugin list allcommand. As this will produce a pretty big list, you can filter the results with
asdf plugin list all | grep node
Now that we’ve added the
nodejs plugin, we will need to download the versions we want to use. In our case, we want both 12.13.0 and 17.3.0 versions.
asdf install nodejs 12.13.0 asdf install nodejs 17.3.0
After installing these versions, the last step is to specify which one to use depending on the project. To do so, head over to the folder of the project that uses 12.13.0 (let’s say
project-A) and select the correct
asdf local nodejs 12.13.0
And that’s it! The 12.13.0 version of Node will be used in the
project-A directory and sub-directories. 🥳
If you now run
ls -al in the project folder to list all the files, you will notice the
.tool-versions file that contains the correct Node version. You can commit it to your version control system.
💡 When cloning the project containing this file, your colleagues don’t even have to manually install the listed versions: they can simply run
asdf install, and the magic wand will take care of downloading all required versions.
Lastly, as we’ve seen earlier, we need to define a default version to use when we are in another folder which has no
.tool-versions file in it or in its parent folders. In our case, we want the default version of Node to be 17.3.0.
asdf global nodejs 17.3.0
💡 You can also specify a version for the current shell.
asdf shell nodejs 17.3.0
And that’s it, we’ve successfully got rid of the pain of having to manually switch between our runtime versions, thanks to our new magic wand. 🪄
asdf, our runtime versions are now managed automatically. When you need to use a new plugin, the steps will always be the same:
- Install the corresponding plugin:
asdf plugin add [plugin]
- Install all the versions you need:
asdf install [plugin] [version]
- Select the local version for each concerned project:
asdf local [plugin] [version]
- Select the default version for this plugin:
asdf global [plugin] [version]
For more information, or if you need help on this awesome tool, don’t hesitate to head over to asdf-vm.com. Also, feel free to star the GitHub Repository of
asdf to support the team behind this project. 😉
I hope this article was useful to you, and I’ll see you in the next ones. 🤘🏼