npm scripts 커스텀 스크립트 작성
Writing powerful custom npm scripts for development workflows, build processes, and automation tasks in Node.js projects.
npm scripts 커스텀 스크립트 작성
Introduction
npm scripts are the most underutilized feature in Node.js projects. They provide a cross-platform way to run commands without additional dependencies. This post covers writing effective npm scripts for common development tasks.
Environment
node --version
# v20.11.0
npm --version
# 10.2.4
# Check available scripts
npm runProblem
Complex development workflows require multiple manual steps:
# Manual process
npm run lint
npm run test
npm run build
npm run deploy
# Forgot a step? Manual errors!Analysis
npm scripts run in the context of node_modules/.bin, so you can use installed packages directly:
{
"scripts": {
"build": "webpack", // Uses local webpack
"test": "jest" // Uses local jest
}
}Special lifecycle scripts:
preinstall → install → postinstall
prepare → prepublish → publish
pretest → test → posttestSolution
Solution 1: Basic script organization
{
"scripts": {
"start": "node dist/server.js",
"dev": "nodemon src/server.ts",
"build": "tsc && node dist/build.js",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"lint": "eslint src/",
"lint:fix": "eslint src/ --fix",
"format": "prettier --write src/"
}
}Solution 2: Compound scripts
{
"scripts": {
"validate": "npm run lint && npm run test",
"prebuild": "npm run validate",
"build": "tsc",
"postbuild": "echo 'Build complete!'",
"predeploy": "npm run build",
"deploy": "node scripts/deploy.js"
}
}Solution 3: Environment-specific scripts
{
"scripts": {
"start": "node dist/server.js",
"start:dev": "NODE_ENV=development nodemon src/server.ts",
"start:prod": "NODE_ENV=production node dist/server.js",
"start:debug": "NODE_ENV=development node --inspect src/server.ts"
}
}Solution 4: Cross-platform scripts
{
"scripts": {
"clean": "rimraf dist",
"build": "tsc",
"start": "node dist/server.js",
"dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"",
"dev:server": "nodemon src/server.ts",
"dev:client": "cd client && npm run dev"
},
"devDependencies": {
"rimraf": "^5.0.0",
"concurrently": "^8.2.0"
}
}Solution 5: Custom script with arguments
{
"scripts": {
"migration": "node scripts/migrate.js",
"seed": "node scripts/seed.js"
}
}// scripts/migrate.js
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const command = process.argv[2];
const database = process.env.DB_NAME || 'myapp_dev';
async function runMigration(action) {
switch (action) {
case 'create':
const name = process.argv[3];
if (!name) {
console.error('Usage: npm run migration create ');
process.exit(1);
}
const timestamp = Date.now();
const filename = `${timestamp}-${name}.sql`;
fs.writeFileSync(
path.join(__dirname, '../migrations', filename),
`-- Migration: ${name}\n\n`
);
console.log(`Created migration: ${filename}`);
break;
case 'run':
console.log(`Running migrations on ${database}...`);
// Run migration logic
break;
default:
console.error('Unknown action:', action);
process.exit(1);
}
}
runMigration(command); Solution 6: Watch mode with nodemon
{
"scripts": {
"dev": "nodemon",
"dev:debug": "nodemon --inspect"
},
"nodemonConfig": {
"watch": ["src"],
"ext": "ts,js,json",
"ignore": ["src/**/*.spec.ts"],
"exec": "ts-node src/server.ts"
}
}Solution 7: Docker scripts
{
"scripts": {
"docker:build": "docker build -t myapp .",
"docker:run": "docker run -p 3000:3000 myapp",
"docker:dev": "docker-compose -f docker-compose.dev.yml up",
"docker:down": "docker-compose down"
}
}Solution 8: Git hooks with scripts
{
"scripts": {
"prepare": "husky install",
"lint-staged": "lint-staged"
},
"lint-staged": {
"*.{js,ts}": ["eslint --fix", "prettier --write"],
"*.{json,md}": ["prettier --write"]
},
"devDependencies": {
"husky": "^9.0.0",
"lint-staged": "^15.0.0"
}
}Lessons Learned
- Use
preandposthooks - Automate setup and cleanup - Keep scripts simple - Complex logic belongs in dedicated scripts
- Use
concurrentlyfor parallel tasks - Run frontend and backend together - Document scripts in README - Help new team members understand the workflow
- Use
npm-run-allfor sequential/parallel script execution
This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.