529

npm@5 has been published, it has a new feature package-lock.json file (after npm install) which confuses me. I want to know, what is the effect of this file?

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
SecretCastle
  • 5,299
  • 3
  • 9
  • 7
  • 2
    package-lock. json to keep track of exact dependency trees at any given time. It will ensure that all clients that download your project and attempt to install dependencies will get the exact same dependency tree. – Manoj May 26 '21 at 13:55

8 Answers8

494

It stores an exact, versioned dependency tree rather than using starred versioning like package.json itself (e.g. 1.0.*). This means you can guarantee the dependencies for other developers or prod releases, etc. It also has a mechanism to lock the tree but generally will regenerate if package.json changes.

From the npm docs:

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."

Edit

To answer jrahhali's question below about just using the package.json with exact version numbers. Bear in mind that your package.json contains only your direct dependencies, not the dependencies of your dependencies (sometimes called nested dependencies). This means with the standard package.json you can't control the versions of those nested dependencies, referencing them directly or as peer dependencies won't help as you also don't control the version tolerance that your direct dependencies define for these nested dependencies.

Even if you lock down the versions of your direct dependencies you cannot 100% guarantee that your full dependency tree will be identical every time. Secondly you might want to allow non-breaking changes (based on semantic versioning) of your direct dependencies which gives you even less control of nested dependencies plus you again can't guarantee that your direct dependencies won't at some point break semantic versioning rules themselves.

The solution to all this is the lock file which as described above locks in the versions of the full dependency tree. This allows you to guarantee your dependency tree for other developers or for releases whilst still allowing testing of new dependency versions (direct or indirect) using your standard package.json.

NB. The previous npm-shrinkwrap.json did pretty much the same thing but the lock file renames it so that it's function is clearer. If there's already a shrink wrap file in the project then this will be used instead of any lock file.

Edit 2023

Since NPM v8.3.0 (2021-12-09), package.json has a property overrides which might help you not to touch package-lock.json file.

{
  "overrides": {
    "foo": "1.0.0"
  }
}

https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides

jbarradas
  • 2,031
  • 3
  • 17
  • 22
Matt
  • 12,569
  • 4
  • 44
  • 42
  • 127
    If having an exact version of dependencies is so sought after, why not enforce specifying the exact version in package.json and forgoe a package-lock.json file? – jmrah Jun 09 '17 at 16:52
  • 29
    @jrahhali - have amended my answer based on your question. – Matt Jun 26 '17 at 10:27
  • 3
    How gets this dependency tree from pacakge.json.lock applied for other developers? Automatically? – Stephan Kristyn Jul 20 '17 at 11:00
  • 82
    Please note that this answer **is no longer correct**! The `package-lock.json` file is being updated **every single time you call npm install** since NPM 5.1. (change in https://github.com/npm/npm/issues/16866, example in https://github.com/npm/npm/issues/17979) It therefore can **no longer be used to set the same versions for all developers**, unless you specify exact versions like `1.2.3` instead of `1.2.*` in your `package.json` file. – Christian Aug 18 '17 at 09:28
  • @jrahhli - Your comment does not take into consideration the package.json of dependencies. You can use exact semver, but that doesn't mean your dependencies will! – user2954463 Aug 30 '17 at 19:18
  • 2
    but if all your dependencies and dependencies of dependencies etc also use exact versions in their own package.json, then it'd not be needed? i.e. don't most packages use exact versions? – Avery235 Oct 07 '17 at 12:57
  • @Avery235 lol Perhaps someday everyone will see the light; probably not though. :p – user1464581 Jan 30 '18 at 22:30
  • The link in the answer is broken. Also, what is the new behavior? – 1.21 gigawatts May 25 '19 at 04:55
  • 27
    You should add a reference to `npm ci` as `npm install` will update the package-lock.json whereas ci uses its content. Only with `npm ci` will you get repeatable robust builds. – k0pernikus Sep 10 '19 at 15:42
  • Interesting finding, for me: the modules in my dependency tree got node_modules/*modules* installed when I did an npm uninstall in one module. The installed node_module/*modules* didn't match the current dependencies of the other modules. Seems that the npm uninstall caused npm to process package.lock and bring the dependency tree to that state, even though it wasn't the state of the other modules as defined in their package.json files. Didn't hurt output though. – Ted Fitzpatrick Oct 23 '19 at 21:36
  • 1
    @Matt I have a package in package.json file: ` "dependencies": { "abcd": "^1.0.66", } ` And this package is locked in package-lock.json file: ``` "abcd": { "version": "1.0.66", } ``` When I execute `npm install` then a new package gets installed of version `1.0.71`. This is happening because of the caret sign and due to the version of npm which is `5.5.1.`. – NN796 Mar 29 '20 at 10:17
  • 1
    @NN796 so you're saying that the package-lock file can't lock the dependency tree? – RayLoveless Apr 15 '20 at 14:26
  • 1
    unfortunate naming decision, *lock* creates an assumption of os file description lock file. shuda called it package-tree, package-versions... – Mickey Perlstein May 20 '20 at 07:39
  • I want to know how npm check if a package's has become vulnerable in application. Even when we are using same version of node and that package like before. – Pradhumn Sharma Aug 11 '20 at 07:06
  • Is it ok if I deleted the integrity line in package-lock.json ? I deleted from some stylesheet and the website became surprisingly faster. – Lama Feb 10 '22 at 15:18
  • 1
    My file is 20000 lines long. How on earth does this happen and how can I fix it? – Neil Mar 11 '22 at 21:28
  • How we can have semantic versioning when package-lock.json is committed and every developer has the same dependencies ? Does it mean, you still need to update npm package despite provided semantic versioning ? – JohnIdlewood Aug 02 '23 at 13:11
93

It's an very important improvement for npm: guarantee exact same version of every package.

How to make sure your project built with same packages in different environments in a different time? Let's say, you may use ^1.2.3 in your package.json, or some of your dependencies are using that way, but how can you ensure each time npm install will pick up same version in your dev machine and in the build server? package-lock.json will ensure that.

npm install will re-generate the lock file.
When on build server or deployment server, do npm ci
(which will read from the lock file, and install the whole package tree)

Paul Verest
  • 60,022
  • 51
  • 208
  • 332
Xin
  • 33,823
  • 14
  • 84
  • 85
  • 22
    Note that this is kinda outdated now. In 5.1.0 onward, "npm install" does not read from the `package-lock.json` file at all. It just installs from `package.json` like it used to. To make use of the `package-lock.json` file, you have to use the new "npm ci" command, which will install the exact versions listed in `package-lock.json` instead of the version-ranges given in `package.json`. – Venryx Jul 20 '18 at 02:21
  • 19
    I'm afraid Venryx is incorrect. `npm install` **does** read from `package-lock.json`. To reproduce, do the following. using this package.json, run `npm install` { ... "devDependencies": { "sinon": "7.2.2" } } Now copy/paste `package.json` and `package-lock.json` to a new directory. Change `package.json` to: "sinon": "^7.2.2" run `npm install`. npm reads from package-lock.json and installs 7.2.2 instead of 7.3.0. Without package-lock.json, 7.3.0 would be installed. – zumafra Mar 23 '19 at 19:45
  • 3
    And not only that, but if you want to do something like add the caret ^ to `package-lock.json`, the only reasonable way to do that is to delete `package-lock.json` and regenerate it using `npm install`. (You don't want to manually edit `package-lock.json`). Changing the value of the "version" property (near the top) of `package.json` will change the same in `package-lock.json` on `npm install`, but adding a caret to a dependency will not do the same to `package-lock.json`. – zumafra Mar 23 '19 at 20:07
  • @zumafra to me is not clear about the metadata like project name, licence etc, that are both in package.json and the package-lock.json one. Would of course those be have modified manually. Also is not clear based on what would be generated the package-lock.json from npm install – Carmine Tambascia Sep 03 '19 at 10:27
  • 3
    Think of `package.json` as something that you can manually modify, and `package-lock.json` as something that you never manually touch. You always version control BOTH files - especially `package-lock.json`. Open both files, manually edit the project name in `package.json`, run `npm install` and watch how the project name changes in `package-lock.json`. `license` doesn't seem to be recorded in `package-lock.json`. – zumafra Sep 04 '19 at 02:31
  • `package.json` is basically a human-readable record of what software your project depends on. `package-lock.json` is a machine-generated record of the EXACT VERSIONS of the software dependencies YOU used (and listed in `package.json`) when you worked on your project. When you give me `package.json` ONLY and I run `npm install` two weeks later, I will have slightly different software dependencies installed on my machine. When you give me `package.json` AND `package-lock.json` and I run `npm install` two weeks later, I will have EXACTLY THE SAME software dependencies installed as you did. – zumafra Sep 04 '19 at 02:32
  • 3
    @zumafra package-lock.json file will be use when doing `npm ci`, `npm install` will just use package.json, even though the lock file is provided – Xin Sep 04 '19 at 22:55
  • @Xin I have a package in package.json file: "dependencies": { "abcd": "^1.0.66", } And this package is locked in package-lock.json file: "abcd": { "version": "1.0.66", } . When I execute `npm install` then a package gets installed with new version of `1.0.71`. This is happening because of the caret sign or due to the version of npm which is `5.5.1.` or both? Please confirm. My understanding is `npm install` should pick the locked version `1.0.66` rather than `1.0.71`. – NN796 Mar 29 '20 at 10:33
  • @NN796 i calrify it again in it. please refer, in summary, it -regenerate new lock file – Xin Mar 29 '20 at 11:03
  • @Xin Thank you. So the lock file gets updated due to the caret sign and the version of the npm which is 5.4.1 right? – NN796 Mar 29 '20 at 12:16
  • @NN796 lock file gets updated just because of `npm install` cause each time execuate, it generates fresh one, and yes if > or ^, it will pickup new ones (be careful, including its sub dependencies) – Xin Apr 02 '20 at 02:50
  • @Xin can you please provide some suggestions on this https://stackoverflow.com/questions/61019398/why-does-npm-install-git-repo-url-rewrite-package-lock-json – NN796 Apr 03 '20 at 20:18
  • I helped that @NN796 – Xin Apr 03 '20 at 21:28
  • As of NPM 6.14.8, none of the answers here seem accurate. I see range operators produced by NPM in the package-lock. `npm install bunyan --save-exact` this yields a package-lock with this bunyan dependency, note the range operators in requires: `"bunyan": { "version": "1.8.14", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.14.tgz", "integrity": "", "requires": { "dtrace-provider": "~0.8", "moment": "^2.19.3", "mv": "~2", "safe-json-stringify": "~1" } }` – Jeremiah Adams Oct 08 '20 at 15:57
  • Is it ok if I deleted the integrity line in package-lock.json ? I deleted from some stylesheet and the website became surprisingly faster. – Lama Feb 10 '22 at 15:19
47

package-lock.json is written to when a numerical value in a property such as the "version" property, or a dependency property is changed in package.json.

If these numerical values in package.json and package-lock.json match, package-lock.json is read from.

If these numerical values in package.json and package-lock.json do not match, package-lock.json is written to with those new values, and new modifiers such as the caret and tilde if they are present. But it is the numeral that is triggering the change to package-lock.json.

To see what I mean, do the following. Using package.json without package-lock.json, run npm install with:

{
  "name": "test",
  "version": "1.0.0",
  ...
  "devDependencies": {
    "sinon": "7.2.2"
  }
}

package-lock.json will now have:

"sinon": {
  "version": "7.2.2",

Now copy/paste both files to a new directory. Change package.json to (only adding caret):

{
  "name": "test",
  "version": "1.0.0",
  ...
  "devDependencies": {
    "sinon": "^7.2.2"
  }
}

run npm install. If there were no package-lock.json file, sinon@7.3.0 would be installed. npm install is reading from package-lock.json and installing 7.2.2.

Now change package.json to:

{
  "name": "test",
  "version": "1.0.0",
  ...
  "devDependencies": {
    "sinon": "^7.3.0"
  }
}

run npm install. package-lock.json has been written to, and will now show:

"sinon": {
  "version": "^7.3.0",
zumafra
  • 1,255
  • 2
  • 13
  • 19
18

One important thing to mention as well is the security improvement that comes with the package-lock file. Since it keeps all the hashes of the packages if someone would tamper with the public npm registry and change the source code of a package without even changing the version of the package itself it would be detected by the package-lock file.

nflaig
  • 673
  • 1
  • 8
  • 15
3

This file is automatically created and used by npm to keep track of your package installations and to better manage the state and history of your project’s dependencies. You shouldn’t alter the contents of this file.

user_ahmed
  • 41
  • 5
1

The goal of package-lock.json file is to keep track of the exact version of every package that is installed so that a product is 100% reproducible in the same way even if packages are updated by their maintainers.

This solves a very specific problem that package.jsonleft unsolved. In package.json you can set which versions you want to upgrade to (patch or minor), using the semver notation.

Milan Kumar Bura
  • 350
  • 5
  • 11
0

package-lock.json: It contains the exact version details that is currently installed for your Application.

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
  • 3
    Hi, and welcome. This question has already been answered. You have to verify if the question has marked as answered seeing if any of the answers has a green ckeck in front of it. – Néstor Jun 03 '20 at 19:15
  • 5
    @Néstor Don't get it wrong. One can answer to already answered question given that the answer is **new** and useful. (although it's not the case in this answer). – Tibebes. M Oct 17 '20 at 06:54
  • 3
    The answer you provided has already been given! Consider improving the quality of the information to make this a valuable answer! – Alexander Grass Jan 03 '21 at 14:07
-2

Package.json file contains the main names of packages & libraries which you installed and you can edit it, but Package-lock.json contains the details of each package and the link of repository of each package (consider it's the details of the packages which came from package.json) Reference

https://web-brackets.com/discussion/69/what-is-the-use-of-package-lock-json-file

Mohamed Atef
  • 115
  • 8