I am creating a nodejs project and wish to have same library versions used across dev, qa, staging and production environment.
Tried package.json but was unable to find good help. Need some suggestion here.
EDITED
{
"dependencies": {
"ioredis": "1.7.5",
"redis": "0.12.1",
"redis-hash": "0.0.4",
"debug": "*"
}
}
Specify your dependencies using the exact versions in the package.json file, and when you run npm install it will get the proper versions of all your dependencies.
If you don't specifiy an exact version for the libraries, there's a chance that there's a new version since the last time you ran the command, you will end up with different versions of your libraries on your servers, which might not be what you want.
NPM has an outdated command which will list all the dependencies that have fallen behind and need to be updated. You can then run npm install.
Related
suppose in the package.json file I have my dependencies as-as -
"dependencies": {
"moment": "^2.22.2"
}
Here, are we saying that for the package "moment" we can use any of version 2.x.x functionality( i.e. we can use the new functions provided by 2.23.2 in our app, though we installed 2.22.2 on our computer) or are we saying that anyone else who uses our code of app can use any 2.x.x version of "moment" package ?
If you set:
"moment": "^2.22.2"
the user will download almost the v2.22.2. In this case you will download the v2.24.0
If you set:
"moment": "2.22.2"
the user will download exactly that version
If you set:
"moment": "~2.22.1"
the user will download almost the v2.22.1. In this case you will download the v2.22.2
You can use the functions in v2.9.9 if and only if the module respect the semver standard.
That is true the 99.999% of times.
can we use any of version 2.x.x functionality( i.e. we can use the new functions provided by 2.9.9 in our app, though we installed 2.22.2 on our computer)
Just to avoid confusion. You will not install version 2.22.2 on your computer. By saying ^2.22.2, npm will look what is the highest version of 2.x.x and install that version. You will never install version 2.22.2. You will install version 2.24, and when moment updates its packages to 2.25.0, you will install that version. So you will always have the latest verison 2.x.x installed, so you will get the functions of 2.9.9.
are we saying that anyone else who uses our code of app can use any 2.x.x version of "moment" package ?
Yes, you can verify this by checking out package-lock.json which is created by NPM and describes the exact dependency tree. https://docs.npmjs.com/files/package-lock.json
If your package.json is version 1.0.0 and you have 2.22.2 dependency on moment, and do npm install, you will see in package-lock.
{
"name": "mypackage",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
}
}
}
So everybody that installs your version 1.0.0 of your package will get moment version 2.24
why do I need to install "moment.js" again (i.e. update it) once its
installed on my computer –
You don't have to to. But the common rule is to leave node_modules out of repositories and only have package.json. So that when you publish your website to for example AWS, Azure or DigitalOcean, they will do npm install and therefore install everything, every time you publish your website.
To clarify how the flow of packages usually is
You create a package/module with specific verison
I decide to use your package
So I will do npm install (to use your package)
NPM will go through the dependency tree and install versions accordingly.
My website works and I am happy
In the meanwhile you are changing your code, and updating your package.
Few months pass and I decide to change my website. So now when I do npm install (because I updated my code), I will get your updates as well.
I really dont know why the NPM has started downloading about 40+ modules on Npm install but my package.json only contains following dependencies.
"devDependencies": {
"typescript": "^1.6.2",
"vscode": "0.10.x"
},
"dependencies": {
"fs": "^0.0.2"
}
Following are the list it started. Besides these modules there are about double of this number downloaded and added below but i didnt show here.
Is there any way to reset. I have tried to remove the modules folder and install again it started adding again.
Yesterday when i run i only get these dependencies only on other PC.
HeadCode is correct. npm3 installs some dependencies in a flat way.
From the docs:
While npm2 installs all dependencies in a nested way, npm3 tries to mitigate the deep trees and redundancy that such nesting causes. npm3 attempts this by installing some secondary dependencies (dependencies of dependencies) in a flat way, in the same directory as the primary dependency that requires it.
So, if you are using npm v2.x on one machine, and npm v3.x on another, you can get very different folder structures under your node_modules folder.
I need to know if the following behavior is normal.
When I npm install, each package from my package.json and the dependencies, don't get installed nested anymore, but each dependency is installed in the node_modules directory. That makes my node_modules directory blown and look like this:
This happened since I updated npm and node.
Now I run:
npm -v 3.3.6
node -v 4.2.1
python 2.7
windows 7
wamp
My package.json file looks like this:
{
"private": true,
"devDependencies": {
"gulp": "^3.8.8"
},
"dependencies": {
"laravel-elixir": "^3.0.0",
"bootstrap-sass": "^3.0.0"
}
}
It's the standard laravel package.json file.
Is there a way to have nested directories again, because I don't like such a blown article with over 100 sub directories.
Update: As Erik Pukinskis mentioned in the comments:
As of npm 3.5, support for --legacy-bundling has been dropped.
Yes, there is a way to have nested directories again by changing npm's (version 3 as of this writing) default behaviour:
Delete the currently present node_modules folder.
Tell npm to install with legacy bundling for this one install:
npm install --legacy-bundling
A "permanent" alternative:
Set your npm config to always use legacy bundling...
npm set legacy-bundling=true
.. and run as usual:
npm install
Note: fetching dependencies with legacy bundling will take a lot more time because many several different versions of the same dependencies will be installed.
Disclaimer: As a non-Windows user I have no need for flat dependencies and want to find self-declared dependencies with ease in favour of automatic deduping. Since installing npm dependencies without legacy bundling already takes an incredible amount of time I'm usually willing to spend those extra minutes install time. It gets back down to 5 directories from previously 700+ (...) in a Laravel Elixir setup with bootstrap (non-sass), font-awesome and jquery added.
That's the new behavior of npm 3 as per this npm blog.
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.
Every day when I run meteor for the first time, meteor goes out to the internet to check for updates in the npm packages.
If I don't have internet connection, I can't run meteor. This kills my productivity. I would like to force this update to not run so I can work.
My command line is:
NODE_OPTIONS=--debug meteor
The output is:
=> Started proxy.
=> Started MongoDB.
npm: updating npm dependencies -- github, colors, aws-sdk, moment, string, urlify, sendgrid, airbrake...
iron-router: updating npm dependencies -- connect...
meteor-collection-management: updating npm dependencies -- mongodb...
kadira: updating npm dependencies -- debug, usage...
Now here is the additional puzzlement. My package.json explicitly specifies the versions of the npm packages.
more packages.json
{
"github": "0.1.15",
"colors": "0.6.2",
"aws-sdk": "2.0.0-rc13",
"moment": "2.5.1",
"string": "1.8.0",
"urlify": "0.3.5",
"sendgrid": "1.0.2",
"airbrake": "0.3.8"
}
The list and versions haven't changed in ages. npm should have no reason to go to the web - it has local copies of the specified versions already.
Now of course there is a possibility that this update is triggered by a sub-dependency - which is why I would like to do:
Force an offline mode when running meteor
AND/OR tell npm to resolve all dependencies completely - so that it does not think it needs to do an update.
UPDATE: I am sort of working around this problem with https://www.npmjs.org/package/sinopia
These related? issues are also showing up on startup:
Package.on_test runs even when not testing
Why does Meteor-Npm keep trying to get a package from the internet