npm scripts
"npm scripts" is a mechanism for running commands defined in the "scripts" field of package.json using npm run. It lets you manage frequently used commands — such as building, testing, and starting a development server — under short, memorable names.
Writing the scripts Field
In the scripts field of package.json, write command names and their corresponding shell commands as key-value pairs.
package.json
{
"name": "future-gadget-lab",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"build": "tsc",
"test": "jest",
"lint": "eslint src"
}
}
| Script | How to run | Description |
|---|---|---|
| start | npm start or npm run start | Script for starting the application. Defines the startup command for production. |
| test | npm test or npm run test | Script for running tests. Calls a test runner such as Jest or Mocha. |
| Others | npm run script-name | npm run is required for any script other than start and test. |
npm start npm test npm run build
pre / post Hooks
Prefixing a script name with pre or post causes another script to run automatically before or after the target script executes.
package.json (pre/post hook example)
{
"scripts": {
"prestart": "echo 'Okabe Rintaro: El Psy Kongroo'",
"start": "node index.js",
"poststart": "echo 'Startup complete. Time machine is ready.'",
"pretest": "npm run lint",
"test": "jest"
}
}
npm start Okabe Rintaro: El Psy Kongroo (index.js executes) Startup complete. Time machine is ready.
Running npm start automatically executes scripts in the order prestart → start → poststart. This is useful for pre-build cleanup or pre-test static analysis.
Parallel Execution with concurrently
To run multiple commands simultaneously, the "concurrently" package is commonly used. It is helpful in cases such as starting a frontend build watcher and a backend server at the same time.
npm install --save-dev concurrently
package.json (parallel execution example)
{
"scripts": {
"dev:server": "node server.js",
"dev:watch": "tsc --watch",
"dev": "concurrently \"npm run dev:server\" \"npm run dev:watch\""
}
}
npm run dev [0] Server started: http://localhost:3000 [1] Watching TypeScript compilation...
The output from each process is displayed with [0] and [1] prefixes.
Setting Environment Variables with cross-env
When setting environment variables inside scripts, the syntax differs between macOS/Linux and Windows. Using "cross-env" lets you use the same syntax regardless of the OS.
npm install --save-dev cross-env
| Environment | Syntax |
|---|---|
| macOS / Linux | NODE_ENV=production node index.js |
| Windows (Command Prompt) | set NODE_ENV=production && node index.js |
| cross-env (cross-platform) | cross-env NODE_ENV=production node index.js |
package.json (cross-env example)
{
"scripts": {
"start": "cross-env NODE_ENV=production node index.js",
"dev": "cross-env NODE_ENV=development nodemon index.js",
"test": "cross-env NODE_ENV=test jest"
}
}
Sample Code
The following shows a package.json that makes use of npm scripts along with a server that reads environment variables.
package.json
{
"name": "steins-gate-api",
"version": "1.0.0",
"description": "Future Gadget Lab time leap management API",
"main": "index.js",
"scripts": {
"prestart": "echo 'Future Gadget Lab startup sequence initiated'",
"start": "cross-env NODE_ENV=production node index.js",
"dev": "cross-env NODE_ENV=development nodemon index.js",
"test": "cross-env NODE_ENV=test jest --coverage",
"lint": "eslint src",
"pretest": "npm run lint"
},
"dependencies": {
"express": "^4.19.2"
},
"devDependencies": {
"cross-env": "^7.0.3",
"nodemon": "^3.1.4",
"jest": "^29.7.0",
"eslint": "^9.6.0"
}
}
index.js
var express = require('express');
var app = express();
// Get current execution mode from environment variable
var env = process.env.NODE_ENV || 'development';
// Future Gadget Lab members
var labMembers = [
{ id: 1, name: "Okabe Rintaro", role: "Lab Chief", email: "okabe@example.com" },
{ id: 2, name: "Makise Kurisu", role: "Researcher", email: "kurisu@example.com" },
{ id: 3, name: "Shiina Mayuri", role: "Cosplay Division", email: "mayuri@example.com" },
{ id: 4, name: "Hashida Itaru", role: "Super Hacker", email: "daru@example.com" },
{ id: 5, name: "Amane Suzuha", role: "Part-time Warrior", email: "suzuha@example.com" }
];
app.get('/members', function(req, res) {
res.json({ env: env, members: labMembers });
});
app.listen(3000, function() {
console.log('Future Gadget Lab API started: http://localhost:3000 [' + env + ']');
});
npm run dev Future Gadget Lab startup sequence initiated Future Gadget Lab API started: http://localhost:3000 [development]
Common Mistakes
Common Mistake 1: Forgetting npm run causes scripts to not execute
To run any script other than start and test, you must always include npm run. Typing only the script name in the terminal does nothing.
build zsh: command not found: build
Add npm run to execute it correctly.
npm run build
Note that npm start and npm test are special shortcuts that can be run without run. All other scripts require the npm run script-name format.
Common Mistake 2: Environment variable syntax differs between Windows and macOS/Linux
When setting environment variables inside scripts, the syntax differs between macOS/Linux and Windows. Writing macOS/Linux-specific syntax directly in package.json will cause scripts to fail on Windows.
The following is an example that works on macOS/Linux but fails on Windows.
{
"scripts": {
"build": "NODE_ENV=production webpack"
}
}
Windows Command Prompt cannot interpret the NODE_ENV=production syntax and will produce an error.
Using the cross-env package allows you to set environment variables with the same syntax regardless of OS.
{
"scripts": {
"build": "cross-env NODE_ENV=production webpack"
}
}
Install cross-env in advance.
npm install --save-dev cross-env
If you find any errors or copyright issues, please contact us.