NVM is slow (> 650ms)
mkscrg opened this issue Β· 9 comments
I find myself running nvm unalias default
after every nvm install
, since it makes new shell creation so much faster. Here it is, with time source ~/.nvm/nvm.sh
in ~/.bash_profile
:
I spend enough time away from Node (and enough time in the shell) that remembering to nvm use
is worth the hassle.
If an intrepid contributor wanted to make NVM faster, where might they start?
You can avoid the need to unalias by adding --no-use
on the end of the line in your profile that does . "$NVM_DIR/nvm.sh"
.
There's two main things that make it slow right now - one is the npm config get prefix
call, which I'm not sure how to speed up since that depends on npm
(and there's a litany of ways npm can locate that prefix) - the other is locating the default alias.
I'd start by comparing the code paths with and without --no-use
(when sourcing) and then profile the use steps.
Aha! --no-use
is nice.
I'll take a look and report back π
Hey guys! I wrote a simple app (kinda) called znvm that combines a bunch of solutions given over here for zsh users.
Features:
- Make zsh with nvm faster by loading only if .nvmrc file found or called explicitly
- Automatically calls nvm use if .nvmrc is present.
- If node vesion in .nvmrv is not installed it will automatically call nvm install <node_version>
- Can be configured to load nvm before certain commands are executed on the shell (such as editors and IDEs)
check it out: https://github.com/Kasahs/.znvm
Just follow the instructions to install
I hope it helps
This 600ms or so delay on EVERY shell start was driving me mad too.
I figured out an alternative work-around:
I put the standard nvm config in my ~/.profile - So it only runs once (not every shell), and from what I glean above, this puts the 'default' node version in place for all following sub-shells... (Right?)
'node' and 'npm' themselves seem to work just fine with the nvm setup only in ~/.profile. So if you're happy to stick with the defaults, all is well.
But then I found "nvm" wouldn't work in shells started from the GUI desktop, because 'nvm' itself is a shell function and hence not exported through sub-shells.
So I came up with this dirty hack:
(Explanation in the comments)
# In ~/.profile include the usual - runs just once at login:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"
And then in ~/.bashrc:
# NVM setup is about the only thing in this script that takes any noticeable time to run.
# Which is not something you want in your .bashrc...
# So, we use a 'just in time' approach. Setup a function that loads the 'real' nvm on first
# use. Note that the 'nvm' function defined here gets over-ridden via sourcing nvm.sh:
# (So you get the ~600ms delay only on first use, in any shell)
export NVM_DIR="$HOME/.nvm"
function nvm() {
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"
nvm "$*"
}
Maybe it's not quite so 'dirty'... Seems to work like a charm...
@peternann the major downside there is that node
, npm
, and any global modules installed in your default node version wonβt be available until after youβve invoked nvm
.
@ljharb - As I mentioned in the post, that's not what I am observing - node, npm, etc work just fine, even before my nvm trigger function is ever run.
I've updated the message above to include the 2-parts of the approach, for abundant clarity.
I'm not 100% sure how nvm works, but I think running the setup once, in .profile/.bash_profile puts enough in place (in exported environment) for node/npm to run. Only 'nvm' itself has trouble (being a shell function and not usually exportable), thus the JIT code above.
(I also wondered about exporting all the nvm shell functions while in .profile, via bash's 'export -f', but didn't try it... - Seems like a large number of functions would need exporting)
@peternann ah, interesting - you're saying that the PATH gets inherited from .profile
, just not the sourced nvm functions?
That seems like it might be an interesting solution, if it works across platforms.
@ljharb Well, yes, PATH is definitely inherited safely by all sub-shells. The Unix world would fall into a heap if not... And yes, it's just functions (like nvm here) that are not reliably inherited. Like I said - The setup above is working like a charm for me.
I wrapped the startup code inside a function like @peternann did, It's much better to get a ~600ms delay when you will actually use nvm
instead of every time you open the terminal.