5

Which is the best practice while saving package.json dependencies?

For example, i see that lot's of dependencies are not fixed, like:

  "tslint": "~5.11.0"

I would like to have fixed dependencies, so that will not change in the future when new developers join a team.

I have little knowledge about package-lock.json and shrinkwrap, but I'm not sure about the "best practice" on this. On this case is an Angular app, but it can be everything. Keeping for example package-lock.json on the repo caused some issues in the past (i know! it is a best practice to push it!)

Any thoughts?

Ricardo Daniel
  • 421
  • 7
  • 15
  • If I may ask, by "fixed" do you mean not updating the dependency version? – Tebogo Khanye Apr 02 '19 at 23:04
  • for example: tslint : 5.11.0 (without ~ or ^ ) – Ricardo Daniel Apr 02 '19 at 23:15
  • There's an option to implement a dependency without neither the ^ nor ~. But in short the ^ indicates you'll be updated to the nearest major version of the dependency whereby ~ updates you to the nearest minor version. Please also see: https://googleweblight.com/i?u=https://stackoverflow.com/questions/22343224/whats-the-difference-between-tilde-and-caret-in-package-json&hl=&tg=82. – Tebogo Khanye Apr 02 '19 at 23:52
  • yes.... i agree, i mean... pointing to an exact version makes sense to me, so there is less chance that something will have unexpected behaivour. Like "tslint": "5.11.0" for example. But I didn't find any source to explain that this is the best practice – Ricardo Daniel Apr 03 '19 at 16:18
  • Please, consider using `npm ci` (clean install) [see why](https://stackoverflow.com/a/64014814/10788155). – Ictus Aug 21 '22 at 10:29

1 Answers1

8

Short answer: Carets (^) and committing your package-lock.json is probably your best approach. This ensures developers always get the same dependencies, and is the least surprising.


Why package-lock.json?

npm specifically recommends you commit your package-lock.json.

It is highly recommended you commit the generated package lock to source control: this will allow anyone else on your team, your deployments, your CI/continuous integration, and anyone else who runs npm install in your package source to get the exact same dependency tree that you were developing on.

(from the npm documentation)

You mentioned pushing package-lock.json to your repository caused some issues in the past. I'm guessing this was due to this issue where the package lock was being ignored and rewritten every time anyone installed anything. This was not the correct behaviour and was fixed in npm@5.4.2, according to this answer.

What you should not do is leave out the package-lock.json and just specify exact versions in your package.json. If you do this, your top level dependencies will look nice and consistent, but their dependencies won't have locked down versions. This way, you're almost as likely to run into bugs, but they'll be harder to find.


Why not npm-shrinkwrap.json?

You also mention shrinkwrap files. Shrinkwrap files are meant for

applications deployed through the publishing process on the registry

(from the npm documentation)

You probably aren't npm publishing your angular webapp, so there's no reason to use npm-shrinkwrap.json.


Why use caret ranges?

I can't find any documentation saying caret (^) ranges are best practice, but I believe they are.

npm makes caret ranges the default option, so it's clear they think this is best practice, though I can't find any of their documentation to justify it.

Using the default is the least surprising approach. If I saw any other kind of version in a package.json, I'd assume it was changed for a good reason, and would be hesitant to update the package without knowing what that reason is, even if it really needed to be updated.

If you ever decide to update all your dependencies at once, caret ranges will serve you well. You're dependencies will normally be locked, but deleting your package-lock.json and rerunning npm install will automatically install the latest versions that are supposedly backwards compatible with the versions you specified (see the npm docs for details on the caret range).


In summary, it's standard to use caret ranges and a package-lock.json. This fulfills your requirement of fixed dependencies, and provides a few other benefits, so it's best to do what's standard, unless you find another reason to change.

Half
  • 5,078
  • 2
  • 10
  • 20
  • 1
    This is the accepted answer. Right now i'm doing that without any issues: caret + package-lock.json is the perfect solution. I checked, and yes... the issue was with an old version on npm. Thanks so much! – Ricardo Daniel May 30 '19 at 16:14