1--- 2section: using-npm 3title: scripts 4description: How npm handles the "scripts" field 5--- 6 7# scripts(7) 8 9## How npm handles the "scripts" field 10 11### Description 12 13The `"scripts"` property of of your `package.json` file supports a number of built-in scripts and their preset life cycle events as well as arbitrary scripts. These all can be executed by running `npm run-script <stage>` or `npm run <stage>` for short. *Pre* and *post* commands with matching names will be run for those as well (e.g. `premyscript`, `myscript`, `postmyscript`). Scripts from dependencies can be run with `npm explore <pkg> -- npm run <stage>`. 14 15### Pre & Post Scripts 16 17To create "pre" or "post" scripts for any scripts defined in the `"scripts"` section of the `package.json`, simply create another script *with a matching name* and add "pre" or "post" to the beginning of them. 18 19```json 20{ 21 "scripts": { 22 "precompress": "{{ executes BEFORE the `compress` script }}", 23 "compress": "{{ run command to compress files }}", 24 "postcompress": "{{ executes AFTER `compress` script }}" 25 } 26} 27``` 28 29### Life Cycle Scripts 30 31There are some special life cycle scripts that happen only in certain situations. These scripts happen in addtion to the "pre" and "post" script. 32* `prepare`, `prepublish`, `prepublishOnly`, `prepack`, `postpack` 33 34**prepare** (since `npm@4.0.0`) 35* Runs BEFORE the package is packed 36* Runs BEFORE the package is published 37* Runs on local `npm install` without any arguments 38* Run AFTER `prepublish`, but BEFORE `prepublishOnly` 39* NOTE: If a package being installed through git contains a `prepare` script, its `dependencies` and `devDependencies` will be installed, and the prepare script will be run, before the package is packaged and installed. 40 41**prepublish** (DEPRECATED) 42* Same as `prepare` 43 44**prepublishOnly** 45* Runs BEFORE the package is prepared and packed, ONLY on `npm publish`. 46 47**prepack** 48* Runs BEFORE a tarball is packed (on "`npm pack`", "`npm publish`", and when installing a git dependencies). 49* NOTE: "`npm run pack`" is NOT the same as "`npm pack`". "`npm run pack`" is an arbitrary user defined script name, where as, "`npm pack`" is a CLI defined command. 50 51**postpack** 52* Runs AFTER the tarball has been generated and moved to its final destination. 53 54#### Prepare and Prepublish 55 56**Deprecation Note: prepublish** 57 58Since `npm@1.1.71`, the npm CLI has run the `prepublish` script for both `npm publish` and `npm install`, because it's a convenient way to prepare a package for use (some common use cases are described in the section below). It has also turned out to be, in practice, [very confusing](https://github.com/npm/npm/issues/10074). As of `npm@4.0.0`, a new event has been introduced, `prepare`, that preserves this existing behavior. A _new_ event, `prepublishOnly` has been added as a transitional strategy to allow users to avoid the confusing behavior of existing npm versions and only run on `npm publish` (for instance, running the tests one last time to ensure they're in good shape). 59 60See <https://github.com/npm/npm/issues/10074> for a much lengthier justification, with further reading, for this change. 61 62**Use Cases** 63 64If you need to perform operations on your package before it is used, in a way that is not dependent on the operating system or architecture of the target system, use a `prepublish` script. This includes tasks such as: 65 66* Compiling CoffeeScript source code into JavaScript. 67* Creating minified versions of JavaScript source code. 68* Fetching remote resources that your package will use. 69 70The advantage of doing these things at `prepublish` time is that they can be done once, in a single place, thus reducing complexity and variability. Additionally, this means that: 71 72* You can depend on `coffee-script` as a `devDependency`, and thus 73 your users don't need to have it installed. 74* You don't need to include minifiers in your package, reducing 75 the size for your users. 76* You don't need to rely on your users having `curl` or `wget` or 77 other system tools on the target machines. 78 79### Life Cycle Operation Order 80 81#### [`npm publish`](/cli-commands/npm-publish) 82 83* `prepublishOnly` 84* `prepare` 85* `prepublish` 86* `publish` 87* `postpublish` 88 89#### [`npm pack`](/cli-commands/npm-pack) 90 91* `prepack` 92* `postpack` 93 94#### [`npm install`](/cli-commands/npm-install) 95 96* `preinstall` 97* `install` 98* `postinstall` 99 100Also triggers 101 102* `prepublish` (when on local) 103* `prepare` (when on local) 104 105#### [`npm start`](/cli-commands/npm-start) 106 107`npm run start` has an `npm start` shorthand. 108 109* `prestart` 110* `start` 111* `poststart` 112 113### Default Values 114npm will default some script values based on package contents. 115 116* `"start": "node server.js"`: 117 118 If there is a `server.js` file in the root of your package, then npm 119 will default the `start` command to `node server.js`. 120 121* `"install": "node-gyp rebuild"`: 122 123 If there is a `binding.gyp` file in the root of your package and you 124 haven't defined your own `install` or `preinstall` scripts, npm will 125 default the `install` command to compile using node-gyp. 126 127### User 128 129If npm was invoked with root privileges, then it will change the uid 130to the user account or uid specified by the `user` config, which 131defaults to `nobody`. Set the `unsafe-perm` flag to run scripts with 132root privileges. 133 134### Environment 135 136Package scripts run in an environment where many pieces of information 137are made available regarding the setup of npm and the current state of 138the process. 139 140 141#### path 142 143If you depend on modules that define executable scripts, like test 144suites, then those executables will be added to the `PATH` for 145executing the scripts. So, if your package.json has this: 146 147```json 148{ 149 "name" : "foo", 150 "dependencies" : { 151 "bar" : "0.1.x" 152 }, 153 "scripts": { 154 "start" : "bar ./test" 155 } 156} 157``` 158 159then you could run `npm start` to execute the `bar` script, which is 160exported into the `node_modules/.bin` directory on `npm install`. 161 162#### package.json vars 163 164The package.json fields are tacked onto the `npm_package_` prefix. So, 165for instance, if you had `{"name":"foo", "version":"1.2.5"}` in your 166package.json file, then your package scripts would have the 167`npm_package_name` environment variable set to "foo", and the 168`npm_package_version` set to "1.2.5". You can access these variables 169in your code with `process.env.npm_package_name` and 170`process.env.npm_package_version`, and so on for other fields. 171 172#### configuration 173 174Configuration parameters are put in the environment with the 175`npm_config_` prefix. For instance, you can view the effective `root` 176config by checking the `npm_config_root` environment variable. 177 178#### Special: package.json "config" object 179 180The package.json "config" keys are overwritten in the environment if 181there is a config param of `<name>[@<version>]:<key>`. For example, 182if the package.json has this: 183 184```json 185{ 186 "name" : "foo", 187 "config" : { 188 "port" : "8080" 189 }, 190 "scripts" : { 191 "start" : "node server.js" 192 } 193} 194``` 195 196and the server.js is this: 197 198```javascript 199http.createServer(...).listen(process.env.npm_package_config_port) 200``` 201 202then the user could change the behavior by doing: 203 204```bash 205 npm config set foo:port 80 206 ``` 207 208#### current lifecycle event 209 210Lastly, the `npm_lifecycle_event` environment variable is set to 211whichever stage of the cycle is being executed. So, you could have a 212single script used for different parts of the process which switches 213based on what's currently happening. 214 215Objects are flattened following this format, so if you had 216`{"scripts":{"install":"foo.js"}}` in your package.json, then you'd 217see this in the script: 218 219```bash 220process.env.npm_package_scripts_install === "foo.js" 221``` 222 223### Examples 224 225For example, if your package.json contains this: 226 227```json 228{ 229 "scripts" : { 230 "install" : "scripts/install.js", 231 "postinstall" : "scripts/install.js", 232 "uninstall" : "scripts/uninstall.js" 233 } 234} 235``` 236 237then `scripts/install.js` will be called for the install 238and post-install stages of the lifecycle, and `scripts/uninstall.js` 239will be called when the package is uninstalled. Since 240`scripts/install.js` is running for two different phases, it would 241be wise in this case to look at the `npm_lifecycle_event` environment 242variable. 243 244If you want to run a make command, you can do so. This works just 245fine: 246 247```json 248{ 249 "scripts" : { 250 "preinstall" : "./configure", 251 "install" : "make && make install", 252 "test" : "make test" 253 } 254} 255``` 256 257### Exiting 258 259Scripts are run by passing the line as a script argument to `sh`. 260 261If the script exits with a code other than 0, then this will abort the 262process. 263 264Note that these script files don't have to be nodejs or even 265javascript programs. They just have to be some kind of executable 266file. 267 268### Hook Scripts 269 270If you want to run a specific script at a specific lifecycle event for 271ALL packages, then you can use a hook script. 272 273Place an executable file at `node_modules/.hooks/{eventname}`, and 274it'll get run for all packages when they are going through that point 275in the package lifecycle for any packages installed in that root. 276 277Hook scripts are run exactly the same way as package.json scripts. 278That is, they are in a separate child process, with the env described 279above. 280 281### Best Practices 282 283* Don't exit with a non-zero error code unless you *really* mean it. 284 Except for uninstall scripts, this will cause the npm action to 285 fail, and potentially be rolled back. If the failure is minor or 286 only will prevent some optional features, then it's better to just 287 print a warning and exit successfully. 288* Try not to use scripts to do what npm can do for you. Read through 289 [`package.json`](/configuring-npm/package-json) to see all the things that you can specify and enable 290 by simply describing your package appropriately. In general, this 291 will lead to a more robust and consistent state. 292* Inspect the env to determine where to put things. For instance, if 293 the `npm_config_binroot` environment variable is set to `/home/user/bin`, then 294 don't try to install executables into `/usr/local/bin`. The user 295 probably set it up that way for a reason. 296* Don't prefix your script commands with "sudo". If root permissions 297 are required for some reason, then it'll fail with that error, and 298 the user will sudo the npm command in question. 299* Don't use `install`. Use a `.gyp` file for compilation, and `prepublish` 300 for anything else. You should almost never have to explicitly set a 301 preinstall or install script. If you are doing this, please consider if 302 there is another option. The only valid use of `install` or `preinstall` 303 scripts is for compilation which must be done on the target architecture. 304 305### See Also 306 307* [npm run-script](/cli-commands/npm-run-script) 308* [package.json](/configuring-npm/package-json) 309* [npm developers](/using-npm/developers) 310* [npm install](/cli-commands/npm-install) 311