lock global npm packages - node.js

Is it possible to lock global packages to a specific version? For example if I do:
$ npm install -g some-awesome-package#1.7.0
if some-awesome-package#1.7.1 exists, can I prevent npm from ever updating this specific package?

The answer appears to be no. I opened this issue but it got closed. It's hard to imagine that I'm the only person with this use case though.

There may be a way to do this through the npm CLI, but I can't find it. There doesn't seem to be a npm shrinkwrap for global packages, either.
I thought it might be possible using npm link (which creates a symlink from a local package to the global folder), but running npm install -g somepackage#foo after npm link, does overwrite the previously installed global package.
One (very hacky) way to force npm to fail when it tries to overwrite your globally installed package is to remove write permissions for the folder (for the user account that runs npm) with something like this chmod -w /usr/local/lib/node_modules/<some package>.
Once you do that, then npm can't install/update that global package because it doesn't have write access. I can't say I recommend going down that road, though.

Related

How to get npm to favor local linked dependency over its published install

I've searched through other questions such as this one, but they all seem to be about a local npm link stopping working for another reason than mine. I assume this is a common use-case issue, so if I'm doing something methodically wrong, I'm more than happy to take suggestions on how I should be doing it.
Principally, I have a private npm module that I'm working on called #organisation/module. When working locally, I'll run npm link on it, and use it within my 'host' project as npm link #organisation/module — this all works great with hot-reloading, etc. I'll also import it as import module from '#organisation/module.
However, since I also want to publish my local changes to npm (as #organisation/module) from time to time, for build testing and production code, I need to run npm install #organisation/module on the host project.
This then seems to break the implicit npm link I set up earlier... I assume mainly because they are the same name, and npm favors an install over a link?
When I want to make live, local changes again, the only way I can currently get it to work is via npm uninstall #organisation/module and then to re-link it.
Is there a way to keep the published module installed (in order to avoid careless mistakes, like forgetting to reinstall it for build testing), but always favour the local, linked instance?
Diagram for ref:
Have you tried locally installing with the other method npm provides.
npm install /absolute/path/packageName
I believe this will change your entry in package.json to look like this:
"dependencies" {
...
"packageName": "file:../../path/to/packageName",
...
}
Since npm link creates a symlink in the global folder, while npm install is local to the project npm install takes precedence. You can read about npm link here: https://docs.npmjs.com/cli/link
To avoid this, my suggestion would be to use npm install <path to local> and when you need to use the production code use npm install #organization/module. This would update your node_modules per code basis. Read about npm install here: https://docs.npmjs.com/cli/install
Hope this helps :)
Go to the directory where your local package is located open package.json change the name from original_name to "original_name_local".
write npm link on terminal at the same location.
After this go to your working directory and write npm install <path to local>
Now whereever you're requiring or importing update the name to "original_name_local"
for example if it's require('space-cleaner') then change it to require('space-cleaner_local')
Like this you can have both local as well as production package just change the name wherever required.
Otherwise you can remove package by removing it from package.json and deleting from node_modules.
if local is needed go to local package directory and on terminal write npm link and then on your working directory write npm install ./path/to/package
if production then again delete the package as told above and write npm install package_name

Doesn't npm install check for a global version first?

I just setup a test, and tried to npm install express even though express already exists globally on my system. To my surprise, instead of using the global version, it ended up re-installing a version locally!? Isn't it supposed to use the global version... Or am I suppose to use -g every time, even when I only want to use the existing global version. Otherwise, what's the point of installing anything locally!?
The answer is "NO". It isn't supposed to use your global version.
If you want to use your global version, then you doesn't need to execute npm install at all because it is already installed.
If you do it then, obviously, you are saying "I want to install it locally to my project". And more than that: "I want to install its latest version unless it is declared in my package.json with other explicitly specified version".
In fact, the actual question is: Why in the hell would you want to not install a dependency of your project locally? To have more version mismatch issues?
As #anshuman_singh says, best practice is to always do an npm install --save.
You are able to use globally installed packages, of course. It could be handy for fast testing code that you will drop just after a few hours or so.
But, anyway: If you doesn't have really hard disk or network bandwidth issues, installing all dependencies locally will avoid you too much trouble in the future.
On the other hand, uploading that modules to your code repository is also a bad idea (maybe that is what you were trying to avoid) because, with different versions of node, most native modules won't work if not rebuild. But most VCS support ignoring files and or directories that must not be uploaded.
For example, in git (.gitignore file):
**/node_modules
In summary:
npm init (if you didn't already it).
npm install --save for all your project dependencies.
npm install --save-dev for dependencies not needed in production (testing stuff).
Don't upload node_modules to your VCS.
After new checkout: npm install or npm install --production (to not install dev-dependencies).
npm install -g only for tools you will use in console.
This way, you are sure that you will have in production (or other dev environments) the exact same version of each package.
And, finally, if you ever want to upgrade some package to its latest version, simply run:
npm install --save <pagkage_name>#latest.
If you’re installing something that you want to use in your program, using require('whatever'), then install it locally, at the root of your project.
If you’re installing something that you want to use in your shell, on the command line or something, install it globally, so that its binaries end up in your PATH environment variable.
The first option is the best in my opinion. Simple, clear, explicit. The second is really handy if you are going to re-use the same library in a bunch of different projects
Install locally-
npm install moduleName
install locally and save in package.json-
npm install moduleName --save
install globally-
npm install moduleName -g

copy npm global installed package to local

If I have a npm package installed globally, and I want to install the same package locally in some project, does npm download the package again or copy it from the global install folder? If not, is there a way to make it do that?
It is not recommended to copy files from global to local. It is pretty normal to have package installed in both places.
Global package in most of the cases is used in terminal.
Local package is used in application itself.
Also you can use npm link to symlink a global package
Install it in both places. Seriously, are you that short on disk
space? It’s fine, really. They’re tiny JavaScript programs.
Install it
globally, and then npm link coffee-script or npm link express (if
you’re on a platform that supports symbolic links.) Then you only need
to update the global copy to update all the symlinks as well.
The first option is the best in my opinion. Simple, clear, explicit. The
second is really handy if you are going to re-use the same library in
a bunch of different projects. (More on npm link in a future
installment.)

repair npm global package symlinks

Recently upgraded to OSX Mavericks and had all my npm global module symlinks wiped out! Reinstalling npm got npm to work again.
Is there a way to have npm recursively go through /usr/local/lib/node_modules/
and create the symlinks in /usr/local/bin for each package? (yes, it is in my Path)
Is there a way to do this a single package at a time?
My Google-fu is failing me at the moment. I have over 40 packages and I would hate to have to reinstall all of them or manually create symlinks for all the bins!
OSX 10.9
npm 1.4.14
node 0.10.29
Run this to rebuild in place without reinstalling:
for i in "$(npm prefix -g)/lib/node_modules/"*; do
sudo npm build -g "$i"
done
But, are you sure that the symlinks are broken, and not that it simply changed your PATH environment variable or something? What does npm bin -g output?
Well this way is easy but it will re-download stuff, but it will still probably be faster than trying to script a way to repair them in place without redownloading:
npm install -g $(ls /usr/local/lib/node_modules)
If you try to manually create the symlinks, you are almost certain to miss some and/or make so mistakes, so I would not recommend that.

Where does npm store node modules?

I just setup official node.js on windows which includes npm in custom directory d:\myserver\nodejs
I tested npm with
npm install less
it works but I can't see any less directory in node_modules\npm\node_modules subdirectory.
Where could I find it (I guess the name of less module is actually less).
under : node_modules
just check where you where pointer "in what directory were you" at the time of the installation
d:\myserver\nodejs -> node_modules
Just for further clarification, google brought me here while looking up where global modules are stored (installed via npm install -g ...).
From the documentation
Local install (default): puts stuff in ./node_modules of the current package root.
Global install (with -g): puts stuff in /usr/local or wherever node is installed.
Install it locally if you’re going to require() it.
Install it globally if you’re going to run it on the command line.
If you need both, then install it in both places, or use npm link.

Resources