Skip to content

Instantly share code, notes, and snippets.

@guyjin
Forked from lukewang1024/npm_scripts_build_tool.md
Created December 1, 2023 20:06
Show Gist options
  • Save guyjin/7a7e9fb7d8ab92eec18d0631d4392224 to your computer and use it in GitHub Desktop.
Save guyjin/7a7e9fb7d8ab92eec18d0631d4392224 to your computer and use it in GitHub Desktop.
Notes from egghead.io course: How to Use npm Scripts as Your Build Tool

Use npm scripts as your build tool

Basic dev task composition

// Dev tasks
{
  "scripts": {
    "eslint": "eslint --cache --fix ./",
    "stylelint": "stylelint '**/*.scss' --syntax scss",
    "stylelint:fix": "stylefmt -R src/",
    "mocha": "mocha spec/ --require babel-register --watch"
  }
}

// Use `&&` to run commands in series
"test": "npm run eslint && npm run stylelint && npm run mocha"

// Use `&` to run commands in parallel
"test": "npm run eslint & npm run stylelint & npm run mocha"

// Use `& wait` to quit `--watch` by Ctrl-C
"test": "npm run eslint & npm run stylelint & npm run mocha & wait"

Use npm-run-all as shortcut

// Dev tasks
{
  "scripts": {
    "eslint": "eslint --cache --fix ./",
    "stylelint": "stylelint '**/*.scss' --syntax scss",
    "stylelint:fix": "stylefmt -R src/",
    "mocha": "mocha spec/ --require babel-register --watch"
  }
}

// Use `npm-run-all` to run commands in series
"test": "npm-run-all eslint stylelint mocha"

// Use `npm-run-all --parallel` to run commands in parallel
"test": "npm-run-all --parallel eslint stylelint mocha"

Use wildcard

// Dev tasks
{
  "scripts": {
    "test": "npm-run-all lint mocha",
    "lint:js": "eslint --cache --fix ./",
    "lint:css": "stylelint '**/*.scss' --syntax scss",
    "lint:css:fix": "stylefmt -R src/",
    "mocha": "mocha spec/ --require babel-register --watch"
  }
}

// Use "lint:*" to match "lint:js" and "lint:css"
"lint": "npm-run-all lint:*"

// Use "lint:**" to match "lint:js", "lint:css" and "lint:css:fix"
"lint": "npm-run-all lint:**"

Use pre post npm script lifecycle hooks

{
  "scripts": {
    "pretest": "npm run lint",
    "test": "mocha spec/ --require babel-register",
    "watch:test": "mocha spec/ --require babel-register --watch",
    "cover": "nyc npm t",
    "postcover": "rm -rf .nyc_output",
    "cover:open": "open coverage/index.html",
    "lint": "npm-run-all lint:**",
    "lint:js": "eslint --cache --fix ./",
    "lint:css": "stylelint '**/*.scss' --syntax scss",
    "lint:css:fix": "stylefmt -R src/"
  }
}

Use -- to pass additional arguments

{
  "scripts": {
    "test": "mocha spec/ --require babel-register",
    "watch:test": "npm test -- --watch",
  }
}

Use | to pipe data from one npm script to another

{
  "scripts": {
    "build": "npm-run-all build:*",
    "prebuild": "rm -rf public/",
    "build:html": "pug --obj data.json src/index.pug --out public/",
    "build:css": "node-sass src/index.scss | postcss -c .postcssrc.json | cssmin > public/index.min.css",
    "build:js": "mustache data.json src/index.mustache.js | uglifyjs > public/index.min.js"
  }
}

Use onchange package to add watch support for tools without watch functionality

"watch:lint": "onchange '**/*.js' '**/*.scss' -- npm run lint"

Use package.json variables

Use npm run env | grep "npm_package" | less to check available variables.

{
  "scripts": {
    "prebuild": "rm -rf public/$npm_package_version/",
    "build:html": "pug --obj data.json src/index.pug --out public/$npm_package_version/",
    "build:css": "node-sass src/index.scss | postcss -c .postcssrc.json | cssmin > public/$npm_package_version/index.min.css",
    "build:js": "mustache data.json src/index.mustache.js | uglifyjs > public/$npm_package_version/index.min.js"
  }
}

Use custom config settings

{
  "config": {
    "port": "1337"
  },
  "scripts": {
    "start": "node index.js",
    "poststart": "npm run build && npm run server",
    "server": "npm-run-all --parallel server:*",
    "server:create": "http-server public/$npm_package_version -p $npm_package_config_port",
    "server:launch": "open http://localhost:$npm_package_config_port",
  }
}

Make scripts work across environments

  • cross-env: "test": "cross-env BABEL_ENV=test mocha spec/ --require babel-register"
  • rimraf (rm -rf): "postcover": "rimraf .nyc_output"
  • opn-cli (open): "cover:open": "opn coverage/index.html"
  • Windows doesn't support single quote: "lint:css": "stylelint \"**/*.scss\" --syntax scss"
  • cross-var:
    • "prebuild": "cross-var rimraf public/$npm_package_version/",
    • Need to wrap the whole command if pipe or redirection exists: "build:css": "cross-var \"node-sass src/index.scss | postcss -c .postcssrc.json | cssmin > public/$npm_package_version/index.min.css\""

Miscs

  • Add git hooks support
    • Use husky / lint-staged + pre-commit + pre-push
  • Change the level of console output
    • Use -s / -q / -d / -dd / -ddd
  • For command completion" npm completion >> ~/.zshrc
  • ntl package is pretty handy as well
  • Use p-s to pull scripts out to package-scripts.js
  • import {exec} from 'shelljs' to extract complex npm script to a node script
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment