Skip to content

Commit

Permalink
fix(docs): update scripts docs
Browse files Browse the repository at this point in the history
The lifecycle events section was very out of date, and lots
of other cleanup needed to happen too

PR-URL: #2690
Credit: @wraithgar
Close: #2690
Reviewed-by: @ruyadorno
  • Loading branch information
wraithgar authored and ruyadorno committed Mar 4, 2021
1 parent 0c881fc commit c8b73db
Showing 1 changed file with 139 additions and 52 deletions.
191 changes: 139 additions & 52 deletions docs/content/using-npm/scripts.md
Expand Up @@ -6,11 +6,19 @@ description: How npm handles the "scripts" field

### Description

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>`.
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>`.

### Pre & Post Scripts

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.
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.

```json
{
Expand All @@ -22,20 +30,35 @@ To create "pre" or "post" scripts for any scripts defined in the `"scripts"` sec
}
```

In this example `npm run compress` would execute these scripts as
described.

### Life Cycle Scripts

There are some special life cycle scripts that happen only in certain situations. These scripts happen in addition to the "pre" and "post" script.
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.

* `prepare`, `prepublish`, `prepublishOnly`, `prepack`, `postpack`

**prepare** (since `npm@4.0.0`)
* Runs any time before the package is packed, i.e. during `npm publish`
and `npm pack`
* Runs BEFORE the package is packed
* Runs BEFORE the package is published
* Runs on local `npm install` without any arguments
* Run AFTER `prepublish`, but BEFORE `prepublishOnly`
* 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.

* 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.

* As of `npm@7` these scripts run in the background

**prepublish** (DEPRECATED)
* Same as `prepare`
* Does not run during `npm publish`, but does run during `npm ci`
and `npm install`. See below for more info.

**prepublishOnly**
* Runs BEFORE the package is prepared and packed, ONLY on `npm publish`.
Expand All @@ -45,7 +68,7 @@ There are some special life cycle scripts that happen only in certain situations
* 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.

**postpack**
* Runs AFTER the tarball has been generated and moved to its final destination.
* 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)

#### Prepare and Prepublish

Expand Down Expand Up @@ -74,51 +97,116 @@ The advantage of doing these things at `prepublish` time is that they can be don

### Life Cycle Operation Order

#### [`npm publish`](/commands/npm-publish)
#### [`npm cache add`](/commands/npm-cache)

* `prepublishOnly`
* `prepare`

#### [`npm ci`](/commands/npm-ci)

* `preinstall`
* `install`
* `postinstall`
* `prepublish`
* `publish`
* `postpublish`
* `preprepare`
* `prepare`
* `postprepare`

These all run after the actual installation of modules into
`node_modules`, in order, with no internal actions happening in between

#### [`npm diff`](/commands/npm-diff)

* `prepare`

#### [`npm env`](/commands/npm-env)

* `env` (You can override the default behavior of `npm env` by defining
a custom `env` entry in your `scripts` object)

#### [`npm install`](/commands/npm-install)

These also run when you run `npm install -g <pkg-name>`

* `preinstall`
* `install`
* `postinstall`
* `prepublish`
* `preprepare`
* `prepare`
* `postprepare`

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`

These are run from the scripts of `<pkg-name>`

#### [`npm pack`](/commands/npm-pack)

* `prepack`
* `prepare`
* `postpack`

#### [`npm install`](/commands/npm-install)
#### [`npm publish`](/commands/npm-publish)

* `prepublishOnly`
* `prepack`
* `prepare`
* `postpack`
* `publish`
* `postpublish`

`prepare` will not run during `--dry-run`

#### [`npm rebuild`](/commands/npm-rebuild)

* `preinstall`
* `install`
* `postinstall`
* `prepare`

Also triggers
`prepare` is only run if the current directory is a symlink (e.g. with
linked packages)

* `prepublish` (when on local)
* `prepare` (when on local or workspaces)
#### [`npm restart`](/commands/npm-restart)

#### [`npm start`](/commands/npm-start)
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)

* `prerestart`
* `restart`
* `postrestart`

`npm run start` has an `npm start` shorthand.
#### [`npm run <user defined>`](/commands/npm-run)

* `pre<user-defined>`
* `<user-defined>`
* `post<user-defined>`

#### [`npm start`](/commands/npm-start)

* `prestart`
* `start`
* `poststart`

### Default Values
npm will default some script values based on package contents.
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.

#### [`npm stop`](/commands/npm-stop)

* `"start": "node server.js"`:
* `prestop`
* `stop`
* `poststop`

If there is a `server.js` file in the root of your package, then npm
will default the `start` command to `node server.js`.
#### [`npm test`](/commands/npm-test)

* `"install": "node-gyp rebuild"`:
* `pretest`
* `test`
* `posttest`

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.

### User

Expand All @@ -131,22 +219,21 @@ 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.


#### path

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:

```json
{
"name" : "foo",
"dependencies" : {
"bar" : "0.1.x"
},
"scripts": {
"start" : "bar ./test"
}
{
"name" : "foo",
"dependencies" : {
"bar" : "0.1.x"
},
"scripts": {
"start" : "bar ./test"
}
}
```

Expand All @@ -159,8 +246,8 @@ 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
`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.

#### configuration
Expand All @@ -176,14 +263,14 @@ there is a config param of `<name>[@<version>]:<key>`. For example,
if the package.json has this:

```json
{
"name" : "foo",
"config" : {
"port" : "8080"
},
"scripts" : {
"start" : "node server.js"
}
{
"name" : "foo",
"config" : {
"port" : "8080"
},
"scripts" : {
"start" : "node server.js"
}
}
```

Expand Down Expand Up @@ -219,10 +306,10 @@ process.env.npm_package_scripts_install === "foo.js"
For example, if your package.json contains this:

```json
{
"scripts" : {
"install" : "scripts/install.js",
"postinstall" : "scripts/postinstall.js",
{
"scripts" : {
"install" : "scripts/install.js",
"postinstall" : "scripts/postinstall.js",
"uninstall" : "scripts/uninstall.js"
}
}
Expand All @@ -239,10 +326,10 @@ If you want to run a make command, you can do so. This works just
fine:

```json
{
"scripts" : {
"preinstall" : "./configure",
"install" : "make && make install",
{
"scripts" : {
"preinstall" : "./configure",
"install" : "make && make install",
"test" : "make test"
}
}
Expand Down

0 comments on commit c8b73db

Please sign in to comment.