You probably have something like:
"typescript":"~2.1.6"
in your package.json
which npm updates to the latest minor version, in your case being 2.4.1
Edit: Question from OP
But that doesn't explain why "npm install" would change the lock file. Isn't the lock file meant to create a reproducible build? If so,
regardless of the semver value, it should still use the same 2.1.6
version.
Answer:
This is intended to lock down your full dependency tree. Let's say typescript v2.4.1
requires widget ~v1.0.0
. When you npm install it
grabs widget v1.0.0
. Later on your fellow developer (or CI build)
does an npm install and gets typescript v2.4.1
but widget
has been
updated to widget v1.0.1
. Now your node module are out of sync. This
is what package-lock.json
prevents.
Or more generally:
As an example, consider
package A:
{ "name": "A", "version": "0.1.0", "dependencies": {
"B": "<0.1.0" } }
package B:
{ "name": "B", "version": "0.0.1", "dependencies": {
"C": "<0.1.0" } }
and package C:
{ "name": "C", "version": "0.0.1" }
If these are the only versions
of A, B, and C available in the registry, then a normal npm install A
will install:
[email protected] -- [email protected]
-- [email protected]
However, if [email protected] is published, then a fresh npm install A will install:
[email protected] -- [email protected]
-- [email protected] assuming the new version did not modify B's dependencies. Of course, the new version of B could include a new
version of C and any number of new dependencies. If such changes are
undesirable, the author of A could specify a dependency on [email protected].
However, if A's author and B's author are not the same person, there's
no way for A's author to say that he or she does not want to pull in
newly published versions of C when B hasn't changed at all.
OP Question 2: So let me see if I understand correctly. What you're
saying is that the lock file specifies the versions of the secondary
dependencies, but still relies on the fuzzy matching of package.json
to determine the top-level dependencies. Is that accurate?
Answer: No. package-lock locks the entire package tree, including the
root packages described in package.json
. If typescript
is locked
at 2.4.1
in your package-lock.json
, it should remain that way until it is
changed. And lets say tomorrow typescript
releases version 2.4.2
.
If I checkout your branch and run npm install
, npm will respect the
lockfile and install 2.4.1
.
More on package-lock.json
:
package-lock.json is automatically generated for any operations where npm modifies either the node_modules tree, or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.
This file is intended to be committed into source repositories, and serves various purposes:
Describe a single representation of a dependency tree such that teammates, deployments, and continuous integration are guaranteed to install exactly the same dependencies.
Provide a facility for users to "time-travel" to previous states of node_modules without having to commit the directory itself.
To facilitate greater visibility of tree changes through readable source control diffs.
And optimize the installation process by allowing npm to skip repeated metadata resolutions for previously-installed packages.
https://docs.npmjs.com/files/package-lock.json
package-lock.json
gets regenerated when i runnpm install
. This smells like a npm bug. Do you use your own registry?--no-save
prevents changing the lockfile, but it doesn't affect the goofy first-level dependency upgrading that the OP mentions.npm i
without changing anything, and mypackage-lock.json
was modified (the versions under all the packages inrequires
changed). It seems intended and not to break anything? More info here