Dev dependencies vs dependencies in node.js - node.js

In a node project I found 2 kind of dependencies:
"dependencies": {
"axios": "0.9.1",
"express": "4.13.4",
"lodash": "4.6.1",
"react": "^0.14.7",
"react-dom": "^0.14.7",
"react-redux": "^4.4.0",
"react-router": "^2.0.0",
"redux": "^3.3.1"
},
"devDependencies": {
"babel-core": "^6.5.2"
}
I know the author install it via npm install babel-core --save -dev
but what is that for? when you push your code, the devDependencies module is still there.

I wrote an article about this however it was taken down.
Snippets from the article:
mod-a
dev-dependents:
- mod-b
dependents:
- mod-c
mod-d
 dev-dependents:
- mod-e
dependents:
- mod-a
----
npm install mod-d
installed modules:
- mod-d
- mod-a
- mod-c
----
checkout the mod-d code repository
npm install
installed modules:
- mod-a
- mod-c
- mod-e
Publishing to npm
If you are publishing to npm, then it is important that you use the correct flag for the correct modules. If it is something that your npm module needs to function, then use the "--save" flag to save the module as a dependency. If it is something that your module doesn't need to function but it is needed for testing, then use the "--save-dev" flag.
# For dependent modules
npm install dependent-module --save
# For dev-dependent modules
npm install development-module --save-dev
Not for npm
If you aren't publishing to npm, it technically doesn't matter which flag you use. However, I find it a good practice to use the "--save" flag for modules that introduce non-standard code into the source files. Then use the "--sav-dev" flag for modules that are required for your compiler to function.
# For modules that introduce non-standard source code
npm install source-module --save
# For modules that your compiler needs to function
npm install compiler-module --save-dev

Dependencies vs dev dependencies
Dev dependencies are modules which are only required during development whereas dependencies are required at runtime.
If you are deploying your application, dependencies has to be installed, or else your app simply will not work. Libraries that you call from your code that enables the program to run can be considered as adependencies.
Eg- React , React - dom
Dev dependency modules need not be installed in the production server since you are not gonna develop in that machine .compilers that covert your code to javascript , test frameworks and document generators can be considered as dev-dependencies since they are only required during development .
Eg- ESLint , Babel , webpack

Main difference between the two is:
-in devdependencies, developer customize or modify the node package according to the requirement. For example while making grunt task we change the task as per requirement in Gruntfile, same as case with babel you are using.
-in dependencies, developer directly use the node package without the change ex-express.
Hopefully it clears your doubt.

Related

why I can't change Typescript version even though I have downgraded the version

so previously, I installed Typecript on my new macbook by running this command
sudo npm install typescript -g
and I got Typescript version 4.7.4. and then I want to deploy the function using this command
firebase deploy
unfortunately, there is a warning like this
WARNING: You are currently running a version of TypeScript which is
not officially supported by #typescript-eslint/typescript-estree.
You may find that it works just fine, or you may not.
SUPPORTED TYPESCRIPT VERSIONS: >=3.3.1 <4.1.0
YOUR TYPESCRIPT VERSION: 4.7.4
Please only submit bug reports when using the officially supported
version.
and then I downgrade to version 4.0.7, but unfortunately that warning still exist, it seems my app is still on v4.7.4 (cached ? ) I am sure I have changed the typescript version on package.json and I also check via terminal like the image below
but why my node app still have version v.4.7.4 ? not v.4.0.7 ? what should I do?
fiuhhh....after 2 days, I finally find the solution
I have to change the dependencies and also the devDependencies, especially these dependencies in the package.json
"dependencies": {
"firebase-admin": "^10.0.2",
"firebase-functions": "^3.18.0",
},
"devDependencies": {
"#typescript-eslint/eslint-plugin": "^5.12.0",
"#typescript-eslint/parser": "^5.12.0",
"eslint": "^8.9.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.25.4",
"typescript": "^4.5.4" // <-- watch this version
},
the problem is ....it seems to me that these dependencies is tightly coupled. it can easily break if it doesn't match. so my solution is to create new project just to copy and paste those dependencies combination above with the latest version recommended by firebase. watch this video if you are confused how to initialize cloud function project
first, Update your firebase tools to the latest version using this command
sudo npm install -g firebase-tools
and change to your directory and init the project
cd desktop
mkdir forCopyPasteDependenciesOnly
firebase init
select cloud function and typescript. and then you copy those dependencies above and paste it on your problematic project
in my case, I also change the typescript globally using the recommended typescript version from the project package.json that you just initialize (4.5.4, not 4.0.7 or 4.7.4 in my case )
sudo npm uninstall -g typescript
sudo npm install -g typescript#4.5.4
and then, in your problematic project, delete your node-modules folder
and delete your package-lock.json. and finally run these 2 commands below
npm cache clean –force
npm install
and when you run firebase deploy you may see errors, but luckily it just error from eslint you just update, you can solve it easily.
I hope it helps
You installed typescript as globally on your system but you changed just in your package.json.
First you should type this npm uninstall -g typescript.
Then npm install -g typescript#your version.
After that you can uninstall your local tsc on your project.

How come a project still runs and builds if the dependency is not satisfied as in package.json?

I created a React app, and to check the behaviors for Gemfile and package.json, I changed one line in package.json from
"react": "^16.14.0",
to
"react": "^17.14.0",
as of writing, React 17 doesn't exist yet. But
npm start
and
npm run-script build
both still work. Both yarn start, yarn build also worked. To compare the behavior, when I do rails start with a modified Gemfile with some version of rails that doesn't exist (such as Rails 7.0), it won't start at all. How does this work with npm and package.json?
The user defined scripts start and build are executed but they don't trigger yarn/npm to inspect the dependency tree.
Node itself will load the package name from node_modules/. Package versions are not inspected at runtime.
An npm install or yarn will fail as they will attempt to install the missing package.

npm install is not adding all dependencies

I issue npm install protractor.
Under /path/to/node_modules/protractor/node_modules, i was expecting all the internal dependencies of protractor npm. But i am seeing only one module, q.
However in /path/to/node_modules/protractor/package.json, i can see all dependencies of protractor listed as,
"dependencies": {
"adm-zip": "0.4.4",
"glob": "~3.2",
"jasmine": "2.3.2",
"jasminewd2": "0.0.6",
"lodash": "~2.4.1",
...................
}
Protractor module is versioned "3.0.0" and npm is versioned 3.3.12, node.js is versioned v5.1.0.
What has changed in these new versions? Since, all npm modules used to maintain their own dependency copies.
npm 3 flattens the dependency tree, so you should see protractor's dependencies in /path/to/node_modules.
If you don't see them there, my first guess is that you might have an npm-shrinkwrap.json file that is preventing modules from being installed, so you could check for that.

Why use peer dependencies in npm for plugins?

Why does, for example, a Grunt plugin define its dependency on grunt as "peer dependencies"?
Why can't the plugin just have Grunt as its own dependency in grunt-plug/node_modules?
Peer dependencies are described here: https://nodejs.org/en/blog/npm/peer-dependencies/
But I don't really get it.
Example
I'm working with AppGyver Steroids at the moment which uses Grunt tasks to build my source files into a /dist/ folder to be served on a local device. I'm quite new at npm and grunt so I want to fully comprehend what is going on.
So far I get this:
[rootfolder]/package.json tells npm it depends on the grunt-steroids npm package for development:
"devDependencies": {
"grunt-steroids": "0.x"
},
Okay. Running npm install in [rootfolder] detects the dependency and installs grunt-steroids in [rootfolder]/node_modules/grunt-steroids.
Npm then reads [rootfolder]/node_modules/grunt-steroids/package.json so it can install grunt-steroids own dependencies.:
"devDependencies": {
"grunt-contrib-nodeunit": "0.3.0",
"grunt": "0.4.4"
},
"dependencies": {
"wrench": "1.5.4",
"chalk": "0.3.0",
"xml2js": "0.4.1",
"lodash": "2.4.1"
},
"peerDependencies": {
"grunt": "0.4.4",
"grunt-contrib-copy": "0.5.0",
"grunt-contrib-clean": "0.5.0",
"grunt-contrib-concat": "0.4.0",
"grunt-contrib-coffee": "0.10.1",
"grunt-contrib-sass": "0.7.3",
"grunt-extend-config": "0.9.2"
},
The "dependencies" packages are installed into [rootfolder]/node_modules/grunt-steroids/node_modules which is logical for me.
The "devDependencies" aren't installed, which I'm sure is controlled by npm detecting I'm just trying to use grunt-steroids, and not develop on it.
But then we have the "peerDependencies".
These are installed in [rootfolder]/node_modules, and I don't understand why there and not in [rootfolder]/node_modules/grunt-steroids/node_modules so that conflicts with other grunt plugins (or whatever) are avoided?
TL;DR: peerDependencies are for dependencies that are exposed to (and expected to be used by) the consuming code, as opposed to "private" dependencies that are not exposed, and are only an implementation detail.
The problem peer dependencies solve
NPM's module system is hierarchical. One big advantage for simpler scenarios is that when you install an npm package, that package brings its own dependencies with it so it will work out of the box.
But problems arise when:
Both your project and some module you are using depend on another module.
The three modules have to talk to each other.
In Example
Let's say you are building YourCoolProject and you're using both JacksModule 1.0 and JillsModule 2.0. And let's suppose that JacksModule also depends on JillsModule, but on a different version, say 1.0. As long as those 2 versions don't meet, there is no problem. The fact that JacksModule is using JillsModule below the surface is just an implementation detail. We are bundling JillsModule twice, but that's a small price to pay when we get stable software out of the box.
But now what if JacksModule exposes its dependency on JillsModule in some way. It accepts an instance of JillsClass for example... What happens when we create a new JillsClass using version 2.0 of the library and pass it along to jacksFunction? All hell will break loose! Simple things like jillsObject instanceof JillsClass will suddenly return false because jillsObject is actually an instance of another JillsClass, the 2.0 version.
How peer dependencies solve this
They tell npm
I need this package, but I need the version that is part of the
project, not some version private to my module.
When npm sees that your package is being installed into a project that does not have that dependency, or that has an incompatible version of it, it will warn the user during the installation process.
When should you use peer dependencies?
When you are building a library to be used by other projects, and
This library is using some other library, and
You expect/need the user to work with that other library as well
Common scenarios are plugins for larger frameworks. Think of things like Gulp, Grunt, Babel, Mocha, etc. If you write a Gulp plugin, you want that plugin to work with the same Gulp that the user's project is using, not with your own private version of Gulp.
I would recommend you to read the article again first. It's a bit confusing but the example with winston-mail shows you the answer why:
For example, let's pretend that winston-mail#0.2.3 specified "winston": "0.5.x" in its "dependencies" object because that's the latest version it was tested against. As an app developer, you want the latest and greatest stuff, so you look up the latest versions of winston and of winston-mail and put them in your package.json as
{
"dependencies": {
"winston": "0.6.2",
"winston-mail": "0.2.3"
}
}
But now, running npm install results in the unexpected dependency graph of
├── winston#0.6.2
└─┬ winston-mail#0.2.3
└── winston#0.5.11
In this case, it is possible to have multiple versions of a package which would cause some issues. Peer dependencies allow npm developers to make sure that the user has the specific module (in the root folder). But you're correct with the point that describing one specific version of a package would lead to issues with other packages using other versions. This issue has to do with npm developers, as the articles states
One piece of advice: peer dependency requirements, unlike those for regular dependencies, should be lenient. You should not lock your peer dependencies down to specific patch versions.
Therefore developers should follow semver for defining peerDependencies. You should open an issue for the grunt-steroids package on GitHub...
peerDependencies explained with the simplest example possible:
{
"name": "myPackage",
"dependencies": {
"foo": "^4.0.0",
"react": "^15.0.0"
}
}
{
"name": "foo"
"peerDependencies": {
"react": "^16.0.0"
}
}
running npm install in myPackage will throw an error because it is trying to install React version ^15.0.0 AND foo which is only compatible with React ^16.0.0.
peerDependencies are NOT installed.

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