Exclude dev dependencies when publishing npm package - node.js

So I'm in the process of publishing a package to npm. It is basically just a simple module that lets users make Ajax calls and can be configured in a few ways.
I have read that it is a good idea to test the install locally and tried that. I have packed the package via the "npm pack" command, change into another directory and then tried installing the packge via "npm install path-to-file-that-was-just-created.tgz".
So far everything works, I have a node_modules folder, that contains my bundled code.
However, is also has installed all the dependencies that I have listed as devDependencies in the package.json of my actual module, even though the only the bundled file is needed and no other depenedencies are defined.
I have tried updating the npm-shrinkwrap.json, and checked that every dependency has the dev property marked as true.
The goal is actually for the user to install this module and then have no dependencies installed, because they do not need babel or mocha, to run the module.
How can I exclude these from the packge?
Thanks!

https://docs.npmjs.com/cli/install
use the --production flag to avoid installing dev dependencies
For published modules, you don't need to do anything, when a user installs your library, only the non-dev dependencies will be installed

If you want your published module to have no dependencies but you still need to have some to build it you can also try to use this command before publishing:
npx json -f package.json -I -e "delete this.devDependencies"
This way only works in CI/CD.
Update: it turned out that npm pkg delete devDependencies does the same without any additional dependency

After running your install, you can prune dev dependencies by running this command:
npm prune --production
this will keep only production dependencies. Documentation from npm here:
If the --production flag is specified or the NODE_ENV environment
variable is set to production, this command will remove the packages
specified in your devDependencies

Related

Whenever I try to run my server via Heroku I get "Error: Cannot find module 'dotenv'"

Browsing stack overflow, I noticed that a common fix is make sure that dotenv is in dependencies and not just devDependencies. Here's a screenshot of the log and the package.json. You'll notice that dotenv is indeed in my dependencies. I also deleted and reinstalled node_modules multiple times but still no luck.
I am requiring the dotenv at the top of my server file as shown here
I fixed the issue. I decided to try uninstalling dotenv and reinstalling, this worked. Apparently, this was different from deleting node modules and npm install.
I see dotenv is added to a devDependency: devDependency are special and are only installed when you do a npm install on the package.json which contains them. Usually, you'll add your development tooling (like test runners, etc.) in devDependencies since they are not required for the application to run.
When we run an application in production, we install dependencies using npm install --production which only installs the dependencies mentioned in the dependencies section of package.json. This is also what Heroku does for you (check their buildpack for Node.js!)
To install a devDependency, you would do: npm i -D <package name>; and to install a production dependency (like your web framework like express), you'd do npm i -S express.
Try running npm i -D dotenv and check if it works (it may also work if you just do a npm i dotenv.

Cannot start npm/yarn

I decided to create React app under Linux and I've used those commands:
npm install -g create-react-app
create-react-app my_app_name
npm start
At this point I've recieved message:
There might be a problem with the project dependency tree.
It is likely not a bug in Create React App, but something you need to fix locally.
The react-scripts package provided by Create React App requires a dependency:
"webpack": "4.19.1"
Don't try to install it manually: your package manager does it automatically.
However, a different version of webpack was detected higher up in the tree:
/home/ktw/node_modules/webpack (version: 4.24.0)
Manually installing incompatible versions is known to cause hard-to-debug issues.
If prefer to ignore this check, add SKIP_PREFLIGHT_CHECK=true to an .env file in your project.
That will permanently disable this message but you might encounter other issues.
To fix the dependency tree, try following the steps below in the exact order:
1. Delete package-lock.json (not package.json!) and/or yarn.lock in your project folder.
2. Delete node_modules in your project folder.
3. Remove "webpack" from dependencies and/or devDependencies in the package.json file in your project folder.
4. Run npm install or yarn, depending on the package manager you use.
In most cases, this should be enough to fix the problem.
If this has not helped, there are a few other things you can try:
5. If you used npm, install yarn (http://yarnpkg.com/) and repeat the above steps with it instead.
This may help because npm has known issues with package hoisting which may get resolved in future versions.
6. Check if /home/ktw/node_modules/webpack is outside your project directory.
For example, you might have accidentally installed something in your home folder.
7. Try running npm ls webpack in your project folder.
This will tell you which other package (apart from the expected react-scripts) installed webpack.
I've done literally every step from this list but unfortunately - with no results.
I've already tried:
chown -R user: node_modules,
npm cache clean --force,
rm -rf node_modules && rm ./package-lock.json && npm install
and I have no idea what is going on.
Do you guys have any idea how to fix that?
It looks like you may have forgotten to do Step #3: Remove "webpack" from dependencies and/or devDependencies in the package.json file in your project folder.
If you are doing the steps as you outline above, when you do npm install again, because Webpack is still in your package.json, it'll reinstall and continue the issue.

Why is npm running prepare script after npm install, and how can I stop it?

Whenever I run npm install <package> it installs the package alright, but then it automatically runs the prepare script.
It's worth mentioning that I've already checked that there is no postinstall script in the package.json.
From https://docs.npmjs.com/misc/scripts:
prepare: Run both BEFORE the package is packed and published, and on
local npm install without any arguments (See below). This is run AFTER
prepublish, but BEFORE prepublishOnly.
Since NPM v5, prepare script is executed when you run npm install
The other answers are fine, but for some additional context, this is to support a workflow where you can use devDependencies to build assets or other generated content for your project.
For example, say you want to use node-sass (CSS preprocessor). You add "node-sass" as a devDependency, then you run the sass command in your "prepare" script, which generates your CSS.
So, when you run npm install, the following happens:
dependencies and devDependencies get installed
your "prepare" script generates your CSS
your project is ready to go with all necessary CSS
And when you run npm publish, something similar happens:
your "prepare" script generates your CSS
your code and generated CSS are published to the npm repo
So now when someone comes along and installs your package, they don't need node-sass or any of your devDependencies. They only need to runtime deps.
The prepare script runs on local install and when installing git dependencies:
prepare: Run both BEFORE the package is packed and published, on local npm install without any arguments, and when installing git dependencies (See below). This is run AFTER prepublish, but BEFORE prepublishOnly.
https://docs.npmjs.com/misc/scripts
You can avoid it with the --ignore-scripts flag:
$ npm install <package> --ignore-scripts
source: https://docs.npmjs.com/cli/install
From the doc https://docs.npmjs.com/misc/scripts
prepare: Run both BEFORE the package is packed and published, and on local npm install without any arguments (See below). This is run AFTER prepublish, but BEFORE prepublishOnly.
prepare script run before publishing and after npm install.
Now if you make an npm install and one of the packages has a prepare script, like for building, and it fails the whole install will fail.
We have two options:
Ignore scripts
npm install --ignore-scripts
That will run the ignore to all packages, which might be not the desired behavior. Imagine a third party package that needs to run prepare and build. If you run with --ignore-scripts this will get skipped.
Make the script optional (better option)
Add a package to the optionalDependencies:
{
optionalDependencies: {
"myPackage": "^1.0.0"
}
}
If a dependency can be used, but you would like npm to proceed if it cannot be found or fails to install, then you may put it in the optionalDependencies object. This is a map of package name to version or url, just like the dependencies object. The difference is that build failures do not cause installation to fail.
Entries in optionalDependencies will override entries of the same name in dependencies, so it's usually best to only put in one place.
Check the doc:
https://docs.npmjs.com/cli/v7/configuring-npm/package-json#optionaldependencies
Note: With this, only the chosen package is concerned. And if it fails the installation will continue. That's usually what you want.
Go with optionalDependencies
As per this answer in this thread:
https://github.com/npm/npm/issues/2817#issuecomment-368661749
the problem with --ignore-scripts is that is ignores all scripts. I just need to be able to ignore a script(s) for a particular package (the one where a build fails to compile on certain platforms). This option usually breaks my code because it has ignored ALL scripts in other packages that actually do need to run.
Anyway, to make this work like the OP I make the offending package optional. Then do a regular install, then a second install with --ignore-scripts. That way I get the scripts of other packages run first before ignoring them all (including the intended) the second time which then "fetches" the source of that package.
It's generally better to go with optionalDependencies. That will most likely suit your needs.

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.

What is the difference between --save and --save-dev?

What is the difference between:
npm install [package_name]
and:
npm install [package_name] --save
and:
npm install [package_name] --save-dev
What does this mean? And what is really the effect of --save and -dev keywords?
The difference between --save and --save-dev may not be immediately noticeable if you have tried them both on your own projects. So here are a few examples...
Let's say you were building an app that used the moment package to parse and display dates. Your app is a scheduler so it really needs this package to run, as in: cannot run without it. In this case you would use
npm install moment --save
This would create a new value in your package.json
"dependencies": {
...
"moment": "^2.17.1"
}
When you are developing, it really helps to use tools such as test suites and may need jasmine-core and karma. In this case you would use
npm install jasmine-core --save-dev
npm install karma --save-dev
This would also create a new value in your package.json
"devDependencies": {
...
"jasmine-core": "^2.5.2",
"karma": "^1.4.1",
}
You do not need the test suite to run the app in its normal state, so it is a --save-dev type dependency, nothing more. You can see how if you do not understand what is really happening, it is a bit hard to imagine.
Taken directly from NPM docs docs#dependencies
Dependencies
Dependencies are specified in a simple object that maps a package name
to a version range. The version range is a string that has one or
more space-separated descriptors. Dependencies can also be identified
with a tarball or git URL.
Please do not put test harnesses or transpilers in your dependencies
object. See devDependencies, below.
Even in the docs, it asks you to use --save-dev for modules such as test harnesses.
--save-dev is used to save the package for development purpose.
Example: unit tests, minification..
--save is used to save the
package required for the application to run.
By default, NPM simply installs a package under node_modules. When you're trying to install dependencies for your app/module, you would need to first install them, and then add them to the dependencies section of your package.json.
--save-dev adds the third-party package to the package's development dependencies. It won't be installed when someone runs npm install directly to install your package. It's typically only installed if someone clones your source repository first and then runs npm install in it.
--save adds the third-party package to the package's dependencies. It will be installed together with the package whenever someone runs npm install package.
Dev dependencies are those dependencies that are only needed for developing the package. That can include test runners, compilers, packagers, etc.
Both types of dependencies are stored in the package's package.json file. --save adds to dependencies, --save-dev adds to devDependencies
npm install documentation can be referred here.
--
Please note that --save is now the default option, since NPM 5. Therefore, it is not explicitly needed anymore. It is possible to run npm install without the --save to achieve the same result.
Let me give you an example,
You are a developer of a very SERIOUS npm library which uses different testing libraries to test the package.
Users download your library and want to use it in their code. Do they need to download your testing libraries as well? Maybe you use jest for testing and they use mocha. Do you want them to install jest as well? Just To run your library?
No. right? That's why they are in devDependencies.
When someone does, npm i yourPackage only the libraries required to RUN your library will be installed. Other libraries you used to bundle your code with or testing and mocking will not be installed because you put them in devDependencies. Pretty neat right?
So, Why do the developers need to expose the devDependancies?
Let's say your package is an open-source package and 100s of people are sending pull requests to your package. Then how they will test the package? They will git clone your repo and when they would do an npm i the dependencies as well as devDependencies.
Because they are not using your package. They are developing the package further, thus, in order to test your package they need to pass the existing test cases as well write new. So, they need to use your devDependencies which contain all the testing/building/mocking libraries that YOU used.
A perfect example of this is:
$ npm install typescript --save-dev
In this case, you'd want to have Typescript (a javascript-parseable coding language) available for development, but once the app is deployed, it is no longer necessary, as all of the code has been transpiled to javascript. As such, it would make no sense to include it in the published app. Indeed, it would only take up space and increase download times.
As suggested by #andreas-hultgren in this answer and according to the npm 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.
However, for webapp development, Yeoman (a scaffolding tool that installs a peer-reviewed, pre-written package.json file amongst other things) places all packages in devDependencies and nothing in dependencies, so it appears that the use of --save-dev is a safe bet in webapp development, at least.
--save-dev saves semver spec into "devDependencies" array in your package descriptor file, --save saves it into "dependencies" instead.
--save-dev is used for modules used in development of the application,not require while running it in production environment
--save is used to add it in package.json and it is required for running of the application.
Example: express,body-parser,lodash,helmet,mysql all these are used while running the application use --save to put in dependencies while mocha,istanbul,chai,sonarqube-scanner all are used during development ,so put those in dev-dependencies .
npm link or npm install will also install the dev-dependency modules along with dependency modules in your project folder
Read Complete And Forget --save-dev Headache
Simplest answer is that --save-dev is useful when you are creating packages for other developers and want to host your package at NPM Registry like lodash, mongoose, express etc. When you are building or writing a Node Server there is no difference between --save and --save-dev because your Node Server implementation is private to you and you will never publish it on NPM.
How NPM Install Works
Whenever we install a new package using npm like npm install express then NPM installs that package to our system and put it into node_modules folder, now NPM will analyze the package.json file of newly installed package i.e express in this case, after analyzing NPM will install all those packages which were mentioned in dependencies section of package.json file of express package. After installing those packages on which express was dependent NPM again analyze the package.json file of all newly installed packages and again install the packages for them, this cycle goes on until all packages are available into node_modules folder to function properly. You can check package dependencies by running npm list in terminal where terminal should point location of your project directory.
How --save-dev Is Related To Above Explained Stuff
Suppose you want to create a new package like express, now while development of this new package you probably want to write some unit testing code and test the package with any other available testing package let's assume mocha in this case. Now you know mocha is only required to test the package not required to use the package. In this case you should install mocha using --save-dev flag, otherwise NPM will install it whenever a developer install your package using NPM. So if we want a dependency not installed when someone install our package from NPM we must install that package using --save-dev in development phase.
Last Thing
Do not mix --save-dev with collaboration development, if someone cloned your package code from a source version control system like github then NPM will surely install all devDependencies i.e package installed using --save-dev also.
Clear answers are already provided. But it's worth mentioning how devDependencies affects installing packages:
By default, npm install will install all modules listed as dependencies in package.json . With the --production flag (or when the NODE_ENV environment variable is set to production ), npm will not install modules listed in devDependencies .
See: https://docs.npmjs.com/cli/install
When you install an npm package using npm install <package-name>, you are installing it as a dependency.
The package is automatically listed in the package.json file, under the dependencies list (as of npm 5: before you had to manually specify --save).
ex. npm install lodash
After pressing enter check your package.json file.
"dependencies": {
"lodash": "4.x",
},
When you add the -D flag, or --save-dev, you are installing it as a development dependency, which adds it to the devDependencies list.
ex. npm install --save-dev lite-server
After pressing enter check your package.json file
"devDependencies": {
"lite-server": "^2.6.1"
},
Development dependencies are intended as development-only packages, that are unneeded in production. For example testing packages, webpack, or Babel.
When you go in production, if you type npm install and the folder contains a package.json file, they are installed, as npm assumes this is a development deploy.
You need to set the --production flag (npm install --production) to avoid installing those development dependencies.
All explanations here are great, but lacking a very important thing: How do you install production dependencies only? (without the development dependencies).
We separate dependencies from devDependencies by using --save or --save-dev.
To install all we use:
npm i
To install only production packages we should use:
npm i --only=production
You generally don't want to bloat production package with things that you only intend to use for Development purposes.
Use --save-dev (or -D) option to separate packages such as Unit Test frameworks (jest, jasmine, mocha, chai, etc.)
Any other packages that your app needs for Production, should be installed using --save (or -S).
npm install --save lodash //prod dependency
npm install -S moment // " "
npm install -S opentracing // " "
npm install -D jest //dev only dependency
npm install --save-dev typescript //dev only dependency
If you open the package.json file then you will see these entries listed under two different sections:
"dependencies": {
"lodash": "4.x",
"moment": "2.x",
"opentracing": "^0.14.1"
},
"devDependencies": {
"jest": "22.x",
"typescript": "^2.8.3"
},
--save-dev (only used in the development, not in production)
--save (production dependencies)
--global or -g (used globally i.e can be used anywhere in our local system)
People use npm on production to do wicked cool stuff, Node.js is an example of this, so you don't want all your dev tools being run.
If you are using gulp (or similar) to create build files to put on your server then it doesn't really matter.
Basically We Write
npm install package_name
But specially for Testing Purpose we don't need to run some package while Application is Running in Normal State so that Node introduce good way to solve this problem. Whenever we write
npm install package_name --save-dev
at that time this package is only installed for development purpose.
I want to add some of my ideas as
I think all differences will appear when someone uses your codes instead of using by yourself
For example, you write an HTTP library called node's request
In your library,
you used lodash to handle string and object, without lodash, your codes cannot run
If someone uses your HTTP library as a part of his code. Your codes will be compiled with his.
your codes need lodash, So you need to put in dependencies to compile
If you write a project like monaco-editor, which is a web editor,
you have bundled all your codes and your product env library using webpack, when build completed, only have a monaco-min.js
So someone doesn't care whether --save or --save-dependencies, only he needs is monaco-min.js
Summary:
If someone wants to compile your codes (use as a library),
put lodash which used by your codes into dependencies
If someone want to add more feature to your codes, he needs unit test and compiler, put these into dev-dependencies
as --save is default option for npm, so I use
npm i package
and for --save-dev, I use
npm i package -D
default option will install package as project dependency where as -D is for development dependencies like testing, lint etc. and install package for development process
you can find all the flags here https://docs.npmjs.com/cli/v8/commands/npm-install

Resources