npm Scripts
npm scripts are custom commands defined in your package.json. They're the standard way to automate tasks in JavaScript projects.
Defining Scripts
Scripts are defined in the scripts field:
{
"scripts": {
"start": "node index.js",
"test": "jest",
"build": "webpack --mode production"
}
}
Running Scripts
# Run a script
npm run start
npm run test
npm run build
# Special scripts (no 'run' needed)
npm start
npm test
npm stop
npm restart
Special Script Names
These scripts have shortcuts:
| Script | Shortcut |
|---|---|
start | npm start |
test | npm test or npm t |
stop | npm stop |
restart | npm restart |
All others require npm run <script>.
Lifecycle Scripts
npm runs certain scripts automatically:
Install Lifecycle
{
"scripts": {
"preinstall": "echo 'Before install'",
"install": "echo 'During install'",
"postinstall": "echo 'After install'"
}
}
Run Lifecycle
For any script, you can add pre/post hooks:
{
"scripts": {
"prebuild": "npm run clean",
"build": "webpack",
"postbuild": "npm run notify"
}
}
When you run npm run build:
prebuildruns firstbuildrunspostbuildruns last
Common Script Patterns
Development Server
{
"scripts": {
"dev": "nodemon src/index.js",
"start": "node src/index.js"
}
}
Build Process
{
"scripts": {
"clean": "rm -rf dist",
"build": "tsc && webpack",
"build:prod": "NODE_ENV=production npm run build"
}
}
Testing
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage"
}
}
Linting and Formatting
{
"scripts": {
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix",
"format": "prettier --write src/"
}
}
Practice: Configure Scripts
Here's a complete scripts section. Study the patterns:
Passing Arguments
Pass arguments to scripts with --:
npm run test -- --watch
npm run build -- --mode development
Environment Variables
Set environment variables inline:
{
"scripts": {
"start:dev": "NODE_ENV=development node src/index.js",
"start:prod": "NODE_ENV=production node src/index.js"
}
}
For cross-platform compatibility, use cross-env:
npm install -D cross-env
{
"scripts": {
"start:dev": "cross-env NODE_ENV=development node src/index.js"
}
}
Running Multiple Scripts
Sequential (&&)
Run one after another:
{
"scripts": {
"validate": "npm run lint && npm run test && npm run build"
}
}
Parallel
Use npm-run-all for parallel execution:
npm install -D npm-run-all
{
"scripts": {
"start": "npm-run-all --parallel start:*",
"start:server": "node server.js",
"start:client": "vite"
}
}
Or use the concurrently package:
{
"scripts": {
"dev": "concurrently \"npm:server\" \"npm:client\"",
"server": "nodemon server.js",
"client": "vite"
}
}
Accessing npm Variables
Scripts can access npm environment variables:
{
"scripts": {
"info": "echo $npm_package_name v$npm_package_version"
}
}
Available variables:
npm_package_name- Package namenpm_package_version- Package versionnpm_lifecycle_event- Current script name
Listing Scripts
# See all available scripts
npm run
# Or in package.json
cat package.json | jq '.scripts'
Script Best Practices
1. Use Descriptive Names
{
"scripts": {
"build:production": "webpack --mode production",
"build:development": "webpack --mode development"
}
}
2. Create a "validate" Script
{
"scripts": {
"validate": "npm run lint && npm run typecheck && npm run test"
}
}
3. Document Complex Scripts
Add comments in README or use a script that explains:
{
"scripts": {
"help": "cat scripts-help.txt"
}
}
4. Use prepare for Setup
{
"scripts": {
"prepare": "husky install"
}
}
Runs automatically after npm install.
Key Takeaways
- Scripts automate common tasks
- npm start/test don't need
run - Pre/post hooks run automatically
- Use && for sequential execution
- cross-env for cross-platform env vars
What's Next?
Let's explore the difference between global and local package installations.

