Doesn't npm install check for a global version first? - node.js

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

Related

How do I prevent npm install from removing packages?

I'm trying to set up a development environment with several packages, and as a result I need to manually install some dependencies. More specifically, I have some local changes in several packages which I need to test before I can push them to github, so I can't just npm install the top level because it won't pick up those change. So I run the first npm install manually on packages which are missing, and then try to run my node code and see which package it is still missing, then try to npm install what it says is missing.
However, when I go to install the second package, it ends up with this message:
added 3 packages from 4 contributors, removed 799 packages and audited 3 packages in 4.197s
The second install removed practically every package that was already installed! I didn't notice this until about the third time, when I realized that I seemed to be installing the same thing over and over.
However can I prevent this particularly naughty behavior and force npm to only install what I tell it to and leave everything else alone?
Have a look at npm link if you need to test against modified packages.
From npm link:
This is handy for installing your own stuff, so that you can work on it and test it iteratively without having to continually rebuild.
Say b is a dependency of a. You made changes to b and want to check if a still works with those changes. Instead of using b in node_modules installed from npm, use your local, modified version:
cd ~/projects/b # go into the package directory
npm link # creates global link
cd ~/projects/a # go into some other package directory.
npm link b # link-install the package
Now, any changes to ~/projects/b will be reflected in ~/projects/a/node_modules/b/.
If your development flow involves updating in parallel packages which depend on one another, you might consider switching your project's package manager to from npm to yarn to take advantage of yarn's workspaces feature.
Yarns's workspaces allow you to easily setup a single monorepo containing all your interconnected dependencies, and let yarn thinking how to link them together in your dev environment.
i had a similar problem today , & thought this might help someone in the future and l have found out that if you install simultaneouly it
npm install --save package1 package2 package3 ...
it worked as l had
npm install xlsx angular-oauth2-oidc
but if you install separately it will have issues
Edit 2 More infor by #Michael
installing multiple packages in the same command also prevents hooks from being installed multiple times
Remove "package-lock.json" file befor installing the new package.
Are you saving the dependencies to package.json?
To Save : npm install --save {package_name}. This will save the package to package.json and install using npm install.
You can't particularly control the dependencies(fully). The dependencies which you have installed might be using dependencies themselves.So when you remove a package, npm deletes all the package's dependencies and the package.

npm install command - please explain

I am starting to learn React Native and I am very new to npm package manager. I read that npm can install packages localy or globaly but I am trying to understand what does that mean.
I am reading this page https://docs.npmjs.com/getting-started/installing-npm-packages-locally, can someone explain to me what does this mean please.
If you want to depend on the package from your own module using something like Node.js' require, then you want to install locally, which is npm install's default behavior. On the other hand, if you want to use it as a command line tool, something like the grunt CLI, then you want to install it globally.
Since I am very new to npm, React Native, Node (never used it), I am confused by the very first sentence in this quote. What does it mean "my own module?
If I want to use CRNA, I guess, I would have to install it globally?
If I am to install a package, say CRNA locally or globally, where do I see it installed on my MacBook Pro?
The difference between local and global install is that local install puts it into the node_modules directory of your project (this is what is referred to as "your own module") while global puts it into a system directory (the exact location depends on your OS, on OSX it should be /usr/local/lib/node_modules).
Basically:
Local install ties the installed module to your project: other projects on your computer do not get it but if your project is copied to another computer the module will be installed there too
global install ties it to your computer: you can use it on all of
your projects on your computer but if your project is copied to
another computer the installed module will not be there
And yes, CRNA should be installed globally as it is a general tool not a project's library dependence.
When you install package globally npm install -g <package name> modules drops in {prefix}/lib/node_modules.
Locally - npm install <package name> - drops package in the current working directory.
If you are going to require module in your project you have to install it locally.
If you want to run in from command line you need to install it globally.
If you need more extenden explanation take a look
Since I am very new to npm, React Native, Node (never used it), I am confused by the very first sentence in this quote. What does it mean "my own module?
If you have package.json file, then everything in the same folder is treated as "module". You add dependencies to it by doing npm install --save foo (--save option adds it under dependencies in your package.json).
If I want to use CRNA, I guess, I would have to install it globally?
Not sure what "CRNA" is. But general rule is that mostly everything (libraries...) are installed locally. Which means that they are added to your package.json and installed in same folder under node_modules.
Only case when you want to install something globally (can be added to package.json but is NOT installed in the same folder under node_modules but probably in your home directory), by doing npm install --global bar (--global installs it globally). Is when tool (not library) is project independent, as you can access it from everywhere. Something like create-react-app.
TLDR:
Local are dependencies (libraries) installed in same folder and (usually) added in your package.json as dependencie.
Global are tools installed in your user home folder and (usually) NOT added in your package.json as dependencie.
Let first start with how nodejs finds package.
Suppose you have some folder structure like-
root
-pixel
-project1
-project2
So, if your are working on project1 and required some npm package, nodejs tries to find a folder named node_modules in current directory. If fails, it goes parent(pixel folder) and tries to find node_modules and goes recursively upto root(which is global).
So, if there any package installed globally, you don't need to install it in your current working directory.
So, why don't we install all packages globally? Isn't it saves our harddisk memory?
Yes, true. But as npm packages are updating and changing its version everytime, its necessary to use specific package in your current working package to avoid collusion.
Then how global packages is useful?
Its good idea to install some cli packages to run directly from command line i.e webpack to easy our task.

Building on Heroku -avoiding global dependencies

According to Heroku I should avoid global dependencies when asking Heroku to build my project. But I still want Bower and Grunt on the command line.
My question is: how then should I be running these tools?
Rather than installing them with npm install -g, should I be adding paths from node_modules to PATH, or the like? (Ubuntu)
If Grunt/Bower are installed globally on development machines -say when someone new starts on the project -then presumably npm install -g grunt-cli might give a different Grunt version to what's in package.json. Hence what Heroku runs and what developers run might accidentally differ.
(Or is that unlikely to be a problem?)
The best practice is to keep everything local, with npm install --save.
That way you can align versions for everyone in the team simply by tweaking the package.json file.
If you only need Bower and Grunt etc. to be available in your dev environments, then install them with npm install --save-dev. This will cause them to be saved in a devDependencies section in your package.json. Dependencies referenced therein will not get distributed to production (e.g. Heroku), but will be available in all your dev environments.
If you really do need Bower and Grunt etc. to be available on Heroku, then install them with npm install --save.
At any rate, npm should automatically save symbolic links to your executables (e.g. grunt-cli) in directory node_modules/.bin, and should take care of adding node_modules/.bin to your PATH, so you don't have to worry about that.

Can't you install socket.io as a global package?

I tried to install socket.io with the -g switch
npm install -g socket.io
and it installed correctly I think.
but running the app it throws the cannot find module error.
Local install, i.e. if socket.io is present in node_modules in my project/package, works though.
So can't it be installed globally?
You misunderstood the meaning of global installation. It allows you to access packages directly from your console. But if you want to require package into your own application, you should add it as a dependency into your packaje.json and install it locally.
Here is the quotation from npm documentation:
Install it locally if you're going to require() it.
Install it globally if you're going to run it on the command line.
When you install a package globally, what you're saying is that you want to use it in your shell (cmd.exe). Something like nodemon is such a package that you would install globally but not include locally as it doesn't need to be included for your app to run, but instead is used to benefit you as the developer.
You install packages without the -g switch when it is necessary for your app to run. In this case it is necessary for socket.io to be installed. Note that locally installed packages should go into your packages.json file so that anyone who installs your app at a later date automatically gets the included packages. Global packages do not appear here.

How to install multiple versions of the same node.js module?

Can I install multiple versions of the same node module globally with npm?
I don't think there is a (good) way to do this.
However, I'm guessing that your use case is this: You have two projects, which require different versions of a globally installed package.
For cases like this, I usually avoid installing packages globally altogether, and install them locally instead (without -g). For example, if you wanted to install a specific older version of the "mocha" package for a given project, you'd do
cd ~/src/myproject
npm install --save-dev mocha#^1.0.0
(Note that we're not using -g here.) Then call it like so:
./node_modules/.bin/mocha
While it is possible, it's probably going to be difficult to maintain without writing your own scripts to manage it. For this, I'm going to assume that you are using MacOS or Linux, and you have node installed in /usr/local/bin
When you install a global module, npm places the module and its dependencies in the same location that node is installed. Usually /usr/local/lib/node_modules, then creates a symbolic link for that module's in /usr/local/bin.
For example, you want to install nodemon, so you run npm install -g nodemon. npm installs nodemon to /usr/local/lib/node_modules/nodemon and creates a symlink at /usr/local/bin/nodemon that points to /usr/local/lib/node_modules/nodemon/bin/nodemon.js
Lets assume that you just installed nodemon#1.8.1, but for some reason you also need nodemon#1.7.3.
To have them both installed at once, but not conflict, you may be able to:
rename the directory for your existing copy of nodemon from nodemon to nodemon18
create a new nodemon18 symlink using ln -s /usr/local/bin/nodemon18 /usr/local/lib/node_modules/nodemon/bin/nodemon.js (don't forget to make it executable)
install nodemon#1.7.3 via npm install -g nodemon#1.7.3
Now, running nodemon from your terminal will run nodemon#1.7.3 and running nodemon18 will run nodemon#1.8.1.
YMMV. I really don't recommend doing this.
Not currently.
(Related: You can install multiple versions of node using with NVM (Node Version Manager): https://github.com/creationix/nvm)

Resources