Difference between ~/.npm, $PROJECT/node_modules, and /usr/lib/node_modules? - node.js

I installed npm and when I did my first sudo npm install some-package -g it installed that package to /usr/lib/node_modules as I expected, but then it also created several files in ~/.npm. What's the difference between these locations?
Other answers here have said that a global installation using -g should install it to your home directory by default, but for me it installs it to /usr/lib/node_modules, am I doing something wrong?
And when I do a local installation without -g it installs to the current directory $PROJECT/node_modules. What's the difference between all these locations, and what should go where?

The system wide package install directory, typically under /usr/lib is usually used for globally installed packages that provide a binary which should be available in your PATH (to be able to execute it from anywhere).
The local install directory node_modules, created by npm install at the location where you're executing npm, is typically located in your project directory and usually used for project specific dependencies.
The ~/.npm contains packages already downloaded. When installing the same package in another location, npm will lookup that package in that cache directory first.
Reference: https://docs.npmjs.com/files/folders
Related files:
.npmrc - NPM configurations at different locations
package.json - Packages and their versions for a project
Hypothetical scenario: two projects using Grunt (a Javascript based buildscripting tool):
Both projects use different Grunt versions. One project is older. Grunt can't be updated without having to adapt the whole build process, another project has just started.
You have to install "grunt-cli" system wide (using the -g flag) since it provides the grunt binary. This CLI binary will lookup for a local "grunt" in your current project directory. The "grunt" npm on the other hand, installed locally (without -g) will then be bootstrapped by the CLI. When downloading grunt for the first project npm will store downloaded packages in ~/.npm, when installing grunt for the second project, npm will lookup packages common to both projects in ~/.npm first.
There are other reasons to install packages globally, the most time they provide a binary that should be located in your PATH.
Alternatively, some packages that typically need to be installed globally can also be installed locally. You'll then have to add the path to that binary (e.g. path/to/your/node_modules/.bin/<BINARY>) to your PATH variable or just specify the full execution path.

Related

Install npm global from a local directory with dependencies

There's a public tool (csso-cli) that can be installed with npm install -g csso-cli to be available globally. Now I need to make a modification to it and change one of its dependencies (csso) to a newer version to use the latest features. So I cloned the repository and installed that with npm install -g ./. It did copy that local code directory to my global npm installation location, but none of the required dependencies were added. There simply isn't a node_modules subdirectory in the install location.
How can I properly install an npm package from a local directory, including all external dependencies, as if it were installed from a public repository? Maybe I need to create some sort of package file first and install that? I don't know much about npm. I searched the web but couldn't find anything. (All instructions are missing the dependencies.) I've read the npm documentation but am still no wiser. That topic isn't covered here, still only incomplete installations without dependencies seem possible. Who needs that?
Looks like I needed the npm pack command. It creates an archive of the package from the local directory. When installing that file with npm install -g my-package-1.0.0.tgz all dependencies are properly installed as well. Plus, the package file doesn't contain the git files.

Is it possible to install global node packages offline?

I need to be able to install the carto module on an offline server. Is there a way that I could package up carto with all of its dependencies, and install it on a server that has no connection to the internet.
The server won't have an initial connection, and will have npm and node installed from a .deb archive.
I've tried using npm-offline, as well as npm-offline-packer. These both require that I have an npm registry or a node project.
I'm hoping to have a start script that can run the required commands and get all packages installed. So far, I'm able to install all ubuntu software, just stuck on node.
An alternative would be installing it in another machine and copying the package(s) you want inside npm's global node_modules.
npm config get prefix
Gets the path to where it is installed. node_modules are usually under lib/ folder. Module executables could be located under bin/. Having both should be enough to use your global module in another machine.
Since you're looking for a start script the steps you need are:
Getting npm prefix via npm config get prefix
Go to that path
Copy executables you want under bin/ i.e. carto#
Copy content you want from lib/node_modules i.e. lib/node_modules/carto
Apply to the machine you want using the same steps described here

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.

Locally installed versus globally installed NPM modules

In my package.json file, I have bower listed as a dependency. After I run npm install, bower gets installed locally. When I try to run bower after installing it locally I get an error
"bower" is not recognized as an internal or external command
It seems the only way to resolve this is to install bower globally. Why should I have to do this? If my project contains a local copy of bower, why won't node use it?
Installing locally makes bower available to the current project (where it stores all of the node modules in node_modules). This is usually only good for using a module like so var module = require('module'); It will not be available as a command that the shell can resolve until you install it globally npm install -g module where npm will install it in a place where your path variable will resolve this command.
Edit: This documentation explains it pretty thorougly.
You can execute your local instance by typing the line below in cmd:
node_modules/bower/bin/bower <bower args>
We use both PHP and JavaScript, so we have composer and npm.
Each of the projects we work on have different packages both for runtime of the package as well as build/dev tools.
As there are version constraints in each project, installing version x of a package globally (that would be run from the command line), would cause us issues, we install all the tooling in each package. Much easier to define in the appropriate composer.json / package.json files.
But running the CLI tools is a pain if you have to constantly add an additional path to the command.
To that end, we have recommend to the team that the following paths are added to your $PATH in the appropriate .bashrc (or equivalent):
./vendor/bin:./node_modules/.bin
(EDIT: For Windows, the paths would be .\vendor\bin;.\node_modules\.bin;)
So, whilst in project X, we have access to the CLI tools for that project. Switch to project Y, and we get that projects tools.
Sure, you are going to get duplications, but each project is maintained by different teams (and some people are in multiple teams), so again, having 1 version in the global setup is an issue there.
Usually you install NPM modules globally if you want them included in your path to be ran from the command line. Since it is installed locally you will have to run it from the node_modules folder.

What does "npm install -g" do?

I am trying to install Less from NPM by running npm install -g less in the command line. I checked the docs for the install command:
In global mode (ie, with -g or --global appended to the command), it
installs the current package context (ie, the current working
directory) as a global package.
What does it mean by "global package"?
You are not required to install Less globally.
Installing it locally means the module will be available only for a specific project (the directory you were in when you ran npm install), as it installs to the local node_modules folder.
A global install will instead put the module into your global package folder (OS dependent), and allows you to run the included executable commands from anywhere. Note that by default you can only require local packages in your code.
See the node.js docs for more info on global vs local packages.
Generally speaking, you should install most modules locally, unless they provide a CLI command that you want to use anywhere.
In the end, I suggest you install less globally, as less provides an executable command that you will likely need in different projects. This is also what the Less docs recommend.
From: https://nodejs.org/en/blog/npm/npm-1-0-global-vs-local-installation/
There are two ways to install npm packages:
globally —- This drops modules in {prefix}/lib/node_modules, and puts executable files in {prefix}/bin, where {prefix} is usually something like /usr/local. It also installs man pages in {prefix}/share/man, if they’re supplied.
locally —- This installs your package in the current working directory. Node modules go in ./node_modules, executables go in ./node_modules/.bin/, and man pages aren’t installed at all.
It simply means that the package you are installing while be available/integrated throughout your Nodejs platform.

Resources