This document discusses using NPM scripts as a build tool. It covers setting up scripts in the package.json file to automate common tasks like linting, testing, building assets, and running dev servers. Examples are provided of setting up scripts for CSS preprocessing, bundling JavaScript, running tests, and more for both AngularJS and React projects. Chaining, piping, and running tasks concurrently with NPM scripts is also covered.
27. 1. Is the base tool broken?
2. Is the Grunt/Gulp plugin broken?
3. Is the my configuration broken?
4. Am I using incompatible version?
Frustrating Debugging
5 . 6
28. Use npm module directly.
Without Grunt/Gulp.
Without Grunt/Gulp plugin.
Use npm scripts.
Solution
5 . 7
34. npm-scripts
publish, install, uninstall, version, test, stop, start
npm run-script
pre and post with matching will be run
(e.g. premyscript, myscript, postmyscript)
6 . 6
43. var gulp = require('gulp'),
webserver = require('gulp-webserver'),
del = require('del'),
sass = require('gulp-sass'),
karma = require('gulp-karma'),
jshint = require('gulp-jshint'),
sourcemaps = require('gulp-sourcemaps'),
spritesmith = require('gulp.spritesmith'),
browserify = require('browserify'),
source = require('vinyl-source-stream'),
buffer = require('vinyl-buffer'),
uglify = require('gulp-uglify'),
gutil = require('gulp-util'),
ngAnnotate = require('browserify-ngannotate');
var CacheBuster = require('gulp-cachebust');
var cachebust = new CacheBuster();
/////////////////////////////////////////////////////////////////////////////////////
//
// cleans the build output
//
/////////////////////////////////////////////////////////////////////////////////////
gulp.task('clean', function (cb) {
del([
'dist'
], cb);
});
/////////////////////////////////////////////////////////////////////////////////////
//
angularjs with gulp
7 . 5
44. angularjs with gulp
integration with bower
Sass (with source maps)
unit testing / integration testing with Karma, Jasmine and PhantomJs
cache busting - to prevent cache problems in all environments, dev
tools opened or closed, etc.
template cache pre-population - to prevent that each template causes
one extra HTTP request
jshint - the de-facto Javascript code quality checker
concatenation
browserify integration - for using the CommonJs require('module')
synchronous import syntax and avoid maintaining config files with
dependencies
Javascript source maps
Angular-friendly Javascript minification
sprite generation
a development web server with live reload, that re-loads the initial
page of the project
7 . 6
46. react with npm scripts
Sass (with source maps)
unit testing / integration testing with Karma, Jasmine and PhantomJs
cache busting - to prevent cache problems in all environments, dev
tools opened or closed, etc.
jade template
eslint - Pluggable JavaScript linter
concatenation
browserify integration - for using the CommonJs require('module')
synchronous import syntax and avoid maintaining config files with
dependencies
Javascript source maps
React-friendly Javascript minification
JSX compile
a development web server with live reload, that re-loads the initial
page of the project
7 . 8
47. var gulp = require('gulp'),
webserver = require('gulp-webserver'),
del = require('del'),
sass = require('gulp-sass'),
karma = require('gulp-karma'),
jshint = require('gulp-jshint'),
sourcemaps = require('gulp-sourcemaps'),
spritesmith = require('gulp.spritesmith'),
browserify = require('browserify'),
source = require('vinyl-source-stream'),
buffer = require('vinyl-buffer'),
uglify = require('gulp-uglify'),
gutil = require('gulp-util'),
ngAnnotate = require('browserify-ngannotate');
var CacheBuster = require('gulp-cachebust');
var cachebust = new CacheBuster();
gulp.task('clean', function (cb) {
del([
'dist'
], cb);
});
gulp.task('bower', function() {
var install = require("gulp-install");
return gulp.src(['./bower.json'])
.pipe(install());
});
gulp.task('build-css', ['clean'], function() {
return gulp.src('./styles/*')
.pipe(sourcemaps.init())
{
"scripts": {
"clean": "rimraf dist/ && mkdirp dist/{js,css,
"autoprefixer": "postcss -u autoprefixer -r di
"scss": "node-sass --output-style expanded --s
"prebuild": "npm run clean && npm test",
"build:js": "browserify src/js/app.jsx --stand
"build:css": "npm run scss && postcss -u autop
"build:html": "jade src/jade/index.jade --pret
"build": "npm-run-all --sequential build:*",
"predev": "npm run clean",
"dev:js": "browserify src/js/app.jsx --standal
"postdev:js": "jade src/jade/index.jade --pret
"dev:css": "npm run scss && npm run autoprefix
"postdev:css": "jade src/jade/index.jade --pre
"dev": "npm run dev:js && npm run dev:css",
"open": "opener http://localhost:9090/html/#/"
"live-reload": "live-reload --port 9091 dist/h
"serve": "http-server -p 9090 dist/",
"watch:css": "onchange "src/scss" -- npm run
"watch:js": "onchange "src/js" -- npm run de
"watch": "npm-run-all --parallel watch:*",
"start": "npm run live-reload & npm run open &
"pretest": "eslint src/js test --ext=jsx --ext
"test:debug": "karma start karma-debug.conf.js
"test": "karma start"
}
}
7 . 9
49. Chaning tasks(&&)
Running command is to run a command only
if the previous command is successful.
"scripts": {
...
"clean": "rimraf dist/ && mkdirp dist/{js,css,html} && copyfiles favicon.ico dist",
...
}
7 . 11
50. Concurrently tasks(&)
Sometimes it is also nice to be able to run
multiple commands at the concurrently.
"scripts": {
...
"watch": "npm run watch-js & npm run watch-less & npm run watch-jade",
...
},
7 . 12
51. Piping tasks(|)
piping (|) the output from browserify into uglifyjs.
"scripts": {
"build-js": "browserify -t reactify app/js/main.js | uglifyjs -mc > static/bundle.js"
}
7 . 13
52. {
"scripts": {
"test": "karma start",
"pretest": "npm run lint",
"posttest": "npm run build",
"postinstall": "bower install"
}
}
npm test
npm install
package.json
usage
Pre & Post scripts
7 . 14
53. "scripts": {
"lint": "eslint src/**/*.js",
"unit": "karma start",
"test": "npm run lint & npm run unit"
}
npm run lint
npm run unit
npm run test
package.json
usage
Sub-tasks
7 . 15
54. "scripts": {
"lint": "eslint src/**/*.js",
"unit": "karma start",
"test": "npm-run-all --sequential lint unit"
}
npm run test
package.json
usage
Sub-tasks
with npm-run-all
7 . 16
55. "scripts": {
"test:lint": "eslint src/**/*.js",
"test:unit": "karma start",
"test": "npm-run-all test:*"
}
npm run test
package.json
usage
Sub-tasks
with namespace
7 . 17
56. npm-build-boilerplate
"scripts": {
"clean": "rm -f dist/{css/*,js/*,images/*}",
"autoprefixer": "postcss -u autoprefixer -r dist/css/*",
"scss": "node-sass --output-style compressed -o dist/css src/scss",
"lint": "eslint src/js",
"uglify": "mkdir -p dist/js && uglifyjs src/js/*.js -m -o dist/js/app.js &&
"imagemin": "imagemin src/images/* -o dist/images",
"icons": "svgo -f src/images/icons && mkdir -p dist/images && svg-sprite-gen
"serve": "browser-sync start --server --files "dist/css/*.css, dist/js/*.js
"build:css": "npm run scss && npm run autoprefixer",
"build:js": "npm run lint && npm run uglify",
"build:images": "npm run imagemin && npm run icons",
"build:all": "npm run build:css && npm run build:js && npm run build:images"
"watch:css": "onchange "src/scss" -- npm run build:css",
"watch:js": "onchange "src/js" -- npm run build:js",
"watch:images": "onchange "src/images" -- npm run build:images",
"watch:all": "npm-run-all -p serve watch:css watch:js watch:images",
"postinstall": "npm run build:all && npm run watch:all"
}
7 . 18
69. Useful Link
Why I Left Gulp and Grunt for npm Scripts
Why npm Scripts?
How to Use npm as a Build Tool
Advanced front-end automation
with npm scripts
8 . 9