1NPM-PACKAGE-LOCKS(5) NPM-PACKAGE-LOCKS(5)
2
3
4
6 npm-package-locks - An explanation of npm lockfiles
7
9 Conceptually, the "input" to npm help install is a npm help 5 pack‐
10 age.json, while its "output" is a fully-formed node_modules tree: a
11 representation of the dependencies you declared. In an ideal world, npm
12 would work like a pure function: the same package.json should produce
13 the exact same node_modules tree, any time. In some cases, this is
14 indeed true. But in many others, npm is unable to do this. There are
15 multiple reasons for this:
16
17 · different versions of npm (or other package managers) may have been
18 used to install a package, each using slightly different installation
19 algorithms.
20
21 · a new version of a direct semver-range package may have been pub‐
22 lished since the last time your packages were installed, and thus a
23 newer version will be used.
24
25 · A dependency of one of your dependencies may have published a new
26 version, which will update even if you used pinned dependency speci‐
27 fiers (1.2.3 instead of ^1.2.3)
28
29 · The registry you installed from is no longer available, or allows
30 mutation of versions (unlike the primary npm registry), and a differ‐
31 ent version of a package exists under the same version number now.
32
33
34 As an example, consider package A:
35
36 {
37 "name": "A",
38 "version": "0.1.0",
39 "dependencies": {
40 "B": "<0.1.0"
41 }
42 }
43
44 package B:
45
46 {
47 "name": "B",
48 "version": "0.0.1",
49 "dependencies": {
50 "C": "<0.1.0"
51 }
52 }
53
54 and package C:
55
56 {
57 "name": "C",
58 "version": "0.0.1"
59 }
60
61 If these are the only versions of A, B, and C available in the reg‐
62 istry, then a normal npm install A will install:
63
64 A@0.1.0
65 `-- B@0.0.1
66 `-- C@0.0.1
67
68 However, if is published, then a fresh npm install A will install:
69
70 A@0.1.0
71 `-- B@0.0.2
72 `-- C@0.0.1
73
74 assuming the new version did not modify B's dependencies. Of course,
75 the new version of B could include a new version of C and any number of
76 new dependencies. If such changes are undesirable, the author of A
77 could specify a dependency on . However, if A's author and B's author
78 are not the same person, there's no way for A's author to say that he
79 or she does not want to pull in newly published versions of C when B
80 hasn't changed at all.
81
82 To prevent this potential issue, npm uses npm help 5 package-lock.json
83 or, if present, npm help 5 shrinkwrap.json. These files are called
84 package locks, or lockfiles.
85
86 Whenever you run npm install, npm generates or updates your package
87 lock, which will look something like this:
88
89 {
90 "name": "A",
91 "version": "0.1.0",
92 ...metadata fields...
93 "dependencies": {
94 "B": {
95 "version": "0.0.1",
96 "resolved": "https://registry.npmjs.org/B/-/B-0.0.1.tgz",
97 "integrity": "sha512-DeAdb33F+"
98 "dependencies": {
99 "C": {
100 "version": "git://github.com/org/C.git#5c380ae319fc4efe9e7f2d9c78b0faa588fd99b4"
101 }
102 }
103 }
104 }
105 }
106
107 This file describes an exact, and more importantly reproducible
108 node_modules tree. Once it's present, any future installation will base
109 its work off this file, instead of recalculating dependency versions
110 off npm help 5 package.json.
111
112 The presence of a package lock changes the installation behavior such
113 that:
114
115 1. The module tree described by the package lock is reproduced. This
116 means reproducing the structure described in the file, using the
117 specific files referenced in "resolved" if available, falling back
118 to normal package resolution using "version" if one isn't.
119
120 2. The tree is walked and any missing dependencies are installed in the
121 usual fashion.
122
123
124 If preshrinkwrap, shrinkwrap or postshrinkwrap are in the scripts prop‐
125 erty of the package.json, they will be executed in order. preshrinkwrap
126 and shrinkwrap are executed before the shrinkwrap, postshrinkwrap is
127 executed afterwards. These scripts run for both package-lock.json and
128 npm-shrinkwrap.json. For example to run some postprocessing on the gen‐
129 erated file:
130
131 "scripts": {
132 "postshrinkwrap": "json -I -e \"this.myMetadata = $MY_APP_METADATA\""
133 }
134
135 Using locked packages
136 Using a locked package is no different than using any package without a
137 package lock: any commands that update node_modules and/or pack‐
138 age.json's dependencies will automatically sync the existing lockfile.
139 This includes npm install, npm rm, npm update, etc. To prevent this
140 update from happening, you can use the --no-save option to prevent sav‐
141 ing altogether, or --no-shrinkwrap to allow package.json to be updated
142 while leaving package-lock.json or npm-shrinkwrap.json intact.
143
144 It is highly recommended you commit the generated package lock to
145 source control: this will allow anyone else on your team, your deploy‐
146 ments, your CI/continuous integration, and anyone else who runs npm
147 install in your package source to get the exact same dependency tree
148 that you were developing on. Additionally, the diffs from these changes
149 are human-readable and will inform you of any changes npm has made to
150 your node_modules, so you can notice if any transitive dependencies
151 were updated, hoisted, etc.
152
153 Resolving lockfile conflicts
154 Occasionally, two separate npm install will create package locks that
155 cause merge conflicts in source control systems. As of , these con‐
156 flicts can be resolved by manually fixing anypackage.jsonconflicts, and
157 then runningnpm install [--package-lock-only]again. npm will automati‐
158 cally resolve any conflicts for you and write a merged package lock
159 that includes all the dependencies from both branches in a reasonable
160 tree. If--package-lock-onlyis provided, it will do this without also
161 modifying your localnode_modules/`.
162
163 To make this process seamless on git, consider installing
164 npm-merge-driver https://npm.im/npm-merge-driver, which will teach git
165 how to do this itself without any user interaction. In short: $ npx
166 npm-merge-driver install -g will let you do this, and even works with
167 versions of npm 5, albeit a bit more noisily. Note that ifpack‐
168 age.jsonitself conflicts, you will have to resolve that by hand and
169 runnpm install` manually, even with the merge driver.
170
172 · https://
173
174 · npm help 5 package.json
175
176 · npm help 5 package-lock.json
177
178 · npm help 5 shrinkwrap.json
179
180 · npm help shrinkwrap
181
182
183
184
185 April 2019 NPM-PACKAGE-LOCKS(5)