summaryrefslogtreecommitdiff
path: root/deps/npm/doc/files/npm-package-locks.md
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/doc/files/npm-package-locks.md')
-rw-r--r--deps/npm/doc/files/npm-package-locks.md145
1 files changed, 145 insertions, 0 deletions
diff --git a/deps/npm/doc/files/npm-package-locks.md b/deps/npm/doc/files/npm-package-locks.md
new file mode 100644
index 0000000000..73786dc91a
--- /dev/null
+++ b/deps/npm/doc/files/npm-package-locks.md
@@ -0,0 +1,145 @@
+npm-package-locks(5) -- An explanation of npm lockfiles
+=====================================================
+
+## DESCRIPTION
+
+Conceptually, the "input" to npm-install(1) is a package.json(5), while its
+"output" is a fully-formed `node_modules` tree: a representation of the
+dependencies you declared. In an ideal world, npm would work like a pure
+function: the same `package.json` should produce the exact same `node_modules`
+tree, any time. In some cases, this is indeed true. But in many others, npm is
+unable to do this. There are multiple reasons for this:
+
+* different versions of npm (or other package managers) may have been used to install a package, each using slightly different installation algorithms.
+
+* a new version of a direct semver-range package may have been published since the last time your packages were installed, and thus a newer version will be used.
+
+* A dependency of one of your dependencies may have published a new version, which will update even if you used pinned dependency specifiers (`1.2.3` instead of `^1.2.3`)
+
+* The registry you installed from is no longer available, or allows mutation of versions (unlike the primary npm registry), and a different version of a package exists under the same version number now.
+
+As an example, consider package A:
+
+ {
+ "name": "A",
+ "version": "0.1.0",
+ "dependencies": {
+ "B": "<0.1.0"
+ }
+ }
+
+package B:
+
+ {
+ "name": "B",
+ "version": "0.0.1",
+ "dependencies": {
+ "C": "<0.1.0"
+ }
+ }
+
+and package C:
+
+ {
+ "name": "C",
+ "version": "0.0.1"
+ }
+
+If these are the only versions of A, B, and C available in the
+registry, then a normal `npm install A` will install:
+
+ A@0.1.0
+ `-- B@0.0.1
+ `-- C@0.0.1
+
+However, if B@0.0.2 is published, then a fresh `npm install A` will
+install:
+
+ A@0.1.0
+ `-- B@0.0.2
+ `-- C@0.0.1
+
+assuming the new version did not modify B's dependencies. Of course,
+the new version of B could include a new version of C and any number
+of new dependencies. If such changes are undesirable, the author of A
+could specify a dependency on B@0.0.1. However, if A's author and B's
+author are not the same person, there's no way for A's author to say
+that he or she does not want to pull in newly published versions of C
+when B hasn't changed at all.
+
+To prevent this potential issue, npm uses package-lock.json(5) or, if present,
+npm-shrinkwrap.json(5). These files are called package locks, or lockfiles.
+
+Whenever you run `npm install`, npm generates or updates your package lock,
+which will look something like this:
+
+ {
+ "name": "A",
+ "version": "0.1.0",
+ ...metadata fields...
+ "dependencies": {
+ "B": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/B/-/B-0.0.1.tgz",
+ "integrity": "sha512-DeAdb33F+"
+ "dependencies": {
+ "C": {
+ "version": "git://github.com/org/C.git#5c380ae319fc4efe9e7f2d9c78b0faa588fd99b4"
+ }
+ }
+ }
+ }
+ }
+
+This file describes an *exact*, and more importantly *reproducible*
+`node_modules` tree. Once it's present, and future installation will base its
+work off this file, instead of recalculating dependency versions off
+package.json(5).
+
+The presence of a package lock changes the installation behavior such that:
+
+1. The module tree described by the package lock is reproduced. This means
+reproducing the structure described in the file, using the specific files
+referenced in "resolved" if available, falling back to normal package resolution
+using "version" if one isn't.
+
+2. The tree is walked and any missing dependencies are installed in the usual
+fashion.
+
+If `preshrinkwrap`, `shrinkwrap` or `postshrinkwrap` are in the `scripts`
+property of the `package.json`, they will be executed in order. `preshrinkwrap`
+and `shrinkwrap` are executed before the shrinkwrap, `postshrinkwrap` is
+executed afterwards. These scripts run for both `package-lock.json` and
+`npm-shrinkwrap.json`. For example to run some postprocessing on the generated
+file:
+
+ "scripts": {
+ "postshrinkwrap": "json -I -e \"this.myMetadata = $MY_APP_METADATA\""
+ }
+
+
+### Using locked packages
+
+Using a locked package is no different than using any package without a package
+lock: any commands that update `node_modules` and/or `package.json`'s
+dependencies will automatically sync the existing lockfile. This includes `npm
+install`, `npm rm`, `npm update`, etc. To prevent this update from happening,
+you can use the `--no-save` option to prevent saving altogether, or
+`--no-shrinkwrap` to allow `package.json` to be updated while leaving
+`package-lock.json` or `npm-shrinkwrap.json` intact.
+
+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.
+
+## SEE ALSO
+
+* https://medium.com/@sdboyer/so-you-want-to-write-a-package-manager-4ae9c17d9527
+* package.json(5)
+* package-lock.json(5)
+* npm-shrinkwrap.json(5)
+* npm-shrinkwrap(1)