6

I have a project where I removed some no-longer needed libraries from my package.json file, removed node_modules, ran npm install, and everything continued to work as expected.

Unfortunately if I follow the same steps above after having deleted package-lock.json, my build suddenly breaks. A new package-lock.json is generated but I now get hundreds of deprecation warnings from some dependencies and even though the project continues to build those same dependencies will break in unexpected places.

If I revert to the previous package-lock.json and again run the same steps (remove node_modules, run npm install), the warnings once again disappear and the build is once more in a safe state.

My understanding is that package-lock.json will update every time we run npm install with the most recent package versions, respecting the caret^ and tilde~ restrictions. Does this update differ if we have an existing package-lock.json vs a fresh install?

Even if there is somehow a conflict between sub-dependencies I'm still confused why updating a package-lock.json with npm install works great but running npm install after deleting that file creates a new package-lock.json that breaks. This happens consistently over many attempts.

dyslexit
  • 689
  • 1
  • 9
  • 18
  • Don't delete `package-lock.json`? Modern node+npm uses `package.json` to determine which dependency version ranges are permitted, and `package-lock.json` to determine which _actual versions_ should be used (especially due to security issues in older versions of dependencies). If you're seeing lots of warnings: read the warnings. There's different kinds, and without saying what you're seeing, there's not much we can say about them other than "peg versions you need pegged, and run `npm audit fix` to make sure any insecure dependency is uplifted to a secure version". – Mike 'Pomax' Kamermans May 26 '21 at 19:15
  • 2
    With package-lock.json still available npm install will install the packages in exactly the versions that are specified in the package-lock.json. if you remove it, some packages may be installed in newer versions, which may break dependencies – derpirscher May 26 '21 at 19:15
  • @derpirscher Thanks for the response, but my understanding is that since npm v5.1.0 `npm install` *will not* install the packages inside package-lock.json. From that version on we need to do `npm ci` for that behavior. That is why I'm confused about what's going on. https://stackoverflow.com/questions/45022048/why-does-npm-install-rewrite-package-lock-json – dyslexit May 26 '21 at 20:26

1 Answers1

2

I was having the same confusion with my own repo.

So I'm writing this my own sake as much as yours, in the hopes I remember it for next time I come looking for a solution.

The update on this npm issue clarified everything for me:

  1. If you have a package.json and you run npm i we generate a package-lock.json from it.
  2. If you run npm i against that package.json and package-lock.json, the latter will never be updated, even if the package.json would be happy with newer versions.
  3. If you manually edit your package.json to have different ranges and run npm i and those ranges aren't compatible with your package- lock.json then the latter will be updated with version that are compatible with your package.json. Further runs of npm i will be as with 2 above.

And here is an explanation on what was happening with your case:

I have a project where I removed some no-longer needed libraries from my package.json file, removed node_modules, ran npm install, and everything continued to work as expected.

In this case it was doing step 2 from above. You have a working package-lock.json in place with all the correct dependency versions. So it reinstalled based on package-lock.json. It did not edit package-lock.json even if your package.json says it would be happy with newer versions.

Unfortunately if I follow the same steps above after having deleted package-lock.json, my build suddenly breaks. A new package-lock.json is generated but I now get hundreds of deprecation warnings from some dependencies and even though the project continues to build those same dependencies will break in unexpected places.

In this case it is doing step 1 from above. No package-lock.json was found, so it recreated your project from package.json, updating to newer versions as your package.json would allow. It then generated a new package-lock.json based on that install. Unfortunately for you, those updated versions broke your project.

If I revert to the previous package-lock.json and again run the same steps (remove node_modules, run npm install), the warnings once again disappear and the build is once more in a safe state.

This is essentially doing the same thing as before. It is doing step 2 from above. Since you once again have a working package-lock.json with all the correct package versions it will reinstall based on package-lock.json. It does not edit package-lock.json even if your package.json says it would be happy with newer versions. This is why it worked again, because none of the packages were upgraded to the problematic version.

My understanding is that package-lock.json will update every time we run npm install with the most recent package versions, respecting the caret^ and tilde~ restrictions. Does this update differ if we have an existing package-lock.json vs a fresh install?

Yes this will differ as described in the steps above. If you have an existing package-lock.json it will respect and install those exact package versions. If you're doing a fresh install it will update to newer (and potentially breaking) versions as are allowed in package.json.

This is why package-lock.json should be committed to version control and never deleted. The npm docs also recommend that.

There might be times where you are tempted to delete package-lock.json to solve conflicts. That is a bad idea, as explained in detail in this question. Instead, you can manually make changes to package.json and then run npm install. That is like doing step 3 above. Alternatively you can do npm update {dependency} or npm install {dependency}@2.1.3 which has the same effect.

TinyTiger
  • 1,801
  • 7
  • 47
  • 92