Skip to content

Instantly share code, notes, and snippets.

@ryanpback
Last active August 20, 2022 20:15
Show Gist options
  • Save ryanpback/1d0b2808f896398eab6106f49b3e99ab to your computer and use it in GitHub Desktop.
Save ryanpback/1d0b2808f896398eab6106f49b3e99ab to your computer and use it in GitHub Desktop.
NVM Autoload
# This is how I've managed to make this work with the least amount of lag time.
# load-nvm from NVM checks the node version every time you cd into another directory which causes noticeable delays.
# This version will get your current working directory and traverse each directory looking for a `.nvmrc` file until it reaches your current directory.
# Once it finds the closest directory with a `.nvmrc` file, it will store that version in a variable `$NVM_VERSION_TO_USE`.
# Next is to hook into the preexec hook. If the command you're running starts with yarn, npm, or node (could maybe check others as well - any command that would invoke node),
# it will then set the node version using NVM.
# Running a yarn command has its own delay (install, test, start, etc.) so the small lag before the yarn command is negligable.
# It will also only set the node version once so long as you haven't switched directories, so subsequent invoking of yarn is quick.
# To run this, add the below script to your .zshrc file or clone this and source it from your .zshrc file. Then:
# Add the following in your .zshrc file
# anywhere below nvm is loaded
# autoload -U add-zsh-hook
# add-zsh-hook chpwd switch-node
# switch-node
----------------------------------------------------------------------------
# Prior to one of the following commands being executed,
# instantiate which node version to use based on switch_node
preexec() {
if [[ "$1" =~ "^yarn" || "$1" =~ "^npm" || "$1" =~ "^node" ]]; then
if [[ $NVM_VERSION_TO_USE != "empty" ]]; then
# remove the 'v' from `cat`ting the .nvmrc file.
# Sometimes it exists, other times it doesn't
local clean_version=${NVM_VERSION_TO_USE:gs/v/}
local current_version=$(nvm version)
local current_clean_version=${current_version:gs/v/}
if [[ "$clean_version" != "$current_clean_version" ]]; then
nvm use $clean_version || nvm install $clean_version
fi
else
nvm use default
fi
fi
}
# Traverse directories to find closest node
# version and store as variable for later.
switch-node() {
local pwd="$PWD"
local pwd_list=("${(@s:/:)pwd}")
local closest=""
local buildPath=""
# Could be improved by traversing up rather than down.
for ((i = 2; i <= $#pwd_list; i++)); do
local pathname=${pwd_list[i]}
if [[ "$i" == "2" ]]; then
buildPath="/$pathname"
else
buildPath="$buildPath/$pathname"
fi
if [ -f "${buildPath}/.nvmrc" ]; then
closest=$buildPath
fi
done
# Set variable for later use. Don't switch
# to version unless node is needed
if [[ $closest == "" ]]; then
export NVM_VERSION_TO_USE="empty"
else
export NVM_VERSION_TO_USE="$(cat $closest/.nvmrc)"
fi
}
@MatthiasPortzel
Copy link

This is cool, but kind of hacky. Alternatives to nvm like Volta are going to be a lot faster if performance is a concern. Volta just puts a program called "node" (or yarn or whatever) first on your path, and then that program figures out what version to use when you call it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment