Created
April 9, 2015 14:07
-
-
Save dcousineau/1476362bdd3b4793a90a to your computer and use it in GitHub Desktop.
Gulp Build System
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var _ = require('underscore') | |
, nodeResolve = require('resolve') | |
, gulp = require('gulp') | |
, gutil = require('gulp-util') | |
, browserify = require('browserify') | |
, watchify = require('watchify') | |
, babelify = require('babelify') | |
, source = require('vinyl-source-stream') | |
, buffer = require('vinyl-buffer') | |
, uglify = require('gulp-uglify') | |
, size = require('gulp-size') | |
, rename = require('gulp-rename') | |
, less = require('gulp-less') | |
, sourcemaps = require('gulp-sourcemaps') | |
, gulpif = require('gulp-if') | |
, minifyCSS = require('gulp-minify-css') | |
, notify = require('gulp-notify') | |
, clean = require('gulp-clean') | |
, hbsfy = require('hbsfy') | |
, jshint = require('gulp-jshint') | |
, ignore = require('gulp-ignore') | |
, svgstore = require('gulp-svgstore') | |
, svgmin = require('gulp-svgmin') | |
, jscs = require('gulp-jscs') | |
, replace = require('gulp-replace') | |
, runSequence = require('run-sequence') | |
, stripify = require('stripify') | |
; | |
var env = process.env.NODE_ENV || 'dev' | |
, production = (env == 'prod') | |
, destPath = './application/static/build' | |
; | |
//// | |
// General | |
//// | |
gulp.task('default', function(cb) { | |
runSequence( | |
'clean', | |
['watch-js', 'watch-less', 'watch-svg'], | |
cb | |
); | |
}); | |
//run before deployments | |
gulp.task('build', function(cb) { | |
runSequence( | |
'clean', | |
['js', 'less', 'svgstore'], | |
cb | |
); | |
}); | |
//// | |
// Style/CSS Tasks | |
//// | |
gulp.task('less', function() { | |
return gulp.src('application/static/src/less/core.less') | |
.pipe(sourcemaps.init()) | |
.pipe(less({ | |
paths: ['node_modules', 'application/static/src/less'] | |
}).on('error', notify.onError({ | |
message: "Error: <%= error.message %>" | |
, title: "LESS Compile Error" | |
}))) | |
.pipe(gulpif(!production, sourcemaps.write('.'))) | |
.pipe(gulp.dest(destPath + '/css')) | |
.pipe(buffer()) | |
.pipe(minifyCSS({ | |
keepSpecialComments: 0 //Drop everything including licensing comments, we will list in app | |
})) | |
.pipe(rename('core.min.css')) | |
.pipe(gulp.dest(destPath + '/css')) | |
; | |
}); | |
gulp.task('watch-less', ['less'], function() { | |
return gulp.watch('application/static/src/less/**/*.less', ['less']); | |
}); | |
//// | |
// Javascript Tasks | |
//// | |
function getNPMPackageIds() { | |
// read package.json and get dependencies' package ids | |
var packageManifest = {}; | |
try { | |
var packageConfig = nodeResolve.sync('./package.json'); | |
if (require.cache[packageConfig]) { | |
delete require.cache[packageConfig]; | |
} | |
packageManifest = require(packageConfig); | |
} catch (e) { | |
// does not have a package.json manifest | |
} | |
return _.keys(packageManifest.dependencies) || []; | |
} | |
gulp.task('vendor-js', function() { | |
var entryFile = __dirname + '/application/static/src/js/__vendor__.js'; | |
var bundler = browserify({ | |
entries: [entryFile] | |
, paths: [__dirname + '/node_modules', __dirname + '/application/static/src/js/vendor'] | |
, debug: !production | |
}); | |
bundler | |
.transform(hbsfy) | |
; | |
// do the similar thing, but for npm-managed modules. | |
// resolve path using 'resolve' module | |
getNPMPackageIds().forEach(function (id) { | |
//Skip projects we will inject globally | |
if (['bootstrap-select'].indexOf(id) !== -1) return; | |
//Handle unpatched projects | |
if (id == 'vintagejs') { | |
bundler.require('vintagejs/dist/vintage', { expose: 'vintagejs/dist/vintage' }); | |
return; | |
} | |
gutil.log(gutil.colors.gray("Adding Vendor:"), gutil.colors.dim(id)); | |
bundler.require(nodeResolve.sync(id), { expose: id }); | |
}); | |
bundler.require(entryFile); | |
var bundle = bundler | |
.bundle() | |
.pipe(source(entryFile)) | |
.pipe(rename(destPath + '/js/vendor.js')) | |
.pipe(gulp.dest('./')) | |
; | |
!production || bundle | |
.pipe(buffer()) | |
.pipe(uglify()) | |
.pipe(rename({extname: '.min.js'})) | |
.pipe(gulp.dest('./')) | |
; | |
return bundle; | |
}); | |
function buildApp(watch) { | |
var entryFile = __dirname + '/application/static/src/js/__init__.js'; | |
var bundler = browserify({ | |
debug: !production | |
, extensions: ['.js', '.hbs'] | |
, paths: [__dirname + '/application/static/src/js'] | |
, cache: {} | |
, packageCache: {} | |
, fullPaths: false | |
}); | |
if (watch) { | |
bundler = watchify(bundler); | |
} | |
getNPMPackageIds().forEach(function (id) { | |
//For now skip bootstrap-select and manually include it if need be | |
if (['bootstrap-select'].indexOf(id) !== -1) return; | |
//Handle unpatched projects | |
if (id == 'vintagejs') { | |
bundler.external('vintagejs/dist/vintage', { expose: 'vintagejs/dist/vintage' }); | |
return; | |
} | |
//bundler.external(nodeResolve.sync(id), { expose: id }) | |
bundler.external(id, {expose: id}); | |
}); | |
//Initialize browserify bundler and setup transforms | |
bundler | |
.transform(hbsfy) | |
.transform(babelify.configure({ | |
//loose: ['es6.classes'] | |
})) | |
; | |
//Load stripify on production builds to kill any console | |
!production || bundler.transform(stripify); | |
//Setup entry point and error reporting | |
bundler | |
.add(entryFile) | |
.on('error', function(e) { | |
var message = e.message.replace(__dirname + '/application/static/src/js/', ''); | |
notify.onError({ | |
message: message | |
, title: "JS Error" | |
})(e); | |
this.emit('end'); | |
}) | |
; | |
var rebundle = function() { | |
var bundle = bundler | |
.bundle() | |
.on('error', function(e) { | |
var message = e.message.replace(__dirname + '/application/static/src/js/', ''); | |
if(process.platform === 'linux'){ | |
message = colorReplace(message, ''); | |
} | |
notify.onError({ | |
message: message | |
, title: "JS Error" | |
})(e); | |
this.emit('end'); | |
}) | |
.pipe(source(entryFile)) | |
.pipe(rename(destPath + '/js/app.js')) | |
.pipe(gulp.dest('./')) | |
; | |
!production || bundle | |
.pipe(buffer()) | |
.pipe(uglify()) | |
.pipe(rename({extname: '.min.js'})) | |
.pipe(gulp.dest('./')) | |
; | |
return bundle; | |
}; | |
if (watch) { | |
bundler | |
.on('update', function(){ | |
runSequence( | |
['lint-js', 'jscs'], | |
function() { | |
//noop on error | |
} | |
); | |
gutil.log("Rebuilding..."); | |
return rebundle(); | |
}) | |
.on('time', function(time) { | |
gutil.log('Rebuilt in', gutil.colors.magenta('' + time/1000 + ' s')); | |
}) | |
; | |
} | |
return rebundle(); | |
} | |
gulp.task('watch-vendor-js', ['vendor-js'], function() { | |
return gulp.watch([ | |
'application/static/src/js/__vendor__.js', | |
'package.json' | |
], ['vendor-js']); | |
}); | |
gulp.task('app-js', function() { | |
return buildApp(false); | |
}); | |
gulp.task('watch-app-js', function(){ | |
return buildApp(true); | |
}); | |
gulp.task('watch-js', ['watch-vendor-js', 'watch-app-js']); | |
gulp.task('js', ['vendor-js', 'app-js']); | |
gulp.task('clean', function () { | |
return gulp.src([ | |
destPath + '/js/*.js', | |
destPath + '/css/*.css', | |
destPath + '/css/*.map', | |
destPath + '/svg/*.svg', | |
'./application/templates/svg/*.svg', | |
'./application/static/compiled-includes/svg/*.svg' | |
], {read: false}) | |
.pipe(clean()); | |
}); | |
gulp.task('lint-js', function () { | |
return gulp.src(['application/static/src/js/**/*.js']) | |
.pipe(ignore.exclude(/js\/vendor\//)) //Ignore vendor files. | |
.pipe(ignore.exclude(/sandbox/i)) | |
.pipe(jshint({ | |
browser: true, | |
browserify: true, | |
jquery: true, | |
nonstandard: true, | |
devel: true, | |
globals: { | |
"ga": true, | |
"FB": true, | |
"Instajam": true, | |
"gapi": true, | |
"tracking": true | |
}, | |
esnext: true, | |
curly: false, //Consider enabling to disallow single line if statements | |
freeze: true, | |
latedef: "nofunc", | |
laxcomma: true, | |
undef: true, | |
eqnull: true, | |
eqeqeq: false, | |
"-W041": false //Disable the warning about requiring === with 0 | |
})) | |
.pipe(notify(function (file) { | |
if (file.jshint.success) { | |
// Don't show something if success | |
return false; | |
} | |
var errors = file.jshint.results.map(function (data) { | |
if (data.error) { | |
return "(" + data.error.line + ':' + data.error.character + ') ' + data.error.reason; | |
} | |
}).join("\n"); | |
return file.relative + " (" + file.jshint.results.length + " errors)\n" + errors; | |
})) | |
.pipe(jshint.reporter('jshint-stylish')) | |
.pipe(jshint.reporter('fail')) | |
; | |
}); | |
gulp.task('jscs', function() { | |
return gulp.src(['application/static/src/js/**/*.js']) | |
.pipe(ignore.exclude(/js\/vendor\//)) //Ignore vendor files. | |
.pipe(ignore.exclude(/sandbox/i)) | |
.pipe(jscs()) | |
; | |
}); | |
gulp.task('lint', ['lint-js', 'jscs']); | |
//// | |
// SVG Tasks | |
//// | |
gulp.task('svgstore', function () { | |
return gulp.src('application/static/src/svg/*.svg') | |
.pipe(svgmin().on('error', function(e) { | |
gutil.log(gutil.colors.red("SVG Minify Error:"), e.message, gutil.colors.red("(Likely empty file)")); | |
return false; | |
})) | |
.pipe(svgstore({ | |
inlineSvg: true | |
})) | |
// make sure that the SVG does not show itself on render | |
// ToDo: This is causing problems when interacting with the SVG. | |
// More info here https://github.com/w0rm/gulp-svgstore#transform-combined-svg: | |
.pipe(replace(/<svg/, '<svg display="none" version="1.1" xmlns="http://www.w3.org/2000/svg"')) | |
.pipe(rename('app.svg')) | |
.pipe(gulp.dest('./application/static/compiled-includes/svg')) | |
}); | |
gulp.task('watch-svg', ['svgstore'], function() { | |
return gulp.watch('application/static/src/svg/*.svg', ['svgstore']); | |
}); | |
//// | |
// Util | |
//// | |
// On linux the colors sometimes cause problems with the notification. | |
function colorReplace(input, replace) { | |
var replaceColors = { | |
"0;31" : "{r", | |
"1;31" : "{R", | |
"0;32" : "{g", | |
"1;32" : "{G", | |
"0;33" : "{y", | |
"1;33" : "{Y", | |
"0;34" : "{b", | |
"1;34" : "{B", | |
"0;35" : "{m", | |
"1;35" : "{M", | |
"0;36" : "{c", | |
"1;36" : "{C", | |
"0;37" : "{w", | |
"1;37" : "{W", | |
"1;30" : "{*", | |
"0" : "{x" | |
}; | |
if ( replace ) | |
{ | |
for( var k in replaceColors ) | |
{ | |
var re = new RegExp( "\\033\\[[" + k + "]*m", "g" ); | |
input = input.replace( re, replaceColors[ k ] ); | |
} | |
} else { | |
input = input.replace( /\033\[[0-9;]*m/g, "" ); | |
} | |
return input; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"dependencies": { | |
"backbone": "^1.1.2", | |
"backbone.marionette": "^2.2.2", | |
"bootstrap": "^3.3.1", | |
"bootstrap-select": "^1.6.3", | |
"cookie-cutter": "^0.1.1", | |
"cropper": "^0.9.1", | |
"fabric": "^1.4.13", | |
"handlebars": "^1.3.0", | |
"jquery": "^2.1.3", | |
"slick-carousel": "^1.3.15", | |
"sortablejs": "^1.1.1", | |
"tinyscrollbar": "^2.4.1", | |
"underscore": "^1.8.2", | |
"video.js": "^4.11.3", | |
"vintagejs": "^1.1.4" | |
}, | |
"devDependencies": { | |
"babelify": "^5.0.4", | |
"browserify": "^7.0.0", | |
"browserify-shim": "^3.8.1", | |
"cheerio": "^0.18.0", | |
"glob": "^4.3.1", | |
"gulp": "^3.8.10", | |
"gulp-clean": "^0.3.1", | |
"gulp-if": "^1.2.5", | |
"gulp-ignore": "^1.2.1", | |
"gulp-jscs": "^1.4.0", | |
"gulp-jshint": "^1.9.0", | |
"gulp-less": "^3.0.1", | |
"gulp-minify-css": "^0.5.1", | |
"gulp-notify": "^2.2.0", | |
"gulp-rename": "^1.2.0", | |
"gulp-replace": "~0.5.3", | |
"gulp-size": "^1.2.1", | |
"gulp-sourcemaps": "^1.2.8", | |
"gulp-svgmin": "^1.1.1", | |
"gulp-svgstore": "^5.0.0", | |
"gulp-uglify": "^1.0.2", | |
"gulp-util": "^3.0.4", | |
"hbsfy": "^2.2.1", | |
"jshint-stylish": "^1.0.0", | |
"resolve": "^1.1.5", | |
"run-sequence": "^1.0.2", | |
"stripify": "^3.0.0", | |
"vinyl-buffer": "^1.0.0", | |
"vinyl-source-stream": "^1.0.0", | |
"watchify": "^2.6.2" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment