Categories
git lockfile node.js npm version-control

Do I commit the package-lock.json file created by npm 5?

2174

npm 5 was released today and one of the new features include deterministic installs with the creation of a package-lock.json file.

Is this file supposed to be kept in source control?

I’m assuming it’s similar to yarn.lock and composer.lock, both of which are supposed to be kept in source control.

7

  • 63

    Short answer: yes. One comment: when package-lock.json changes you can make a commit of just that change, separate from other source changes. This makes git log easier to deal with.

    Aug 29, 2017 at 23:07


  • 30

    A file can’t help produce a deterministic install if it doesn’t exist.

    – Alan H.

    Sep 30, 2017 at 6:11

  • 8

    Depends on the project. github.com/npm/npm/issues/20603

    – Gajus

    May 13, 2018 at 1:21


  • 4

    If you really trust npm sure, the purpose is to more explicitly report what the project is using. If you really want predictability ignore this file and instead install your node_modules (see .npmrc and related config in the answers+comment) and use that to track what’s actually changing rather than what your package manager states it’s doing. Ultimately: wich is more important? Your package manager or the code you’re using.

    – jimmont

    Nov 30, 2018 at 18:15

  • 3

    Given the popularity of yarn, and its warning: package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in order to avoid resolution inconsistencies caused by unsynchronized lock files. To clear this warning, remove package-lock.json, I think there should be some answers here clarifying when folks should not commit package-lock.json.

    – nealmcb

    Aug 5, 2020 at 14:16

2361

Yes, package-lock.json is intended to be checked into source control. If you’re using npm 5+, you may see this notice on the command line: created a lockfile as package-lock.json. You should commit this file. According to npm help 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.

One key detail about package-lock.json is that it cannot be published, and it
will be ignored if found in any place other than the toplevel package. It shares
a format with npm-shrinkwrap.json, which is essentially the same file, but
allows publication. This is not recommended unless deploying a CLI tool or
otherwise using the publication process for producing production packages.

If both package-lock.json and npm-shrinkwrap.json are present in the root of
a package, package-lock.json will be completely ignored.

30

  • 117

    In what kind of projects is it actually helpful to commit the file? The whole point of semver and package.json is that updated compatible dependencies shouldn’t need to be noted.

    May 27, 2017 at 12:05

  • 69

    The key word is “shouldn’t need to be” – but in practice people don’t follow semver perfectly. That’s why you can use package-lock.json and package.json together to make it easy to update packages but still making sure every developer and every deployed application is using the same dependency tree.

    May 31, 2017 at 8:51

  • 43

    @trusktr: Sindre Sorhus recommends using “Lockfiles for apps, but not for packages.”

    – vine77

    Jun 23, 2017 at 18:17

  • 34

    Another thing is, package-lock.json is ignored for publishing on NPM, so if a developer uses it for a library dev, then they are minimizing the chance that they will catch a regression from an updated dependency version, and therefore will pass that bug onto end users. For this reason, not using a lock file for library dev increases the chance of shipping less bugs.

    – trusktr

    Jul 19, 2017 at 22:49


  • 183

    Personally I’ve now had to resort to adding package-lock.json to my .gitignore… it was causing me far more problems than solving them. It always conflicts when we merge or rebase, and when a merge results in a package-lock.json being corrupted on the CI server, it’s just a pain to have to stay fixing it.

    Aug 13, 2017 at 18:37

302

Yes, you SHOULD:

  1. commit the package-lock.json.
  2. use npm ci instead of npm install when building your applications both on your CI and your local development machine

The npm ci workflow requires the existence of a package-lock.json.


A big downside of npm install command is its unexpected behavior that it may mutate the package-lock.json, whereas npm ci only uses the versions specified in the lockfile and produces an error

  • if the package-lock.json and package.json are out of sync
  • if a package-lock.json is missing.

Hence, running npm install locally, esp. in larger teams with multiple developers, may lead to lots of conflicts within the package-lock.json and developers to decide to completely delete the package-lock.json instead.

Yet there is a strong use-case for being able to trust that the project’s dependencies resolve repeatably in a reliable way across different machines.

From a package-lock.json you get exactly that: a known-to-work state.

In the past, I had projects without package-lock.json / npm-shrinkwrap.json / yarn.lock files whose build would fail one day because a random dependency got a breaking update.

Those issue are hard to resolve as you sometimes have to guess what the last working version was.

If you want to add a new dependency, you still run npm install {dependency}. If you want to upgrade, use either npm update {dependency} or npm install ${dependendency}@{version} and commit the changed package-lock.json.

If an upgrade fails, you can revert to the last known working package-lock.json.


To quote npm doc:

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. Additionally, the diffs from these
changes are human-readable and will inform you of any changes npm has
made to your node_modules, so you can notice if any transitive
dependencies were updated, hoisted, etc.

And in regards to the difference between npm ci vs npm install:

  • The project must have an existing package-lock.json or npm-shrinkwrap.json.
  • If dependencies in the package lock do not match those in package.json, npm ci will exit with an error, instead of updating
    the package lock.
  • npm ci can only install entire projects at a time: individual dependencies cannot be added with this command.
  • If a node_modules is already present, it will be automatically removed before npm ci begins its install.
  • It will never write to package.json or any of the package-locks: installs are essentially frozen.

Note: I posted a similar answer here

6

  • 44

    This answer deserves more credit, especially using npm ci. Using this mitigates most of the issues people have experienced with package lock.

    – JamesB

    Jun 13, 2019 at 21:42

  • 4

    I’ve found using fixed version in package.json (no caret or tilde) to be a much much cleaner option. This saves me from whose build would fail one day because a random dependency got a breaking update kind of issue. Though it leaves the possibility of child’s dependency çausing the same issue.

    May 29, 2020 at 6:40

  • 1

    Is it still relevant that we should always use npm ci? From the docs it looks like this is incorrect. npm install “This command installs a package and any packages that it depends on. If the package has a package-lock, or an npm shrinkwrap file, or a yarn lock file, the installation of dependencies will be driven by that, respecting the following order of precedence:” npm ci “If a node_modules is already present, it will be automatically removed before npm ci begins its install.” Certainly npm ci should be used as part of your CI/CD process, but seems excessive on dev machine??

    – Thomas

    Apr 22, 2021 at 15:22


  • 1

    Thank you so MUCH! i knew there had to be an “npm i” that was read-only style. IF according to the documentation the lock file is used to sync me up to whatever the previous change was, but “npm i” would always write to the package-lock.json and then what? it didnt’ make sense for me (the one being synced) to now have changes to check in. I will try using “npm ci” from now on and see if the problems go away.

    – diox8tony

    Jul 12, 2021 at 17:34


  • I am running into this. But I just needed to install a package based on a change that another developer pushed. The docs say you can’t install an individual package with npm ci. If you use npm i [email protected] it still dramatically changed my package-lock.json file. Now I don’t know what to do.

    – MattoMK

    Feb 24 at 19:43

140

Yes, it’s intended to be checked in. I want to suggest that it gets its own unique commit. We find that it adds a lot of noise to our diffs.

8

  • 25

    it’s fair to debate whether it should be checked into your source code repository, but publishing this file to npm is not really up for debate – you must include either your package-lock.json or your shrinkwrap file into your npm registry. if you do not, your published package will be subject to unpinned changes of dependencies of your 1st generation dependencies. you won’t notice this to be a problem until one of those 2nd+ generation dependencies publishes a breaking change, and your published package becomes mysteriously broken. this package-lock.json file was created to solve that problem.

    Sep 10, 2017 at 15:16

  • 11

    @BetoAveiga by noise I mean that the commits with package-lock.json can have so many lines of node package versions, that any other work in that commit becomes hidden.

    – xer0x

    Nov 25, 2017 at 7:45

  • 9

    I usually keep package installations separate from other work. I never need to diff a commit like “Installed chai and mocha”, because I already know what changed.

    – Keith

    Dec 14, 2017 at 17:45

  • 4

    Any advice regarding the package-lock.json file when working on a SCM system with trunks and branching? I’m making some changes on a branch that need to be merged to trunk… do I now have to (somehow) resolve conflicts between the two package-lock.json files? This feels painful.

    – kmiklas

    Jan 23, 2018 at 21:35


  • 8

    @guerillapresident As I understand it, you’re partially correct. Publishing this file to npm is not up for debate. You can’t publish it.

    May 10, 2018 at 15:03