What are npm scripts and how do lifecycle scripts work in npm?
npm scripts are commands defined in the scripts field of package.json, used to automate common project tasks.
Basic Syntax
json{ "scripts": { "start": "node index.js", "dev": "nodemon index.js", "build": "webpack --mode production", "test": "jest", "lint": "eslint src/" } }
Running Scripts
Use npm run <script-name> or npm <script-name> (for special commands like start, stop, test):
bashnpm run dev npm start npm test
Lifecycle Scripts
npm provides special lifecycle scripts that automatically execute on specific events:
Installation Related Lifecycle
json{ "scripts": { "preinstall": "echo 'Installing dependencies...'", "install": "node setup.js", "postinstall": "echo 'Dependencies installed!'", "preuninstall": "echo 'Uninstalling...'", "postuninstall": "echo 'Uninstalled!'" } }
Execution order:
preinstallinstallpostinstall
Publishing Related Lifecycle
json{ "scripts": { "prepublishOnly": "npm run build && npm run test", "prepack": "npm run build", "postpack": "echo 'Package packed!'", "publish": "node publish.js", "postpublish": "echo 'Published!'" } }
Execution order:
prepublishOnlyprepackpreparepostpackpublishpostpublish
Other Lifecycle
json{ "scripts": { "prestart": "npm run build", "start": "node index.js", "poststart": "echo 'Server started!'", "pretest": "npm run lint", "test": "jest", "posttest": "npm run coverage" } }
Passing Arguments to Scripts
You can pass arguments to scripts:
json{ "scripts": { "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage" } }
Pass additional arguments when running:
bashnpm run test -- --verbose
Arguments after -- are passed to the script command.
Environment Variables
npm scripts can access environment variables provided by npm:
json{ "scripts": { "build": "webpack --env.NODE_ENV=$npm_package_config_env", "start": "node $npm_package_main" } }
Common environment variables:
npm_package_name: Package namenpm_package_version: Package versionnpm_package_main: Main entry filenpm_package_scripts_*: Other scriptsnpm_config_*: npm configurationnpm_lifecycle_event: Current lifecycle event name
Cross-Platform Compatibility
Handling cross-platform compatibility of npm scripts:
Using cross-env
json{ "scripts": { "build": "cross-env NODE_ENV=production webpack" } }
Using rimraf (cross-platform delete)
json{ "scripts": { "clean": "rimraf dist" } }
Common Script Patterns
Development Environment Scripts
json{ "scripts": { "dev": "nodemon index.js", "dev:debug": "nodemon --inspect index.js", "dev:hot": "webpack serve --hot" } }
Build Scripts
json{ "scripts": { "build": "webpack --mode production", "build:dev": "webpack --mode development", "build:analyze": "webpack --mode production --analyze" } }
Test Scripts
json{ "scripts": { "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage", "test:ci": "jest --ci --coverage --maxWorkers=2" } }
Code Quality Scripts
json{ "scripts": { "lint": "eslint src/", "lint:fix": "eslint src/ --fix", "format": "prettier --write \"src/**/*.js\"", "typecheck": "tsc --noEmit" } }
Git Hook Scripts (using husky)
json{ "scripts": { "prepare": "husky install", "precommit": "lint-staged" } }
Parallel and Sequential Execution
Use & for parallel execution, && for sequential execution:
json{ "scripts": { "parallel": "npm run lint & npm run test", "sequential": "npm run lint && npm run test", "all": "npm run lint && npm run test && npm run build" } }
Use npm-run-all tool for more flexibility:
json{ "scripts": { "dev": "npm-run-all --parallel dev:*", "dev:server": "nodemon index.js", "dev:client": "webpack serve" } }
Best Practices
- Naming Convention: Use colons to separate related scripts (e.g.,
test:watch) - Documentation: Document custom scripts in README
- Error Handling: Ensure scripts return non-zero exit codes on failure
- Performance Optimization: Avoid unnecessary repetitive operations
- Environment Isolation: Use environment variables to manage different environment configurations
- Dependency Management: Install development tools as devDependencies
Debugging Tips
View Script Execution Details
bashnpm run <script> -- --verbose
View Actual Command Being Executed
bashnpm run <script> -n
Debug Local Packages Using npm link
bashnpm link ../my-local-package
npm scripts are the core of project automation, and using them properly can significantly improve development efficiency and project maintainability.