Skip to content

Instantly share code, notes, and snippets.

@fl0w

fl0w/lazynvm.sh

Last active Oct 23, 2020
Embed
What would you like to do?
# lazyload nvm
# all props goes to http://broken-by.me/lazy-load-nvm/
# grabbed from reddit @ https://www.reddit.com/r/node/comments/4tg5jg/lazy_load_nvm_for_faster_shell_start/
lazynvm() {
unset -f nvm node npm npx
export NVM_DIR=~/.nvm
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
if [ -f "$NVM_DIR/bash_completion" ]; then
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
fi
}
nvm() {
lazynvm
nvm $@
}
node() {
lazynvm
node $@
}
npm() {
lazynvm
npm $@
}
npx() {
lazynvm
npx $@
}
@christophemarois

This comment has been minimized.

Copy link

@christophemarois christophemarois commented Jul 17, 2018

In zsh, I have a different setup in my ~/.zshrc that not only lazyloads nvm and node, but also any globally-installed package

# Add every binary that requires nvm, npm or node to run to an array of node globals
NODE_GLOBALS=(`find ~/.nvm/versions/node -maxdepth 3 -type l -wholename '*/bin/*' | xargs -n1 basename | sort | uniq`)
NODE_GLOBALS+=("node")
NODE_GLOBALS+=("nvm")

# Lazy-loading nvm + npm on node globals call
load_nvm () {
  export NVM_DIR=~/.nvm
  [ -s "$(brew --prefix nvm)/nvm.sh" ] && . "$(brew --prefix nvm)/nvm.sh"
}

# Making node global trigger the lazy loading
for cmd in "${NODE_GLOBALS[@]}"; do
  eval "${cmd}(){ unset -f ${NODE_GLOBALS}; load_nvm; ${cmd} \$@ }"
done
@fl0w

This comment has been minimized.

Copy link
Owner Author

@fl0w fl0w commented Oct 23, 2018

updated for CLI npx and bash completion

@nicholasmakhija

This comment has been minimized.

Copy link

@nicholasmakhija nicholasmakhija commented Dec 5, 2019

Thanks @christophemarois, I've been hunting for a solution like this one!

@plopezlpz

This comment has been minimized.

Copy link

@plopezlpz plopezlpz commented Apr 24, 2020

@christophemarois this is gold, thanks

@VincentN

This comment has been minimized.

Copy link

@VincentN VincentN commented Apr 29, 2020

Updated @christophemarois's script with npx, removed brew paths for nvm, added bash completion and updated the unset -f function call:

# Add every binary that requires nvm, npm or node to run to an array of node globals
NODE_GLOBALS=(`find ~/.nvm/versions/node -maxdepth 3 -type l -wholename '*/bin/*' | xargs -n1 basename | sort | uniq`)
NODE_GLOBALS+=("node")
NODE_GLOBALS+=("nvm")
NODE_GLOBALS+=("npx")

# Lazy-loading nvm + npm on node globals call
load_nvm () {
  export NVM_DIR=~/.nvm
  [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
  if [ -f "$NVM_DIR/bash_completion" ]; then
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
  fi
}

# Making node global trigger the lazy loading
for cmd in "${NODE_GLOBALS[@]}"; do
  eval "${cmd}(){ unset -f ${cmd} >/dev/null 2>&1; load_nvm; ${cmd} \$@; }"
done

Thanks for sharing!

@adriaanvanrossum

This comment has been minimized.

Copy link

@adriaanvanrossum adriaanvanrossum commented May 7, 2020

I got this error with @christophemarois and @VincentN script:

bash: eval: line xx: syntax error: unexpected end of file

I changed

eval "${cmd}(){ unset -f ${NODE_GLOBALS} >/dev/null 2>&1; load_nvm; ${cmd} \$@ }"

to

eval "${cmd}(){ unset -f ${cmd} >/dev/null 2>&1; load_nvm; ${cmd} \$@; }"

Note the change of NODE_GLOBALS and the ; at the end.

@VincentN

This comment has been minimized.

Copy link

@VincentN VincentN commented May 15, 2020

@adriaanvanrossum, oops. Updated the script!

@laur89

This comment has been minimized.

Copy link

@laur89 laur89 commented Jun 26, 2020

Unsetting NODE_GLOBALS still makes sense. My take (tested only in bash):

export NVM_DIR="$HOME/.nvm"
mapfile -t __NODE_GLOBALS < <(find "$NVM_DIR/versions/node/"*/bin/ -maxdepth 1 -mindepth 1 -type l -print0 | xargs --null -n1 basename | sort --unique)
__NODE_GLOBALS+=(node nvm)

# instead of using --no-use flag, load nvm lazily:
_load_nvm() {
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
}

for cmd in "${__NODE_GLOBALS[@]}"; do
    eval "function ${cmd}(){ unset -f ${__NODE_GLOBALS[*]}; _load_nvm; unset -f _load_nvm; ${cmd} \"\$@\"; }"
done
unset cmd __NODE_GLOBALS

@alexbraga

This comment has been minimized.

Copy link

@alexbraga alexbraga commented Aug 20, 2020

@VincentN is this the approach I should take if I want it to be applied to nodemon, for example?
Because with the original lazynvm.sh when I try to run nodemon inside a project I get a "command not found" error

@king-11

This comment has been minimized.

Copy link

@king-11 king-11 commented Sep 16, 2020

@laur89 I ran into this error while using your code snippet
command not found: mapfile

also I am not able to use yarn globals using any of the above snippets @VincentN @christophemarois please any suggestion

@laur89

This comment has been minimized.

Copy link

@laur89 laur89 commented Sep 16, 2020

command not found: mapfile

This suggests you're not using bash, as mapfile is bash builtin. As I stated above, the snippet was only ever tested in bash.

@king-11

This comment has been minimized.

Copy link

@king-11 king-11 commented Sep 16, 2020

@laur89 thanks for your snippet and reply. So I just used a combined script took some parts from yours and some from @christophemarois now this works with yarn globals and node version is same for projects using yarn as well.

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 loads nvm bash_completion

NODE_GLOBALS=(`find ~/.nvm/versions/node -maxdepth 3 -type l -wholename '*/bin/*' | xargs -n1 basename | sort | uniq`)
NODE_GLOBALS+=(node nvm yarn)

_load_nvm() {
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
}

for cmd in "${NODE_GLOBALS[@]}"; do
eval "function ${cmd}(){ unset -f ${NODE_GLOBALS[*]}; _load_nvm; unset -f _load_nvm; ${cmd} \$@; }"
done
unset cmd NODE_GLOBALS

export PATH="$PATH:$HOME/.yarn/bin"```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.