yumyo / Npm-Tips-and-Tricks

Tips and Tricks for working with NPM scripts.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NPM Tips and Tricks

This information was generated from the egghead.io video series How to Use npm Scripts as Your Build Tool by Elijah Manor. See that for a better description and more information. Thanks go to egghead.io and Elijah since this document would not exist without their work.

While the idea of the video series is to use npm for managing your build process, it also contains a lot of npm tips and tricks that can be useful in general. Which is why I pulled out some of the key concepts here.

You can click on the section titles to go to the original video lessons for each topic.

You can also find more information about these npm commands and features in the npm documentation.

At the bottom of this document is a list of the various npm packages used in the examples.

  • npm init (prompts for package info)

  • npm init --force (no prompts, use default)

  • npm init --yes (same as --force)

  • npm init -f (same as --force)

  • npm init -y (same as --yes)

    MIT license, permissive, few restrictions

  • npm run (list all scripts)

  • npm test (runs the test script)

  • npm t (runs the test script)

npm knows about the "test" and "start" scripts. To run them:
npm test or npm t
npm start

typical start script:  "node index.js"

"eslint" : "eslint --cache --fix ./"
--cache don't relint files that haven't changed
--fix autofix some rules with simple solutions

npm run env -- list NPM provided environment variables
npm run-script eslint (to run the eslint script)
npm run eslint (same as run-script)

Use && between commands to run them in series.

If any command fails, the rest of the line is aborted.

scripts: {  
  "lint" : "npm run eslint && npm run stylelint",  
  "eslint": "eslint --cache --fix ./",  
  "stylelint": "stylelint '**/*.scss' --syntax scss"  
}  

Use & between commands to run them in parallel.
Use wait to allow a long running process to be terminated with CTRL-C.

scripts: {  
  "lint" : "npm run eslint & npm run stylelint",  
  "eslint": "eslint --cache --fix ./",  
  "stylelint": "stylelint '**/*.scss' --syntax scss",  
  "watch" : "npm run lint & gulp watch & wait"  
}  

npm i npm-run-all -D
By default scripts will run in series, add --parallel switch to run in parallel.
You don't need wait when using npm-run-all.

scripts: {  
  "lint" : "npm-run-all --parallel eslint stylelint",  
  "eslint": "eslint --cache --fix ./",  
  "stylelint" "stylelint '**/*.scss' --syntax scss"  
}  

npm supports a wildcard when running scripts.
Name scripts with a common prefix, "lint:" in the example below.
Use "*" to match one level, or "**" to match multiple levels.

scripts: {  
  "lint" : "npm-run-all lint:**",  
  "lint:js": "eslint --cache --fix ./",  
  "lint:css": "stylelint '**/*.scss' --syntax scss",  
  "lint:css:fix": "stylefmt -R src/"  
}  
scripts: {  
  "pretest": "npm run lint", 
  "test": "some command to run tests",  
  "lint" : "npm-run-all lint:**",  
  "lint:js": "eslint --cache --fix ./",  
  "lint:css": "stylelint '**/*.scss' --syntax scss",  
  "lint:css:fix": "stylefmt -R src/"  
}  

In the example below:
The "cover" script runs tests under the nyc app to collect test coverage data.
The "postcover" script clean up the output generated by nyc.
The "cover:open" script opens the coverage report in a browser.

scripts: {  
  "pretest": "npm run lint",  
  "test": "some command to run tests",   
  "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 to an npm script.

Say you wanted two versions of some task, perhaps you want a lint script that only lints and a second script to lint and fix.

scripts: {  
  "lint:js": "eslint --cache ./",  
  "lint:js:fix": "eslint --cache --fix ./"  
}

The issue above that there is now duplicate config for the two commands.

Instead of doing that, the second script can just call the first, passing in the additional flag. Note you need the additional -- to tell npm that what follows is the addional flags to be appended to the command.

scripts: {  
  "lint:js": "eslint --cache ./",  
  "lint:js:fix": "npm run lint:js -- --fix"  
}  

Use the | character to send the output of one program as the input to another program.
Use the > character to redirect console output to some file.

scripts: {  
  "prebuild": "rm -rf public/",
  "build": "npm-run-all build:*",
  "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",
}  

Some applications support a --watch flag to look for file changes, but what about those applciations that don't have watch support built in?

Use onchange.

scripts: {
  "test": "script to run tests",
  "watch": "npm-run-all --parallel watch:*",
  "watch:test": "npm t -- -watch",
  "watch:lint": "onchange '**/*.js' '**/*.sass -- npm run lint",
  "lint" : "npm-run-all lint:**",  
  "lint:js": "eslint --cache --fix ./",  
  "lint:css": "stylelint '**/*.scss' --syntax scss" , 
  "lint:css:fix": "stylefmt -R src/"  
}

npm exposes the properties defined in the package.json file as enviornment variables you can use in npm scripts. Things like "name", "version".

npm run env -- list all the npm environment variables. package properties begin with "npm_package_"

The example below uses the "version" in the package.json file to put the output to a version specific folder in public.
Note: These examples use Linux format for using env variables.

scripts: {  
  "prebuild": "rm -rf public/$npm_package_version/",
  "build": "npm-run-all build:*",
  "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/index.min.css",
  "build:js": "mustache data.json src/index.mustache.js | uglifyjs > public/$npm_package_version/index.min.js",
}  

package.json can have a "config" section. You can use these config settings in your npm scripts. Config settings are exposed as enviornment variables with an "npm_package_config_" prefix.

npm run env

config: {  
  "port": 1337
},  
scripts: {  
  "poststart" : "npm-run-all buld server",
  "build" : "command to do the build, see examples above",
  "server" : "npm-run-all server:*",  
  "server:start": "http-server public/$npm_package_version -p $npm_package_config_port",
  "server:launch": "open http://localhost:$npm_package_config_port/index.html",
}  

You can also override the default config values in the package.json file from the command line.

npm config set key value -- override default config setting in package.json.
npm config list -- list current config settings
npm config delete key -- remove override and go back to default config setting.

See npm-config for more npm config commands for getting and setting config properties.

The npm husky package allows you to create npm scripts that are run before git commands.

npm install husky -D

scripts: {  
  "precommit" : "npm run test",
  "prepush":  "npm run test"
}  

Now, when you run your git commit command:

git commit -am "commit message"

husksy will run your tests first and only allow the commit to go through if the tests pass. You can add a --no-verify flag to the commit command to bypass the tests during the commit.

If you don't want to run the tests before every local commit, use the prepush script instead. That runs the tests prior to the push to the remote.

Ref: npm-config

When running npm scripts you can pass in additional command line arguments to control the level of output.

npm start --loglevel silent
npm start -silent
npm start -s

Log Levels are:

  • --loglevel silent, -silent, -s
  • --loglevel warn, -quiet, -q
  • --loglevel info, -d
  • --loglevel verbose, -verbose, -dd
  • --loglevel silly, -ddd (can be useful for debugging npm scripts)

Need to run your npm scripts in different environment?

Set an enviornment variable

If you need to set an environment variable in your npm script, the following only works on Mac and Linux...

scripts: {  
  "test" : "BABEL_ENV=test mocha spec/ --require babel-register",
}  

and this only works on windows...

scripts: {  
  "test" : "set BABEL_ENV=test && mocha spec/ --require babel-register",
}  

Use cross-env to set environment variables in a platform independent manor. npm install cross-env -d

This now works on Mac, Linux and Windows...

scripts: {  
  "test" : "cross-env BABEL_ENV=test mocha spec/ --require babel-register",
}  

Delete Files

If you need to delete files in your npm script, the following only works on Mac and Linux...

scripts: {  
  "postcover" : "rm -rf .nyc_output",
}  

Use rimraf to delete files in a platform independent manor.
npm install rimraf -d

This now works on Mac, Linux and Windows...

scripts: {  
  "postcover" : "rimraf .nyc_output",
}  

Open Files

If you need to open files, like an index.html file, in your npm script, the following only works on Mac and Linux...

scripts: {  
  "cover:open" : "open coverage/index.html",
}  

Use opn-cli to open files in a platform independent manor.
npm install opn-cli -d

This now works on Mac, Linux and Windows...

scripts: {  
  "cover:open" : "opn coverage/index.html",
}  

Include quotes in script commands

If you need to include quotes in a script command,open files, Linux and Mac will accept single quotes...

scripts: {  
  "lint:css": "stylelint '**/*.scss' --syntax scss" , 
}  

But on Windows you need to use double quotes and since we are already in a string, we need to escape them. This will also work on Linux and Mac.

scripts: {  
  "lint:css": "stylelint \"**/*.scss\" --syntax scss" , 
}  

Reference an environment variable

If you need to reference an environment variable in an npm script...

On Mac/Linux, use $ to reference an environment variable.

scripts: {  
  "prebuild": "rimraf public/$npm_package_version/",
}  

On Windows, use % (before and after) to reference an environment variable.

scripts: {  
  "prebuild": "rimraf public/%npm_package_version%/",
}  

Use cross-var to reference an environment variable in a platform independent manor.
npm install cross-var -d

scripts: {  
  "prebuild": "cross-var public/$npm_package_version/",
}  

Note: cross-var doesn't work across pipes or output redirects.
In that case you need to pass cross-var one big string.

scripts: {  
  "build:css": "cross-var \"node-sass src/index.scss | postcss -c .postcssrc.json | cssmin > public/$npm_package_version/index.min.css\"",
}  

npm run -- list available scripts

npm completion can enable tab completion. See link for Windows.

Another option is to install the ntl (node task list) command... npm install ntl -g

Use script name of "//", npm will ignore this script. You can have more than one of these. However, "npm run" will only list the last comment.

scripts: {  
  "//": "Helpful comment here!!",
  "start": "node index.js",
  "//": "Another helpful comment here!!",
}  

See the video for more options. (None looked particularly appealing to me.)

See video link.

See video link.

See video link.

npm modules:

These are the npm modules referenced in the lessons.
npm install {moduleName} -D

-D add to devDependencies

  • eslint - lint js file, similar to jslint, jshint
  • stylelint - CSS style linter
  • npm-run-all - Runs multiple npm scripts in series or parallel
  • stylefmt - Automatically formats CSS files
  • nyc - Generate test coverage reports (Babel, Istanbul ???)
  • pug-cli - Command line interface for Pug, a clean, whitespace-sensitive template language for writing HTML
  • node-sass - SASS to CSS compiler
  • postcss-cli - Command line interface for postcss
  • cssmin - CSS minifier
  • mustache -
  • uglify-js - Javascript minifier
  • onchange - Use glob patterns to watch file sets and run an npm script when anything is added, changed or deleted.
  • http-server - A simple zero-configuration command-line http server for serving up static files.
  • husky - Integrates git hooks with npm scripts
  • cross-env - Run commands that set environment variables across platforms
  • rimraf - Deleted files across platforms
  • opn-cli - Open files across platforms
  • cross-var - Reference environment variables across platform
  • ntl - Node task list command line app.
  • p-s - All the benefits of npm scripts without the cost of a bloated package.json and limits of json

About

Tips and Tricks for working with NPM scripts.