dependabot/npm_and_yarn/main/copy-to-clipboard-4.0.2
@reggi/path-to-regexp
dependabot/npm_and_yarn/main/copy-to-clipboard-4.0.2
dependabot/npm_and_yarn/main/eslint-10.4.0
dependabot/npm_and_yarn/main/npmcli/eslint-config-7.0.0
dependabot/npm_and_yarn/main/proc-log-7.0.0
dependabot/npm_and_yarn/npm_and_yarn-826852524d
dependabot/npm_and_yarn/npm_and_yarn-ab9a7f4bc2
deprecate-totp-2fa
dhei/classic-tokens
gat-bypass-2fa-docs
jpg619/fix-accessibility-content-flow
jpg619/version-bump-tar-2
kartykp/gat-bypass-2fa-docs
kartykp/upgrade-path-to-regex
main
maitxn/version-bump-tar
patch-1
reggi/cache-based-on-version
reggi/dev-engines
reggi/fix-transform-prettier
reggi/overrides
update-search-sensitivity
| 1 | --- |
| 2 | title: scripts |
| 3 | section: 7 |
| 4 | description: How npm handles the "scripts" field |
| 5 | github_repo: npm/cli |
| 6 | github_branch: release/v10 |
| 7 | github_path: docs/lib/content/using-npm/scripts.md |
| 8 | redirect_from: |
| 9 | - /cli-documentation/v10/misc/scripts |
| 10 | - /cli-documentation/v10/using-npm/scripts |
| 11 | - /cli/v10/misc/scripts |
| 12 | --- |
| 13 | |
| 14 | ### Description |
| 15 | |
| 16 | The `"scripts"` property 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>`. |
| 17 | |
| 18 | ### Pre & Post Scripts |
| 19 | |
| 20 | To 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. |
| 21 | |
| 22 | ```json |
| 23 | { |
| 24 | "scripts": { |
| 25 | "precompress": "{{ executes BEFORE the `compress` script }}", |
| 26 | "compress": "{{ run command to compress files }}", |
| 27 | "postcompress": "{{ executes AFTER `compress` script }}" |
| 28 | } |
| 29 | } |
| 30 | ``` |
| 31 | |
| 32 | In this example `npm run compress` would execute these scripts as described. |
| 33 | |
| 34 | ### Life Cycle Scripts |
| 35 | |
| 36 | There are some special life cycle scripts that happen only in certain situations. These scripts happen in addition to the `pre<event>`, `post<event>`, and `<event>` scripts. |
| 37 | |
| 38 | - `prepare`, `prepublish`, `prepublishOnly`, `prepack`, `postpack`, `dependencies` |
| 39 | |
| 40 | **prepare** (since `npm@4.0.0`) |
| 41 | |
| 42 | - Runs BEFORE the package is packed, i.e. during `npm publish` and `npm pack` |
| 43 | - Runs on local `npm install` without any arguments |
| 44 | - Runs AFTER `prepublish`, but BEFORE `prepublishOnly` |
| 45 | |
| 46 | - 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. |
| 47 | |
| 48 | - As of `npm@7` these scripts run in the background. To see the output, run with: `--foreground-scripts`. |
| 49 | |
| 50 | **prepublish** (DEPRECATED) |
| 51 | |
| 52 | - Does not run during `npm publish`, but does run during `npm ci` and `npm install`. See below for more info. |
| 53 | |
| 54 | **prepublishOnly** |
| 55 | |
| 56 | - Runs BEFORE the package is prepared and packed, ONLY on `npm publish`. |
| 57 | |
| 58 | **prepack** |
| 59 | |
| 60 | - Runs BEFORE a tarball is packed (on "`npm pack`", "`npm publish`", and when installing a git dependency). |
| 61 | - 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. |
| 62 | |
| 63 | **postpack** |
| 64 | |
| 65 | - Runs AFTER the tarball has been generated but before it is moved to its final destination (if at all, publish does not save the tarball locally) |
| 66 | |
| 67 | **dependencies** |
| 68 | |
| 69 | - Runs AFTER any operations that modify the `node_modules` directory IF changes occurred. |
| 70 | - Does NOT run in global mode |
| 71 | |
| 72 | #### Prepare and Prepublish |
| 73 | |
| 74 | **Deprecation Note: prepublish** |
| 75 | |
| 76 | Since `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). |
| 77 | |
| 78 | See [https://github.com/npm/npm/issues/10074](https://github.com/npm/npm/issues/10074) for a much lengthier justification, with further reading, for this change. |
| 79 | |
| 80 | **Use Cases** |
| 81 | |
| 82 | If 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: |
| 83 | |
| 84 | - Compiling CoffeeScript source code into JavaScript. |
| 85 | - Creating minified versions of JavaScript source code. |
| 86 | - Fetching remote resources that your package will use. |
| 87 | |
| 88 | The 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: |
| 89 | |
| 90 | - You can depend on `coffee-script` as a `devDependency`, and thus your users don't need to have it installed. |
| 91 | - You don't need to include minifiers in your package, reducing the size for your users. |
| 92 | - You don't need to rely on your users having `curl` or `wget` or other system tools on the target machines. |
| 93 | |
| 94 | #### Dependencies |
| 95 | |
| 96 | The `dependencies` script is run any time an `npm` command causes changes to the `node_modules` directory. It is run AFTER the changes have been applied and the `package.json` and `package-lock.json` files have been updated. |
| 97 | |
| 98 | ### Life Cycle Operation Order |
| 99 | |
| 100 | #### [`npm cache add`](/cli/v10/commands/npm-cache) |
| 101 | |
| 102 | - `prepare` |
| 103 | |
| 104 | #### [`npm ci`](/cli/v10/commands/npm-ci) |
| 105 | |
| 106 | - `preinstall` |
| 107 | - `install` |
| 108 | - `postinstall` |
| 109 | - `prepublish` |
| 110 | - `preprepare` |
| 111 | - `prepare` |
| 112 | - `postprepare` |
| 113 | |
| 114 | These all run after the actual installation of modules into `node_modules`, in order, with no internal actions happening in between |
| 115 | |
| 116 | #### [`npm diff`](/cli/v10/commands/npm-diff) |
| 117 | |
| 118 | - `prepare` |
| 119 | |
| 120 | #### [`npm install`](/cli/v10/commands/npm-install) |
| 121 | |
| 122 | These also run when you run `npm install -g <pkg-name>` |
| 123 | |
| 124 | - `preinstall` |
| 125 | - `install` |
| 126 | - `postinstall` |
| 127 | - `prepublish` |
| 128 | - `preprepare` |
| 129 | - `prepare` |
| 130 | - `postprepare` |
| 131 | |
| 132 | If there is a `binding.gyp` file in the root of your package and you haven't defined your own `install` or `preinstall` scripts, npm will default the `install` command to compile using node-gyp via `node-gyp rebuild` |
| 133 | |
| 134 | These are run from the scripts of `<pkg-name>` |
| 135 | |
| 136 | #### [`npm pack`](/cli/v10/commands/npm-pack) |
| 137 | |
| 138 | - `prepack` |
| 139 | - `prepare` |
| 140 | - `postpack` |
| 141 | |
| 142 | #### [`npm publish`](/cli/v10/commands/npm-publish) |
| 143 | |
| 144 | - `prepublishOnly` |
| 145 | - `prepack` |
| 146 | - `prepare` |
| 147 | - `postpack` |
| 148 | - `publish` |
| 149 | - `postpublish` |
| 150 | |
| 151 | #### [`npm rebuild`](/cli/v10/commands/npm-rebuild) |
| 152 | |
| 153 | - `preinstall` |
| 154 | - `install` |
| 155 | - `postinstall` |
| 156 | - `prepare` |
| 157 | |
| 158 | `prepare` is only run if the current directory is a symlink (e.g. with linked packages) |
| 159 | |
| 160 | #### [`npm restart`](/cli/v10/commands/npm-restart) |
| 161 | |
| 162 | If there is a `restart` script defined, these events are run, otherwise `stop` and `start` are both run if present, including their `pre` and `post` iterations) |
| 163 | |
| 164 | - `prerestart` |
| 165 | - `restart` |
| 166 | - `postrestart` |
| 167 | |
| 168 | #### [`npm run <user defined>`](/cli/v10/commands/npm-run-script) |
| 169 | |
| 170 | - `pre<user-defined>` |
| 171 | - `<user-defined>` |
| 172 | - `post<user-defined>` |
| 173 | |
| 174 | #### [`npm start`](/cli/v10/commands/npm-start) |
| 175 | |
| 176 | - `prestart` |
| 177 | - `start` |
| 178 | - `poststart` |
| 179 | |
| 180 | If there is a `server.js` file in the root of your package, then npm will default the `start` command to `node server.js`. `prestart` and `poststart` will still run in this case. |
| 181 | |
| 182 | #### [`npm stop`](/cli/v10/commands/npm-stop) |
| 183 | |
| 184 | - `prestop` |
| 185 | - `stop` |
| 186 | - `poststop` |
| 187 | |
| 188 | #### [`npm test`](/cli/v10/commands/npm-test) |
| 189 | |
| 190 | - `pretest` |
| 191 | - `test` |
| 192 | - `posttest` |
| 193 | |
| 194 | #### [`npm version`](/cli/v10/commands/npm-version) |
| 195 | |
| 196 | - `preversion` |
| 197 | - `version` |
| 198 | - `postversion` |
| 199 | |
| 200 | #### A Note on a lack of [`npm uninstall`](/cli/v10/commands/npm-uninstall) scripts |
| 201 | |
| 202 | While npm v6 had `uninstall` lifecycle scripts, npm v7 does not. Removal of a package can happen for a wide variety of reasons, and there's no clear way to currently give the script enough context to be useful. |
| 203 | |
| 204 | Reasons for a package removal include: |
| 205 | |
| 206 | - a user directly uninstalled this package |
| 207 | - a user uninstalled a dependant package and so this dependency is being uninstalled |
| 208 | - a user uninstalled a dependant package but another package also depends on this version |
| 209 | - this version has been merged as a duplicate with another version |
| 210 | - etc. |
| 211 | |
| 212 | Due to the lack of necessary context, `uninstall` lifecycle scripts are not implemented and will not function. |
| 213 | |
| 214 | ### User |
| 215 | |
| 216 | When npm is run as root, scripts are always run with the effective uid and gid of the working directory owner. |
| 217 | |
| 218 | ### Environment |
| 219 | |
| 220 | Package scripts run in an environment where many pieces of information are made available regarding the setup of npm and the current state of the process. |
| 221 | |
| 222 | #### path |
| 223 | |
| 224 | If you depend on modules that define executable scripts, like test suites, then those executables will be added to the `PATH` for executing the scripts. So, if your package.json has this: |
| 225 | |
| 226 | ```json |
| 227 | { |
| 228 | "name": "foo", |
| 229 | "dependencies": { |
| 230 | "bar": "0.1.x" |
| 231 | }, |
| 232 | "scripts": { |
| 233 | "start": "bar ./test" |
| 234 | } |
| 235 | } |
| 236 | ``` |
| 237 | |
| 238 | then you could run `npm start` to execute the `bar` script, which is exported into the `node_modules/.bin` directory on `npm install`. |
| 239 | |
| 240 | #### package.json vars |
| 241 | |
| 242 | The package.json fields are tacked onto the `npm_package_` prefix. So, for instance, if you had `{"name":"foo", "version":"1.2.5"}` in your package.json file, then your package scripts would have the `npm_package_name` environment variable set to "foo", and the `npm_package_version` set to "1.2.5". You can access these variables in your code with `process.env.npm_package_name` and `process.env.npm_package_version`, and so on for other fields. |
| 243 | |
| 244 | See [`package.json`](/cli/v10/configuring-npm/package-json) for more on package configs. |
| 245 | |
| 246 | #### current lifecycle event |
| 247 | |
| 248 | Lastly, the `npm_lifecycle_event` environment variable is set to whichever stage of the cycle is being executed. So, you could have a single script used for different parts of the process which switches based on what's currently happening. |
| 249 | |
| 250 | Objects are flattened following this format, so if you had `{"scripts":{"install":"foo.js"}}` in your package.json, then you'd see this in the script: |
| 251 | |
| 252 | ```bash |
| 253 | process.env.npm_package_scripts_install === "foo.js" |
| 254 | ``` |
| 255 | |
| 256 | ### Examples |
| 257 | |
| 258 | For example, if your package.json contains this: |
| 259 | |
| 260 | ```json |
| 261 | { |
| 262 | "scripts": { |
| 263 | "install": "scripts/install.js", |
| 264 | "postinstall": "scripts/install.js" |
| 265 | } |
| 266 | } |
| 267 | ``` |
| 268 | |
| 269 | then `scripts/install.js` will be called for the install and post-install stages of the lifecycle. Since `scripts/install.js` is running for two different phases, it would be wise in this case to look at the `npm_lifecycle_event` environment variable. |
| 270 | |
| 271 | If you want to run a make command, you can do so. This works just fine: |
| 272 | |
| 273 | ```json |
| 274 | { |
| 275 | "scripts": { |
| 276 | "preinstall": "./configure", |
| 277 | "install": "make && make install", |
| 278 | "test": "make test" |
| 279 | } |
| 280 | } |
| 281 | ``` |
| 282 | |
| 283 | ### Exiting |
| 284 | |
| 285 | Scripts are run by passing the line as a script argument to `sh`. |
| 286 | |
| 287 | If the script exits with a code other than 0, then this will abort the process. |
| 288 | |
| 289 | Note that these script files don't have to be Node.js or even JavaScript programs. They just have to be some kind of executable file. |
| 290 | |
| 291 | ### Best Practices |
| 292 | |
| 293 | - Don't exit with a non-zero error code unless you _really_ mean it. If the failure is minor or only will prevent some optional features, then it's better to just print a warning and exit successfully. |
| 294 | - Try not to use scripts to do what npm can do for you. Read through [`package.json`](/cli/v10/configuring-npm/package-json) to see all the things that you can specify and enable by simply describing your package appropriately. In general, this will lead to a more robust and consistent state. |
| 295 | - Inspect the env to determine where to put things. For instance, if the `npm_config_binroot` environment variable is set to `/home/user/bin`, then don't try to install executables into `/usr/local/bin`. The user probably set it up that way for a reason. |
| 296 | - Don't prefix your script commands with "sudo". If root permissions are required for some reason, then it'll fail with that error, and the user will sudo the npm command in question. |
| 297 | - Don't use `install`. Use a `.gyp` file for compilation, and `prepare` for anything else. You should almost never have to explicitly set a preinstall or install script. If you are doing this, please consider if there is another option. The only valid use of `install` or `preinstall` scripts is for compilation which must be done on the target architecture. |
| 298 | - Scripts are run from the root of the package folder, regardless of what the current working directory is when `npm` is invoked. If you want your script to use different behavior based on what subdirectory you're in, you can use the `INIT_CWD` environment variable, which holds the full path you were in when you ran `npm run`. |
| 299 | |
| 300 | ### See Also |
| 301 | |
| 302 | - [npm run-script](/cli/v10/commands/npm-run-script) |
| 303 | - [package.json](/cli/v10/configuring-npm/package-json) |
| 304 | - [npm developers](/cli/v10/using-npm/developers) |
| 305 | - [npm install](/cli/v10/commands/npm-install) |