confusion about npm install and npm update

1.2k Views Asked by At

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 [email protected] 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:

  1. 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?
  2. 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?
1

There are 1 best solutions below

2
On

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