@@ -1,104 +1,256 @@
"use strict" ;
/* global console */
'use strict' ;
var gulp = require ( 'gulp' ) ;
var gutil = require ( 'gulp-util' ) ;
var browserify = require ( 'gulp-browserify' ) ;
var del = require ( 'del' ) ;
var uglify = require ( 'gulp-uglify' ) ;
var gulpif = require ( 'gulp-if' ) ;
var exec = require ( 'child_process' ) . exec ;
var notify = require ( 'gulp-notify' ) ;
var buffer = require ( 'vinyl-buffer' ) ;
var argv = require ( 'yargs' ) . argv ;
// sass
var sass = require ( 'gulp-sass' ) ;
var postcss = require ( 'gulp-postcss' ) ;
var autoprefixer = require ( 'autoprefixer-core' ) ;
var sourcemaps = require ( 'gulp-sourcemaps' ) ;
// BrowserSync
var browserSync = require ( 'browser-sync' ) ;
// js
var watchify = require ( 'watchify' ) ;
var browserify = require ( 'browserify' ) ;
var source = require ( 'vinyl-source-stream' ) ;
// image optimization
var imagemin = require ( 'gulp-imagemin' ) ;
// linting
var jshint = require ( 'gulp-jshint' ) ;
var watch = require ( 'gulp-watch' ) ;
var stylish = require ( 'jshint-stylish' ) ;
var refresh = require ( 'gulp-livereload' ) ;
var sass = require ( 'gulp-sass ' ) ;
// testing/mocha
var mocha = require ( 'gulp-mocha ' ) ;
// livereload
var lr = require ( 'tiny-lr' ) ;
var server = lr ( ) ;
// File sources
var sources = {
scripts : [
'./src/*.js' ,
'./src/apps/**/*.js' ,
'./src/apps/**/*.jsx'
] ,
css : './src/scss/**/*.scss' ,
sass : './src/scss/app.scss' ,
statics : [
'./src/*.html' ,
'./src/static/**/*' ,
] ,
browserify : './src/app.js'
} ;
// Build destination
var buildDir = './www/' ;
// gulp build --production
var production = ! ! argv . production ;
// determine if we're doing a build
// and if so, bypass the livereload
var build = argv . _ . length ? argv . _ [ 0 ] === 'build' : false ;
var watch = argv . _ . length ? argv . _ [ 0 ] === 'watch' : true ;
// Tasks
// * build JavaScript (browserify)
// * copy static files
// * lint JavaScript
// * build sass
// * live-reload server
// ----------------------------
// Error notification methods
// ----------------------------
var beep = function ( ) {
var os = require ( 'os' ) ;
var file = 'gulp/error.wav' ;
if ( os . platform ( ) === 'linux' ) {
// linux
exec ( "aplay " + file ) ;
} else {
// mac
console . log ( "afplay " + file ) ;
exec ( "afplay " + file ) ;
}
} ;
var handleError = function ( task ) {
return function ( err ) {
beep ( ) ;
notify . onError ( {
message : task + ' failed, check the logs..' ,
sound : false
} ) ( err ) ;
gutil . log ( gutil . colors . bgRed ( task + ' error:' ) , gutil . colors . red ( err ) ) ;
} ;
} ;
// --------------------------
// CUSTOM TASK METHODS
// --------------------------
var tasks = {
scripts : function ( ) {
gulp . src ( sources . browserify )
. pipe ( browserify ( {
debug : ! gutil . env . production
} ) )
. pipe ( gulp . dest ( buildDir ) )
. pipe ( refresh ( server ) ) ;
// --------------------------
// Delete build folder
// --------------------------
clean : function ( cb ) {
del ( [ 'build/' ] , cb ) ;
} ,
statics : function ( ) {
gulp . src ( sources . statics )
. pipe ( gulp . dest ( buildDir ) )
. pipe ( refresh ( server ) ) ;
// --------------------------
// Copy static assets
// --------------------------
assets : function ( ) {
return gulp . src ( './client/assets/**/*' )
. pipe ( gulp . dest ( 'build/assets/' ) ) ;
} ,
lint : function ( ) {
var files = sources . scripts ;
files . push ( './gulpfile.js' ) ;
gulp . src ( files )
. pipe ( jshint ( '.jshintrc' ) )
. pipe ( jshint . reporter ( stylish ) ) ;
// --------------------------
// HTML
// --------------------------
// html templates (when using the connect server)
templates : function ( ) {
gulp . src ( 'templates/*.html' )
. pipe ( gulp . dest ( 'build/' ) ) ;
} ,
// --------------------------
// SASS (libsass)
// --------------------------
sass : function ( ) {
gulp . src ( sources . sass )
. pipe ( sass ( ) )
. pipe ( gulp . dest ( buildDir + 'css/' ) )
. pipe ( refresh ( server ) ) ;
return gulp . src ( './client/scss/*.scss' )
// sourcemaps + sass + error handling
. pipe ( gulpif ( ! production , sourcemaps . init ( ) ) )
. pipe ( sass ( {
sourceComments : ! production ,
outputStyle : production ? 'compressed' : 'nested'
} ) )
. on ( 'error' , handleError ( 'SASS' ) )
// generate .maps
. pipe ( gulpif ( ! production , sourcemaps . write ( {
'includeContent' : false ,
'sourceRoot' : '.'
} ) ) )
// autoprefixer
. pipe ( gulpif ( ! production , sourcemaps . init ( {
'loadMaps' : true
} ) ) )
. pipe ( postcss ( [ autoprefixer ( { browsers : [ 'last 2 versions' ] } ) ] ) )
// we don't serve the source files
// so include scss content inside the sourcemaps
. pipe ( sourcemaps . write ( {
'includeContent' : true
} ) )
// write sourcemaps to a specific directory
// give it a file and save
. pipe ( gulp . dest ( 'build/css' ) ) ;
} ,
livereload : function ( ) {
server . listen ( 35729 , function ( err ) {
if ( err ) {
return console . log ( err ) ;
}
// --------------------------
// Browserify
// --------------------------
browserify : function ( ) {
var bundler = browserify ( './client/js/index.js' , {
debug : ! production ,
cache : { }
} ) ;
}
// determine if we're doing a build
// and if so, bypass the livereload
var build = argv . _ . length ? argv . _ [ 0 ] === 'build' : false ;
if ( watch ) {
bundler = watchify ( bundler ) ;
}
var rebundle = function ( ) {
return bundler . bundle ( )
. on ( 'error' , handleError ( 'Browserify' ) )
. pipe ( source ( 'build.js' ) )
. pipe ( gulpif ( production , buffer ( ) ) )
. pipe ( gulpif ( production , uglify ( ) ) )
. pipe ( gulp . dest ( 'build/js/' ) ) ;
} ;
bundler . on ( 'update' , rebundle ) ;
return rebundle ( ) ;
} ,
// --------------------------
// linting
// --------------------------
lintjs : function ( ) {
return gulp . src ( [
'gulpfile.js' ,
'./client/js/index.js' ,
'./client/js/**/*.js'
] ) . pipe ( jshint ( ) )
. pipe ( jshint . reporter ( stylish ) )
. on ( 'error' , function ( ) {
beep ( ) ;
} ) ;
} ,
// --------------------------
// Optimize asset images
// --------------------------
optimize : function ( ) {
return gulp . src ( './client/assets/**/*.{gif,jpg,png,svg}' )
. pipe ( imagemin ( {
progressive : true ,
svgoPlugins : [ { removeViewBox : false } ] ,
// png optimization
optimizationLevel : production ? 3 : 1
} ) )
. pipe ( gulp . dest ( './client/assets/' ) ) ;
} ,
// --------------------------
// Testing with mocha
// --------------------------
test : function ( ) {
return gulp . src ( './client/**/*test.js' , { read : false } )
. pipe ( mocha ( {
'ui' : 'bdd' ,
'reporter' : 'spec'
} )
) ;
} ,
} ;
gulp . task ( 'browser-sync' , function ( ) {
browserSync ( {
server : {
baseDir : "./build"
} ,
port : process . env . PORT || 3000
} ) ;
} ) ;
gulp . task ( 'reload-sass' , [ 'sass' ] , function ( ) {
browserSync . reload ( ) ;
} ) ;
gulp . task ( 'reload-js' , [ 'browserify' ] , function ( ) {
browserSync . reload ( ) ;
} ) ;
gulp . task ( 'reload-templates' , [ 'templates' ] , function ( ) {
browserSync . reload ( ) ;
} ) ;
// --------------------------
// Register our tasks
// CUSTOMS TASKS
// --------------------------
// default
gulp . task ( 'default' , function ( ) {
gulp . run ( 'lint:js' , 'build:js' , 'copy:static' ) ;
gulp . task ( 'clean' , tasks . clean ) ;
// for production we require the clean method on every individual task
var req = build ? [ 'clean' ] : [ ] ;
// individual tasks
gulp . task ( 'templates' , req , tasks . templates ) ;
gulp . task ( 'assets' , req , tasks . assets ) ;
gulp . task ( 'sass' , req , tasks . sass ) ;
gulp . task ( 'browserify' , req , tasks . browserify ) ;
gulp . task ( 'lint:js' , tasks . lintjs ) ;
gulp . task ( 'optimize' , tasks . optimize ) ;
gulp . task ( 'test' , tasks . test ) ;
// --------------------------
// DEV/WATCH TASK
// --------------------------
gulp . task ( 'watch' , [ 'assets' , 'templates' , 'sass' , 'browserify' , 'browser-sync' ] , function ( ) {
// --------------------------
// watch:sass
// --------------------------
gulp . watch ( './client/scss/**/*.scss' , [ 'reload-sass' ] ) ;
// --------------------------
// watch:js
// --------------------------
gulp . watch ( './client/js/**/*.js' , [ 'lint:js' , 'reload-js' ] ) ;
// --------------------------
// watch:html
// --------------------------
gulp . watch ( './templates/**/*.html' , [ 'reload-templates' ] ) ;
gutil . log ( gutil . colors . bgGreen ( 'Watching for changes...' ) ) ;
} ) ;
// gulp task setup
gulp . task ( 'build:js' , tasks . scripts ) ;
gulp . task ( 'build:sass' , tasks . sass ) ;
gulp . task ( 'copy:static' , tasks . statics ) ;
gulp . task ( 'lint:js' , tasks . lint ) ;
gulp . task ( 'livereload' , tasks . livereload ) ;
// development watch & livereload
gulp . task ( 'dev' , function ( ) {
// start the livereload server
gulp . run ( 'livereload' ) ;
// watch for js changes
gulp . watch ( sources . scripts , function ( event ) {
gulp . run ( 'lint:js' , 'build:js' ) ;
} ) ;
gulp . watch ( sources . statics , function ( event ) {
gulp . run ( 'copy:static' ) ;
} ) ;
gulp . watch ( sources . css , function ( event ) {
gulp . run ( 'build:sass' ) ;
} ) ;
} ) ;
// build task
gulp . task ( 'build' , [
'clean' ,
'templates' ,
'assets' ,
'sass' ,
'browserify'
] ) ;
gulp . task ( 'default' , [ 'watch' ] ) ;