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 B@0.0.2 is published, then a fresh npm install A will
69 install:
70
71 A@0.1.0
72 `-- B@0.0.2
73 `-- C@0.0.1
74
75 assuming the new version did not modify B's dependencies. Of course,
76 the new version of B could include a new version of C and any number of
77 new dependencies. If such changes are undesirable, the author of A
78 could specify a dependency on B@0.0.1. However, if A's author and B's
79 author are not the same person, there's no way for A's author to say
80 that he or she does not want to pull in newly published versions of C
81 when B hasn't changed at all.
82
83 To prevent this potential issue, npm uses npm help 5 package-lock.json
84 or, if present, npm help 5 shrinkwrap.json. These files are called
85 package locks, or lockfiles.
86
87 Whenever you run npm install, npm generates or updates your package
88 lock, which will look something like this:
89
90 {
91 "name": "A",
92 "version": "0.1.0",
93 ...metadata fields...
94 "dependencies": {
95 "B": {
96 "version": "0.0.1",
97 "resolved": "https://registry.npmjs.org/B/-/B-0.0.1.tgz",
98 "integrity": "sha512-DeAdb33F+"
99 "dependencies": {
100 "C": {
101 "version": "git://github.com/org/C.git#5c380ae319fc4efe9e7f2d9c78b0faa588fd99b4"
102 }
103 }
104 }
105 }
106 }
107
108 This file describes an exact, and more importantly reproducible
109 node_modules tree. Once it's present, any future installation will base
110 its work off this file, instead of recalculating dependency versions
111 off npm help 5 package.json.
112
113 The presence of a package lock changes the installation behavior such
114 that:
115
116 1. The module tree described by the package lock is reproduced. This
117 means reproducing the structure described in the file, using the
118 specific files referenced in "resolved" if available, falling back
119 to normal package resolution using "version" if one isn't.
120
121 2. The tree is walked and any missing dependencies are installed in the
122 usual fashion.
123
124
125 If preshrinkwrap, shrinkwrap or postshrinkwrap are in the scripts prop‐
126 erty of the package.json, they will be executed in order. preshrinkwrap
127 and shrinkwrap are executed before the shrinkwrap, postshrinkwrap is
128 executed afterwards. These scripts run for both package-lock.json and
129 npm-shrinkwrap.json. For example to run some postprocessing on the gen‐
130 erated file:
131
132 "scripts": {
133 "postshrinkwrap": "json -I -e \"this.myMetadata = $MY_APP_METADATA\""
134 }
135
136 Using locked packages
137 Using a locked package is no different than using any package without a
138 package lock: any commands that update node_modules and/or pack‐
139 age.json's dependencies will automatically sync the existing lockfile.
140 This includes npm install, npm rm, npm update, etc. To prevent this
141 update from happening, you can use the --no-save option to prevent sav‐
142 ing altogether, or --no-shrinkwrap to allow package.json to be updated
143 while leaving package-lock.json or npm-shrinkwrap.json intact.
144
145 It is highly recommended you commit the generated package lock to
146 source control: this will allow anyone else on your team, your deploy‐
147 ments, your CI/continuous integration, and anyone else who runs npm
148 install in your package source to get the exact same dependency tree
149 that you were developing on. Additionally, the diffs from these changes
150 are human-readable and will inform you of any changes npm has made to
151 your node_modules, so you can notice if any transitive dependencies
152 were updated, hoisted, etc.
153
154 Resolving lockfile conflicts
155 Occasionally, two separate npm install will create package locks that
156 cause merge conflicts in source control systems. As of npm@5.7.0, these
157 conflicts can be resolved by manually fixing any package.json con‐
158 flicts, and then running npm install [--package-lock-only] again. npm
159 will automatically resolve any conflicts for you and write a merged
160 package lock that includes all the dependencies from both branches in a
161 reasonable tree. If --package-lock-only is provided, it will do this
162 without also modifying your local node_modules/.
163
164 To make this process seamless on git, consider installing
165 npm-merge-driver https://npm.im/npm-merge-driver, which will teach git
166 how to do this itself without any user interaction. In short: $ npx
167 npm-merge-driver install -g will let you do this, and even works with
168 pre-npm@5.7.0 versions of npm 5, albeit a bit more noisily. Note that
169 if package.json itself conflicts, you will have to resolve that by hand
170 and run npm install manually, even with the merge driver.
171
173 · https://medium.com/@sdboyer/so-you-want-to-write-a-package-man‐
174 ager-4ae9c17d9527
175
176 · npm help 5 package.json
177
178 · npm help 5 package-lock.json
179
180 · npm help 5 shrinkwrap.json
181
182 · npm help shrinkwrap
183
184
185
186
187 October 2019 NPM-PACKAGE-LOCKS(5)