1SCRIPTS(7) SCRIPTS(7)
2
3
4
6 scripts - How npm handles the "scripts" field
7
8 Description
9 The "scripts" property of your package.json file supports a number of
10 built-in scripts and their preset life cycle events as well as arbi‐
11 trary scripts. These all can be executed by running npm run-script
12 <stage> or npm run <stage> for short. Pre and post commands with match‐
13 ing names will be run for those as well (e.g. premyscript, myscript,
14 postmyscript). Scripts from dependencies can be run with npm explore
15 <pkg> -- npm run <stage>.
16
17 Pre & Post Scripts
18 To create "pre" or "post" scripts for any scripts defined in the
19 "scripts" section of the package.json, simply create another script
20 with a matching name and add "pre" or "post" to the beginning of them.
21
22 {
23 "scripts": {
24 "precompress": "{{ executes BEFORE the `compress` script }}",
25 "compress": "{{ run command to compress files }}",
26 "postcompress": "{{ executes AFTER `compress` script }}"
27 }
28 }
29
30 In this example npm run compress would execute these scripts as de‐
31 scribed.
32
33 Life Cycle Scripts
34 There are some special life cycle scripts that happen only in certain
35 situations. These scripts happen in addition to the pre<event>,
36 post<event>, and <event> scripts.
37
38 • prepare, prepublish, prepublishOnly, prepack, postpack, dependencies
39
40
41 prepare (since npm@4.0.0)
42
43 • Runs any time before the package is packed, i.e. during npm publish
44 and npm pack
45
46 • Runs BEFORE the package is packed
47
48 • Runs BEFORE the package is published
49
50 • Runs on local npm install without any arguments
51
52 • Run AFTER prepublish, but BEFORE prepublishOnly
53
54 • NOTE: If a package being installed through git contains a prepare
55 script, its dependencies and devDependencies will be installed, and
56 the prepare script will be run, before the package is packaged and
57 installed.
58
59 • As of npm@7 these scripts run in the background. To see the output,
60 run with: --foreground-scripts.
61
62
63 prepublish (DEPRECATED)
64
65 • Does not run during npm publish, but does run during npm ci and npm
66 install. See below for more info.
67
68
69 prepublishOnly
70
71 • Runs BEFORE the package is prepared and packed, ONLY on npm publish.
72
73
74 prepack
75
76 • Runs BEFORE a tarball is packed (on "npm pack", "npm publish", and
77 when installing a git dependencies).
78
79 • NOTE: "npm run pack" is NOT the same as "npm pack". "npm run pack" is
80 an arbitrary user defined script name, where as, "npm pack" is a CLI
81 defined command.
82
83
84 postpack
85
86 • Runs AFTER the tarball has been generated but before it is moved to
87 its final destination (if at all, publish does not save the tarball
88 locally)
89
90
91 dependencies
92
93 • Runs AFTER any operations that modify the node_modules directory IF
94 changes occurred.
95
96 • Does NOT run in global mode
97
98
99 Prepare and Prepublish
100 Deprecation Note: prepublish
101
102 Since npm@1.1.71, the npm CLI has run the prepublish script for both
103 npm publish and npm install, because it's a convenient way to prepare a
104 package for use (some common use cases are described in the section be‐
105 low). It has also turned out to be, in practice, very confusing
106 https://github.com/npm/npm/issues/10074. As of npm@4.0.0, a new event
107 has been introduced, prepare, that preserves this existing behavior. A
108 new event, prepublishOnly has been added as a transitional strategy to
109 allow users to avoid the confusing behavior of existing npm versions
110 and only run on npm publish (for instance, running the tests one last
111 time to ensure they're in good shape).
112
113 See https://github.com/npm/npm/issues/10074 for a much lengthier justi‐
114 fication, with further reading, for this change.
115
116 Use Cases
117
118 If you need to perform operations on your package before it is used, in
119 a way that is not dependent on the operating system or architecture of
120 the target system, use a prepublish script. This includes tasks such
121 as:
122
123 • Compiling CoffeeScript source code into JavaScript.
124
125 • Creating minified versions of JavaScript source code.
126
127 • Fetching remote resources that your package will use.
128
129
130 The advantage of doing these things at prepublish time is that they can
131 be done once, in a single place, thus reducing complexity and variabil‐
132 ity. Additionally, this means that:
133
134 • You can depend on coffee-script as a devDependency, and thus your
135 users don't need to have it installed.
136
137 • You don't need to include minifiers in your package, reducing the
138 size for your users.
139
140 • You don't need to rely on your users having curl or wget or other
141 system tools on the target machines.
142
143
144 Dependencies
145 The dependencies script is run any time an npm command causes changes
146 to the node_modules directory. It is run AFTER the changes have been
147 applied and the package.json and package-lock.json files have been up‐
148 dated.
149
150 Life Cycle Operation Order
151 npm help cache add
152 • prepare
153
154
155 npm help ci
156 • preinstall
157
158 • install
159
160 • postinstall
161
162 • prepublish
163
164 • preprepare
165
166 • prepare
167
168 • postprepare These all run after the actual installation of modules
169 into node_modules, in order, with no internal actions happening in
170 between
171
172
173 npm help diff
174 • prepare
175
176
177 npm help install
178 These also run when you run npm install -g <pkg-name>
179
180 • preinstall
181
182 • install
183
184 • postinstall
185
186 • prepublish
187
188 • preprepare
189
190 • prepare
191
192 • postprepare
193
194
195 If there is a binding.gyp file in the root of your package and you
196 haven't defined your own install or preinstall scripts, npm will de‐
197 fault the install command to compile using node-gyp via node-gyp re‐
198 build
199
200 These are run from the scripts of <pkg-name>
201
202 npm help pack
203 • prepack
204
205 • prepare
206
207 • postpack
208
209
210 npm help publish
211 • prepublishOnly
212
213 • prepack
214
215 • prepare
216
217 • postpack
218
219 • publish
220
221 • postpublish
222
223
224 prepare will not run during --dry-run
225
226 npm help rebuild
227 • preinstall
228
229 • install
230
231 • postinstall
232
233 • prepare
234
235
236 prepare is only run if the current directory is a symlink (e.g. with
237 linked packages)
238
239 npm help restart
240 If there is a restart script defined, these events are run, otherwise
241 stop and start are both run if present, including their pre and post
242 iterations)
243
244 • prerestart
245
246 • restart
247
248 • postrestart
249
250
251 npm help run <user defined>
252 • pre<user-defined>
253
254 • <user-defined>
255
256 • post<user-defined>
257
258
259 npm help start
260 • prestart
261
262 • start
263
264 • poststart
265
266
267 If there is a server.js file in the root of your package, then npm will
268 default the start command to node server.js. prestart and poststart
269 will still run in this case.
270
271 npm help stop
272 • prestop
273
274 • stop
275
276 • poststop
277
278
279 npm help test
280 • pretest
281
282 • test
283
284 • posttest
285
286
287 npm help version
288 • preversion
289
290 • version
291
292 • postversion
293
294
295 A Note on a lack of npm help uninstall scripts
296 While npm v6 had uninstall lifecycle scripts, npm v7 does not. Removal
297 of a package can happen for a wide variety of reasons, and there's no
298 clear way to currently give the script enough context to be useful.
299
300 Reasons for a package removal include:
301
302 • a user directly uninstalled this package
303
304 • a user uninstalled a dependant package and so this dependency is be‐
305 ing uninstalled
306
307 • a user uninstalled a dependant package but another package also de‐
308 pends on this version
309
310 • this version has been merged as a duplicate with another version
311
312 • etc.
313
314
315 Due to the lack of necessary context, uninstall lifecycle scripts are
316 not implemented and will not function.
317
318 User
319 When npm is run as root, scripts are always run with the effective uid
320 and gid of the working directory owner.
321
322 Environment
323 Package scripts run in an environment where many pieces of information
324 are made available regarding the setup of npm and the current state of
325 the process.
326
327 path
328 If you depend on modules that define executable scripts, like test
329 suites, then those executables will be added to the PATH for executing
330 the scripts. So, if your package.json has this:
331
332 {
333 "name" : "foo",
334 "dependencies" : {
335 "bar" : "0.1.x"
336 },
337 "scripts": {
338 "start" : "bar ./test"
339 }
340 }
341
342 then you could run npm start to execute the bar script, which is ex‐
343 ported into the node_modules/.bin directory on npm install.
344
345 package.json vars
346 The package.json fields are tacked onto the npm_package_ prefix. So,
347 for instance, if you had {"name":"foo", "version":"1.2.5"} in your
348 package.json file, then your package scripts would have the npm_pack‐
349 age_name environment variable set to "foo", and the npm_package_version
350 set to "1.2.5". You can access these variables in your code with
351 process.env.npm_package_name and process.env.npm_package_version, and
352 so on for other fields.
353
354 See npm help package.json for more on package configs.
355
356 current lifecycle event
357 Lastly, the npm_lifecycle_event environment variable is set to which‐
358 ever stage of the cycle is being executed. So, you could have a single
359 script used for different parts of the process which switches based on
360 what's currently happening.
361
362 Objects are flattened following this format, so if you had
363 {"scripts":{"install":"foo.js"}} in your package.json, then you'd see
364 this in the script:
365
366 process.env.npm_package_scripts_install === "foo.js"
367
368 Examples
369 For example, if your package.json contains this:
370
371 {
372 "scripts" : {
373 "install" : "scripts/install.js",
374 "postinstall" : "scripts/install.js",
375 "uninstall" : "scripts/uninstall.js"
376 }
377 }
378
379 then scripts/install.js will be called for the install and post-install
380 stages of the lifecycle, and scripts/uninstall.js will be called when
381 the package is uninstalled. Since scripts/install.js is running for
382 two different phases, it would be wise in this case to look at the
383 npm_lifecycle_event environment variable.
384
385 If you want to run a make command, you can do so. This works just
386 fine:
387
388 {
389 "scripts" : {
390 "preinstall" : "./configure",
391 "install" : "make && make install",
392 "test" : "make test"
393 }
394 }
395
396 Exiting
397 Scripts are run by passing the line as a script argument to sh.
398
399 If the script exits with a code other than 0, then this will abort the
400 process.
401
402 Note that these script files don't have to be Node.js or even Java‐
403 Script programs. They just have to be some kind of executable file.
404
405 Best Practices
406 • Don't exit with a non-zero error code unless you really mean it. Ex‐
407 cept for uninstall scripts, this will cause the npm action to fail,
408 and potentially be rolled back. If the failure is minor or only will
409 prevent some optional features, then it's better to just print a
410 warning and exit successfully.
411
412 • Try not to use scripts to do what npm can do for you. Read through
413 npm help package.json to see all the things that you can specify and
414 enable by simply describing your package appropriately. In general,
415 this will lead to a more robust and consistent state.
416
417 • Inspect the env to determine where to put things. For instance, if
418 the npm_config_binroot environment variable is set to /home/user/bin,
419 then don't try to install executables into /usr/local/bin. The user
420 probably set it up that way for a reason.
421
422 • Don't prefix your script commands with "sudo". If root permissions
423 are required for some reason, then it'll fail with that error, and
424 the user will sudo the npm command in question.
425
426 • Don't use install. Use a .gyp file for compilation, and prepare for
427 anything else. You should almost never have to explicitly set a pre‐
428 install or install script. If you are doing this, please consider if
429 there is another option. The only valid use of install or preinstall
430 scripts is for compilation which must be done on the target architec‐
431 ture.
432
433 • Scripts are run from the root of the package folder, regardless of
434 what the current working directory is when npm is invoked. If you
435 want your script to use different behavior based on what subdirectory
436 you're in, you can use the INIT_CWD environment variable, which holds
437 the full path you were in when you ran npm run.
438
439
440 See Also
441 • npm help run-script
442
443 • npm help package.json
444
445 • npm help developers
446
447 • npm help install
448
449
450
451
452 September 2022 SCRIPTS(7)