Skip to content

Instantly share code, notes, and snippets.

@gfguthrie
Created September 27, 2019 22:02
Show Gist options
  • Save gfguthrie/9f9e3908745694c81330c01111a9d642 to your computer and use it in GitHub Desktop.
Save gfguthrie/9f9e3908745694c81330c01111a9d642 to your computer and use it in GitHub Desktop.
Lazy Load Homebrew NVM but still have default aliased Node in PATH
# normal brew nvm shell config lines minus the 2nd one
# lazy loading the bash completions does not save us meaningful shell startup time, so we won't do it
export NVM_DIR="$HOME/.nvm"
[ -s "/usr/local/opt/nvm/etc/bash_completion" ] && . "/usr/local/opt/nvm/etc/bash_completion" # This loads nvm bash_completion
# add our default nvm node (`nvm alias default 10.16.0`) to path without loading nvm
export PATH="$NVM_DIR/versions/node/v$(<$NVM_DIR/alias/default)/bin:$PATH"
# alias `nvm` to this one liner lazy load of the normal nvm script
alias nvm="unalias nvm; [ -s "/usr/local/opt/nvm/nvm.sh" ] && . "/usr/local/opt/nvm/nvm.sh"; nvm $@"
@jacobq
Copy link

jacobq commented Oct 7, 2019

Just to be clear, this assumes you installed NVM globally with NVM_DIR=/usr/local/opt/nvm, right?

@gfguthrie
Copy link
Author

Just to be clear, this assumes you installed NVM globally with NVM_DIR=/usr/local/opt/nvm, right?

The paths here are representative of the default Homebrew/NVM setup, and would need to be modified if your nvm installation or NVM_DIR are actually in a different location.

@jacobq
Copy link

jacobq commented Oct 7, 2019

The paths here are representative of the default Homebrew/NVM setup

Ah, gotcha -- somehow I read past homebrew. The default NVM_DIR is apparently different on Linux (${HOME}/.nvm).

@yo1dog
Copy link

yo1dog commented Oct 30, 2019

Nice. I actually had something very similar figured out when I found your solution. An improvement suggestion: The contents of $NVM_DIR/alias/default may already start with v (nvm alias default v1.2.3). This removes the v prefix if it exists preventing vv1.2.3:

export PATH="$NVM_DIR/versions/node/v${$(<$NVM_DIR/alias/default)#v}/bin:$PATH"

@kingcocomango
Copy link

`
export NVM_DIR="$HOME/.nvm"
#[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
#[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" # This loa

function _install_nvm() {
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This sets up nvm
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" # load nvm
}

alias nvm="unalias nvm; _install_nvm; nvm $@"
alias node="unalias node; _install_nvm; node $@"
alias npm="unalias npm; _install_nvm; npm $@"
alias yarn="unalias yarn; _install_nvm; yarn $@"
`
Is what im using currently. This avoids slowdowns opening and/or doing some stuff with sublimetext.
NB: you probably want to make any sublimetext utilities point at a direct executable under nvm, they dont run .bashrc sometimes.

@gfguthrie
Copy link
Author

@kingcocomango my solution obviates the need to point at anything under the nvm directory, as the executables are already in the PATH. There is no slowdown for anything other than the initial call to nvm itself.

I indeed had something similar to your solution initially until discovering it was insufficient for my needs.

@yo1dog
Copy link

yo1dog commented Nov 5, 2019

my solution obviates the need to point at anything under the nvm directory, as the executables are already in the PATH.

This is correct. Otherwise you would have to create an alias for every globally installed npm package binary (eg eslint). Further, there is no need to install nvm before using any of those binaries (node, npm, eslint, etc.)

@kingcocomango
Copy link

Makes sense, thank you!

@nilshartmann
Copy link

Hi @gfguthrie, thanks a ton for the snippet!

Works perfectly (I only had to adjust the path to nvm.sh) and it makes opening a new terminal fast again 🎉

There is only a problem if default version is set to lts (lts/*) then the path resolving does not work. So it's important to set the default alias to a concrete version. Not a big deal imho.

@gfguthrie
Copy link
Author

@nilshartmann good point about lts alias, thank you for sharing!

@yo1dog
Copy link

yo1dog commented Jan 18, 2020

I recently ran into the same problem with using an alias (lts/erbium) as the default. I solved with this:

DEFAULT_NODE_VER='default';
while [ -s "$NVM_DIR/alias/$DEFAULT_NODE_VER" ]; do
  DEFAULT_NODE_VER="$(<$NVM_DIR/alias/$DEFAULT_NODE_VER)"
done;

Simply follows the chain of alias starting with default until it gets something that is not an alias (does not exist in $NVM_DIR/alias/) which it assumes is the version number. Full example:

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

DEFAULT_NODE_VER='default';
while [ -s "$NVM_DIR/alias/$DEFAULT_NODE_VER" ]; do
  DEFAULT_NODE_VER="$(<$NVM_DIR/alias/$DEFAULT_NODE_VER)"
done;

export PATH="$NVM_DIR/versions/node/v${DEFAULT_NODE_VER#v}/bin:$PATH"
alias nvm='unalias nvm; [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" --no-use; nvm'

@crhistianramirez
Copy link

I'm a bit stuck on this part:

export PATH="$NVM_DIR/versions/node/v$(<$NVM_DIR/alias/default)/bin:$PATH"

I run this to debug:

echo "$NVM_DIR/versions/node/v$(<$NVM_DIR/alias/default)/bin"

and I get:

/home/crhistian/.nvm/versions/node/vnode/bin

It seems like for whatever reason $NVM_DIR/alias/default is evaluating to node and not an actual version 🤔

@gfguthrie
Copy link
Author

@crhistianramirez you probably just need to set your default version again to the one you want: nvm alias default 10.16.0 <- replace the version number with one you have installed/want to be the default

@LeonardoGentile
Copy link

@yo1dog your solution (mac) seems to create an infine loop for me

@LeonardoGentile
Copy link

LeonardoGentile commented Feb 5, 2020

@gfguthrie
Doing this I can't seems to activate the default nvm node version.
In a terminal: nvm alias default v8.11.1, it seems to be set correctly.
I open a new terminal: nvm ls ->

        v8.11.1
        v13.7.0
->       system
default -> v8.11.1
node -> stable (-> v13.7.0) (default)
stable -> 13.7 (-> v13.7.0) (default)
iojs -> N/A (default)
lts/* -> lts/argon (-> N/A)
lts/argon -> v4.9.1 (-> N/A)
lts/boron -> v6.17.1 (-> N/A)
lts/carbon -> v8.17.0 (-> N/A)
lts/dubnium -> v10.18.1 (-> N/A)
lts/erbium -> v12.14.1 (-> N/A)

The default is indeed v8.11.1 but the active version of node is the system installed one, not the chosen default 🤔

@gfguthrie
Copy link
Author

@LeonardoGentile if you echo $PATH, is the path to node in there correctly? If you copied my example exactly, but then use the v in the version you make default, it probably is not correct. You can specify the version without the v, modify the script to not add it, or use the first example @yo1dog posted that takes care of it either way.

@yo1dog
Copy link

yo1dog commented Feb 5, 2020

@yo1dog your solution (mac) seems to create an infine loop for me

You running with BASH or ZSH? I found that BASH does not allow for local outside of functions which causes an error and an infinite loop as DEFAULT_NODE_VER is empty and [ -s ... ] on a directory always returns 0.

I updated the script to remove local so it should work under BASH as well.

@LeonardoGentile
Copy link

@LeonardoGentile if you echo $PATH, is the path to node in there correctly? If you copied my example exactly, but then use the v in the version you make default, it probably is not correct. You can specify the version without the v, modify the script to not add it, or use the first example @yo1dog posted that takes care of it either way.

That was it 👍

@LeonardoGentile
Copy link

@yo1dog your solution (mac) seems to create an infine loop for me

You running with BASH or ZSH? I found that BASH does not allow for local outside of functions which causes an error and an infinite loop as DEFAULT_NODE_VER is empty and [ -s ... ] on a directory always returns 0.

I updated the script to remove local so it should work under BASH as well.

On bash, that why 👍 thanks

@olestole
Copy link

Works great, thanks! It would make it even clearer if you made sure to add comments about:

  • Running nvm alias default [preffered node-version]
  • Changing "/usr/local/opt/nvm/nvm.sh" to your local nvm.sh location

@sescotti
Copy link

sescotti commented Apr 12, 2020

Worked just fine on MacOS and zsh 👍 . One small caveat I noticed by using this is that you cannot run which nvm anymore, it will echo the executable output instead of returning the bin location.

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