package-lock.json contains dynamic version.


(Domvel) #1

Why are dynamic versions in my package-lock.json like ^1.2.3 or ~1.2.3 instead of 1.2.3?
And why are these version overwritten by npm install? This lock-file should contain only the fixed installed versions of node_modules. Because only one version is installed.

I expected a locked / fixed versions in package-lock.json. So that every developer in my team and our build-system uses the same version. To prevent bugs in (hidden) updates.

Example (Snippet of package-lock.json)

{
  "name": "test",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "@angular-devkit/build-optimizer": {
      "version": "0.0.35",
      "resolved": "http://repo.ino.local:8081/repository/npm-group/@angular-devkit/build-optimizer/-/build-optimizer-0.0.35.tgz",
      "integrity": "sha512-7JxZZAYFSCc0tP6+NrRn3b2Cd1b9d+a3+OfwVNyNsNd2unelqUMko2hm0KLbC8BXcXt/OILg1E/ZgLAXSS47nw==",
      "dev": true,
      "requires": {
        "loader-utils": "^1.1.0",
        "source-map": "^0.5.6",
        "typescript": "~2.6.1",
        "webpack-sources": "^1.0.1"
      }
    }
  }
}

Versions

npm version: 6.4.1
platform: win32 (Windows 10 Pro (1809) 64bit)

A colleague has the npm version 5.6.0 on the same platform.
And he produces fixed version entries in the package-lock.json with this npm version.
If I use npm install (npm i) the package-lock.json will be overwrite it with dynamic version. Why?
We never removed the package-lock.json.

Is this a bug? Or a misunderstanding?


(Lars Willighagen) #2

The version ranges in requires objects in the lock file don’t actually determine what versions are being installed, that’s determined by the version field on each dependency (which should be static, and not a range). If the wrong packages are being installed, please let us know.


(Domvel) #3

Not only the dependencies of the package.json are a part of my project, also the dependencies of the dependencies. Every software from node_modules. I thought the intention of the package-lock.json is to “lock” the version of installed packages. That every developer, every system which checks out the project from git to build, has the exact same result.
This isn’t possible when the node_modes versions are “blurry”. e.g. One day I compile my software with a sub-dependency version 1.0.0 and another day with 1.0.1 because of version range in package-lock.json. This could produce a critical problem because 1.0.1 could have changes that are not compatible with my software or contains new bugs. I do not mean that hypothetically. It’s experience.
After hours and hours we found the bug. A dependency of a dependency has been updated to a faulty version. Because npm installed the latest version because of range-version in package-lock.json.
This should not be the idea behind package-lock.json.

To your “question” Yes, wrong packages (versions) are being installed. Because of a range-version in package-lock.json.
In fact, every developer in my team produces another package-lock.json without changes in package.json. Every developer just use npm install and every time, the package-lock.json is overwriten. One developer commits the package-lock.json with ALL versions fixed without ranges ^ or ~ etc. And another developers package-lock.json contains range-versions. That’s a buggy (unexpected) behavior.

If the package-lock.json is not intended to lock versions, but only to list dependency dependencies, this is a missunderstanding. BUT in my opinion - and I’m sure this is the opinion of the most developers - there must be a solution to lock ALL versions. Not only in package.json, also in package-lock.json. Because I want the same software in my node_modules if I don’t update / touched the package.json. To have a stable build with exactly the same result. Every time.
Otherwise your project setup - as written above - might contain an error because a dependency (package-lock.json, not your deps from package.json) has changed in the version. Or the build fails and you look in vain for the error. If you have no control of this (lock versions), this could be a very critical problem. - Please correct me if I am wrong.


(John Gee) #4

The package-lock.json does lock down the versions that get installed.

You may see changes in the package-lock when doing installs using different versions of npm (especially between major version like 5.6.0 to 6.4.1). You will also see changes when the package.json and package-lock.json are incompatible. You also often used to see changes when going between different operating systems, but that has been improving steadily and is good in latest versions of npm.

From the point of view of a reproducible install, what matters is what gets installed. In your example you show that the package-lock file changes, but you do not show what gets installed is different. Is it different?

I think older versions of npm used to update the package-lock to match the current node_modules, rather than treat package-lock.json as definitive, so to get clean install I used to often do steps like:

git checkout -- package-lock.json
rm -rf node_modules
npm install

Again, much better with recent versions of npm and package-lock.json is authoritative. I don’t do that now.

Lastly, to minimise package-lock.json changes my team all use the same version of npm. Not strictly needed, but simple.


(Flyguolai) #5

Have the same problem

It seems too dangerous for doing the building action in any project.

For me, it cause a big problem for my company’s production. Fortunately, we get the old build version of the software, so we can get back to the old version , and find out what the problem is. This cost a lot time to find out why do we have this problem.

I review my local package-lock.json and the version on my server which is used to building all projects. It seems like somedays ago , if a project didn’t have any packlock-lock.json in your project , the npm will install will add a package-lock.json file with all dependencies with ‘^’ and ‘~’ version. But i find another package-lock.json file which is never changed in my local PC , all the version of package.json is exact and stable.

Even I didn’t find the CHANGELOG or other document about this change.

If someone got idea about why the package-lock.json does this awesome feature , tell me , tks.


(Domvel) #6

Now I’m a bit confused. "The package-lock.json does lock versions? Ok, then there is a bug in the latest npm version I’m using 6.4.1. Because it actually does not lock the versions. It does not contain the installed version. It contains range-version informations and no one has an idea what version is actually installed. In other words: It installs random software. That sounds hard and deliberately exaggerated, but in fact, every npm install can inject an bug by installing a new version.

In my case there was a dependency of an dependency in lock file that updated from the developer of the package. He only increased the patch-version (major.minor.patch) which should be a bug fix. But he changes the complete scope which is a minor or major change. … Another case brought a bug to a bugfix patch version.
Whatever, there should be a (working) way to lock all versions of the dependencies in package-lock.json. npm should not update automatically by range-version. The developer should invoke an update manually. The build of my project should be reproducible.

Again: In my case I check out the git with a package-lock.json which contains only locked version. (without node_modules folder) and call npm install. After that the package-lock.json is nearly complete overwritten with range-version. Other developers have different results. One developers npm produces the package-lock.json with fixed versions and mine npm overwrites it with blurry versions. (as written in above posts.)


(Lars Willighagen) #7

In the example you provided you can see that the version field of @angular-devkit/build-optimizer is actually a fixed version (0.0.35). There are version ranges in the requires field, but those don’t determine what versions are being installed. They simply refer to other packages in the top-level dependencies field, just like @angular-devkit/build-optimizer. And just like @angular-devkit/build-optimizer, the version fields are fixed.

I cannot reproduce npm install upgrading packages when a lock file is present.


(Domvel) #8

You’re completly right. :facepalm: Only the requires versions are changed. The version is static. Thanks for the information that the version field is important and representing the installed packages.
It’s insteressting that npm version 5.6.0 writes locked versions into the requires field and npm version 6.4.1 range-versions. For that it’s could be recommended that all developers in a team uses the same npm version. Is there an explainsion of the requires field and why npm 6.4.x handles it in another way than 5.6.x?

Just for the log a screenshot which shows the issue.
On the left side it’s a package-lock.json from npm 5.6.0 and right 6.4.1. After npm install. The version field is static. That’s the same value. (OK)


I do not quite understand that with the requires field. (e.g. the difference between npm 5 and 6 left/right side of comparison). But good to know that the field “version” is crucial.


(Lars Willighagen) #9

They changed it in 6.0.0, I think to better match the dependencies field in package.jsons and make comparisons easier.