Chapter 18: Node NPM Scripts
1. What are npm scripts really?
npm scripts are custom commands you define inside the package.json file under the key “scripts”.
Instead of typing long commands every day, you give them short, memorable names and run them with:
|
0 1 2 3 4 5 6 |
npm run <script-name> |
or special shortcuts:
|
0 1 2 3 4 5 6 7 |
npm start npm test |
Why are they so important?
- They make your project portable — anyone who clones your repo can run the same commands
- They hide complexity (long flags, environment variables, chained tools…)
- They become the single source of truth for how to develop, build, test, lint, format, etc.
- Almost every serious Node.js / JavaScript project lives and dies by its scripts section
2. Basic syntax – the minimal example
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "name": "my-project", "scripts": { "start": "node index.js", "dev": "nodemon index.js", "test": "echo \"No tests yet\" && exit 1" } } |
Run them like this:
|
0 1 2 3 4 5 6 7 8 |
npm start # runs node index.js npm run dev # runs nodemon index.js npm test # prints message (this is the default when you run npm test) |
Special shortcuts (you don’t need run):
- npm start → runs “start” script
- npm test → runs “test” script
- npm restart → runs “restart” or stop + start
- npm stop → runs “stop” script
3. Real-world npm scripts – typical patterns in 2026
Here’s a modern, realistic scripts section you see in many mid-to-large projects:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
{ "scripts": { // ─── Development ──────────────────────────────────────── "dev": "nodemon --watch src --ext ts,js --exec tsx src/index.ts", "dev:debug": "node --inspect src/index.ts", // ─── Start / Production ───────────────────────────────── "start": "node dist/index.js", "preview": "npm run build && npm start", // ─── Build ────────────────────────────────────────────── "build": "tsc && tsup", "build:watch": "tsc --watch", // ─── Code Quality ─────────────────────────────────────── "lint": "eslint . --ext .ts,.tsx", "lint:fix": "eslint . --ext .ts,.tsx --fix", "format": "prettier --write .", "format:check": "prettier --check .", // ─── Testing ──────────────────────────────────────────── "test": "vitest run", "test:watch": "vitest", "test:coverage": "vitest run --coverage", "test:ui": "vitest --ui", // ─── Database / Prisma ────────────────────────────────── "db:generate": "prisma generate", "db:migrate": "prisma migrate deploy", "db:push": "prisma db push", "db:studio": "prisma studio", "db:reset": "prisma migrate reset --force", // ─── Other utilities ──────────────────────────────────── "typecheck": "tsc --noEmit", "clean": "rm -rf dist node_modules/.cache", "prepare": "husky install", "postinstall": "prisma generate", "release": "standard-version && git push --follow-tags origin main && npm publish" } } |
4. Most popular real patterns & explanations
Pattern 1 – Development server (hot reload)
|
0 1 2 3 4 5 6 |
"dev": "nodemon --watch src --ext ts,js --exec tsx src/index.ts" |
or with tsx + dotenv:
|
0 1 2 3 4 5 6 |
"dev": "tsx watch --env-file=.env src/index.ts" |
tsx watch is very popular in 2025–2026 because:
- Native TypeScript support
- Fast reload
- No need for separate compilation step
Pattern 2 – Build commands (TypeScript → JavaScript)
|
0 1 2 3 4 5 6 7 |
"build": "tsc && tsup", "build:watch": "tsc --watch" |
Common combinations:
- tsc (official TypeScript compiler) + tsup / esbuild / vite / rollup
- tsc –noEmit only for type checking
Pattern 3 – Linting & formatting
|
0 1 2 3 4 5 6 7 8 9 |
"lint": "eslint . --ext .ts,.tsx", "lint:fix": "eslint . --ext .ts,.tsx --fix", "format": "prettier --write .", "format:check": "prettier --check ." |
Many teams combine them:
|
0 1 2 3 4 5 6 |
"check": "npm run lint && npm run format:check && npm run typecheck" |
Pattern 4 – Testing
|
0 1 2 3 4 5 6 7 8 9 |
"test": "vitest run", "test:watch": "vitest", "test:coverage": "vitest run --coverage", "test:related": "vitest --run --related" |
Vitest is currently one of the most popular choices in 2026 (very fast, Vite-powered)
Pattern 5 – Database / migration scripts
|
0 1 2 3 4 5 6 7 8 9 10 |
"db:generate": "prisma generate", "db:migrate": "prisma migrate deploy", "db:dev": "prisma migrate dev", "db:reset": "prisma migrate reset --force", "db:studio": "prisma studio" |
Very common in Prisma projects
Pattern 6 – Pre & Post hooks (automatic tasks)
|
0 1 2 3 4 5 6 7 8 |
"prepare": "husky install", // runs after npm install "precommit": "lint-staged", // used with husky "postinstall": "prisma generate" |
5. Useful tricks & best practices
Run multiple commands in one script
|
0 1 2 3 4 5 6 |
"check:all": "npm run lint && npm run format:check && npm run typecheck && npm run test" |
Use cross-env for environment variables (cross-platform)
|
0 1 2 3 4 5 6 |
"dev:prod-like": "cross-env NODE_ENV=production nodemon src/index.js" |
Pass arguments to scripts
|
0 1 2 3 4 5 6 7 |
npm run test -- --watch npm run test -- --run InMemoryUserRepository.test.ts |
Use environment variables inside scripts
|
0 1 2 3 4 5 6 |
"start:prod": "cross-env NODE_ENV=production node dist/index.js" |
Best practice naming conventions
- dev, start, build, test, lint, format → almost universal
- Prefixes: db:, test:, build:, lint:, typecheck:
- Suffixes: :watch, :fix, :check, :coverage, :ui
Summary – Quick cheat sheet of common scripts
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
{ "scripts": { "dev": "tsx watch src/index.ts", "start": "node dist/index.js", "build": "tsup", "lint": "eslint .", "lint:fix": "eslint . --fix", "format": "prettier --write .", "test": "vitest run", "test:watch": "vitest", "typecheck": "tsc --noEmit", "db:generate": "prisma generate", "db:migrate": "prisma migrate deploy", "prepare": "husky install" } } |
Would you like to go deeper into any of these areas?
- Creating advanced chained workflows (lint → format → test → build)
- How to use environment variables inside scripts safely
- Setting up husky + lint-staged (pre-commit hooks)
- Difference between npm run vs npx vs direct binary calls
- Best scripts for TypeScript + ESM + Vite / tsup / esbuild projects
- Scripts for CI/CD (GitHub Actions, Vercel, Render…)
Just tell me which direction feels most useful right now — I’ll continue with concrete examples and
