I'd like to use the stable node version as the default, but use a specific version automatically if I open a shell in a directory with a .nvmrc.
Currently, if I specify a default alias, that default overrides .nvmrc until I manually run nvm use.
The current way to do that would be to make a .nvmrc file in / as the default, and then use a local .nvmrc file to modify it.
Either the default alias, or nvmrc, has to "win" when nvm.sh is sourced. I added rc behavior after default was already in place, and I didn't want to override it at that time. I'm happy to explore switching the prioritization - this is the only place default is used, so I'd generally expect it to have a special meaning.
Excellent, putting stable in /.nvmrc works the way I intended, but allowing .nvmrc to override the default alias probably matches others' expectations. Either way, thanks!
To add on this: How difficult would it be to automatically switch to the version supplied in .nvmrc when I change into a directory from an existing shell?
Is there another way to accomplish this, other than "overwriting" system 'cd' with a bash script that changes the directory and then calls nvm use?
As far as I know there'd only be two ways:
1) overwriting cd, which is what rvm does and imo is a horrifically complex and bad model
2) shadowing both node and npm, and checking for .nvmrc on every invocation, which I suspect would both be slow as well as brittle if people alias or rename their binaries.
@ljharb re option (2), I can see where the brittleness would come in, although if someone is smart enough to install nvm, I'd expect them to be smart enough to not alias or rename their binaries. But why do you think it would be slow? The search in the directory tree, or is there something else you can see?
I think somewhat a bigger problem would be the .nvmrc files published together with modules in npm, because going deep into node_modules could result in a different node than your project...
Still, I really want to see this happen :) The whole point of having nvm for me is so I can easily switch between projects - and having to type an extra command every time is kind of a pain. And with the whole "lots of small modules" shebang I'm switching/cd-ing a LOT.
@dominykas I've learned from managing this project that a great many people make the mistake of aliasing or renaming builtins and binaries :-) it would be slow because it has to recursively check disk paths (since it looks upwards until / for the first .nvmrc file it finds).
Try this:
cdn() {
cd $@
nvm use 2>/dev/null | tail -1
}
(i changed the help content in 230b479648aa5eb75b4be27e7ca46bcad44340a2 to output to stderr, and will release it shortly, so that that won't output a blank line). Would that work, without complicating nvm itself?
Fair enough :) Aliasing would probably also have issues with globally installed modules' binary paths (e.g. global grunt), wouldn't it?
cdn does solve "one command to change dir and swap over to correct version of node" problem, but it isn't _the_ solution. It means that you have to make a decision each time - do I want to cd or to cdn and you certainly don't want cdn to become the habit/default that you use.
I wonder... Are the rvm discussions on the tradeoffs of making the cd decision open/available in public?
This is the commit in rvm that introduced the cd feature: https://github.com/wayneeseguin/rvm/commit/89f683aa2d6405c685de386d26018c6fbc5195ff
hmm, rvm's approach isn't as bad as I feared it was. Ours would be just nvm use - but not just if .nvmrc exists, if .nvmrc exists in any directory above it up to / and nvm current didn't match the contents of .nvmrc - so it's not exactly what I'd call simple :-/
That's just the original version - it got quite complicated down the road: https://github.com/wayneeseguin/rvm/blob/master/scripts/cd (although I did see simpler implementations of this in the history). For now I tried to look up the date when they introduced, so that I can try to find the actual discussions/reasoning (if any) for the first impl version.
There's dead silence in the issues of rvm between Sep/2009 and Aug/2010 and the commit is from Nov/2009. #Archeology
Anyways, the slow part is not walking up the directory tree (takes up to 0.004s from 15 levels deep to root on my Macbook Air with an SSD) - resolving the real version from the value in .nvmrc takes 0.05s with nvm_version() (order of magnitude slower).
I added this to my ~/.profile:
nvm_switch_if_needed() {
local NVM_RC_VERSION
local REAL_VERSION
read NVM_RC_VERSION < $(nvm_find_nvmrc)
REAL_VERSION=$(nvm_version $NVM_RC_VERSION)
[ "$(nvm_version_path $REAL_VERSION)/bin" == "$NVM_BIN" ] || nvm use
}
cd() { builtin cd "$@"; time nvm_switch_if_needed; }
Obviously not production ready (I do have /.nvmrc), but cd without a change takes 0.08s and with a change - 0.2s. Both are bearable.
dominykas@patti ~/devel/libs/buster/buster-reporter-sauce/node_modules/grunt-saucelabs/node_modules/request/node_modules/lodash.merge/node_modules/lodash._basecreatecallback/node_modules/lodash.bind/node_modules/lodash._createwrapper/node_modules/lodash._basecreatewrapper/node_modules/lodash._basecreate
/node_modules/lodash._isnative $ nvm use 0.10
Now using node v0.10.37
dominykas@patti ~/devel/libs/buster/buster-reporter-sauce/node_modules/grunt-saucelabs/node_modules/request/node_modules/lodash.merge/node_modules/lodash._basecreatecallback/node_modules/lodash.bind/node_modules/lodash._createwrapper/node_modules/lodash._basecreatewrapper/node_modules/lodash._basecreate
/node_modules/lodash._isnative $ cd ..
Found '/.nvmrc' with version <iojs>
Now using io.js v1.6.2
real 0m0.228s
user 0m0.134s
sys 0m0.205s
dominykas@patti ~/devel/libs/buster/buster-reporter-sauce/node_modules/grunt-saucelabs/node_modules/request/node_modules/lodash.merge/node_modules/lodash._basecreatecallback/node_modules/lodash.bind/node_modules/lodash._createwrapper/node_modules/lodash._basecreatewrapper/node_modules/lodash._basecreate
/node_modules $ cd lodash._isnative/
real 0m0.074s
user 0m0.044s
sys 0m0.066s
dominykas@patti ~/devel/libs/buster/buster-reporter-sauce/node_modules/grunt-saucelabs/node_modules/request/node_modules/lodash.merge/node_modules/lodash._basecreatecallback/node_modules/lodash.bind/node_modules/lodash._createwrapper/node_modules/lodash._basecreatewrapper/node_modules/lodash._basecreate
/node_modules/lodash._isnative $ time nvm_rc_version
Found '/.nvmrc' with version <iojs>
real 0m0.007s
user 0m0.004s
sys 0m0.003s
I'm not too good at bash, so I'm not sure if I should PR this (with an opt-in env var setting) myself ;) Pretty sure there's also space for optimization - surely the nvm_version can have a cache of some sort or some other speed up?
Thanks for doing the research. What about if you use nvm which $NVM_RC_VERSION and compare that to which node? Could you also make your nvm_switch_if_needed function use nvm_rc_version and $NVM_RC_VERSION?
If we can get to a place where nvm_switch_if_needed works reliably with all nvm use cases, I'd absolutely accept it as a PR (with tests), with this cd use case in mind for the future.
As for the cd patch, I feel like that'd be better as an optional section in the README with a "proceed at your own risk" warning, but then cd() { builtin cd "$@"; nvm_switch_if_needed; } would be the only thing people needed to add to their profile. Thoughts?
I guess cd() { builtin cd "$@"; nvm_switch_if_needed; } in README is just as good as export NVM_AUTO_SWITCH=true in README :) Also this probably needs some testing against collisions with rvm, etc.
I'll revisit your suggestions a little later - just noticed that when .nvmrc is NOT in a root folder, the detection is somewhat slower (~0.15s instead of ~0.05s - something to do with how filesystem cache works?) - so obviously more testing is needed. Also I'd like to wait for whatever perf improvement #703 gives.
Sounds good!
function chpwd() {
if [ -r $PWD/.node-version ]; then
nvm use `cat $PWD/.node-version`
fi
}
I've been using this and it works.
ZSH only, though: http://www.refining-linux.org/archives/42/ZSH-Gem-8-Hook-function-chpwd/
@callumacrae why .node-version instead of .nvmrc? I've never seen any project use that as a convention.
Couple other version managers use it. Doesn't really make any difference though :)
http://stackoverflow.com/questions/27425852/what-uses-respects-the-node-version-file
OK, been using this cd() approach for 2 months now, without any trouble or noticing the slowdown - 100ms is nothing.
Still need to test with rvm (I don't use Ruby in my daily life).
Also just realized that probably something also needs to be done about pushd / popd.
Haven't had any issues with rvm.
Any movement on this? This would be an excellent feature.
@jennifer-mann it's unlikely this will be added as a feature, but i'd be happy to add any needed internal machinery for it, and document it in the readme. A PR for that is welcome.
Hey ya'll, would appreciate feedback on this - https://github.com/lalitkapoor/nvm-auto-switch Based on https://github.com/creationix/nvm/issues/603#issuecomment-88617225 by @dominykas
In case you work with both rvm and nvm, you can do this
cat > $HOME/.rvm/hooks/after_cd_nvm
#!/usr/bin/env bash
if [ -e .nvmrc ]; then
nvm use
fi
chmod 775 $HOME/.rvm/hooks/after_cd_nvm
rvm does all the heavy lifting and checks for the .nvmrc after each cd.
Most helpful comment
In case you work with both rvm and nvm, you can do this
cat > $HOME/.rvm/hooks/after_cd_nvmchmod 775 $HOME/.rvm/hooks/after_cd_nvmrvm does all the heavy lifting and checks for the
.nvmrcafter eachcd.