nvm-sh / nvm

Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions
MIT License
79.62k stars 7.97k forks source link

nvm very slow to start #2724

Closed abejfehr closed 8 months ago

abejfehr commented 2 years ago

Operating system and version:

nvm debug output:

```sh nvm --version: v0.38.0 $TERM_PROGRAM: iTerm.app $SHELL: /bin/zsh $SHLVL: 1 whoami: 'some-user' ${HOME}: /Users/some-user ${NVM_DIR}: '${HOME}/.nvm' ${PATH}: ${NVM_DIR}/versions/node/v16.13.2/bin:${HOME}/.rbenv/bin:${HOME}/.rbenv/shims:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:${HOME}/Library/Android/sdk/emulator:${HOME}/Library/Android/sdk/tools:${HOME}/Library/Android/sdk/tools/bin:${HOME}/Library/Android/sdk/platform-tools $PREFIX: '' ${NPM_CONFIG_PREFIX}: '' $NVM_NODEJS_ORG_MIRROR: '' $NVM_IOJS_ORG_MIRROR: '' shell version: 'zsh 5.8 (x86_64-apple-darwin20.0)' uname -a: 'Darwin 20.6.0 Darwin Kernel Version 20.6.0: Wed Jun 23 00:26:31 PDT 2021; root:xnu-7195.141.2~5/RELEASE_X86_64 x86_64' checksum binary: 'shasum' OS version: macOS 11.5.2 20G95 curl: /usr/bin/curl, curl 7.64.1 (x86_64-apple-darwin20.0) libcurl/7.64.1 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.41.0 wget: not found sed: /usr/bin/sed cut: /usr/bin/cut basename: /usr/bin/basename rm: /bin/rm mkdir: /bin/mkdir xargs: /usr/bin/xargs git: /usr/local/bin/git, git version 2.31.0 grep: /usr/bin/grep, grep (BSD grep) 2.5.1-FreeBSD awk: /usr/bin/awk, awk version 20200816 nvm current: v16.13.2 which node: ${NVM_DIR}/versions/node/v16.13.2/bin/node which iojs: iojs not found which npm: ${NVM_DIR}/versions/node/v16.13.2/bin/npm npm config get prefix: ${NVM_DIR}/versions/node/v16.13.2 npm root -g: ${NVM_DIR}/versions/node/v16.13.2/lib/node_module ```

nvm ls output:

```sh v14.18.3 v16.1.0 -> v16.13.2 default -> 14 (-> v14.18.3) iojs -> N/A (default) unstable -> N/A (default) node -> stable (-> v16.13.2) (default) stable -> 16.13 (-> v16.13.2) (default) lts/* -> lts/gallium (-> v16.13.2) lts/argon -> v4.9.1 (-> N/A) lts/boron -> v6.17.1 (-> N/A) lts/carbon -> v8.17.0 (-> N/A) lts/dubnium -> v10.24.1 (-> N/A) lts/erbium -> v12.22.9 (-> N/A) lts/fermium -> v14.18.3 lts/gallium -> v16.13.2 ```

How did you install nvm?

The bash script from the README. I also have the zsh shell extension from the README to automatically run nvm use on each directory change.

What steps did you perform?

Create a new iTerm tab or pane

What happened?

It's very slow to start every time

I've followed these steps to get some zsh profiling output, this is what it looks like:

Found '/Users/some-user/some-folder/some-repo/.nvmrc' with version <16>
Now using node v16.13.2 (npm v8.1.2)
num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    4       10828.88  2707.22   55.01%   6985.65  1746.41   35.49%  nvm
 2)    1       11108.00 11108.00   56.43%   6012.77  6012.77   30.54%  nvm_auto
 3)    2        3506.05  1753.03   17.81%   3311.19  1655.59   16.82%  nvm_ensure_version_installed
 4)    1        8514.78  8514.78   43.25%   2781.13  2781.13   14.13%  load-nvmrc
 5)    2         194.86    97.43    0.99%    194.86    97.43    0.99%  nvm_is_version_installed
 6)    2         202.59   101.30    1.03%    162.91    81.46    0.83%  nvm_die_on_prefix
 7)    1         125.08   125.08    0.64%    119.30   119.30    0.61%  nvm_rc_version
 8)    2          37.65    18.83    0.19%     37.65    18.83    0.19%  compaudit
 9)    4          36.83     9.21    0.19%     36.83     9.21    0.19%  nvm_grep
10)    1          62.11    62.11    0.32%     24.45    24.45    0.12%  compinit
11)    2          14.20     7.10    0.07%     14.20     7.10    0.07%  nvm_echo
12)    8          39.68     4.96    0.20%      2.84     0.36    0.01%  nvm_npmrc_bad_news_bears
13)    2           1.05     0.53    0.01%      1.05     0.53    0.01%  nvm_has
14)    1           0.39     0.39    0.00%      0.39     0.39    0.00%  add-zsh-hook
15)    1           0.09     0.09    0.00%      0.09     0.09    0.00%  compdef
16)    1           0.18     0.18    0.00%      0.08     0.08    0.00%  complete
17)    1       11108.06 11108.06   56.43%      0.06     0.06    0.00%  nvm_process_parameters
18)    1           0.04     0.04    0.00%      0.04     0.04    0.00%  nvm_is_zsh
19)    1           0.04     0.04    0.00%      0.04     0.04    0.00%  nvm_is_iojs_version
20)    1           0.02     0.02    0.00%      0.02     0.02    0.00%  bashcompinit

-----------------------------------------------------------------------------------

17)    1       11108.06 11108.06   56.43%      0.06     0.06    0.00%  nvm_process_parameters
       1/1     11108.00 11108.00   56.43%   6012.77  6012.77             nvm_auto [2]

-----------------------------------------------------------------------------------

       1/1     11108.00 11108.00   56.43%   6012.77  6012.77             nvm_process_parameters [17]
 2)    1       11108.00 11108.00   56.43%   6012.77  6012.77   30.54%  nvm_auto
       1/4      5095.23  5095.23   25.88%     41.58    41.58             nvm [1]

-----------------------------------------------------------------------------------

       2/4     10760.61  5380.31   54.66%   6917.38  3458.69             nvm [1]
       1/4      5733.65  5733.65   29.13%     26.69    26.69             load-nvmrc [4]
       1/4      5095.23  5095.23   25.88%     41.58    41.58             nvm_auto [2]
 1)    4       10828.88  2707.22   55.01%   6985.65  1746.41   35.49%  nvm
       1/1         0.04     0.04    0.00%      0.04     0.04             nvm_is_iojs_version [19]
       2/2         1.05     0.53    0.01%      1.05     0.53             nvm_has [13]
       1/2         8.41     8.41    0.04%      8.41     8.41             nvm_echo [11]
       1/1       125.08   125.08    0.64%    119.30   119.30             nvm_rc_version [7]
       2/2       202.59   101.30    1.03%    162.91    81.46             nvm_die_on_prefix [6]
       2/2      3506.05  1753.03   17.81%   3311.19  1655.59             nvm_ensure_version_installed [3]
       2/4     10760.61  5380.31   54.66%   6917.38  3458.69             nvm [1]

-----------------------------------------------------------------------------------

 4)    1        8514.78  8514.78   43.25%   2781.13  2781.13   14.13%  load-nvmrc
       1/4      5733.65  5733.65   29.13%     26.69    26.69             nvm [1]

-----------------------------------------------------------------------------------

       2/2      3506.05  1753.03   17.81%   3311.19  1655.59             nvm [1]
 3)    2        3506.05  1753.03   17.81%   3311.19  1655.59   16.82%  nvm_ensure_version_installed
       2/2       194.86    97.43    0.99%    194.86    97.43             nvm_is_version_installed [5]

-----------------------------------------------------------------------------------

       2/2       202.59   101.30    1.03%    162.91    81.46             nvm [1]
 6)    2         202.59   101.30    1.03%    162.91    81.46    0.83%  nvm_die_on_prefix
       8/8        39.68     4.96    0.20%      2.84     0.36             nvm_npmrc_bad_news_bears [12]

-----------------------------------------------------------------------------------

       2/2       194.86    97.43    0.99%    194.86    97.43             nvm_ensure_version_installed [3]
 5)    2         194.86    97.43    0.99%    194.86    97.43    0.99%  nvm_is_version_installed

-----------------------------------------------------------------------------------

       1/1       125.08   125.08    0.64%    119.30   119.30             nvm [1]
 7)    1         125.08   125.08    0.64%    119.30   119.30    0.61%  nvm_rc_version
       1/2         5.79     5.79    0.03%      5.79     5.79             nvm_echo [11]

-----------------------------------------------------------------------------------

10)    1          62.11    62.11    0.32%     24.45    24.45    0.12%  compinit
       1/2        37.65    37.65    0.19%      0.74     0.74             compaudit [8]

-----------------------------------------------------------------------------------

       8/8        39.68     4.96    0.20%      2.84     0.36             nvm_die_on_prefix [6]
12)    8          39.68     4.96    0.20%      2.84     0.36    0.01%  nvm_npmrc_bad_news_bears
       4/4        36.83     9.21    0.19%     36.83     9.21             nvm_grep [9]

-----------------------------------------------------------------------------------

       1/2        37.65    37.65    0.19%      0.74     0.74             compinit [10]
       1/2        36.91    36.91    0.19%     36.91    36.91             compaudit [8]
 8)    2          37.65    18.83    0.19%     37.65    18.83    0.19%  compaudit
       1/2        36.91    36.91    0.19%     36.91    36.91             compaudit [8]

-----------------------------------------------------------------------------------

       4/4        36.83     9.21    0.19%     36.83     9.21             nvm_npmrc_bad_news_bears [12]
 9)    4          36.83     9.21    0.19%     36.83     9.21    0.19%  nvm_grep

-----------------------------------------------------------------------------------

       1/2         8.41     8.41    0.04%      8.41     8.41             nvm [1]
       1/2         5.79     5.79    0.03%      5.79     5.79             nvm_rc_version [7]
11)    2          14.20     7.10    0.07%     14.20     7.10    0.07%  nvm_echo

-----------------------------------------------------------------------------------

       2/2         1.05     0.53    0.01%      1.05     0.53             nvm [1]
13)    2           1.05     0.53    0.01%      1.05     0.53    0.01%  nvm_has

-----------------------------------------------------------------------------------

14)    1           0.39     0.39    0.00%      0.39     0.39    0.00%  add-zsh-hook

-----------------------------------------------------------------------------------

16)    1           0.18     0.18    0.00%      0.08     0.08    0.00%  complete
       1/1         0.09     0.09    0.00%      0.09     0.09             compdef [15]

-----------------------------------------------------------------------------------

       1/1         0.09     0.09    0.00%      0.09     0.09             complete [16]
15)    1           0.09     0.09    0.00%      0.09     0.09    0.00%  compdef

-----------------------------------------------------------------------------------

18)    1           0.04     0.04    0.00%      0.04     0.04    0.00%  nvm_is_zsh

-----------------------------------------------------------------------------------

       1/1         0.04     0.04    0.00%      0.04     0.04             nvm [1]
19)    1           0.04     0.04    0.00%      0.04     0.04    0.00%  nvm_is_iojs_version

-----------------------------------------------------------------------------------

20)    1           0.02     0.02    0.00%      0.02     0.02    0.00%  bashcompinit

What did you expect to happen?

I expected it to load faster

Is there anything in any of your profile files that modifies the PATH?

There's a few things being added for android development, ANDROID_HOME, JAVA_HOME, etc

ljharb commented 2 years ago

PRs to improve specific slow places are appreciated. This kind of profiling output is also very helpful, since it helps highlight what needs work.

pcrouthers commented 2 years ago

Im having same issue

abejfehr commented 2 years ago

I've done a bit of digging and there seems to be a lot of custom logic (and therefore additional complexity) to support "iojs".

I might be being naive, but does anyone even use iojs? Their website looks like it was updated semi-recently, but they seem to mention that nvm doesn't support it yet (when it has for 7 years!):

If you are used to nvm, then we have good news for you: an io.js compatible version is coming soon!

I've deleted anything pertaining to "iojs" from my nvm.sh file and it seems to be running a bit faster too.

Would this project be interested in a PR to remove iojs support?

Edit: I just noticed that the link to io.js' repo from nvm's README file just redirects to node's repo now

ljharb commented 2 years ago

The plumbing for that is also needed to support node RCs and nightlies, so even if i wanted to remove it (i don’t - i have 300+ repos that test on it, which constitutes over 10% of npm’s download traffic that benefits from the support) i don’t think it’d end up making things faster since we still want to add RC support in particular.

I’d love a PR that made the existing feature set faster, of course :-)

kaznovac commented 2 years ago

this plugin makes loading of nvm zsh functions lazy https://github.com/lukechilds/zsh-nvm (on my machine >800ms -> ~40ms)

works great and has some interesting options; ... however it has not seen the update for nearly 2 years

it would be a good course of action to incorporate the logic from that script into this one

jrowlingson commented 1 year ago

A lazy loading approach can be used as a work around if you're seeing lag before the prompt becomes usable. The following can be added to your .zshrc (or .*rc):

lazy_load_nvm() {
  unset -f node nvm
  export NVM_DIR=~/.nvm
  [[ -s "$NVM_DIR/nvm.sh" ]] && source "$NVM_DIR/nvm.sh"
}

node() {
  lazy_load_nvm
  node $@
}

nvm() {
  lazy_load_nvm
  node $@
}
OutdatedVersion commented 1 year ago

A lazy loading approach can be used as a work around if you're seeing lag before the prompt becomes usable. The following can be added to your .zshrc (or .*rc):

lazy_load_nvm() {
  unset -f node nvm
  export NVM_DIR=~/.nvm
  [[ -s "$NVM_DIR/nvm.sh" ]] && source "$NVM_DIR/nvm.sh"
}

node() {
  lazy_load_nvm
  node $@
}

nvm() {
  lazy_load_nvm
  node $@
}

Thanks for linking this! I ended up needing to make a few changes, if anyone else runs into hiccups:

lazy_load_nvm() {
-  unset -f node nvm
+  unset -f npm node nvm
  export NVM_DIR=~/.nvm
  [[ -s "$NVM_DIR/nvm.sh" ]] && source "$NVM_DIR/nvm.sh"
+  [ -s "$NVM_DIR/bash_completion" ] && source "$NVM_DIR/bash_completion"
}

+ npm() {
+  lazy_load_nvm
+  npm $@
+ }

node() {
  lazy_load_nvm
  node $@
}

nvm() {
  lazy_load_nvm
-  node $@
+  nvm $@
}
ljharb commented 1 year ago

Note that any lazy loading approach has some caveats; namely that any global packages you have installed won't be available until the first time you run nvm, npm, or node.

abejfehr commented 1 year ago

The lazy loading approaches don't work for me since I'm using the zsh hook that automatically runs nvm use on each directory change. I want my node version to be correct when I switch between directories because I have many projects that use many node versions.

Edit: I just realized this also includes functions for node/npm/etc and that looks like it'd work, so maybe I'll try that.

aprilmintacpineda commented 1 year ago

The lazy loading approaches don't work for me since I'm using the zsh hook that automatically runs nvm use on each directory change. I want my node version to be correct when I switch between directories because I have many projects that use many node versions.

Edit: I just realized this also includes functions for node/npm/etc and that looks like it'd work, so maybe I'll try that.

That's handy! Can you share how you are doing that? A link perhaps?

zyf0330 commented 1 year ago

This is my hack in the .zshrc.

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" --no-use
NODE_DEFAULT_PATH="${NVM_DIR}/versions/default/bin"
PATH="${NODE_DEFAULT_PATH}:${PATH}"
switchNode() {
  local NODE_PATH TARGET_NODE_VERSION
  if [ -f '.nvmrc' ]; then
    TARGET_NODE_VERSION="$(nvm version $(cat .nvmrc))"
    NODE_PATH="${NVM_DIR}/versions/node/${TARGET_NODE_VERSION}/bin"
  else
    TARGET_NODE_VERSION="$(nvm version default)"
    NODE_PATH="${NODE_DEFAULT_PATH}"
  fi
  if [ "${TARGET_NODE_VERSION}" != "$(nvm current)" ]; then
    PATH="${NODE_PATH}:${PATH}"
  fi
}
switchNode
add-zsh-hook chpwd switchNode
bazuka5801 commented 1 year ago

Just use asdf with asdf-nodejs plugin without digging and troubleshooting nvm, I also faced with this problem and moved to asdf without any problems. https://asdf-vm.com/guide/getting-started.html

linorabolini commented 1 year ago

If anyone is interested, I have made it so it lazy loads on cmd run. I haven't found a solution like this one yet but I know it is a combination of the solutions from above.

load-nvmrc() {
  local node_version="$(nvm version)"
  local nvmrc_path="$(nvm_find_nvmrc)"

  if [ -n "$nvmrc_path" ]; then
    local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

    if [ "$nvmrc_node_version" = "N/A" ]; then
      nvm install
    elif [ "$nvmrc_node_version" != "$node_version" ]; then
      nvm use 
    fi
  elif [ "$node_version" != "$(nvm version default)" ]; then
    nvm use default
  fi
}

if [ -s "$HOME/.nvm/nvm.sh" ]; then
  export NVM_DIR="$HOME/.nvm"
  nvm_cmds=(nvm node npm yarn)
  for cmd in $nvm_cmds ; do
    alias $cmd="unalias $nvm_cmds && unset nvm_cmds && . $NVM_DIR/nvm.sh --no-use && load-nvmrc && $cmd"
  done
fi
camunoz2 commented 1 year ago

Take into account that the lazy load approach breaks the LSP servers with nvim if nvm is not loaded previously. I have that problem, and running NVM at least one time before opening nvim solve it.

lucasjohnston commented 1 year ago

The main culprit for me was the load-nvmrc function which runs every time a folder is opened. I did two things to simplify the steps taken:

  1. Only run nvm if a .nvmrc file exists in the current directory, its parent (to a depth of 3), or in its immediate child. This is super quick so doesn't slow down opening new directories, and means cd'ing into and out of directories will trigger an nvm change as expected.
  2. Lazily load nvm when running a command without using internal nvm components which haven't loaded yet

It's not perfect, but it retains the majority of nvm's primary features and stops me waiting forever for my shell to resolve.

Here's my implementation:

# these lazily load nvm before your node commands
nvm_lazy_load() {
    unset -f nvm node npm npx
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
    load-nvmrc
}
nvm() {
    nvm_lazy_load
    nvm $@
}
node() {
    nvm_lazy_load
    node $@
}
npm() {
    nvm_lazy_load
    npm $@
}
npx() {
    nvm_lazy_load
    npx $@
}
autoload -U add-zsh-hook

# this loads nvmrc when a file exists, and finds the path of the nvmrc file itself
load-nvmrc() {
  local node_version="$(nvm version)"
  local nvmrc_path=""
  local dir="$PWD"

  # Look for .nvmrc file in current directory and parent directories
  while [[ "$dir" != "" && ! -e "$dir/.nvmrc" ]]; do
    dir="${dir%/*}"
  done

  # If .nvmrc file was found, set nvmrc_path
  if [[ -e "$dir/.nvmrc" ]]; then
    nvmrc_path="$dir/.nvmrc"
  fi

  if [ -n "$nvmrc_path" ]; then
    echo "Found $nvmrc_path, switching to node $(cat "${nvmrc_path}")"
    local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

    if [ "$nvmrc_node_version" = "N/A" ]; then
      nvm install
    elif [ "$nvmrc_node_version" != "$node_version" ]; then
      nvm use
    fi
  elif [ "$node_version" != "$(nvm version default)" ]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}

# this is ran on every directory, and checks if an nvmrc file exists (parent or child) first
trigger-nvm() {
  if [[ -n $(find . -maxdepth 2 -name '*.nvmrc' -type f -print -quit) || -f ../.nvmrc || -f ../../.nvmrc || -f ../../../.nvmrc ]]; then 
    nvm_lazy_load
    load-nvmrc
  fi
}
add-zsh-hook chpwd trigger-nvm
ljharb commented 1 year ago

Note that nvm doesn’t do that - that’s just in the readme, and something you added yourself.

Note that your item 2 will mean you can’t use globally installed npm packages in the default node version until nvm has loaded.

lucasjohnston commented 1 year ago

@ljharb You're correct that it's not supported by the maintainers, but as you say it is the part of the README instructions for the zsh shell. I think it should at least have a warning that it could result in a slow shell, or in an ideal world the example should be replaced entirely.

Whether it is officially supported or not is irrelevant if a problematic solution is being signposted to new users as part of the instructions – less "something you added yourself", more "something we suggested". Happy to contribute a PR if useful!

Agreed my solution isn't the best (unless you want to add an nvm loader for every globally installed package), but it does the job for me as I don't have any globally installed packages that depend on a specific version of node. Do you have any suggestions on how to fix?

ljharb commented 1 year ago

@lucasjohnston i'm the maintainer, and sure, either one is a great idea. PRs are welcome.

No, I don't have any way to avoid fully loading nvm that avoids that caveat, which is the sole reason there's no official mechanism to do that (or better, the sole reason it's not just The Way nvm works)

ElvenSpellmaker commented 1 year ago

I have a slightly modified solution by @linorabolini for bash (you'll need to copy their first part):

if [ -s "$HOME/.nvm/nvm.sh" ]; then
  export NVM_DIR="$HOME/.nvm"
  nvm_cmds=(nvm node npm yarn)
  for cmd in "${nvm_cmds[@]}" ; do
    alias $cmd="echo \"'nvm' loading... It's super slow, hold onto your hat...\" && unalias ${nvm_cmds[*]} && unset nvm_cmds && . $NVM_DIR/nvm.sh --no-use && load-nvmrc && $cmd"
  done
fi
jrowlingson commented 1 year ago

I've since switched node version managers (fnm). Offering this as a workaround for folks seeking help and finding this issue.

navels commented 1 year ago

I'm finding myself in this same situation but it seemingly just started happening today, 20+ seconds to start zsh because of these nvm processes taking so long.

Is there a way to figure out what aspect of nvm initialization is actually causing the problem?

Update: how odd, it has resolved.

ylluminate commented 9 months ago

Thank you @linorabolini for your suggestion. Given that node etc. and nvm get very infrequent use from me since I mostly work with V and Ruby, having this to lighten up my load for shell load time is a wonderful help. Wish it would get mainline integration.

abejfehr commented 8 months ago

I just wanted to share that since this issue I've long since switched to mise and it's very performant, and is essentially a drop-in replacement for nvm (for my purposes anyway)

ljharb commented 8 months ago

Sounds like this should be closed.

If anyone's still having performance issues with the latest version of nvm, please file a new issue. If you're having trouble with the unsupported snippets in the readme, a PR to improve them would be most welcome.

LinusU commented 8 months ago

For anyone else finding this after reading the blog posts lately about measuring ZHS startup times:

My shell took just over 300ms to start, as measured by hyperfine. I commented out the nvm part and it dropped down to around 45ms.

I googled around and found fnm, which seems to be a port of nvm to Rust. After adding fnm to my .zshrc, and installing the same Node.js version I already before via nvm, I measured my shell startup time as 51ms.

My conclusion: for now I will replace nvm with fnm which seems to be a drop in replacement but with a 40x speedup 🐎


If anyone's still having performance issues with the latest version of nvm, please file a new issue.

I'm not sure if this is a "performance issue", so I'm a bit hesitant to open a new issue. ~300ms shell startup is probably fine for a lot of people, and I'm not sure that this could be fixed in nvm without switching to a complied language. But if you think that this can be improved and want any more measurements or insight I'm happy to help!

jrowlingson commented 8 months ago

@LinusU @abejfehr - this is what I had suggested but it was marked as spam

ljharb commented 8 months ago

yes, advertising other projects in any repo is quite unwelcome, and isn't a workaround for those who wish to keep using the same project.

ylluminate commented 8 months ago

I think for those who still want to use nvm-proper then it is important that a lazy loading option be integrated into the trunk. I personally am hesitant to use Rust-based tools when I can avoid them as I personally like neither the ecosystem nor the language.

And yes, advertising other projects is bad form in these places. Definitely a catch 22 since I can understand the desire to share your success and options, which is appreciated, but it can easily be seen as a slap to this project by those who invest such efforts and sacrifices to make it and keep it going... Humans are funny things.

Anyway, thanks to the developers of this project for your passion and sacrifice for such a tool.

linorabolini commented 8 months ago

yes, advertising other projects in any repo is quite unwelcome, and isn't a workaround for those who wish to keep using the same project.

i want to disagree here too, i don't consider it as advertisement, it literally solved my problem because it's incredibly fast.

lashchev commented 8 months ago

I have just installed NVM on a new Windows 11 laptop to use it with Git Bash and WSL. I honestly envy all the commentators above since you are fighting for a sub-second speed improvement. For me, it takes 10 seconds to start NVM. .bash_profile:

TIMEFORMAT='Starting NVM took %R seconds.'
time {
  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
}

Output on session start: Starting NVM took 10.343 seconds. nvm-windows has the same performance, probably because of the same nvm.sh under the hood. I am not sure if opening a new ticket is worth it since even on the main page of this project, it is mentioned that NVM supports Windows in some cases and refers to some other projects. Will this case be investigated if I open a new ticket?

ljharb commented 8 months ago

@lashchev nvm-windows is an entirely different project, and I'm pretty sure doesn't use nvm.sh at all.

Some of it is just that Windows is slow. inherently.

Yes, if you can file a new issue with a fully filled out template, I'd love to address it - however, I don't use Windows, so it's difficult for me to do anything myself (altho i can review a PR and test it on a local vm)

outranker commented 4 months ago

For me, it takes 10 seconds to start NVM.

for me it's taking about 30 seconds and it's crazy

joshheyse commented 1 month ago

Here is my attempt at the lazy loading solution. This only requires loading nvm if you need to get a node version that is not already installed (or you explicitly call nvm).

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
if [[ -d $NVM_DIR ]]; then

  unset_nvm_lazy_path() {
    export PATH=$(echo $PATH | sed "s|${NVM_LAZY_PATH}:||" )
    unset NVM_LAZY_PATH
  }

  set_nvm_lazy_path() {
    unset_nvm_lazy_path
    export NVM_LAZY_PATH="$1"
    export path=($NVM_LAZY_PATH $path)
  }

  nvm_lazy_load() {
    unset -f nvm
    echo "Loading NVM"
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

    unset_nvm_lazy_path
    add-zsh-hook -d chpwd check_for_nvmrc
    unset check_for_nvmrc
  }

  function get_node_dir() {
    local target_ver=${1:-$(cat "$NVM_DIR/alias/default")}
    target_ver=$(echo $target_ver | sed s/v//)
    local version="$(find $NVM_DIR/versions/node -maxdepth 1 -exec basename {} \; \
                          | sed s/v// \
                          | grep $target_ver \
                          | sort --version-sort --reverse)"
    [[ -n $version ]] && echo "$NVM_DIR/versions/node/v$version/bin"
  }

  function nvm() {
    nvm_lazy_load
    nvm $@
  }

  function check_for_nvmrc() {
    local dir="$PWD"

    # Look for .nvmrc file in current directory and parent directories
    while [[ -n "$dir" && ! -f "$dir/.nvmrc" ]]; do
      dir="${dir%/*}"
    done

    if [[ -z "$dir" ]]; then
      return
    fi

    local target_ver="$(get_node_dir $(cat "$dir/.nvmrc"))"
    if [[ -n $target_ver ]]; then
      set_nvm_lazy_path $target_ver
    else
      nvm_lazy_load
      nvm use
    fi

  }

  set_nvm_lazy_path "$(get_node_dir)"
  add-zsh-hook chpwd check_for_nvmrc

fi
ulises-castro commented 3 weeks ago

Here is my attempt at the lazy loading solution. This only requires loading nvm if you need to get a node version that is not already installed (or you explicitly call nvm).

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
if [[ -d $NVM_DIR ]]; then

  unset_nvm_lazy_path() {
    export PATH=$(echo $PATH | sed "s|${NVM_LAZY_PATH}:||" )
    unset NVM_LAZY_PATH
  }

  set_nvm_lazy_path() {
    unset_nvm_lazy_path
    export NVM_LAZY_PATH="$1"
    export path=($NVM_LAZY_PATH $path)
  }

  nvm_lazy_load() {
    unset -f nvm
    echo "Loading NVM"
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

    unset_nvm_lazy_path
    add-zsh-hook -d chpwd check_for_nvmrc
    unset check_for_nvmrc
  }

  function get_node_dir() {
    local target_ver=${1:-$(cat "$NVM_DIR/alias/default")}
    target_ver=$(echo $target_ver | sed s/v//)
    local version="$(find $NVM_DIR/versions/node -maxdepth 1 -exec basename {} \; \
                          | sed s/v// \
                          | grep $target_ver \
                          | sort --version-sort --reverse)"
    [[ -n $version ]] && echo "$NVM_DIR/versions/node/v$version/bin"
  }

  function nvm() {
    nvm_lazy_load
    nvm $@
  }

  function check_for_nvmrc() {
    local dir="$PWD"

    # Look for .nvmrc file in current directory and parent directories
    while [[ -n "$dir" && ! -f "$dir/.nvmrc" ]]; do
      dir="${dir%/*}"
    done

    if [[ -z "$dir" ]]; then
      return
    fi

    local target_ver="$(get_node_dir $(cat "$dir/.nvmrc"))"
    if [[ -n $target_ver ]]; then
      set_nvm_lazy_path $target_ver
    else
      nvm_lazy_load
      nvm use
    fi

  }

  set_nvm_lazy_path "$(get_node_dir)"
  add-zsh-hook chpwd check_for_nvmrc

fi

Thank you, this issues was driving me crazy. It was making my zsh pretty sloooooooooowwwwwww.

Forget it, I just give up on NVM. I just switch to FNM is written in Rust and faster. Now my zsh run soo much faster.