Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support .nvmrc #128

Closed
SteveALee opened this issue Jan 8, 2016 · 20 comments
Closed

Support .nvmrc #128

SteveALee opened this issue Jan 8, 2016 · 20 comments

Comments

@SteveALee
Copy link

Alows project to speicify the version to be used.
See nvm usage

or perhaps parse closet available version from package.json engines

@coreybutler
Copy link
Owner

I don't think this is a route I want to go down. The primary reason is it would require some very ugly hacking to recreate/mimic the node binary. For example, calling node index.js means the hacked/faked node.exe would need to first parse the package.json file (if it even exists) to determine the version and then execute the real node.exe for the appropriate version.

Some other similar projects have attempted to use .bat files to accomplish this. This approach is fragile, and it goes against the primary objective of the architecture.

I also just don't think the demand is widespread for this.

@gruber76
Copy link

The .nvmrc support is a fairly important aspect of using NVM with a CI system. I don't link the package.json suggestion, especially as it breaks compatibility with nvm, but would a pull request with support for .nvmrc be accepted?

@coreybutler
Copy link
Owner

@gruber76 - I probably won't accept a PR on this.

.nvmrc, package.json... they both require the same nasty hack.

@simoneb
Copy link

simoneb commented Mar 3, 2016

@coreybutler I'm not sure I understand your rationale for not wanting to support this. Wouldn't having this feature simply fallback to looking into the .nvmrc file whenever nvm is invoked without specifying a version number? Hence, what nasty hacks are you talking about?

@coreybutler
Copy link
Owner

The nasty hack: rewrite symlinks for Windows.

NVM for Windows works by changing the symlink target to the desired physical node installation directory. This is a system-wide change.

Let's say you fire up a script by specifying version 0.12.0 in a .nvmrc file, then fire up a second script without a .nvmrc. The symlink would point to v0.12.0 (from the first instantiation). If the 2nd script requires something else (like v4.2.6) with no .nvmrc, it will fail. This introduces environment instability when using symlinks because there is no true process isolation.

The only way to truly isolate a version on a per-process basis is to have nvm.exe redirect to the version the script is requesting instead of allowing the operating system to do it. I really don't want to recreate something the operating system already does for us.

If people really want to use a per-process/project approach, a more appropriate solution is isolating the runtime environment. Personally, I use Docker for that.

@gruber76
Copy link

gruber76 commented Mar 3, 2016

Forgive me for my ignorance, here. My primary use case is developing node/web applications using bower/grunt/gulp, etc. with multiple teams. For me, it is extremely rare that I would have multiple versions running within five minutes of each other. For this use case, the .nvmrc file is how my teams specify what node should be doing.

I'm having trouble seeing in the situation you describe (script A versus script B) how supporting .nvmrc would be any more troublesome than having script A (or a user of script A) calling nvm to set the version and then forgetting to set it before running script B. But I'm guessing there are some common use cases for nvm that are much harder core than mine. Possibly, for instance, if my CI servers had a heavier load.

I do have a hackey workaround to offer up to anyone else who needs it. The following in a pre-run bat script:

set /p nodev=<.nvmrc
nvm install %nodev%
nvm use %nodev%

@SteveALee
Copy link
Author

Why not put the nvm command to set the required version in a npm script?

Steve Lee
Sent from my mobile device Please excuse typing errors
On 3 Mar 2016 16:50, "gruber76" notifications@github.com wrote:

Forgive me for my ignorance, here. My primary use case is developing
node/web applications using bower/grunt/gulp, etc. with multiple teams. For
me, it is extremely rare that I would have multiple versions running within
five minutes of each other. For this use case, the .nvmrc file is how my
teams specify what node should be doing.

I'm having trouble seeing in the situation you describe (script A versus
script B) how supporting .nvmrc would be any more troublesome than having
script A (or a user of script A) calling nvm to set the version and then
forgetting to set it before running script B. But I'm guessing there are
some common use cases for nvm that are much harder core than mine.
Possibly, for instance, if my CI servers had a heavier load.

I do have a hackey workaround to offer up to anyone else who needs it. The
following in a pre-run bat script:

set /p nodev=<.nvmrc
nvm install %nodev%
nvm use %nodev%


Reply to this email directly or view it on GitHub
#128 (comment)
.

@josh-egan-ps
Copy link

Supporting the .nvmrc file would be really helpful. We have many projects, and they don't all run the same version of node. The .nvmrc file is at the root of each repo to ensure that the correct version of node is being used for a given project.

As a side note, it's also kind of annoying that nvm install must be followed by nvm use. I'm curious to know the reasoning behind requiring the second step after an install. I can see how installing and using are different things, but I wonder if there is ever a use case where someone would download and install, but not use.

Our work-around for this is that we have a file named install-node.js that lives at the root of each project. Whenever we switch to a project, we run node install-node from the command line. The contents of the install-node.js file are as follows:

var childProcess = require('child_process')
var fs = require('fs')

var nodeVersion = fs.readFileSync('.nvmrc', 'utf8').trim()

var command = "nvm install " + nodeVersion + " && nvm use " + nodeVersion
console.log('executing command: ' + command)
childProcess.exec(command, function(error, stdout, stderr) {
  if (stdout) console.log(stdout.toString())
  if (stderr) console.error(stderr.toString())
  if (error) console.error(error)
})

@coreybutler
Copy link
Owner

@josh-egan-ps - The separation between install and use was mostly for mass environment configuration. I will often install several versions of node before flipping between them. However; it seems perfectly reasonable to have a flag, like nvm install -u 5.9.1 to install and automatically use... or automatically use the version and have a flag to not use it. I'll definitely consider adding this.

For everyone - If you really need to switch on a per-project basis, consider putting nvm use x.x.x && node index.js in the npm start script section of your package.json. A common best practice is to always use npm start to launch a node app.

@SteveALee
Copy link
Author

For everyone - If you really need to switch on a per-project basis, consider putting nvm use x.x.x && node index.js in the npm start script section of your package.json. A common best practice is to always use npm start to launch a node app.

That might actually be too late in the case any npm build scripts used during install that depend on node / npm version. Or other tools such as grunt etc run expicitly They could fail during install with the wrong version of node / npm. or use the wrong version causing other problems, BTW I'm assuming the other best practice of having everything locally installed (ie not -g) so version dependencies are never a problem.

Thus it's good practice to use the npm install to setup every thing. You can then add a preinstall step to use nvm use. eg add

    "preinstall": "nvm use x.x.x",

That should be OK even if the original npm version will be running in the parent process. The install step will launch a new shell so all actions should pick up the new node and npm.

You might even want to add a pre start step than installs.

@coreybutler
Copy link
Owner

@SteveALee - yeah, you're right, my earlier suggestion wouldn't work. It would be too late in the process to launch reliably.

@SteveALee
Copy link
Author

@coreybutler In the end I went for this

"preinstall":"nvm use 4.4.1 || echo nvm not found: check node version && pause",

@SteveALee
Copy link
Author

Perhaps a nvm use -i x.x.x option would be good? That is, install if not already there?

@lehni
Copy link

lehni commented Nov 7, 2017

I would like to suggest to implement a part of this at least:

On Linux / Mac, in a folder with a .nvmrc file present, I can run nvm use without specifying a concrete version, and the installed version that matches the content of .nvmrc gets activated. If the file says 8, then the latest installed version of Node 8 gets installed.

I combine this on my systems with a script that overloads cd so that I can cd into a directory and the right version of node gets activated, with this script in .bashrc:

# Support .nvmrc
load-nvmrc() {
  if [[ -f .nvmrc && -r .nvmrc ]]; then
    nvm use
  elif [[ $(nvm version) != $(nvm version default)  ]]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}
# Override `cd` to auto-load correct version of Node on enterting directory.
cd() { builtin cd "$@"; 'load-nvmrc'; }

This could easily work on Windows too, if nvm was respecting these files.

@coreybutler
Copy link
Owner

A .nvmrc won't be implemented by default. However; the roadmap has a plan for hook support (#190). A pre-use script could be used to adjust the version according to any file they want (including package.json, .nvmrc, or anything else you choose).

@yinzara
Copy link

yinzara commented Jan 1, 2019

Since this issues seems to be nearly dead, I've got a workaround Powershell script that should mimic the functionality of "nvm use" and "nvm install" if the .nvmrc file contains a single digit node version.

nvm install (Get-Content .nvmrc) would work fine however nvm use (Get-Content .nvmrc) won't work (because when a single digit version is passed to install, it installs the most recent revision of that node version but nvm use with a single digit appends '.0.0' to it instead of getting the most recent.

@coreybutler If you updated the "use" command in nvm.go to use the same code as install, it would make this fix unnecessary (i.e.):
if len(version) == 1 { version = findLatestSubVersion(version) } else { version = cleanVersion(version) }

The following script will use "nvm list available" and filter the list for the highest LTS version that matches the .nvmrc file's version and then 'nvm use' it. If it is not installed, it 'nvm install's it then 'nvm use' it.
((nvm use (nvm list available | Where-Object -FilterScript { $_ -like ('* ' + (Get-Content .nvmrc)) + '.*'})[0].split('|')[2].trim()) -like '*not installed*') -and (nvm install (nvm list available | Where-Object -FilterScript { $_ -like ('* ' + (Get-Content .nvmrc) + '.*') })[0].split('|')[2]) -and (nvm use (nvm list available | Where-Object -FilterScript { $_ -like ('* ' + (Get-Content .nvmrc) + '.*') })[0].split('|')[2].trim())

@jamesguan
Copy link

Just want to request the support of nvm use to read from an .nvmrc file. It would really make my node development experience between Mac and Windows to be seamless.

@KevinGhadyani-minted
Copy link

KevinGhadyani-minted commented Oct 30, 2020

Is this closed because it was fixed or is not going to be changed?

Is there another Windows-compatible version of nvm which uses the same API as the *nix versions?

@Lewiscowles1986
Copy link

[[ -s "./.nvmrc" ]] && export NODEV=$(cat .nvmrc) nvm use $NODEV works for me. It checks that the file exists and is non-zero length (git bash for windows) and then works to tell nvm-windows to use it. No idea why author is uninterested in this, but it's not rocket science to add it.

@coreybutler
Copy link
Owner

@KevinGhadyani-minted This was closed because it will not be added.

For Everyone:

There are too many variations of different shells on Windows to support this with a script. For example, export is not an actual Windows keyword (set and setx are). Neither is cat. While nvmrc could be implemented, a better approach is the hooks system, which is on the roadmap for "rt".

There are no direct ports of the original nvm on Windows.

While I understand the desire to have the same tool between mac and Windows, they are different platforms. In the early days, I attempted to provide some parity with nvm (which is why the tool is called NVM for Windows, a poor naming choice). However; the development patterns required to support each OS don't always translate very well, because none of the version managers were designed specifically for cross-platform use.

I develop extensively on mac, Windows, and Linux and believe there are better ways to manage JavaScript runtimes than the approaches implemented in any current version managers. This is why I'm working on "rt", a runtime manager to succeed NVM4W. See #565 for more details. The truth is the pandemic hurt the pace of my business ventures and sponsorships aren't putting food on the table. As much as I'd like to promise a release date, I can't. The only thing I will mention is I finally ordered a new Windows computer, so I will be able to put a little more effort into "rt" once that arrives.

Repository owner locked and limited conversation to collaborators Jan 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

10 participants