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

Ability to use nvm to launch a specific version of node. #16

Closed
tracker1 opened this issue Oct 24, 2014 · 30 comments
Closed

Ability to use nvm to launch a specific version of node. #16

tracker1 opened this issue Oct 24, 2014 · 30 comments

Comments

@tracker1
Copy link

Although one could use batch files for this, and just accept that the symlink will swap around... it would be nice if one could nvm (version) -run somescript or similar for executing npm scripts with a specific version of node... with everything after the -run passed to node as parameters... nvm 0.11.10 -run --harmony my-new-tool.js as an example.. because I'm moving towards doing new projects with 0.11 and older ones still on 0.10, it would be nice to be able to set my services to use the appropriate version.

@coreybutler
Copy link
Owner

This is something I've thought about, but haven't yet come up with an approach I feel is robust enough. I am also still pondering whether this is even appropriate for the tool or not, since it would extend the scope from being a simple installation/version manager into actually running node.

This introduces some foreign elements into the workflow.... for starters, node would be running as a subprocess of NVM for Windows. Since NVM for Windows is written in Go, node would be subject to some outlying constraints. For example, process.title = "My App"; would not work as expected because unlike Node, Go cannot change a Windows process name. There's also a need for piping stdout and stderr from the node child process to the Go process. Bottom line is you're not working directly with node, you're working with Node thru Go.

nvm and nodist have this feature, and I see value from a simplicity perspective... but I don't know if the quirks are worth it right now... one of the main driving factors that led me to create this project i nthe first place was to avoid quirks.

That said, I'm open to ideas because I do think this would make cherry-picking a version of node a trivial effort.

In the meantime, you could just type %NVM_HOME%\v0.11.14\node --harmony my-new-tool.js.

@coreybutler coreybutler mentioned this issue Nov 18, 2014
@mattheyan
Copy link

mattheyan commented May 11, 2016

Edit: Sorry about rehashing this. I just realized that this issue was closed ;)

Maybe this is a bad idea, but I'll throw it out there...

What about instead of having %PROGRAMFILES%\nodejs on the path, have another folder with node.bat and npm.bat files. They would search for an .nvmrc file from the current working directory and call that version of node or npm directly if found, or fall back to %PROGRAMFILES%\nodejs if not. I know I'm glossing over some technical details but it _seems_ like that might be do-able.

Also, this wouldn't necessarily have to be a part of nvm proper, but it would be nice if it could be incorporated for convenience. It doesn't seem like this conflicts with nvm, and the majority of the value still remains in installing different versions of node and managing the symlink for the normal use cases.

Anyway, just an idea to consider.

@coreybutler
Copy link
Owner

@mattheyan - Using a batch file still means wrapping node, so there will still be quirks and incompatibilities. The only way to guarantee node will run as intended is to run node directly, not through a wrapper. Unfortunately, I tried this with node-windows and there have been more issues with wrapper workarounds than anything related to the project.

There are some interesting things happening with Go 1.7 that might, and I really stress the might, make this possible. However; that's still quite a ways from being released. I've been keeping my eyes on this for a while though (I would actually like to have this myself), and if a reliable solution becomes available, I'll definitely look into adding it.

@tracker1
Copy link
Author

A .cmd file should handle calling npm, or executing node with the appropriate stdin/stdout, as it's a pretty inherent part of windows... it actually sounds like an interesting idea.

@mattheyan
Copy link

Yeah, I was thinking it could work in most cases. Node on windows does utilize bat/cmd file redirects a lot it seems. @coreybutler I don't doubt these quirks you mention exist, but I'm curious to hear what kind you've seen and whether they're common use-cases or obscure edge cases. Either way I understand why it would give you pause incorporating in nvm. And, like I mentioned before, there are other technical hurdles to overcome. But, I do think it would be really valuable if it could be done, if not in nvm proper then maybe in a companion tool.

@coreybutler
Copy link
Owner

Well the process.title glitch I mentioned above is a big one from the node-windows community.

However; the most prominent issues crop up around the file system. There are typically a bunch of issues with __dirname and __filename, as well as process.cwd() or anything else related to relative directory paths. I've received 100's of questions about this. The "wrapper" executable (winsw in the case of node-windows) runs from a different directory than node is installed in, so resolving filepaths can (and often do) differ. These issues can be worked around, but it causes alot of headaches for folks when their app works in one place and not in another, seemingly for no apparent reason.

File system permissions can also be a challenge, as can passing in environment variables, all for the same reasons. When you wrap an executable, you're basically passing in a user to run it with too.

Remember, this project will no longer be Windows-only in the next release. In some experimentation within Docker, there have been other issues based on the file system. It has to do with how Docker is implementing volumes, so not directly an NVM4W thing, but I use it as an example of an emerging practice (containerization) that depends on an executable behaving the way it's supposed to.

When I initially released NVM4W, I exchanged a few thoughts with Sindre Sorhus, who maintains the awesome-node list. I tried to add both NVM4W and nvm to that list, but he objected to nvm (which uses a wrapper). The gist of it was too many people were experiencing glitches, so I'm sure there is stuff I haven't seen yet either.

@mattheyan
Copy link

Thanks for the insight @coreybutler. I must admit I don't fully understand the nature of these issues, but it sounds like you've experienced pain from this in the past, so I see why you'd be hesitant to do this. I may revisit this at some point as a separate tool, and maybe I'll run into the same issues when I do (in which case you can say "I told you so" :P).

Feel free to close this issue since I think it was closed when I rehashed it - I would but it doesn't look like I can. Thanks again for the info and thoughts :)

@coreybutler
Copy link
Owner

@mattheyan - If you do produce a companion tool, stay in touch. Like I said before, it is something I am also interested in. If there is a good companion tool, I'd certainly put up a link to it in the README here.

@jednano
Copy link

jednano commented Feb 14, 2018

PowerShell

nvm use $(Get-Content .nvmrc)

Bash

cat .nvmrc | nvm use

Command Prompt

Can't figure it out.

@nerdkid93
Copy link

@jedmao

Command Prompt

for /f usebackq %i in (`type .nvmrc`) do nvm use %i

@rofrol
Copy link

rofrol commented Jun 14, 2018

for git bash this works

$ nvm use `cat .nvmrc`

@danielkcz
Copy link

danielkcz commented Oct 22, 2018

Regarding Powershell, I've tried adding this to my profile script to automate switching. It works, but there is a rather big downside that nvm use is not checking if the same version is already used and elevated prompt jumps in every time.

if (Test-Path .nvmrc) {
    nvm use $(Get-Content .nvmrc)
}

@coreybutler Would it be possible to add that check, even with some command line flag?

@coreybutler
Copy link
Owner

.nvmrc is not supported, so a check won't do any good. .nvmrc is a an nvm for unix concept (different project).

@danielkcz
Copy link

danielkcz commented Oct 23, 2018

@coreybutler That's not what I mean, you don't need to care about such file at all. What is needed is a check to nvm use and don't do anything if a specified version is currently selected. With that check in place and the small script above it's possible to mimic unix behavior fairly good.

Whenever I would open Powershell in a folder containing .nvmrc it would get switched to that version. I am aware it's not ideal, but it's surely better than to keep remembering version of Node for each project and manually switching it.

To add more context, I am using Visual Studio Code which has integrated Powershell terminal that always opens in root folder of the project. With that in place I can get NVM switch when I use that.

@coreybutler
Copy link
Owner

coreybutler commented Oct 23, 2018

@FredyC NVM4W doesn't run when a script is run (i.e. node index.js), so I'm not entirely sure when a check like that would even happen. The nvmrc concept is based on the premise that node is shimmed (i.e. called through a wrapper utility). NVM4W doesn't work that way. When you run node.exe, you're actually running Node directly... not a wrapper.

Additionally, your example only works on systems with powershell, which is not necessarily available or installed on all versions of Windows. While a powershell implementation isn't difficult, it should highlight the fact there are all kinds of different Windows configurations to account for.

There have been alot of requests like this, focusing more on environment management than version management. The proposed solution is a hooks feature, currently on the v2.0.0 roadmap. This would allow developers to run whatever scripts they want in response to NVM4W events, similar to git hooks.

@danielkcz
Copy link

danielkcz commented Oct 24, 2018

Sorry, my explanation must be terrible if you are still not getting it :) Forget about .nvmrc, I don't expect NVM4W to do anything with that file.

What I am asking is simply extending nvm use command so it checks if the specified version is currently used and if its, it will just print message and exit. It can require optional command line flag for that. The current behavior is that it always tries to use a specified version causing a popup for elevated command.

Clear so far? I am not asking anything else from NVM4W. Reading .nvmrc file will be done outside of its scope. That file can be called whatever I like it for that matter.

@just-Bri
Copy link

Sorry to necro this 2 year old thread but I'm trying to setup the same thing.
In linux I have this in my bashrc:

if [ -f .nvmrc ]; then
  nvm use
fi

That obviously wont work in Windows but I adapted it to powershell and added a runAs to allow running as admin:

Function runNvmUse([string]$version) {
  Start-Process -Verb RunAs nvm use $version
}
if (Test-Path .nvmrc) {
  $version = Get-Content .nvmrc
  runNvmUse($version)
}

But I am getting this error: "A positional parameter cannot be found that accepts argument '14.16.0'"

@marckassay
Copy link

@reifnotreef replacing Start-Process line with the following seems to work:

 Invoke-Expression -Command "nvm use $version"

@tracker1
Copy link
Author

tracker1 commented Nov 2, 2021

Could probably get the output from node --version and check against it in the .nvmrc file to only switch/elevate when necessary in the Powershell prompt/script. For that matter, could probably create a powershell version of nvm that's much closer to the *nix (bash?) version. In that it's only in the prompt/terminal, not global.

@earonesty
Copy link

without this feature, it breaks the use of nvm for ci/cd on systems that can handle more than 1 job. kindof broken, imo. changing global values is wack

@ktzsolt
Copy link

ktzsolt commented Nov 23, 2022

Came here to find a solution how I can build (ci/cd) on a windows build machine 2 different apps that are using different node versions. So this nvm-windows is not a solution for this because it can switch only the node version globally, what CI/CD would need is to switch node version only for that specific session it is running in. :(

If you know any alternative solution please share it (I can not use linux or docker in this project even though I would like)

@coreybutler
Copy link
Owner

@ktzsolt you can still use NVM4W with two versions running at the same time... but you have to call the node.exe using the full path.

For example, consider this NVM4W installation:
image

image

Your app needs to use the absolute path of the directory, or you could create a node.cmd or node.bat file in each app directory pointing to the appropriate version. This allows two versions to be used simultaneously.

@ktzsolt
Copy link

ktzsolt commented Nov 23, 2022

@coreybutler Thanks for the quick reply, could you help me how I could run npm commands with this solution? Like npm version for start?

UPDATE: never mind I think I figured it out, but could you validate it? Also what are the pitfalls if any that I should be mindful of? Thanks!

\nvm\v17.9.0> .\npm.cmd version
{
  npm: '8.5.5',
  node: '17.9.0',
  v8: '9.6.180.15-node.16',
  uv: '1.43.0',
  zlib: '1.2.11',
  brotli: '1.0.9',
  ares: '1.18.1',
  modules: '102',
  nghttp2: '1.47.0',
  napi: '8',
  llhttp: '6.0.4',
  openssl: '3.0.2+quic',
  cldr: '40.0',
  icu: '70.1',
  tz: '2021a3',
  unicode: '14.0',
  ngtcp2: '0.1.0-DEV',
  nghttp3: '0.1.0-DEV'
}
\nvm\v10.12.0> .\npm.cmd version
{ npm: '6.4.1',
  ares: '1.14.0',
  cldr: '33.1',
  http_parser: '2.8.0',
  icu: '62.1',
  modules: '64',
  napi: '3',
  nghttp2: '1.34.0',
  node: '10.12.0',
  openssl: '1.1.0i',
  tz: '2018e',
  unicode: '11.0',
  uv: '1.23.2',
  v8: '6.8.275.32-node.35',
  zlib: '1.2.11' }

@coreybutler
Copy link
Owner

@ktzsolt you figured it out... it's basically the same as the solution I mentioned above, but referencing npm instead of node:

image

@coreybutler
Copy link
Owner

I've added the solution (above) to the common issues wiki

@ktzsolt
Copy link

ktzsolt commented Nov 24, 2022

@coreybutler What I also had to do is to run for the specific npm.cmd this command:
\nvm\v10.12.0> .\npm.cmd config set scripts-prepend-node-path true

After this I was able to run npm commands, but whitout this I would get this warning:

npm WARN lifecycle npm is using D:\BuildTools\nvm\v10.12.0\node.exe but there is no node binary in the current PATH. Use the --scripts-prepend-node-path option to include the path for the node binary npm was executed with.

And subsequently many errors.

@bronsonmock
Copy link

bronsonmock commented Aug 15, 2023

In case someone comes here for usage with .nvmrc files, here is an alias solution for git bash users. The alias solves the following issues:

  1. Attempts to use .nvmrc from CWD if no version argument is supplied for install and use commands
  2. Solves Error when issuing 'nvm use' command in git-bash terminal #140 by delegating use commands to windows command prompt (Permission restrictions still apply; may generate elevated permissions prompt)

.bashrc

function nvm() {
    if [ $# -eq 1 ] && [[ "$1" == install ]]; then
        command nvm install $(cat .nvmrc)
    elif [[ "$1" == use ]]; then
        [ $# -gt 1 ] && ver="$2" || ver=$(cat .nvmrc)
        command cmd //c nvm use "$ver"
    else
        command nvm "$@"
    fi
}

Note: if the [arch] parameter is important to you, you will need to modify the alias to account for it.

Edit:

As noted by @bdanbury below, you may not need the double forward slash on the c parameter depending on your setup. However, if you are using Git for Windows, you will need the two slashes to avoid the POSIX-to-Windows path conversion. As noted here: git-for-windows/git#4798 (comment)

My environment:
Git for Windows v2.22.0
Windows 10 22H2 19045.4529

@bdanbury
Copy link

bdanbury commented Jan 30, 2024

command cmd //c nvm use "$ver"

On my machine, I didn't need two slashes before the c parameter, only one. But otherwise thank you!!

command cmd /c nvm use "$ver"

GNU bash, version 5.2.15(3)-release (x86_64-pc-cygwin)
Microsoft Windows [Version 10.0.19045.3803]

Repository owner deleted a comment from raphaelsetin Mar 14, 2024
@luizxrs
Copy link

luizxrs commented Jul 8, 2024

This worked for me in windows, just make sure if everything else is working properly

paste this at the end of your $profile file

function nvmFunc {
    param(
        [string]$Argument,
        [string]$Version = ""
    )

    if ($Argument -eq "install" -and $Version -eq "") {
        & nvm install (Get-Content .nvmrc)
    }
    elseif ($Argument -eq "use") {
        if ($Version -eq "") {
            $ver = Get-Content .nvmrc
        }
        else {
            $ver = $Version
        }
        & cmd /c nvm use $ver
    }
    else {
        & nvm $Argument
    }
}

Set-alias nvm nvmFunc

@rizqikazukun
Copy link

Cool Thanks.

This worked for me in windows, just make sure if everything else is working properly

paste this at the end of your $profile file

function nvmFunc {
    param(
        [string]$Argument,
        [string]$Version = ""
    )

    if ($Argument -eq "install" -and $Version -eq "") {
        & nvm install (Get-Content .nvmrc)
    }
    elseif ($Argument -eq "use") {
        if ($Version -eq "") {
            $ver = Get-Content .nvmrc
        }
        else {
            $ver = $Version
        }
        & cmd /c nvm use $ver
    }
    else {
        & nvm $Argument
    }
}

Set-alias nvm nvmFunc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests