Deciding whether to save to devDependencies or dependencies? - node.js

I'm building a react/express app and want to make sure I'm setting up my package.json so that dev packages go under devDependencies, and production packages go under dependencies.
When downloading a new npm package, what's the quickest way to find out whether I can save it using --save or using --save-dev? For example, here is my current package.json:
"devDependencies": {
"babel-eslint": "^7.2.3",
"babel-loader": "^7.1.2",
"eslint": "^4.6.0",
"eslint-plugin-react": "^7.3.0",
"jest": "^20.0.4"
},
"dependencies": {
"babel-cli": "^6.26.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"ejs": "^2.5.7",
"express": "^4.15.4",
"pm2": "^2.6.1",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"webpack": "^3.5.5"
}
I had a hard time looking up which section each package should go on. I tried looking it up for each individual dependency but never got a really decisive answer so I don't know if I did so optimally.
What's the best way when downloading an npm package to find whether I can save it using --save-dev?

Generally, dependencies (--save) are for packages that are referenced by your application code: code that runs when someone uses your app. devDependencies (--save-dev) are for packages used by the developers of your app: compilation/build tooling and testing.
There is no strict restriction in npm or node that says package x must go into dependencies or devDependencies. You could install webpack in either but if we follow the logic above, the most appropriate section for it is devDependencies.
When you publish your package to npm, a user doing an npm install for your package can choose to install, along with your package's code, dependencies (the usual), devDependencies, or both. If they're not going to be modifying code in your package, they won't need anything from devDependencies. This is one reason to keep the two sections cleanly separated.

This is what I do. I'm curious to know if there is a better way:
Look up your package on the npmjs.com site and see how they recommend installing it.
If they recommend installing it with --save (or simple without any --save option), it belongs in dependencies.
If they recommend installing it with --save-dev (or --dev or -D), it usually belongs in devDependencies.
E.g.:
https://www.npmjs.com/package/#babel/runtime
npm install --save #babel/runtime
put it into dependencies
https://www.npmjs.com/package/#babel/core
npm install --save-dev #babel/core
put it into devDependencies
Exceptions:
I've noticed that this method is not always reliable. E.g. resize-observer-polyfill which recommends installing it with --save-dev but the project I'm working on uses it in production. Then again, if you're using webpack, it might bundle it in for you anyway :).

Related

How to install only typescript dependencies and build (package.json, npm), avoid 150MB of dependencies when building

I want to know if there is a way to:
install only the needed dependencies to build avoiding 150MB of garbage;
build;
then remove the dependencies only needed to build but not for run.
That's more of a doubt than a need for now
I have the following dependencies:
"devDependencies": {
"#types/node": "^16.0.0",
"#typescript-eslint/eslint-plugin": "^4.31.1",
"#typescript-eslint/parser": "^4.31.1",
"commitizen": "^4.2.4",
"cz-conventional-changelog": "3.3.0",
"eslint": "^7.12.1",
"eslint-config-prettier": "^8.3.0",
"eslint-config-standard": "^16.0.3",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^5.0.0",
"prettier": "^2.4.1",
"ts-node-dev": "^1.1.8",
"typescript": "^4.3.5"
},
"dependencies": {
"dotenv": "^10.0.0"
}
And I noticed something, I have a lot of useless dependencies when compiling typescript, because just to compile, I only need 3:
"devDependencies": {
"#types/node": "^16.0.0",
"typescript": "^4.3.5"
},
"dependencies": {
"dotenv": "^10.0.0"
}
Only these 3 dependencies are like 60MB, and if I really want to, I can compile, remove the dependencies and use npm install --production what would let me with ~1MB, what is great for me, because the final can be as light as possible (a bit exaggerated, but cool).
Now when I do the full npm install with all dependencies, I reach 150MB (that's really disappoint).
My question is, there is a way, to minimize the dependencies install in the build process, other than moving types to dependencies (because they aren't "production" dependencies, only for "build")?
Actually when building I do this:
npm i
npm run build
rm -rf node_modules # not sure if needed
npm i --production
This will generate a small build, but in the process I will need to install around 150MB of unneeded packages.
Notes:
I was thinking about removing it before build, but I want to avoid to do it
I thought about optional dependencies, but looks like they don't have this purpose
I want to keep the dependencies because they keep the code consistent when working with other people and help to avoid mistakes
the "bigger" dependency is typescript with 61M and, the second one is prettier 20M, I need only typescript to build, but I don't need any of them to run.
I just want to "solve" this when building, I don't really care about it when coding
The problem here is not in the final build, is in the process that download unnecessary dependencies
The problem here is not in the final build, is in the process that download unnecessary dependencies
Is this done in docker?
A solution exists for this - you cache the dependencies based on the content of the package-lock.json or yarn.lock
https://medium.com/#stepanvrany/how-to-build-nodejs-docker-image-using-cache-c401137661d0

Is is possible to install dependancies with single line command?

My Node.js
package.json
has following dependancies
"dependencies": {
"body-parser": "^1.18.3",
"express": "^4.16.4",
"mongoose": "^5.3.10",
"nodemon": "^1.18.5"
},
"devDependencies": {
"eslint": "^5.8.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-plugin-import": "^2.14.0"
},
I am new to JS,so I want to know if we can somehow invoke package.json without going for
npm install
for every package.
When you use the command npm install or npm i, it will install all dependencies from your package.json.
As a result you get all the dependencies listed in the package.json from the current folder
You can see the documentation concerning this command here : npm install
Welcome to JS world, I'm fairly new to JS myself but I believe there two possible solutions to your problem:
npm install multiple dependencies
It is possible to install multiple dependencies at the same time with one npm install command, you may find more information that could be helpful in the documentation.
For example:
npm install got koa fs-extra
Here I have installed all 3 of my project dependencies at once.
Pre Populate package.json
You can manually add the package dependencies in the correct format to your package.json file. You might the npm documentation on the package.json file helpful.
You then will need to run:
npm install
This will take the dependencies in the package.json file and install them into the node_modules/ directory.

How do I identify which npm packages are just peer dependencies?

I'm trying to remove unused packages from the package.json files for a few projects but I'm running into issues with peer dependencies. There are some tools, such as depcheck, which try to list all of the "unused" packages, but it doesn't differentiate between actual unused packages, and packages that are unused because they're peer dependencies.
Is there a package out there, or some npm command I'm not familiar with, that will allow me to either list all peer dependencies in my project or, at the very least, allow me to type in a package name and see if that package is installed because it's a peer dependency of another package?
For posterity, here's an example of just the dependencies for one of my projects. In this project, I know for instance that reflect-metadata is a peer dependency of #nestjs/common, but I only discovered that after uninstalling it.
"dependencies": {
"#google-cloud/storage": "^3.2.1",
"#google-cloud/vision": "^1.3.0",
"#google/maps": "^0.5.5",
"#nestjs/common": "^6.6.7",
"#nestjs/core": "^6.6.7",
"#nestjs/platform-express": "^6.6.7",
"#slack/webhook": "^5.0.1",
"#typeform/api-client": "^1.5.1",
"algoliasearch": "^3.34.0",
"array-uniq": "^2.1.0",
"basic-auth": "^2.0.1",
"child-process-promise": "^2.2.1",
"class-transformer": "^0.2.3",
"class-validator": "^0.10.0",
"express": "^4.17.1",
"firebase-admin": "^8.5.0",
"firebase-functions": "^3.2.0",
"geoip-lite": "^1.3.8",
"geolib": "^3.0.4",
"glob": "^7.1.4",
"hbs": "^4.0.4",
"hubspot-api": "^2.2.10",
"json2csv": "^4.5.3",
"lodash": "^4.17.15",
"luxon": "^1.17.2",
"node-fetch": "^2.6.0",
"postmark": "^2.2.9",
"promise-settle": "^0.3.0",
"qrcode": "^1.4.1",
"redux": "^4.0.4",
"reflect-metadata": "^0.1.13",
"rxjs": "^6.5.3",
"sales-tax": "^2.0.10",
"sanitize-filename": "^1.6.3",
"sharp": "^0.23.0",
"stripe": "^7.9.0"
},
This is a great question, not sure why it was downvoted.
Unfortunately I don't know of an existing, nicely automated way to do this.
You can test an individual package like so:
npm uninstall some-package && npm ls
If there are any peer dependency violations, they will be printed out and the command will exit nonzero.
So you could combine this with the output of one of the other tools mentioned, iterate through the candidates for orphaned packages, remove them one-by-one, and test the output between each change. Then do an npm uninstall --save to commit the ones that didn't produce an error, or npm install to roll back the ones that do. This could be automated, but I will leave that as an exercise to the reader.
check-peer-deps
Verifies that the peerDependency requirements of all top level dependencies are satisfied.
Installation
You can install this on your system with:
npm i -g check-peer-deps
Please note that this utility requires npm to be available.
Usage
Simply change into the directory of the project you wish to check the peerDependencies of and run the program.
 cd foobar
 check-peer-deps
If the minimum versions of all your top level peerDependencies are satisfied then there will be no output, otherwise you will see something similar to this:
check-peer-deps A dependency satisfying eslint-config-airbnb-base's peerDependency of 'eslint#^4.9.0' was not found! Current: eslint#^4.6.0 Package dependencies can satisfy the peerDependency? Yes
This tells you that eslint-config-airbnb-base is requiring eslint#^4.9.0 as a peerDependency, but the project currently only specifies eslint#^4.6.0, allowing a potential issue to arise if eslint#4.6.0 was installed and not updated before installing. The output also tells you that although the minimum allowed version is too low, the maximum allowed version does satisfy the peerDependencies requirement.
install-peers-cli
CLI to install project's peerDependencies, without side effects. Works with npm, yarn. Supports yarn workspaces flow.
Install
yarn
$ yarn add --dev install-peers-cli
npm
$ npm install --save-dev install-peers-cli
Usage
Add package.json script:
{
"scripts": {
"install-peers": "install-peers"
}
}
Then run yarn install-peers (or npm run install-peers) to install peer dependencies of your project. It won't update lock files or modify package.json, keeping your setup pure and clean. Any other lifecycle script could be used depending on your use case.
You still may see "unmet peer dependency" warnings during regular install phase, due to installation flow of npm/yarn.
There will be a file called package-lock.json after once you do npm install.
By analyzing package-lock.json file, you can understand the dependencies of each package.
For more details this blog can be referred.
Dependencies of a package are required for the correct running of the package.
But there are some optional dependencies, which can be skipped.
You can use --no-optional argument while installing so these extra packages will not be installed.
But make sure your application is working fine without these optional packages.

Angular 2 UNMET PEER Dependency Error on Windows 10

I am trying to run my web application on a Windows 10 Machine with the package.json (given below). I have Node version 5.6.0 and Npm version 3.6.0. But unfortunately it's always throwing an UNMET Peer Dependency Error and the following files of the AngularLoader Hierarchy fails to load when I run my project(powered by Laravel PHP): shim.js, zone.js, reflect.js, system.js. Contrary the same config runs absolutely smooth on a Linux Dev Machine. Any sort of help for installing the same on the Windows Machine will be highly appreciated as I am quite new to the Angular 2 Domain.
I have already tried the following:
rm -rf node_modules/
npm cache clean
npm install
And also installing like npm install angular/core angular/common angular-forms
P:S: Upgrading to Angular 4 is not an option. Sorry!!!
Here is my package.json:
{
"private": true,
"scripts": {
"prod": "gulp --production",
"dev": "gulp watch"
},
"devDependencies": {
"bootstrap-sass": "^3.3.7",
"gulp": "^3.9.1",
"jquery": "^3.1.0",
"laravel-elixir": "^6.0.0-11",
"laravel-elixir-vue-2": "^0.2.0",
"laravel-elixir-webpack-official": "^1.0.2",
"lodash": "^4.16.2",
"vue": "^2.0.1",
"vue-resource": "^1.0.3"
},
"dependencies": {
"#angular/common": "^2.1.2",
"#angular/core": "^2.1.2",
"#angular/forms": "^2.1.2",
"#ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.11",
"#types/jquery": "^2.0.41",
"jquery": "^3.2.1",
"ng2-ui": "^0.11.5",
"rxjs": "^5.0.0-beta.12",
"zone.js": "^0.6.26"
}
}
Here is the full install log of the Windows Machine:`
Link to Error Doc
If you use libraries that depend on Angular 4 you can expect these errors.
Take ng-bootstrap 1.0.0-alpha.25 for example; If you check the CHANGELOG.md file;
BREAKING CHANGES
ng-bootstrap requires a minimal version of Angular 4.0.3
So why does this happen? Short answer; you should get rid of the version tags ^and ~ as this is your problem to begin with:
"^1.0.0-alpha.11" allows for versions >= 1.0.0-alpha.11 < 2.0.0
use "#ng-bootstrap/ng-bootstrap": "1.0.0-alpha.11" instead.
I suggest you read up on npm semver
Some might say you do not have to drop it completely but I've had my fair share of issues. Not all developers understand semantic versioning it seems. Also, it's a very bad idea to use these wildcards with alpha and beta packages as they come with breaking changes by default it seems.
How to fix it from here?
You say you have a Linux Dev Machine where you can build this app without any issues. Try doing an npm shrinkwrap on that machine. This will write an npm-shrinkwrap.json file with all used library versions at that time. Then, when doing an npm install on the Windows 10 machine, this file will be checked to see what versions should be downloaded instead.

node.js - how to install a single dependency globally?

My package.json file looks like this:
{
"name": "tets",
"version": "1.0.0",
"devDependencies": {
"chai": "^3.0.0",
"gulp": "^3.9.0",
"gulp-concat": "^2.6.0",
"gulp-less": "^3.0.3",
"gulp-minify-css": "^1.2.0",
"gulp-plumber": "^1.0.1",
"gulp-rename": "^1.2.2",
"gulp-uglify": "^1.2.0",
"karma": "^0.12.0",
"karma-chai": "^0.1.0",
"karma-mocha": "^0.2.0",
"karma-phantomjs-launcher": "^0.2.0",
"mocha": "^2.2.5"
}
}
To install this locally I would run npm install and to install all dependencies globally I would run npm install -g. I only want to install gulp globally, though. Is there any way to accomplish this?
As a caveat, I've integrated a gulpfile into a .NET project and have it running via a post-build event. As a pre-build event, I'm executing npm install to ensure everything is setup correctly. My hope is that any code to install only gulp globally can be added to the package.json file so I can keep my pre-build event to just npm install. Unless adding npm install gulp -g to my pre-build event is acceptable...
So #FaridNouriNeshat pointed me to a solution where gulp is accessed locally which is probably the most appropriate thing to do rather than globally install it into someone's machine. In my case, I altered my post-build event in my .NET app to point to the local install of gulp rather than a global install.
"$(SolutionDir)\Gorman.Abe.Web\node_modules\.bin\gulp" styles scripts

Resources