Prerequisites
- Basic understanding of JavaScript 📝
- TypeScript installation ⚡
- VS Code or preferred IDE 💻
What you'll learn
- Understand npm scripts fundamentals 🎯
- Apply npm scripts in real projects 🏗️
- Debug common npm script issues 🐛
- Write type-safe automation scripts ✨
🎯 Introduction
Welcome to this exciting tutorial on NPM Scripts! 🎉 In this guide, we’ll explore how npm scripts can transform your TypeScript development workflow from manual tedium to automated bliss.
You’ll discover how npm scripts can become your personal build assistant 🔧, running tests, bundling code, and deploying applications with simple commands. Whether you’re building web applications 🌐, server-side APIs 🖥️, or libraries 📚, mastering npm scripts is essential for professional TypeScript development.
By the end of this tutorial, you’ll feel confident automating your entire development pipeline! Let’s dive in! 🏊♂️
📚 Understanding NPM Scripts
🤔 What are NPM Scripts?
NPM scripts are like having a personal butler 🎩 for your project. Think of them as automated helpers that handle all the repetitive tasks you’d normally do manually - compiling TypeScript, running tests, starting dev servers, and much more!
In TypeScript terms, npm scripts are commands defined in your package.json
that automate development tasks 🤖. This means you can:
- ✨ Automate repetitive tasks
- 🚀 Standardize workflows across teams
- 🛡️ Ensure consistent build processes
💡 Why Use NPM Scripts?
Here’s why developers love npm scripts:
- Consistency 🔒: Same commands work everywhere
- Team Collaboration 👥: Everyone uses identical workflows
- Time Saving ⏰: Automate complex sequences
- Documentation 📖: Scripts serve as runnable docs
Real-world example: Imagine building a TypeScript web app 🛒. With npm scripts, you can run npm run build:prod
and automatically compile TypeScript, minify assets, run tests, and deploy - all with one command!
🔧 Basic Syntax and Usage
📝 Simple Example
Let’s start with a friendly package.json:
{
"name": "my-awesome-project",
"version": "1.0.0",
"scripts": {
"hello": "echo 'Hello, TypeScript! 👋'",
"build": "tsc",
"dev": "tsc --watch",
"test": "jest"
}
}
💡 Explanation: Scripts live in the scripts
section. Run them with npm run <script-name>
or just npm test
for special scripts!
🎯 Common Script Patterns
Here are patterns you’ll use daily:
{
"scripts": {
"// 🏗️ Build commands": "",
"build": "tsc",
"build:watch": "tsc --watch",
"build:prod": "tsc --build --verbose",
"// 🧪 Testing commands": "",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"// 🚀 Development commands": "",
"dev": "ts-node src/index.ts",
"start": "node dist/index.js",
"clean": "rimraf dist coverage"
}
}
🎯 Pro Tip: Use comments in scripts (they’re ignored by npm) to organize your commands!
💡 Practical Examples
🛒 Example 1: E-commerce App Automation
Let’s build a complete automation setup:
{
"name": "shopping-paradise",
"scripts": {
"// 🛍️ Development workflow": "",
"dev": "concurrently \"npm run dev:api\" \"npm run dev:web\"",
"dev:api": "ts-node-dev --respawn src/api/server.ts",
"dev:web": "vite --port 3000",
"// 🏗️ Build pipeline": "",
"prebuild": "npm run clean && npm run lint",
"build": "npm run build:api && npm run build:web",
"build:api": "tsc --project tsconfig.server.json",
"build:web": "vite build",
"postbuild": "npm run test",
"// 🧪 Quality assurance": "",
"lint": "eslint src/**/*.ts --fix",
"typecheck": "tsc --noEmit",
"test": "jest --passWithNoTests",
"test:e2e": "playwright test",
"// 🚀 Deployment": "",
"deploy:staging": "npm run build && aws s3 sync dist/ s3://my-staging-bucket",
"deploy:prod": "npm run build && npm run test:e2e && aws s3 sync dist/ s3://my-prod-bucket",
"// 🧹 Maintenance": "",
"clean": "rimraf dist coverage .nyc_output",
"fresh": "npm run clean && rm -rf node_modules && npm install"
},
"dependencies": {
"express": "^4.18.0",
"typescript": "^5.0.0"
},
"devDependencies": {
"concurrently": "^7.6.0",
"ts-node-dev": "^2.0.0",
"rimraf": "^4.0.0",
"eslint": "^8.0.0",
"jest": "^29.0.0",
"playwright": "^1.30.0"
}
}
💡 Notice: We use pre
and post
hooks! prebuild
runs before build
, postbuild
runs after!
🎮 Example 2: Game Development Workflow
Let’s make it fun with a TypeScript game project:
{
"name": "space-invaders-ts",
"scripts": {
"// 🎮 Game development": "",
"dev": "webpack serve --mode development --open",
"dev:debug": "npm run dev -- --env debug=true",
"// 🏗️ Building the game": "",
"build": "npm run build:game && npm run build:assets",
"build:game": "webpack --mode production",
"build:assets": "node scripts/optimize-assets.js",
"// 🧪 Game testing": "",
"test": "jest src/**/*.test.ts",
"test:gameplay": "npm run build && node scripts/test-gameplay.js",
"// 📊 Performance monitoring": "",
"analyze": "webpack-bundle-analyzer dist/bundle.js",
"lighthouse": "lhci autorun",
"// 🚀 Release pipeline": "",
"prerelease": "npm run lint && npm run test",
"release": "semantic-release",
"postrelease": "npm run deploy:itch"
}
}
🎯 Try it yourself: Add a script that generates sprite sheets automatically!
🏦 Example 3: Banking API with Security Checks
For the security-conscious developers:
{
"name": "secure-banking-api",
"scripts": {
"// 🔒 Security-first development": "",
"dev": "npm run security:check && ts-node-dev src/server.ts",
"dev:secure": "npm run dev -- --env NODE_ENV=development_secure",
"// 🛡️ Security pipeline": "",
"security:check": "npm audit && npm run security:deps",
"security:deps": "snyk test",
"security:code": "semgrep --config=auto src/",
"// 🏗️ Secure builds": "",
"prebuild": "npm run security:check && npm run lint:security",
"build": "tsc && npm run build:encrypt-env",
"build:encrypt-env": "node scripts/encrypt-secrets.js",
"// 🧪 Security testing": "",
"test": "jest",
"test:integration": "jest --config jest.integration.config.js",
"test:security": "npm run test:penetration && npm run test:compliance",
"test:penetration": "node scripts/security-tests.js",
"test:compliance": "node scripts/compliance-check.js"
}
}
🚀 Advanced Concepts
🧙♂️ Advanced Topic 1: Cross-Platform Scripts
When you’re ready to level up, handle different operating systems:
{
"scripts": {
"// 🌍 Cross-platform magic": "",
"clean": "shx rm -rf dist coverage",
"copy:assets": "shx cp -r assets dist/",
"build:windows": "npm run clean && tsc && npm run copy:assets",
"build:unix": "rm -rf dist && tsc && cp -r assets dist/",
"build": "npm-run-all clean build:*",
"// 🎯 Environment-specific builds": "",
"build:dev": "cross-env NODE_ENV=development npm run build",
"build:prod": "cross-env NODE_ENV=production npm run build",
"// 🔄 Parallel execution": "",
"test:all": "npm-run-all --parallel test:unit test:integration test:e2e",
"lint:all": "npm-run-all --parallel lint:ts lint:css lint:json"
},
"devDependencies": {
"shx": "^0.3.4",
"cross-env": "^7.0.3",
"npm-run-all": "^4.1.5"
}
}
🏗️ Advanced Topic 2: Custom Script Arguments
For the brave developers who want dynamic scripts:
{
"scripts": {
"// 🎛️ Dynamic script arguments": "",
"test:file": "jest -- $1",
"build:env": "cross-env NODE_ENV=$NODE_ENV npm run build",
"deploy:branch": "node scripts/deploy.js --branch=$BRANCH",
"// 🔧 Conditional execution": "",
"maybe:test": "if-env NODE_ENV=production && npm test",
"maybe:lint": "if-env CI=true && npm run lint:strict || npm run lint"
}
}
Usage examples:
# 🎯 Test specific file
npm run test:file user.test.ts
# 🌍 Build for specific environment
NODE_ENV=staging npm run build:env
# 🌿 Deploy specific branch
BRANCH=feature/new-payment npm run deploy:branch
⚠️ Common Pitfalls and Solutions
😱 Pitfall 1: The “PATH Not Found” Trap
// ❌ Wrong way - might not find binaries!
{
"scripts": {
"build": "/usr/local/bin/tsc"
}
}
// ✅ Correct way - use npx or rely on node_modules/.bin!
{
"scripts": {
"build": "tsc",
"build:alt": "npx tsc"
}
}
💡 Pro Tip: npm automatically adds node_modules/.bin
to PATH when running scripts!
🤯 Pitfall 2: Forgetting Cross-Platform Compatibility
// ❌ Unix-only - fails on Windows!
{
"scripts": {
"clean": "rm -rf dist && mkdir dist"
}
}
// ✅ Cross-platform - works everywhere!
{
"scripts": {
"clean": "shx rm -rf dist && shx mkdir -p dist"
}
}
😰 Pitfall 3: Long Command Lines
// ❌ Unreadable mess!
{
"scripts": {
"build": "tsc && webpack --config webpack.prod.js --output-path dist --mode production && node scripts/post-build.js && echo 'Build complete!'"
}
}
// ✅ Split into logical steps!
{
"scripts": {
"prebuild": "tsc",
"build": "webpack --config webpack.prod.js",
"postbuild": "node scripts/post-build.js && echo 'Build complete! 🎉'"
}
}
🛠️ Best Practices
- 🎯 Use Semantic Names:
build:prod
notbp
- 📝 Document Complex Scripts: Add comments explaining what they do
- 🔄 Use Pre/Post Hooks: Let npm orchestrate your workflow
- 🌍 Think Cross-Platform: Use tools like
shx
andcross-env
- ⚡ Parallelize When Possible: Use
npm-run-all
for speed - 🛡️ Fail Fast: Use
&&
to stop on errors - ✨ Keep It Simple: Break complex tasks into smaller scripts
🧪 Hands-On Exercise
🎯 Challenge: Build a Complete TypeScript Project Automation
Create a comprehensive npm scripts setup for a full-stack TypeScript application:
📋 Requirements:
- 🏗️ Separate builds for frontend and backend
- 🧪 Testing pipeline with unit, integration, and E2E tests
- 🔒 Security and code quality checks
- 🚀 Multi-environment deployment
- 📊 Performance monitoring and bundle analysis
- 🧹 Maintenance and cleanup tasks
🌟 Bonus Points:
- Add Docker support
- Implement semantic versioning
- Create GitHub Actions integration
- Add automated dependency updates
💡 Solution
🔍 Click to see solution
{
"name": "fullstack-typescript-app",
"version": "1.0.0",
"scripts": {
"// 🚀 Main commands": "",
"dev": "npm-run-all --parallel dev:*",
"build": "npm-run-all clean lint test build:*",
"test": "npm-run-all --parallel test:*",
"deploy": "npm run deploy:staging",
"// 🏗️ Development servers": "",
"dev:frontend": "vite --port 3000",
"dev:backend": "ts-node-dev --respawn server/src/index.ts",
"dev:db": "docker-compose up -d postgres redis",
"// 🔨 Build pipeline": "",
"prebuild": "npm run clean",
"build:frontend": "vite build --outDir ../dist/public",
"build:backend": "tsc --project server/tsconfig.json",
"build:docker": "docker build -t myapp:latest .",
"postbuild": "npm run test:smoke",
"// 🧪 Testing suite": "",
"test:unit": "jest --config jest.unit.config.js",
"test:integration": "jest --config jest.integration.config.js",
"test:e2e": "playwright test",
"test:smoke": "node scripts/smoke-tests.js",
"// 🔍 Code quality": "",
"lint": "npm-run-all --parallel lint:*",
"lint:ts": "eslint '{client,server}/src/**/*.ts' --fix",
"lint:css": "stylelint 'client/src/**/*.css' --fix",
"lint:format": "prettier --write '{client,server}/src/**/*.{ts,tsx,css,json}'",
"// 🛡️ Security checks": "",
"security": "npm-run-all security:*",
"security:audit": "npm audit --audit-level moderate",
"security:deps": "snyk test",
"security:code": "semgrep --config=auto server/src/",
"// 📊 Analysis and monitoring": "",
"analyze": "npm-run-all analyze:*",
"analyze:bundle": "webpack-bundle-analyzer dist/public/assets",
"analyze:deps": "depcheck",
"analyze:performance": "lighthouse http://localhost:3000",
"// 🚀 Deployment": "",
"predeploy:staging": "npm run build && npm run security",
"deploy:staging": "aws s3 sync dist/ s3://myapp-staging",
"deploy:prod": "npm run test:e2e && aws s3 sync dist/ s3://myapp-prod",
"postdeploy:prod": "node scripts/notify-deployment.js",
"// 🧹 Maintenance": "",
"clean": "shx rm -rf dist coverage .nyc_output",
"fresh": "npm run clean && shx rm -rf node_modules && npm install",
"update:deps": "ncu -u && npm install",
"// 📦 Release management": "",
"preversion": "npm run build && npm test",
"version": "conventional-changelog -p angular -r 2 -i CHANGELOG.md -s",
"postversion": "git push --follow-tags"
},
"dependencies": {
"express": "^4.18.0",
"typescript": "^5.0.0"
},
"devDependencies": {
"npm-run-all": "^4.1.5",
"shx": "^0.3.4",
"cross-env": "^7.0.3",
"ts-node-dev": "^2.0.0",
"jest": "^29.0.0",
"playwright": "^1.30.0",
"eslint": "^8.0.0",
"prettier": "^2.8.0",
"snyk": "^1.1000.0"
}
}
🎓 Key Takeaways
You’ve learned so much! Here’s what you can now do:
- ✅ Create npm scripts with confidence 💪
- ✅ Avoid common mistakes that trip up beginners 🛡️
- ✅ Apply best practices in real projects 🎯
- ✅ Debug script issues like a pro 🐛
- ✅ Automate entire workflows with TypeScript! 🚀
Remember: npm scripts are your automation superpower! They turn manual drudgery into one-command magic. 🎩✨
🤝 Next Steps
Congratulations! 🎉 You’ve mastered npm scripts automation!
Here’s what to do next:
- 💻 Practice with the exercise above
- 🏗️ Automate your current project’s workflow
- 📚 Move on to our next tutorial: Advanced Build Tools
- 🌟 Share your automation wins with the community!
Remember: Every automation expert started with a single script. Keep building, keep automating, and most importantly, have fun making your development life easier! 🚀
Happy scripting! 🎉🛠️✨