npm Scripts and package.json Mastery (2026)
Most developers only use npm install and npm run dev. Here's everything else npm scripts can do for you.
package.json Deep Dive
{
"name": "my-awesome-project",
"version": "1.2.3",
"description": "A well-configured project",
// Scripts are where the magic happens
"scripts": {
// Basic scripts
"start": "node server.js",
"dev": "nodemon server.js",
"build": "tsc && vite build",
"test": "jest --coverage",
// Pre/post hooks (auto-run before/after!)
"pretest": "npm run lint",
"postbuild": "npm run size-check",
// Complex scripts
"clean": "rimraf dist build .tsbuildinfo",
"typecheck": "tsc --noEmit",
"lint": "eslint 'src/**/*.{js,ts}'",
"lint:fix": "npm run lint -- --fix",
"format": "prettier --write 'src/**/*.{js,ts,json,md}'",
"prepare": "husky install",
// Deployment
"deploy:staging": "NODE_ENV=staging npm run build && rsync -avz dist/ staging:/app/",
"deploy:prod": "NODE_ENV=production npm run build && rsync -avz dist/ prod:/app/"
},
// Dependencies
"dependencies": {
"express": "^4.18.0", // Runtime dependencies
"lodash": "^4.17.21"
},
"devDependencies": {
"typescript": "^5.3.0", // Development only
"jest": "^29.7.0",
"eslint": "^8.56.0"
},
// Important metadata
"engines": {
"node": ">=18.0.0", // Required Node version
"npm": ">=9.0.0"
},
"main": "dist/index.js", // Entry point for require()
"types": "dist/index.d.ts", // Entry point for TypeScript
"files": [ // What gets published to npm
"dist",
"README.md"
],
"bin": { // CLI commands
"my-tool": "./bin/cli.js"
}
}
Script Patterns You Need
# === Running Scripts ===
# Basic usage
npm run dev # Runs the "dev" script
npm test # "test" is special — can omit "run"
# Passing arguments
npm run test -- --grep "auth" # Everything after -- goes to the script
npm run build -- --mode production
# Sequential execution
npm run clean && npm run build && npm run test
# Parallel execution (& is your friend)
"dev": "concurrently \"npm run dev:server\" \"npm run dev:client\""
# Or:
"dev": "npm-run-all --parallel dev:*"
# Cross-platform compatibility!
# ❌ Windows-incompatible:
"clean": "rm -rf dist"
# ✅ Use cross-platform tools:
"clean": "rimraf dist" # rimraf works everywhere
"copy": "cp src dist" # ❌ Not cross-platform
"copy": "cpx src dist" # ✅ cpx or copyfiles
# Environment variables in scripts
"dev": "cross-env NODE_ENV=development nodemon server.js"
# cross-env handles Windows/Linux/Mac differences
# Script composition (DRY principle)
"prettify": "prettier --write '**/*.{js,css}'",
"lintify": "eslint src/**/*.js --fix",
"fixall": "npm run prettify && npm run lintify"
Lifecycle Scripts (The Hidden Power)
{
"scripts": {
// These run automatically at specific times:
"preinstall": "echo 'Installing...'",
"postinstall": "node scripts/postinstall.js",
// postinstall runs after every npm install!
// Great for: generating files, setup checks, download binaries
"prepublishOnly": "npm run typecheck && npm run lint && npm run test",
// Runs BEFORE npm publish (not on npm install)
// Safety net: prevents publishing broken code
"preversion": "npm run test",
"version": "git add -A && git commit -m 'release v%s'",
"postversion": "git push && git push --tags",
// Automate version bumping workflow!
"pack": "npm pack --dry-run | head -n 20",
// Preview what would be published without actually publishing
}
}
Managing Dependencies Like a Pro
# === Installation ===
npm install express # Save to dependencies
npm install -D jest # Save to devDependencies
npm install -g typescript # Install globally
npm install express@latest # Latest version
npm install express@^4.18.0 # Compatible version range
# === Version Ranges ===
# "^4.18.0" = >=4.18.0 <5.0.0 (compatible, most common)
# "~4.18.0" = >=4.18.0 <4.19.0 (patch updates)
# "4.18.0" = exactly 4.18.0 (locked)
# "*" = any version (dangerous!)
# "next" = next release (cutting edge)
# "latest" = latest stable
# === Updating ===
npm outdated # Check for outdated packages
npm update # Update per package.json rules
npx npm-check-updates -u # Update package.json to latest versions
# Then: npm install to apply
# === Auditing ===
npm audit # Check for vulnerabilities
npm audit fix # Auto-fix if possible
npm audit fix --force # Force fix (may break things, use carefully!)
# === Cleaning up ===
npm prune # Remove extraneous packages
npm dedupe # Reduce duplication
# === Analyzing Bundle ===
npm ls --depth=0 # Top-level deps only
npm ls express # Why was this installed? (dependency tree)
du -sh node_modules # How big is it?
npx depcheck # Find unused dependencies
npx why express@4.17 # Why is this version installed?
Workspaces (Monorepo Basics)
// Root package.json
{
"name": "monorepo",
"private": true,
"workspaces": [
"packages/*",
"apps/*"
],
"scripts": {
"build": "npm run build --workspaces-if-present",
"test": "npm test --workspaces-if-present",
"clean": "npm exec --workspaces -- rimraf dist node_modules"
}
}
# Benefits:
# - Shared node_modules (saves disk space, faster installs)
# - Run scripts across all packages at once
# - Packages can depend on each other via workspace:*
# - Single npm install at root installs everything
# Add internal dependency:
# cd packages/utils
# npm install workspace:shared-types
# This creates a symlink! No need to publish.
Useful npm Config Tricks
# Set default config
npm config set init-author-name "Your Name"
npm config set init-author-email "you@example.com"
npm config set init-license MIT
npm config set init-version 1.0.0
# Per-project config (.npmrc)
# .npmrc file in project root:
save-exact=true # Always save exact versions (no ^)
package-lock=true # Always generate lockfile
engine-strict=true # Fail if Node version doesn't match engines
# Speed up installs
npm config set prefer-offline true
npm config set audit=false # Skip audit during install (faster)
npm config set fund=false # No funding message
# Registry configuration
npm config set registry https://registry.npmmirror.com # Mirror (China)
# Or scoped registries:
# @scope:registry=https://private-registry.com
# //private-registry.com/:_authToken=xxx
# View current config
npm config list
npm config list -l # Include defaults
What's your favorite npm trick? What do you wish npm could do that it can't?
Follow @armorbreak for more practical developer guides.
Top comments (0)