NPM Scripts | Package JSON

what are NPM Scripts?

NPM scripts are, well, scripts. We use scripts to automate repetitive tasks. For example, building your project, minifying Cascading Style Sheets (CSS) and JavaScript (JS) files. Scripts are also used in deleting temporary files and folders, etc,. There are many ways to pull this off — you could write bash/batch scripts, or use a task runner like Gulp or Grunt. However, a lot of people are moving over to NPM scripts for their simplicity and versatility. They also offer possibility of having fewer tools to learn, use, and keep track of.

Now that we have (some) idea of what NPM scripts are and what they can do for us, let’s go ahead and write some!

The Scripts Object in package.json

Most of our work will happen in the package.json file that NPM uses as a manifest of sorts. This is the file that is created when you run npm init.

Here’s a sample package.json file:

{
  "name": "team-management",
  "private": true,
  "scripts": {
    "start": "meteor run",
    "test": "meteor test --once --driver-package meteortesting:mocha",
  },
  "dependencies": {
    "@babel/runtime": "^7.3.4",
    "meteor-node-stubs": "^0.4.1",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-router": "^5.0.1",
    "react-router-dom": "^5.0.1"
  }
}

You’ve probably seen this tons of times in your package.json files. And you probably know that you can type npm start to execute the script. But this example illustrates the first important aspect of NPM scripts — they are simply terminal commands. They run in the shell of the OS on which they’re executed. So it might be bash for Linux and cmd.exe for Windows.

At this point, you might be rather unimpressed. But keep reading to see how powerful NPM scripts really are.

Custom Scripts

The script we just saw is one of the “special” NPM scripts. You can execute it by simply typing npm start. These are scripts with names that NPM recognizes and attaches special meaning to. For example, you can write a script called prepublish. NPM will execute the script before your package is packed and published, and also when you run npm install locally without any arguments. More on such scripts here.

But NPM also let’s you define your own custom scripts. This is where the power of NPM scripts starts to show itself.

Let’s look at a super basic custom NPM script that outputs “hello world” to the console. Add this to the scripts object of your package.json file:

"say-hello": "echo 'Hello World'"

The scripts object in your package.json file should look like this:

"scripts": {
      "start": "node index.js", 
      "say-hello": "echo 'Hello World!'"
 }

npm run --silent say-hello

Calling NPM Scripts Within Other NPM Scripts

One downside of using NPM scripts shows up when your script is fairly complex (and long). This problem is compounded by the fact that the JSON spec does not support comments. There are a few ways around this problem. One way is to divide your script into small single-purpose scripts and then call them within other NPM scripts. The way to call an NPM script within another is straightforward. Modify your scripts object so that it looks like this:

"scripts": {
  "say-hello": "echo 'Hello World'",  
  "awesome-npm": "npm run say-hello && echo 'echo NPM is awesome!'"
}

Since NPM scripts execute in the shell, calling npm run say-hello within another NPM script is almost intuitive.

For those of you who are not very comfortable with terminal commands, the &&in the script is used to delimit two commands. Thus, the second command executes after the successful execution of the first command.

Now when you run npm run awesome-npm, the say-hello script executes first, outputting “Hello World” to the console, followed by the part of the script after the &&, which outputs “NPM is awesome!”

Here’s a use case where this might be useful. Suppose you’re automating the build process of your application. Let’s say you’re using Webpack as a bundler and your distribution code goes into a directory called “dist”.

You might start with cleaning the directory. This can be done by either deleting its contents or deleting the directory itself and then making it again. Let’s go with the latter approach. Your command might look something like this:

rm -r dist && mkdir dist

Note that this uses bash commands. You will learn how to write cross-platform NPM scripts later in this article.

After this, you might invoke the bundler by executing the webpack command.

You can execute these commands in succession by using the &&operator. However, for the sake of demonstration and modularity, let’s split this into two NPM scripts that call each other.

Here’s what the scripts object would look like in this use case:

"scripts": {
  "clean": "rm -r dist && mkdir dist",
  "build": "npm run clean && webpack"
}

There you have it! How to split a more complex task into smaller NPM scripts.

Calling Shell and Node Scripts

At times, you may have to write scripts far more complex than ones that can be achieved in 2–3 commands. When this situation arises, one solution is to write bash or JS scripts (or scripts in any scripting language you like) and call them from NPM scripts.

Let’s quickly write a bash script that says hello to you. Create a file called hello.sh in your root directory and paste this code in it:

#!/usr/bin/env bash
# filename: hello.shecho "What's your name?"read nameecho 
"Hello there, $name!"

It’s a simple script that echoes your name back to you. Now modify the package.jsonfile so that the scripts object has this line of code:

"bash-hello": "bash hello.sh"

Now, when you run npm run bash-hello, it asks you for your name and then says hello to you! Brilliant.

You can do the same thing with JS scripts run using node. An advantage of this approach is that this script will be platform independent since it uses node to run.

Last updated