Back

Practical Uses of NPM Scripts Beyond Just Build and Start

Practical Uses of NPM Scripts Beyond Just Build and Start

Frontend developers often start with simple npm run build or npm run start commands, but NPM scripts can do much more for your workflow. You can leverage NPM scripts to automate repetitive tasks, streamline development, and make your projects more maintainable.

Key Takeaways

  • NPM scripts provide a simple, dependency-free way to automate your frontend workflow
  • Use pre/post hooks to chain commands without complex syntax
  • Leverage cross-platform utilities to ensure scripts work for all team members
  • Combine multiple scripts with npm-run-all for complex workflows
  • Access package.json data through environment variables for dynamic scripts

What Are NPM Scripts and Why Use Them?

NPM scripts are custom commands defined in your package.json file under the "scripts" section. They provide a simple way to run command-line tools and automate tasks without installing global packages or complex build tools.

{
  "name": "my-project",
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build"
  }
}

The main advantages of NPM scripts over task runners like Gulp or Grunt:

  • Zero configuration: Use them right out of the box with any npm project
  • Direct access to CLI tools: No abstraction layers or plugins to worry about
  • Dependency tracking: Tools are installed as project dependencies, ensuring everyone uses the same versions
  • Simplified workflow: No need to learn another tool’s syntax

10 Practical NPM Scripts for Frontend Developers

1. Linting and Formatting Code

Consistent code style improves readability and reduces errors. Add these scripts to automatically lint and format your code:

"scripts": {
  "lint": "eslint src/**/*.js",
  "lint:fix": "eslint src/**/*.js --fix",
  "format": "prettier --write \"src/**/*.{js,jsx,css,scss,json}\""
}

Run npm run lint to check for issues or npm run format to automatically format your code.

2. Cleaning Build Directories

Before creating a new build, clean up previous build artifacts:

"scripts": {
  "clean": "rimraf dist",
  "prebuild": "npm run clean",
  "build": "webpack"
}

The prebuild script automatically runs before build, ensuring a clean slate every time.

3. Running Tests with Different Configurations

Create various test scripts for different scenarios:

"scripts": {
  "test": "jest",
  "test:watch": "jest --watch",
  "test:coverage": "jest --coverage",
  "test:e2e": "cypress run"
}

4. Managing Environment Variables

Set up different environments for development, testing, and production:

"scripts": {
  "dev": "cross-env NODE_ENV=development webpack serve",
  "build:dev": "cross-env NODE_ENV=development webpack",
  "build:prod": "cross-env NODE_ENV=production webpack"
}

The cross-env package ensures these scripts work across different operating systems.

5. Watching for Changes

Automatically rebuild when files change:

"scripts": {
  "watch:css": "sass --watch src/styles:dist/styles",
  "watch:js": "webpack --watch",
  "watch": "npm-run-all --parallel watch:*"
}

The npm-run-all package allows running multiple scripts in parallel.

6. Synchronizing Environment Files

Create a script to copy environment template files:

"scripts": {
  "sync-env": "node -e \"require('fs').copyFileSync('.env.example', '.env', fs.constants.COPYFILE_EXCL)\"",
  "postinstall": "npm run sync-env"
}

The postinstall hook runs automatically after npm install, ensuring new team members get the environment file.

7. Validating Package Dependencies

Check for outdated, duplicate, or vulnerable dependencies:

"scripts": {
  "check:deps": "npm outdated",
  "check:security": "npm audit",
  "check:duplicates": "npx depcheck"
}

8. Generating Documentation

Automatically generate documentation from code comments:

"scripts": {
  "docs": "jsdoc -c jsdoc.json",
  "predeploy": "npm run docs"
}

9. Custom Release Workflows

Automate versioning and releases:

"scripts": {
  "version:patch": "npm version patch",
  "version:minor": "npm version minor",
  "version:major": "npm version major",
  "release": "npm run build && npm publish"
}

10. Optimizing Assets

Compress images and other assets:

"scripts": {
  "optimize:images": "imagemin src/images/* --out-dir=dist/images",
  "prebuild": "npm run clean && npm run optimize:images"
}

Advanced NPM Script Techniques

Chaining Scripts with Pre/Post Hooks

NPM automatically runs scripts prefixed with “pre” or “post” before or after the main script:

"scripts": {
  "prebuild": "npm run lint",
  "build": "webpack",
  "postbuild": "npm run test"
}

When you run npm run build, it automatically executes prebuild, then build, then postbuild.

Passing Arguments to Scripts

Pass arguments to your scripts using --:

npm run lint -- --fix

This passes the --fix flag to the actual linting command.

Using Environment Variables in Scripts

Access package.json data through environment variables:

"scripts": {
  "echo-version": "echo $npm_package_version"
}

When you run npm run echo-version, it prints your package version.

Cross-Platform Compatibility

Ensure your scripts work on all operating systems with these tools:

  1. rimraf - Cross-platform alternative to rm -rf
  2. cross-env - Set environment variables across platforms
  3. npm-run-all - Run multiple scripts in sequence or parallel

Example of cross-platform scripts:

"scripts": {
  "clean": "rimraf dist",
  "copy": "copyfiles -u 1 src/**/*.html dist",
  "dev": "cross-env NODE_ENV=development npm-run-all clean copy --parallel watch:*"
}

Real-World Example: Complete Frontend Workflow

Here’s a comprehensive set of scripts for a modern frontend project:

{
  "scripts": {
    "clean": "rimraf dist",
    "lint:js": "eslint src/**/*.js --fix",
    "lint:css": "stylelint src/**/*.scss --fix",
    "lint": "npm-run-all --parallel lint:*",
    "test": "jest",
    "test:watch": "jest --watch",
    "format": "prettier --write \"src/**/*.{js,jsx,scss,json,md}\"",
    "validate": "npm-run-all --parallel lint test",
    "build:css": "sass src/styles:dist/styles --style compressed",
    "build:js": "webpack --mode production",
    "build": "npm-run-all clean lint --parallel build:*",
    "watch:css": "sass --watch src/styles:dist/styles",
    "watch:js": "webpack --watch",
    "serve": "browser-sync start --server dist --files dist",
    "dev": "npm-run-all clean --parallel watch:* serve",
    "prepublish": "npm run build",
    "version": "npm run format && git add -A src",
    "postversion": "git push && git push --tags"
  }
}

This setup provides:

  • Code quality checks with linting and testing
  • Automated formatting
  • Optimized builds for production
  • Development server with hot reloading
  • Version management and publishing workflow

Conclusion

By implementing these practical NPM scripts, you’ll streamline your development process, improve code quality, and make your projects more maintainable. Start small by adding scripts for the tasks you perform most frequently, then gradually expand your automation toolkit.

FAQs

NPM scripts are simpler, require no plugins, and have zero configuration. They're ideal for straightforward tasks, while Gulp may be better for complex build processes requiring fine-grained control.

Yes, add --loglevel verbose to see detailed output or use 'npm run debug' with the debug package for even more information.

Use the npm-run-all package with the --parallel flag: npm-run-all --parallel script1 script2.

To use wildcards in NPM scripts safely, wrap the pattern in quotes to prevent shell expansion. This ensures the script works reliably across different environments and shell configurations.

NPM exposes them as environment variables: $npm_package_name, $npm_package_version, etc.

Listen to your bugs 🧘, with OpenReplay

See how users use your app and resolve issues fast.
Loved by thousands of developers