Clarification of the --save option for npm install - node.js

First experiences with node.js/npm. From the npm-install docs I read:
npm install takes 3 exclusive, optional flags which save or update the package version in your main package.json:
--save: Package will appear in your dependencies.
--save-dev: Package will appear in your devDependencies.
--save-optional: Package will appear in your optionalDependencies.
But I can't understand how it works in practice. If, for example, I run the command:
npm install bower --save-dev
I'd expect to find a package.json file in the current directory with devDependencies set to the installed version of bower, instead I find nothing.
Am I doing/expecting something wrong?
Using node v0.10.21, npm 1.3.12 on Ubuntu 12.04 x64

npm won't create package.json for you, but it will create the necessary dependencies for you as long as package.json exists and is legal JSON.
Create it like so
echo {} > package.json
Then, doing npm i --save whatever will add whatever#~x.x.x as a dependency as expected. The file needs to be there, and be JSON, that's it.

npm install only fetches the packages from the registry and puts them in your ./node_modules. It updates your package.json to register this new dependency if you tell it to.
Your package.json has three dependency blocks :
dependencies - these are needed for your app to run.
devDependencies - these are needed for the developer environments for your app (this is how your teammates can get the packages that you recently added to the project. The dependencies listed here are not required on production hosts.)
optionalDependencies - These packages are optional and it is OK if npm cant reolve the package to install. i.e a build failure does not cause npm install to fail (Note however, that your app should handle cases where the package cannot be found.)
Here is the behavior with the different usages of the npm install command:
$ npm install async #Only installs, no change made to package.json
$ npm install async --save #Installs, adds async#version to dependencies block
$ npm install async --save-dev # Installs, adds async#version to the devDependencies block
$ npm install async --save-optional # Installs, adds async#version to the optionalDependencies block

Related

Does npm install exclude dev dependencies?

When I am in a Node.js project and run npm install, npm installs both, dependencies and dev dependencies. If I do not want to install the dev dependencies, I can run npm install --production.
Question 1: If I do not provide --production: Are the dependencies' dev dependencies installed, too, or only their actual dependencies?
Now, what if I am in a Node.js project and install a new dependency, something such as:
npm install foo
This installs foo's dependencies, of course.
Question 2: But what about its dev dependencies? Are they installed, too, or are they skipped?
Answers to your questions:
Yes dev dependencies will be installed in npm install only way it wont install dev dependencies is when NODE_ENV is set to production
No dev dependencies of your external modules won't be installed see here
When you run npm install by default both dependencies and devDependency dependencies are also installed. Because if once is going to develop a package, we would download it e.g. from git and go to root folder and run.
npm install
so you would expect to have devDependencies to.
npm install "$package"
doesn't install the devDependencies by default. But if you really want to install development packages in that case, you can set the dev config option to true:
npm install "$package" --dev
Node applications use multiple methods to maintain dependency versioning up to date but there are multiple dependency types that need to be considered. Dependencies are found in a node application's root directory within the package.json file. I will go through the different dependency types and list some defining features or characteristics:
Dependencies:
These are specified in a simple object that maps a package name to a version range. The version range is a string which has one or more space-separated descriptors. Dependencies can also be identified with a tarball or git URL.
npm install from a directory that contains package.json
npm install $package on any other directory
dependencies are required to run
Installed transitively: if A requires B, and B requires C. then C gets installed, otherwise B could not work, and neither would A.
devDependencies:
If someone is planning on downloading and using module in their program, then they probably don't want or need to download and build the external test or documentation framework that you use. In this case it's best to map these additional items in a devDependencies object, which is not installed when the user is installing the package unless specifically passing in --dev. These are typically installed when doing a traditional npm install from the root of the package.
npm install on a directory that contains package.json, unless the developer passes the --production flag.
not installed on npm install "$package" on any other directory, unless you give it the --dev option
Are not installed transitively
Other Dependency types:
These are less commonly used but may serve a purpose.
peerDependencies
optionalDependencies

npm install fails because package is missing in registry

I have an issue with a project where we are using node and brunch. The issue is current specific to brunch, but could occur for any module would be my guess.
The easiest way to currently reproduce this, is to do the following in a new folder:
npm init
npm install --save-dev brunch
The issue here is that brunch depends on loggy, which in turn depends on ansi-color, which no longer has an entry in the npmregistry:
https://registry.npmjs.org/ansi-color
I think this might be the github project: https://github.com/loopj/commonjs-ansi-color
In any case, I am unable to proceed, and all our builds fail because they are not able to fetch the given dependency.
I could perhaps use npm shrinkwrap in some way, but that depends on the modules already existing in node_modules, which I am currently missing.
So how can I force npm to use ansi-color from a different location, or ignore the dependency?
Not sure about npm 2 but you can fix this with beta npm 3. npm 3 has flat node_modules directory. So sub modules can sit in the top level. Read the Changelog.
The missing modules can be installed directly from their Github repo as a toplevel dependency in your project. If npm finds the module with the same version in node_modules directory, it won't look for it anymore in the registry.
Install npm 3:
npm install -g npm#3-latest
Then install depencies:
//install missing module from other location
npm install https://github.com/loopj/commonjs-ansi-color.git --save-dev
npm install --save-dev brunch
It looks like ansi-color is back on the npm registry ("https://registry.npmjs.org/ansi-color" is back online)

What does -save-dev mean in npm install grunt --save-dev

I've just started using Grunt.js. It is pretty hard to set up and I am at the point of creating a package.json file.
Following this tutorial, it says there are 3 ways to create a package.json file.
The first is to do npm install grunt --save-dev
But what does --save-dev means? I tried looking but it ends in vain.
--save-dev: Package will appear in your devDependencies.
According to the npm install docs.
If someone is planning on downloading and using your module in their program, then they probably don't want or need to download and build the external test or documentation framework that you use.
In other words, when you run npm install, your project's devDependencies will be installed, but the devDependencies for any packages that your app depends on will not be installed; further, other apps having your app as a dependency need not install your devDependencies. Such modules should only be needed when developing the app (eg grunt, mocha etc).
According to the package.json docs
Edit: Attempt at visualising what npm install does:
yourproject
dependency installed
dependency installed
dependency installed
devDependency NOT installed
devDependency NOT installed
devDependency installed
dependency installed
devDependency NOT installed
There are (at least) two types of package dependencies you can indicate in your package.json files:
Those packages that are required in order to use your module are listed under the "dependencies" property. Using npm you can add those dependencies to your package.json file this way:
npm install --save packageName
Those packages required in order to help develop your module are listed under the "devDependencies" property. These packages are not necessary for others to use the module, but if they want to help develop the module, these packages will be needed. Using npm you can add those devDependencies to your package.json file this way:
npm install --save-dev packageName
To add on to Andreas' answer, you can install only the dependencies by using:
npm install --production
When you use the parameter "--save" your dependency will go inside the #1 below in package.json. When you use the parameter "--save-dev" your dependency will go inside the #2 below in package.json.
#1. "dependencies": these packages are required by your application in production.
#2. "devDependencies": these packages are only needed for development and testing
Documentation from npm for npm install <package-name> --save and npm install <package-name> --save-dev can be found here:
https://docs.npmjs.com/getting-started/using-a-package.json#the-save-and-save-dev-install-flags
A package.json file declares metadata about the module you are developing. Both aforementioned commands modify this package.json file. --save will declare the installed package (in this case, grunt) as a dependency for your module; --save-dev will declare it as a dependency for development of your module.
Ask yourself: will the installed package be required for use of my module, or will it only be required for developing it?
For me the first answer appears a bit confusing, so to make it short and clean:
npm install <package_name> saves any specified packages into dependencies by default. Additionally, you can control where and how they get saved with some additional flags:
npm install <package_name> --no-save Prevents saving to dependencies.
npm install <package_name> ---save-dev updates the devDependencies in your package. These are only used for local testing and development.
You can read more at in the dcu
–save
The package installed is core dependency.
–save-dev
The package installed is not a core rather development dependency.
Use only when developing
--save-dev means omit in production environments, use only in development environments (smaller, and probably faster).

How generate nodejs express dependencies package.json

As I started to develop my first nodejs express application, I added many packages with npm.
I would like to know if there is a way to generate a package.json file containing all the current dependencies or the list of the current packages under the nodes_modules directory.
Just run npm init in the same directory as your project.
You'll be asked a list of questions (name, version, description, etc.) and once complete, it will generate a package.json file with all of the dependencies as currently installed in the node_modules directory.
Run npm list to see what you have installed. Run npm shrinkwrap to build a npm-shrinkwrap.json file, which you can use as a starting reference to build a proper package.json. My workflow is always to update package.json and then run npm install. I never run npm install foo to get some package because it creates risk of forgetting to add it to package.json and then having your application fail to start on deployment.
Updated to add: These days I do run npm install --save foo or npm install --save-dev foo since I have now decided the ~0.4.3 version numbers it adds to package.json are better than my former preference for 0.4.x since the ~ gives you a more precise minimum version number.

How do you prevent install of "devDependencies" NPM modules for Node.js (package.json)?

I have this in my package.json file (shortened version):
{
"name": "a-module",
"version": "0.0.1",
"dependencies": {
"coffee-script": ">= 1.1.3"
},
"devDependencies": {
"stylus": ">= 0.17.0"
}
}
I am using NPM version 1.1.1 on Mac 10.6.8.
When I run the following command from the project root, it installs both the dependencies and devDependencies:
npm install
I was under the impression that this command installed the devDependencies:
npm install --dev
How do I make it so npm install only installs dependencies (so production environment only gets those modules), while something like npm install --dev installs both dependencies and devDependencies?
The npm install command will install the devDependencies along other dependencies when run inside a package directory, in a development environment (the default).
In version 8.x and above use --omit=dev flag to install only regular dependencies:
npm install --omit=dev
This will install only dependencies, and not devDependencies, regardless of the value of the NODE_ENV environment variable.
If you use 6.x or an earlier version, you need to use the --only=prod flag instead.
Note:
Before v3.3.0 of npm (2015-08-13), the option was called --production, i.e.
npm install --production
You may also need --no-optional flag.
I run into that problem too! npm install is somewhat confusing and web posts keep bringing in the -d/--dev flags as if there is an explicit 'development' install mode.
npm install will install both "dependencies" and "devDependencies"
npm install --production will only install "dependencies"
npm install --dev will only install "devDependencies"
The new option is:
npm install --only=prod
If you want to install only devDependencies:
npm install --only=dev
If you have already installed all your dependencies, and you want to avoid having to download your production packages from NPM again, you can simply type:
npm prune --production
This will remove your dev dependencies from your node_modules folder, which is helpful if you're trying to automate a two step process like
Webpack my project, using dev dependencies
Build a Docker image using only production modules
Running npm prune in between will save you from having to reinstall everything!
If you read this POST in 2016, please achieve what you want by using
--only={prod[uction]|dev[elopment]}
argument will cause either only devDependencies or only non-devDependencies to be installed regardless of the NODE_ENV.
from: https://docs.npmjs.com/cli/install
When using "npm install" the modules are loaded and available throughout your application regardless of if they are "devDependencies" or "dependencies". Sum of this idea: everything which your package.json defines as a dependency (any type) gets installed to node_modules.
The purpose for the difference between dependencies/devDependencies/optionalDependencies is what consumers of your code can do w/ npm to install these resources.
Per the documentation: https://npmjs.org/doc/json.html...
If someone is planning on downloading and using your module in their
program, then they probably don't want or need to download and build
the external test or documentation framework that you use.
In this case, it's best to list these additional items in a
devDependencies hash.
These things will be installed whenever the --dev configuration flag
is set. This flag is set automatically when doing npm link or when
doing npm install from the root of a package, and can be managed like
any other npm configuration param. See config(1) for more on the
topic.
However, to resolve this question, if you want to ONLY install the "dependencies" using npm, the following command is:
npm install --production
This can be confirmed by looking at the Git commit which added this filter (along with some other filters [listed below] to provide this functionality).
Alternative filters which can be used by npm:
--save => updates dependencies entries in the {{{json}}} file
--force => force fetching remote entries if they exist on disk
--force-latest => force latest version on conflict
--production => do NOT install project devDependencies
--no-color => do not print colors
#dmarr try using npm install --production
npm will install dev dependencies when installing from inside a package (if there is a package.json in the current directory). If it is from another location (npm registry, git repo, different location on the filesystem) it only installs the dependencies.
I suggest to use npm ci. If you want to install only production-needed packages (as you wrote - without devDependencies) then:
npm ci --only=production
or
NODE_ENV=production npm ci
If you prefer oldschool npm install then:
npm install --production
or
NODE_ENV=production npm install
Here is good answer why you should use npm ci.
It's worth mentioning that you can use the NODE_ENV environment variable to achieve the same result. Particularly useful if you're containerizing your Node application (e.g. Docker).
NODE_ENV=production npm install
The above code will install all your dependencies but the dev ones (i.e. devDependencies).
if you need to use environment variables in your Dockerfile more information can be found here.
Environment variables are easy to overwrite whenever needed (e.g. if you want to run your test suite say on Travis CI). If that were the case you could do something like this:
docker run -v $(pwd):/usr/src/app --rm -it -e NODE_ENV=production node:8 npm install
NPM Documentation here
production
Default: false
Type: Boolean
Set to true to run in "production" mode.
devDependencies are not installed at the topmost level when running local npm install without any arguments.
Set the NODE_ENV="production" for lifecycle scripts.
Happy containerization =)
npm install --production --no-optional
It installs only deps from dependencies and will ignore optionalDependencies and devDependencies
Use npm install packageName --save this will add package in dependencies, if you use npm install packageName --save-dev then it devDependencies.
npm install packageName --save-dev should be used for adding packages for development purpose. Like adding TDD packages (Chai, mocha, etc). Which are used in development and not in production.
I have found that, when trying to install dev dependencies for a package that contains a node addon, you cannot avoid building the addon when running npm install --dev even if you just want to install the devDependencies. So, I had to go around npm's back:
node -e 'console.log( Object.keys( require( "./package.json" ).devDependencies ) );' | \
sed -e "s/^[^']*'//" -e "s/'.*$//" | \
xargs npm install
Or, better (and more succinctly) yet,
node -e 'Object.keys( require( "./package.json" ).devDependencies )
.map( function( item ){ console.log( item ) } );' | xargs npm install
I ran into a problem in the docker node:current-slim (running npm 7.0.9) where npm install appeared to ignore --production, --only=prod and --only=production. I found two work-arounds:
use ci instead (RUN npm ci --only=production) which requires an up-to-date package-lock.json
before npm install, brutally edit the package.json with:
RUN node -e 'const fs = require("fs"); const pkg = JSON.parse(fs.readFileSync("./package.json", "utf-8")); delete pkg.devDependencies; fs.writeFileSync("./package.json", JSON.stringify(pkg), "utf-8");'
This won't edit your working package.json, just the one copied to the docker container.
Of course, this shouldn't be necessary, but if it is (as it was for me), there's your hack.
Need to add to chosen answer: As of now, npm install in a package directory (containing package.json) will install devDependencies, whereas npm install -g will not install them.
npm install --production is the right way of installing node modules which are required for production. Check the documentation for more details
Now there is a problem, if you have package-lock.json with npm 5+. You have to remove it before use of npm install --production.

Resources