nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
107.78k stars 29.68k forks source link

Allow multiple installs of Node on Windows with msi #4603

Closed felixfbecker closed 6 years ago

felixfbecker commented 8 years ago

image

It should be possible to install different Node versions to different directories with the msi. Actually, many programs like Java JDK, MySQL Server, PostgreSQL or Python version the installs by minor releases by default. It should at least be _possible_ (if not the default) to install Node versions like this

C:\Program Files\NodeJS\4.0
C:\Program Files\NodeJS\5.4

...but the installer either errors or uninstalls the previous version, depending on order of install. People should be allowed to install to whatever location and these separate installs should be uninstallable separately from Control Panel (with their version in the name). The installer should simply have a checkbox (next to "Add to PATH") to uninstall the previous version for easy upgrades.

felixfbecker commented 8 years ago

Some comment wether this will get on the backlog or not would be nice

Fishrock123 commented 8 years ago

Not many people work on the installers in general, if you feel strongly about this you may have to work on it yourself. :) I'm not very familiar with the installers (especially windows) but I can try to help/point to the right people.

I'm not familiar enough with windows installations to tell if this is actually a good idea though. cc @nodejs/platform-windows

MylesBorins commented 8 years ago

My main concern with something like this would be how a system would handle multiple installs in the path. is it only the most recent that is linked to? It seems like this could be a breaking change for systems, but I don't really know the installer so this is speculation.

@felixfbecker is there a reason you prefer this to be handled by the node installer rather than a userland module such as nvm-windows?

cjihrig commented 8 years ago

I'm not saying that the installer shouldn't handle these cases, but for the time being, you'll likely have a better experience if you use a version manager like nvm-windows, as @TheAlphaNerd mentioned.

felixfbecker commented 8 years ago

@TheAlphaNerd It is pretty easy to configure whats in the %PATH% on Windows, there is a very nice GUI for it:

image (You can see how I installed 5.4 in a versioned directory, but I cannot install a second version next to)

People can either set for themselves what version should be there or just check "change PATH" when they install a new version, the old entry should then get replaced by the new one.

The msi is the primary and recommended installation method for Node on Windows, and just how programs are installed on Windows. Even NPM says under how to install to Windows "get the msi, npm is in it". msi is for Windows what pkg is for Mac. Version managers bypasses the native installation methods on Windows, you don't get an entry in control panel for uninstalling, you dont get shortcuts in start menu, etc. They dont share global NPM packages between versions, create symlinks and switch their targets, download node versions in AppData directories so it does not need administrative rights etc to solve a problem that shouldnt exist in the first place. I want my programs to be installed in Program Files and uninstallable via Control Panel, and I should be able to install as many versions of this in parallel as needed. I can then set my PATH to the newest one or whatever I need the most often and when I need another version, I can just reference the full path. And if I want, I can download a new msi and install it from the command line - no need for version managers (I havent tested this with Node, but most msis allow you to do so).

@Fishrock123 I indeed feel quite strongly about this: Everyone respects how files should be layed out on Unix file hierachy and everyone is ok with needing sudo to do stuff, but on Windows often the motto is install anywhere, avoid UAC at all cost. To often you see "just download the zip and put it in C:\" or installers like Squirrel that dont allow you to customize the install location.

Unfortunately, I have never worked with installers before. I will try to take a look at it. But from what I understand, at least noone is opposed to this :)

MylesBorins commented 8 years ago

@felixfbecker thanks for sharing! I definitely think that this could be a big improvement to the windows workflow!

Let us know what we can do to help support you as you dig into this problem

felixfbecker commented 8 years ago

@TheAlphaNerd @Fishrock123 I found out that the stuff is located under tools\msvs\msi, but the solution file requires VS 2010 (I have 2015). Is there a reason for this? Do I have to install VS 2010 to hack on this?

cicorias commented 8 years ago

it's built using the wix tools which is an open source msi creation tool.

orangemocha commented 8 years ago

This is something that I have been recently looking into and discussing with @joaocgreis. I agree in principle that the MSI installing only one version is too limiting. The issue of adding multiple versions / creating conflicts with the global PATH is probably the single biggest complication as already mentioned.

Python allows side-by-side installation of different major versions. That can be simply implemented by changing the upgrade code with each major version. Python also add a launcher to the path (py.exe, pyw.exe) which then select a particular version of the engine based on a shebang line in the script (or other default configuration). I am considering implementing something similar for Node.

felixfbecker commented 8 years ago

@orangemocha Why make it so complicated? Just give the user the choice to overwrite an existing PATH entry on install. Uninstalling previous versions would be the default anyway, so people who install multiple versions should know what they are doing. It's easy to detect what version is currently in PATH by doing node -v, and like I said it is easy to switch PATH settings on Windows manually.

The point with python was really the problem that there is a huge gap between Python 2.x and Python 3.x. I would like to not limit this on major versions, but minor by default with a directory structure like in my original post. But people could also install patch versions by changing the install dir. I dont think shebang is needed as there isnt even a concept of shebangs in Windows. package.json provides a wonderful way to match supported Node versions for a project with all semver goodness. And if you use pm2 for example, you can specify the node runtime with an absolute path to a specific version.

felixfbecker commented 8 years ago

I read a bit about WiX and tried to understand the code but I don't think I'm able to contribute here. Sorry.

benjamingr commented 8 years ago

Pinging some wix friends.

@giltayar @AdirAmsalem @bolshchikov any chance you could get someone from the wix tools team to look into this?

giltayar commented 8 years ago

@benjamingr - those are two different Wix-es. The Wix you're referring to is a developer tool for building msi-s. The wix we are part of is a Consumer Saas for building web sites.

giltayar commented 8 years ago

Having said that, doesn't nvm work on Windows?

benjamingr commented 8 years ago

Oh oops, my bad - you guys are working on so many things related to web technologies I just assumed that it was the same company. Apologies Gil Adir and Sergey.

giltayar commented 8 years ago

I just googled nvm windows, and got this: https://github.com/coreybutler/nvm-windows

orangemocha commented 8 years ago

At the moment nvm for Windows is the best tool that I know of to run multiple versions on the same machine.

Just give the user the choice to overwrite an existing PATH entry on install.

I am concerned that this could introduce some problems / confusion based on the order of installs and uninstalls. I can't say for sure until we test it thoroughly.

The point with python was really the problem that there is a huge gap between Python 2.x and Python 3.x. I would like to not limit this on major versions, but minor by default

Major versions of Node als have many differences between them. They are major versions - by definition - because they introduce breaking changes. Minor upgrades within the same major are supposed to be backward-compatible. In light of that, majors seem like a good place to change the upgrade code. But if we had a solid side-by-side story, and a valid reason to, we could get more granular than that.

cicorias commented 8 years ago

If we can work out the aspects of how the PATH gets presented to the process along with the NPM pairing (as today they're in the same location/PATH) I can certainly handle the wix tooling / msi creation.

I do agree NVM for windows would be ideal as well, although the way that works today is via a symbolic link that switches it for any process that runs after the "use" version is issued. Not sure that's the desired approach.

Ideally, something that would allow side-by-side of 2 process simultaneously using version A and version B along with a paired version of NPM (and perhaps global NPM modules0.

Looking back to the opening comment on this issue, is this reasonable, with NPM/node_modules dangling off each path (duplication is OK?) - eg. if you switch versions, any global NPM modules would need to be installed again.:

C:\Program Files\NodeJS\4.0
C:\Program Files\NodeJS\5.4
felixfbecker commented 8 years ago

@cicorias The situation that NPM and NodeJS, despite having independent versions, laying in one folder by default is of course troubling. It is only the npm executable though - the global modules are always in %appdata%\npm. This is kind of weird, because while on Linux I believe global modules are truly installed globally (for all users) and need sudo, while on Windows, it's only for the current user and does not require "run as admin" (which creates its own problems, for example npm global modules can only be added to the path for the current user). I don't know if that is actually a problem - as far as I know, when I currently upgrade my Node version, my %appdata%\npm and therefor my global modules is left untouched.

Does it impose any problems, when the global modules are shared between versions (as they are right now), besides that engine constraints might get violated?

One option of course would be to install NodeJS and NPM in separate folders:

C:\Program Files
 |-- NodeJS
 |   |-- 4.0
 |   \-- 5.4
 \-- NPM
     |-- 3.3
     \-- 2.14

But npm itself is only an npm module, and the handling on Windows always caused trouble with self-updating npm. Another option would be to simply add the global npm module path to the PATH and put npm in there as a global module? That way everyone would be able to self-update with npm install -g npm or install any version independently of Node with npm install -g npm@2.14 (just like you can on any other OS).

Global modules should actually only be installed to ~\AppData\Roaming\npm if npm/node was installed locally to ~\AppData\Local. If they are installed globally to C:\Program Files, then the global modules should be in C:\ProgramData\NPM - and ProgramData doesnt even require admin rights (does this belong here or should I open an issue at the npm repo?). Anyway, either global modules would simply be shared by all node / npm installs, or the global modules directory needs to be versioned too:

C:\ProgramData\NPM\2.14
C:\ProgramData\NPM\3.3
felixfbecker commented 8 years ago

Is somebody working on this?

nvm is not really a solution. It allows you to switch between versions, but not have multiple versions side-by-side.

giltayar commented 8 years ago

True, but the switch is per-shell, so in essence, it does run multiple versions side by side.

On Sun, Jan 24, 2016 at 1:02 PM Felix Becker notifications@github.com wrote:

Is somebody working on this?

nvm is not really a solution. It allows you to switch between versions, but not have multiple versions side-by-side.

— Reply to this email directly or view it on GitHub https://github.com/nodejs/node/issues/4603#issuecomment-174280025.

felixfbecker commented 8 years ago

@giltayar AFAIK the switch is not per shell. It switches the target of a symlink in C:\Program Files\nodejs to different directories.

giltayar commented 8 years ago

I use nvm on the Mac, and it is definitely per-shell. Not sure about Windows, though.

On Sun, Jan 24, 2016 at 1:24 PM Felix Becker notifications@github.com wrote:

@giltayar https://github.com/giltayar AFAIK the switch is not per shell. It switches the target of a symlink in C:\Program Files\nodejs to different directories.

— Reply to this email directly or view it on GitHub https://github.com/nodejs/node/issues/4603#issuecomment-174284439.

felixfbecker commented 8 years ago

See https://github.com/coreybutler/nvm-windows:

As a result, NVM for Windows maintains a single symlink that is put in the system PATH during installation only. Switching to different versions of node is a matter of switching the symlink target. As a result, this utility does not require you to run nvm use x.x.x every time you open a console window. When you do run nvm use x.x.x, the active version of node is automatically updated across all open console windows. It also persists between system reboots, so you only need to use nvm when you want to make a change.

I could certainly build my own version manager by downloading the node.exe binaries, placing them in C:\Program Files\<version>, and do

path C:\Program Files\NodeJS\<version>;%PATH%

or

Add-PathVariable C:\Program Files\NodeJS\<version> -Prepend

in a shell to switch versions (or just reference the full path). But then I would not get the benefits of the msi (npm and uninstalling from control panel / package control)

benjamingr commented 8 years ago

Oh cool, great to know this is possible @felixfbecker although it's hacky. Although personally I don't install node from the installer I can see the appeal.

If you're interested (are you?) - what would you need in order to be able to start working on a PR?

felixfbecker commented 8 years ago

@benjamingr Yeah it is hacky, especially because you have to install npm manually. That means

After that, global modules will be installed to where your node binary was, so C:\Program Files if you installed for all users (which means --global installs need admin rights). If you placed the node binary in %USERPROFILE%\AppData\Local\NodeJS\<version>, you don't need admin rights. Global modules, including npm itself, will not be shared across versions because it cannot be assured that they are compatible with other node versions. This is what I would be going for for the msi.

I am interested, but I don't have any experience with Wix or C++. Maybe you can tell me

  1. What do I need to build / test the installer
  2. In what files is the current behavior defined (canceling install if there is already a version)
Trott commented 7 years ago

Is this regarded by the project as a desirable feature? Or is this considered something that is better left to the ecosystem/version managers? /cc @nodejs/build @nodejs/platform-windows @ljharb

ljharb commented 7 years ago

This seems like something the version management working group should handle, and also something that core should either handle on all platforms at once holistically, or by adopting a suite of existing tools to cover all platforms (this approach was rejected), or not at all.

DanielSundberg commented 7 years ago

So it seems like the community is left with "not at all" at the moment?

Trott commented 7 years ago

So it seems like the community is left with "not at all" at the moment?

The core project handles it not-at-all at the moment, but the community has options like https://github.com/coreybutler/nvm-windows (although @felixfbecker has explained why that is not an ideal solution for their use case).

DanielSundberg commented 7 years ago

Yes I think everyone writing in this thread know about nvm-windows, but it's not targeted at for example build servers. Instead of rolling our own solution we would like to know if something will happen in the near future.

ljharb commented 7 years ago

There's also https://github.com/jasongin/nvs

DanielSundberg commented 7 years ago

@ljharb, that's more like what I'm looking for! That project has somehow slipped under my radar..

refack commented 7 years ago

I disagree with calling PATH manipulations or unzipping, "hacky". It's an amazing feature of node that it's xcopyable, requires no installer, and can work without global state. Just unzip and it works!

IMHO we should declare the zip as the official binary package, and soft deprecate the installer.

gireeshpunathil commented 7 years ago

I agree with @refack. node being a self-contained executable - with no dll, no registry settings, no headless services to start, no configuration files and no trace / lock files leaving remnant in the system - may be one of the simplest language runtime in terms of the package structure, and a zip installer looks relatively clean, handy and light-weight.

tniessen commented 7 years ago

I agree that node's self-containedness is awesome, and I personally try to avoid installer packages on Windows whenever I can, but even though the zip might be the best option for advanced setups, I still think we should provide an installer (and probably not deprecate it). Node.js is a very popular programming framework and it seems like many new programmers decide to start with node, given that it allows full-stack development with nothing but JavaScript. These users benefit from a Windows installer because they don't have to configure anything manually, don't need to pick suitable locations for node and NPM, don't need to configure the PATH and so on. Secondly, I think it is a valid point that npm --global should install into a truly global directory, not into a per-user directory, if Node is installed for all users. Modern MSI packages allow to differentiate between "per user" and "all users" setups, allowing us to provide both options to users. If users want a secure way to install packages globally with just the zip, they will need to configure the directories and permissions themselves. Last but not least, our installer should optimally provide a clean uninstall, something users will need to do manually without it.

I think for MSI packages we will need to use different package GUIDs to allow the installation of multiple versions, so they will show up as different packages in "programs and features".

One problem arising from this issue is that even if we change our installer to allow multiple installations, we would still need to re-release all Windows packages, and I don't think this is going to happen (maybe for 6.x, 7.x and 8.x).

felixfbecker commented 7 years ago

MSIs are really nothing but a ZIP file with an XML manifest that tells Windows what should go where. And the fact that it can customise your install location and then automatically add the folder to your PATH is its biggest feature for Node users over a plain ZIP file. MSIs allow you to uninstall (rollback) at any time, even during an installation, with an exact undo of all done installation steps.

refack commented 7 years ago

IMHO we should declare the zip as the official binary package, and soft deprecate the installer.

  1. I was being a bit trollish and intentionally provocative, sorry...
  2. I was referring only to Windows, where the binary is pre built and uniform, and the OS minutia is known.
  3. I'm suggesting only to change the sales pitch to — "zip is the recommended binary package". The MSI should still be available, and eco-system version managers are most welcome.

MSIs are really nothing but a ZIP file with an XML manifest that tells Windows what should go where. And the fact that it can customise your install location and then automatically add the folder to your PATH is its biggest feature for Node users over a plain ZIP file. MSIs allow you to uninstall (rollback) at any time, even during an installation, with an exact undo of all done installation steps.

IMHO, for Node.js, the problem is mostly that of perception. When users assume the MSI contains magic, and that not using it is a hack, I think we are doing them a disservice...

@felixfbecker I acknowledge that for many use-cases the MSI is the perfect tool, but IMHO for your case (and probably for most multi-version systems), a version manager is a better solution.

Maybe we should migrate the logic from the MSI to a batch/powershell script, and use the installer just as a GUI form for collection of configuration choices (and to wrap the running of said script in a transaction). this way we get stronger parity between the zip package and the MSI, and have made the install "magic" transparent.

as an aside, and this paragraph is not an invitation to bikeshed, more of a mea culpa ¯_(ツ)_/¯: I'm biased against MSIs, because they are black-box-ish. In products when they are the only binary package available I unzip them and manually do the registration and ENV changes. Personally I much prefer NSIS installers, that are easier to unzip and to de-compile-out the install script. I also acknowledge that I'm an edge-case and that MSIs have their advantages (atomicity, minimal required elevation, coordination with other installers etc.)

refack commented 7 years ago

Secondly, I think it is a valid point that npm --global should install into a truly global directory, not into a per-user directory, if Node is installed for all users. Modern MSI packages allow to differentiate between "per user" and "all users" setups, allowing us to provide both options to users. If users want a secure way to install packages globally with just the zip, they will need to configure the directories and permissions themselves. Last but not least, our installer should optimally provide a clean uninstall, something users will need to do manually without it.

👍

felixfbecker commented 7 years ago

well Windows package managers like choco or package control (Install-Package) work with MSIs. Every MSI can be installed from the command line without running it in a GUI. A batch install script is not atomic - if it fails midway through you cannot rollback. And that can happen during the installation, a drive can fail, permissions can be insufficient, a registry edit can fail, etc (changing the PATH persistently is a registry edit afaik).

refack commented 7 years ago

well Windows package managers like choco or package control (Install-Package) work with MSIs. Every MSI can be installed from the command line without running it in a GUI. A batch install script is not atomic - if it fails midway through you cannot rollback. And that can happen during the installation, a drive can fail, permissions can be insufficient, a registry edit can fail, etc (changing the PATH persistently is a registry edit afaik).

Acknowledged 👍

tniessen commented 7 years ago

I will probably have some time off this weekend to put some work into the installer, no promises though. I think the primary points to consider are

  1. global vs user-local installation
  2. npm global module path depending on (1)
  3. co-existence of different versions on a single machine

Is this correct and complete?

felixfbecker commented 7 years ago

Yeah, that looks good. Also adding to PATH, which is already supported by the current installer.

refack commented 7 years ago

@tniessen See https://github.com/nodejs/node/issues/12345 and https://github.com/nodejs/node/issues/10402 (full list of 15 open windows installer issues) AFAIK the hottest issues could be solved if we add a new checkbox "overwrite previous configuration" (and "purge" style checkbox on uninstall "remove user configuration")

refack commented 7 years ago

And if we call a "Windows Installer improvements" weekend hackathon, I'll try to:

(my wife is flying to a conference in Portugal so I'll have bored-out-of-my-skull time)

felixfbecker commented 7 years ago

cobble up a paired install script that can be run independently of the MSI

fine with me as long as the MSI installation stays atomic (and doesn't just call a batch script)

refack commented 7 years ago

cobble up a paired install script that can be run independently of the MSI

fine with me as long as the MSI installation stays atomic (and doesn't just call a batch script)

Actually some the the issues are directly related to that, if npm fails during install, atomicity is broken...

@felixfbecker can we get a pledge for some bug fixing from you as well 😜

joshgav commented 7 years ago

cc @yodurr @joaocgreis

vsemozhetbyt commented 7 years ago

Let me humbly remind of https://github.com/nodejs/node/issues/6273 :)

refack commented 7 years ago

https://github.com/nodejs/node/issues/819 - add entry points for translation