why not specify a specified version then we don't need the package-lock.json - node.js

I'm new to NPM, sorry if my questions sounds stupid. Below is my question:
Q1-
When I install a package and specify a specified version, for example:
npm install xxx#3.5.1
but why in the package.json file, it becomes:
{
"devDependencies": {
"xxx": "^3.5.1"
}
}
I know that the extra caret (the ^ character) will accept versions like 3.5.2, 3.6.0 but not 4.0.0. But I did explicitly specify that I want version 3.5.1, so why NPM still add ^ in front of the version?
Q2-
If NPM install package with version which I what users specify, then we don't need the package-lock.json file, do we? Since all versions in the package.json file are unique and unambiguous?

1.
You can add --save-exact
npm install lodash --save --save-exact - installs the latest version and saves the exact version in the dependencies in the package.json.
2.
^ and ~ is the way npm offer to you to get the latest source of dependencies. It's risky sometimes though.
Read this for more detailed explanation. https://bytearcher.com/articles/semver-explained-why-theres-a-caret-in-my-package-json/

Related

confusion about npm install and npm update

I am learning about the differences between package.json and package-lock.json
I been experimenting on a package with only one dependency called chance
I first installed it via npm i chance#1.0.0 and the package.json has "chance": "^1.0.0" and package-lock.json has "version": "1.0.0".
Because I wanted to see the effect that the lock file has on the version, I went ahead and deleted package-lock.json and node_modules, I ran npm install, the version of chance stays the same in package.json, which is "chance": "^1.0.0". In the newly created lock file, the version of chance became "chance": {"version": "1.1.8",, so it updated itself.
I then deleted package-lock.json and node_modules again and ran npm update, the results seemed to be the same with the previous experiment – in package.json I have "^1.0.0" in package.json and "1.1.8" in package-lock.json
My questions are:
in either case, with "^1.0.0" in package.json and "1.1.8" in package-lock.json, which version of the dependency am I actually using in my project, I guess it is 1.1.8 right? so by merely looking at the versions in package.json is not enough to determine the exact version of the dependencies used in a project?
When does running npm install change the lock file? I know that if we delete the lock file, it will generate a new one with the newest versions in the allowable ranges from package.json. But are there any cases where npm install would change the lock file even if I didn't delete the lock file?
So, the answer is a bit complex. Essentially there are 2 things at play: The version of the package you want/need, and the version of the package that is installed.
When you are building a project, you probably don't care what specific version of a given dependency is. Most of the time you want the latest one, or the latest patch near a specific major version. The package.json is supposed to document what you, the developer, believe is required for your project to work. So, if you put in the package json "chance": "1.0.0", it would mean that only version 1.0.0 exactly is acceptable, and any other version is unacceptable. If you put "chance": "^1.0.0", it means any version compatible with 1.0.0 is acceptable. So 1.2 or 1.3 might also be fine, but 1.4 might introduce a change that breaks compatibility.
Once you decide what packages you want, by writing the package json, you run npm install. npm install can't always install exactly the versions you want. For example, imagine you want to install two packages: React v1.13 and momentJS v2.8. So you add these to your package json like this:
(Note: these version numbers and dependancies are not based on real React or Moment version numbers)
"momentJS" : "2.8",
"react" : "1.13"
then you run npm install. And you get an error: Package dependencies cannot be resolved. (or something like that). The problem is that React version 1.13 requires momentJS 2.9, but your package json specifies that you want version 2.8 exactly. You can't have both, so npm isn't able to resolve the conflict. A fix would be:
"momentJS" : "^2.8",
"react" : "1.13"
Now you are saying that you need a version of moment compatible with 2.8, and you are okay with npm adjusting that to satisfy other packages. Run npm install again and npm might install version 2.9, which satisfies both your requirement of "compatible with 1.8" and React, which wants 2.9. Now, the web app I'm currently working on has over 1,000 dependancies total, so npm absolutely needs to be able to adjust version numbers in order to get all of those packages to play nice.
Now there is often more than one way to solve a dependancy graph--more than one way to adjust all the version numbers to make every package happy. Your package lock file records what the current solution is and what actual packages are installed.
All the options for specifying package verions are here
Hope that helps!
Also: the second part of your question was "will npm change the lock file without me deleting it?" And the answer is: basically everytime you run npm install, npm changes the lock file. What npm does try to do is change the lock file as little as possible with each new install and keep most packages the same

Difference between `npm i` and `npm i <package name>`

In my React Native project, I have a given version of react in my package.json, but if I run npm i react, it will install the latest version of react. If I run npm i though, will it install all the packages in my package.json, with the versions given in the package.json? I don't want it to install the latest versions of all the packages, so I'm scared to try it without asking.
You should go through documentation before getting into anything :)
Using npm i will install whatever is stated in the package.json. If the package.json binds the packages to versions, then it will install that specific version. Most often, package.json would use the ^ character before the package version, which stands for any version above the mentioned version, and if that is the case for you, yes, npm i will install the latest version of those packages.

How to update version of a package in package-lock.json and/or package.json using npm to latest version?

Say you get a warning in some libraries in a repo about security concerns from github. You want to quickly bump the version just to make the github warnings going away. You are not worried about re-installing, rebuilding and testing.
Is there a way to do this with npm?
npm update mypackage does not do anything.
Now it works different, if you notice package versions in package lock.json have a prefix, sometimes its ~ sometimes ^, they have big importance when it comes to package updating, as fixing package mismatches is the worst hell.
Suppose you have package in package.json called packX with version ~1.1.1 or ^1.1.1
When you run npm update for packX npm will first of all check the version prefix for it.
If there is ~ in this case it will be understood as install packX version >=1.1.1 and <1.2.0 so the highest version it can install can only be in range of 1.1.N, it will not go up to 1.2.N.
If there is ^ then it will be understood as >=1.1.1 <2.0.0 so the highest version that can be installed will be in range of 1.N.N but connot go up to 2.N.N
Hope My explication is clear enough, anyways you can check the docs for details
npm update will only update minor versions.
Eg: It will update version 1.2.3 to 1.5.2
But it will not update version 1.2.3 to 2.0.1 because there can be breaking changes.
To check new major releases of the packages, you run npm outdated
To update to a new major versions for all the packages, you can use npm-check-updates
npm install -g npm-check-updates
Then run ncu -u
This will upgrade all the versions in the package.json file, to dependencies and devDependencies, so npm can install the new major version. Now you can update packages to new major releases by npm update
Reference

Specific Angular Cli Version is not installed

I need to install Angular CLI in the version 1.6.8. When I am executing this command:
npm install -g #angular/cli#1.6.8
it is getting installed well. But when I am check the version using ng -v, it displays the latest version, in my case 1.7.4.
For my code compatibility, I need version 1.6.8. And even in my dependencies in package.json, I have specified the cli as version 1.6.8 :
"#angular/cli": "^1.6.8"
Does anybody know the issue? How can I install version 1.6.8?
if you are inside a directory that has node_modules ng -v would report that version, not the global one. For updating your global CLI, move to a directory that doesn't have node_modules installed and then execute
npm uninstall -g #angular-cli
npm cache clean
npm install -g #angular/cli#1.6.8
You can change the version of the angular-cli in the package.json if you want to stick to the particular version remove the ^ symbol but this would be local
"#angular/cli": "1.6.8"
^ it means update the minor and patch version to the latest and keep the major version same.
This command will install the CLI globally on your machine.
npm install -g #angular/cli#1.6.8
So, if you have an application that already has CLI version 1.7.4 included in it, you will see that version when you run ng -v. If you would like to downgrade to an earlier version, change the version in the package.json to the exact version you would like to use, and run npm install.
In your package.json you have this:
"#angular/cli": "^1.6.8"
What you need to change it to is this:
"#angular/cli": "1.6.8"
Remove the caret from the version number.
The caret tells npm that is can install versions of a library higher than what is listed, but only if the version is a minor or patch change. So, going from version 1.6.8 to 1.7.4 is OK, but it won't jump to version 6.0.0 when that comes out.
See here for more details.

Make `npm install --save` add a strict version to package.json

When you run npm install --save somepackage, it usually adds something like this into package.json:
"dependencies": {
"somepackage": "^2.1.0"
}
Because the version is prepended with a caret(^), this means that if you later run npm install, it might install version 2.3.0 instead. This can be undesirable for fairly obvious reasons. npm shrinkwrap is useful, but doesn't really solve the problem.
So, I have several questions:
When installing a package, is it possible to specify that you want it to be set to a specific version in package.json (no caret before the version number)?
When publishing a package to npm, is there any way to prevent the default of including the caret before the version when other developers install your package?
To specify by default a exact version, you can change your npm config with save-exact:
npm config set save-exact true
You can also specify the prepend version with a tilde with save-prefix.
And, no you can't force user to update to a minor or a patch version, NPM uses semver and it's the recommend way of publishing packages.
You can change the default behaviour by using the --save-exact option.
// npm
npm install --save --save-exact react
// yarn
yarn add --exact react
I created a blog post about this if anyone is looking for this in the future.
https://www.dalejefferson.com/blog/how-to-save-exact-npm-package-versions/
Run:
npm install --save --save-exact my-module#my-specific-version
Adding an answer to make this advice easier to see.

Resources