I use version A and install a package (say coffeelint
) globally. Then I switch to version B. The previously installed package (coffeelint
) is not available with version B. So I Need to install it all over again.
C:\> nvm use 0.10.33
C:\> npm install -g coffeelint
C:\> coffeelint -v
1.6.1
C:\> nvm use 0.10.32
C:\> coffeelint -v
'coffeelint' is not recognized as an internal or external command,
operable program or batch file.
Without nvm, npm installs global packages to C:\Users\[username]\AppData\Roaming\npm
. But with nvm, it install in C:\Users\[username]\AppData\Roaming\nvm\[version]\npm_modules
.
Is there a way to change this behaviour?
It's possible, but not natural to change the behavior.
Without nvm, there is only one version of node running. If you were to install another version of node without nvm, you'd overwrite the existing install. Nvm is just switching the version to prevent having to do this. I have had a couple of requests for this feature, and I myself am interested in it. However; it introduces problems, and potentially a lot of support headaches. For instance, a shared global npm directory would allow any module to be installed, but you might need different versions of a module for different versions of node. I already have requests to cherry-pick a version (i.e. specify nvm -v X.X.X myscript.js
) to run node... I could see a desire to cherry pick versions of modules too (which nvm will never support).
Furthermore, this introduces a new problem... it'd be entirely possible to install a module on the wrong version of node. npm won't allow this right now. If a module specifies a newer version of node (say 0.10.33) and you're running an older version, the install will abort. However; if I add this feature to nvm with a shared global space, then it'd be possible to use 0.10.33 to install the module, then switch to 0.10.26 and have the module fail.
I've been thinking about a couple of ways to potentially implement this, but it goes back to a common principle... does NVM just manage the environment, or does it manage the workflow? As a workflow guy, I really want a solution to this, but I'm not sure if it _should_ be in nvm.
We can let the current behavior be default and provide an option to switch the npm directories between global and node version in use.
Default behaviour:
nvm use 0.10.33 --set-modules-dir=inuse
Using Global Directory:
nvm use 0.10.33 --set-modules-dir=global
This will let the users control the environment in the way they like.
It's not a matter of syntax, it's a matter of principle and support headaches :-) However; this is a good idea and I'll keep it in mind when I do the next round of updates.
Yes, I know it's not about syntax. What I gave was just a pseudo code for the idea.
Glad to hear that you liked it. :)
@vkbansal - I moved your last comments into its own issue (issue #29).
I'll likely still add something for this in the next release, but I completely forgot to post that it's already possible to set a common global node_modules
directory using .npmrc
. See the config options for details. I'm closing this permanently, but I'll likely add something of some sort to assist with this in the future (since most people don't know about these options).
@coreybutler I fully understand your concerns about shared node modules across versions, but would it be possible to have a sort of a hook that could automatically do an npm install -g
on a list of specified modules every time you switch version using nvm use <version>
?
As an example, let's say you could define global packages with a command like nvm add-global <package>
that would save this package's name somewhere. Whenever you would do nvm use <version>
, nvm could read all packages saved with add-global
and do a global npm install
for each of those once the version switch has been made.
I don't have knowledge of Go so I can't write a POC for this, but I guess it could be do-able.
@ClementParis016 - I've actually been thinking about a hook system similar to how git does it... for example, if a post-use
script exists, it would run after the user executes a nvm use x.x.x
.
I really don't want to change the NVM4W executable in a manner that reflects opinions in workflow, but NVM4W shouldn't stifle it either. The git approach does a great job of allowing users to add their own opinionated functionality without affecting the core application. I like to think of it like "command line webhooks", and I believe it is a solution that could work for everyone.
@coreybutler Any simple fix for this problem at the moment?
I know #190 is still open, and I believe --set-modules-dir=global
works, but any quick solution?
@sparcut -
tldr; no quick solution.
_Long Answer:_
The npm flag only allows you to change the global directory for a specific installation. Technically, it'd be possible to run that command every time the user runs nvm use x.x.x
, but the integrity of the modules in relation to the active version of Node cannot be guaranteed.
For example, many modules rely on newer versions of Node (4.x.x+). Switching to a prior version can (and likely would) regress anytime npm install
is run. Dealing with native modules and node-gyp introduces an even more complex can of worms. In cases where the version change is minor, the impact may be far less.
The subject of a shared global module directory spanning multiple versions is very complex and generally ill-advised due to it being a breeding ground for incompatibility issues. However; since there are situations where it could be helpful, people shouldn't be prevented from doing this... even if general practice advises against it. The hook system is the only way I can think of giving users control to do this.
At the end of the day, NVM4W is a _node_ version manager. It's not an npm manager (other than being part of the node installation) and it's not a project manager (which are very opinionated). It will continue to do this one thing well, but I do feel exposing more points for extension is a part of that process.
@coreybutler I'm thinking in something like this:
https://github.com/creationix/nvm#default-global-packages-from-file-while-installing
What do you think?
@maxigs7 I'm not opposed to the concept, but I _currently won't_ accept a PR for implementing it... purely on the grounds that the hooks system is already on the project roadmap for 2.0.0 and I feel that is a more appropriate place to implement this. You're welcome to do this in your own fork in the interim.
To me, it makes more sense to trigger a user script whenever a new installation occurs (like git hooks). Nothing would prevent a user from maintaining a default package list and installing them on each new version event.
Until the hook system is implemented, I'm currently doing:
tr -d \r < %nvm_home%\node-packages | xargs npm install -g
where node-packages
contains something like:
prettier
http-server
yarn
This re-installs all packages listed in the file, or updates them if they already exist. tr
and xargs
come from git for windows.
Most helpful comment
@ClementParis016 - I've actually been thinking about a hook system similar to how git does it... for example, if a
post-use
script exists, it would run after the user executes anvm use x.x.x
.I really don't want to change the NVM4W executable in a manner that reflects opinions in workflow, but NVM4W shouldn't stifle it either. The git approach does a great job of allowing users to add their own opinionated functionality without affecting the core application. I like to think of it like "command line webhooks", and I believe it is a solution that could work for everyone.