Skip to content

Instantly share code, notes, and snippets.

@troywarr
Created March 25, 2015 22:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save troywarr/199908fd29c8c47d269e to your computer and use it in GitHub Desktop.
Save troywarr/199908fd29c8c47d269e to your computer and use it in GitHub Desktop.
Complete gulpfile to demonstrate an issue using BrowserSync.
gulp = require('gulp')
gulpIf = require('gulp-if')
less = require('gulp-less')
minifyCSS = require('gulp-minify-css')
notify = require('gulp-notify')
rename = require('gulp-rename')
imageMin = require('gulp-imagemin')
uglify = require('gulp-uglify')
jade = require('gulp-jade')
svgSprite = require('gulp-svg-sprite')
plumber = require('gulp-plumber')
bump = require('gulp-bump')
coffeeLint = require('gulp-coffeelint')
size = require('gulp-size')
gutil = require('gulp-util')
cache = require('gulp-cached')
sourcemaps = require('gulp-sourcemaps')
templatizer = require('templatizer')
browserify = require('browserify')
transform = require('vinyl-transform')
pngCrush = require('imagemin-pngcrush')
del = require('del')
opn = require('opn')
browserSync = require('browser-sync')
_ = require('lodash')
# fs = require('fs')
# htmlify = require('gulp-angular-htmlify')
# rev = require('gulp-rev')
# concat = require('gulp-concat')
# mocha = require('gulp-mocha')
# karma = require('gulp-karma')
# protractorLib = require('gulp-protractor')
# changed = require('gulp-changed')
# templateCache = require('gulp-angular-templatecache')
# chai = require('chai') # TODO: needed?
### SHORTCUTS ###
buildTasks = [
'root'
'fonts'
'styles'
'scripts'
'images'
'jade-js'
'jade-html'
'ng-html'
'ng-views'
]
# protractor = protractorLib.protractor
# webdriver_standalone = protractorLib.webdriver_standalone
# webdriver_update = protractorLib.webdriver_update
### ENVIRONMENT ###
PROD = gutil.env.prod
DEV = !PROD
### PATHS ###
paths = # NOTE: avoid relative paths that start with ./ (see: http://stackoverflow.com/a/22391756/167911)
root: '.'
src: 'src'
dist: 'dist'
bower: 'bower_components'
npm: 'node_modules'
start: 'index.html' # entry point loaded in browser
coffeelint: 'coffeelint.json'
hobo: '../hobofest/public/ng'
### CONFIG ###
opts =
jade:
doctype: 'html' # prevent attribute expansion; needed for Angular directives
rev:
merge: true # merge with existing rev-manifest.json (don't overwrite)
size:
showFiles: true # show the size of individual files
uglify:
mangle: false # don't mangle names (prevents Angular DI breakage)
### UTILS ###
# error handling
handleError = (err) ->
notify.onError(
title: 'Gulp Error'
message: "#{err.message}"
)(err)
@emit 'end'
# bump version
# e.g., `gulp bump --minor`
gulp.task 'bump', ->
gulp
.src [
"#{paths.root}/bower.json"
"#{paths.root}/package.json"
]
.pipe bump
type: switch
when argv.major then 'major'
when argv.minor then 'minor'
else 'patch'
.pipe gulp.dest paths.root
# start BrowserSync server
gulp.task 'serve', ->
browserSync
server:
baseDir: paths.dist
directory: true
open: false
port: 3001
ui:
port: 3003
startPath: paths.start
, (err, bs) ->
url = bs.options.getIn(['urls', 'local']).replace(':3001/', ':3002/') # use nginx proxy
opn(url)
console.log("Started BrowserSync via nginx proxy at #{url}")
# lint scripts
# TODO: add JS support
gulp.task 'lint', ->
gulp
.src "#{paths.src}/scripts/**/*.coffee"
.pipe coffeeLint(paths.coffeelint)
.pipe coffeeLint.reporter()
### HOBO STACK INTEGRATION ###
# copy output to Hobo stack
gulp.task 'hobo', ->
gulp
.src '**/*.*',
cwd: paths.dist
.pipe cache 'hobo'
.pipe gulp.dest paths.hobo
# clean Hobo stack output
gulp.task 'clean:hobo', (done) ->
del paths.hobo,
force: true
, done
# watch dist output for changes we'll need to copy to Hobo stack
gulp.task 'watch:hobo', ->
gulp.watch "#{paths.dist}/**/*.*", ['hobo']
### WRAPPERS ###
# clean entire dist folder
gulp.task 'clean:dist', (done) ->
del paths.dist, done
# clean everything
gulp.task 'clean', [
'clean:dist'
'clean:hobo'
]
# watch everything
gulp.task 'watch', [
'watch:root'
'watch:fonts'
'watch:styles'
'watch:scripts'
'watch:images'
'watch:jade-js'
'watch:jade-html'
'watch:ng-html'
'watch:ng-views'
'watch:icons'
'watch:hobo'
]
### SRC: ROOT ###
# copy root directory files (CNAME, robots.txt, etc.)
gulp.task 'root', ->
gulp
.src "#{paths.src}/root/**/*"
.pipe cache 'root'
.pipe gulp.dest paths.dist
# clean 'root' task output
gulp.task 'clean:root', (done) ->
del [
"#{paths.dist}/CNAME"
"#{paths.dist}/iframeResizer.contentWindow.min.js"
"#{paths.dist}/iframeResizer.min.js"
"#{paths.dist}/robots.txt"
], done
# watch root files
gulp.task 'watch:root', ->
gulp.watch "#{paths.src}/root/**/*", ['root', browserSync.reload]
### SRC: FONTS ###
# copy fonts
gulp.task 'fonts', ->
gulp
.src [
"#{paths.src}/fonts/**/*" # add new fonts here (4 common formats)
"#{paths.npm}/bootstrap/dist/fonts/**/*"
]
.pipe cache 'fonts'
.pipe gulp.dest "#{paths.dist}/fonts"
# clean font files
gulp.task 'clean:fonts', ->
del "#{paths.dist}/fonts/**/*.*", done
# watch font files
gulp.task 'watch:fonts', ->
gulp.watch [
"#{paths.src}/fonts/**/*"
"#{paths.npm}/bootstrap/dist/fonts/**/*"
], ['fonts', browserSync.reload]
### SRC: STYLES ###
# compile LESS and minify
gulp.task 'styles', ['clean:styles'], ->
gulp
.src "#{paths.src}/styles/index.less"
.pipe plumber handleError
.pipe gulpIf DEV, sourcemaps.init()
.pipe less()
.pipe gulpIf DEV, sourcemaps.write()
.pipe gulpIf PROD, minifyCSS()
# .pipe gulpIf PROD, rev()
.pipe rename
extname: '.min.css'
.pipe size opts.size
.pipe gulp.dest "#{paths.dist}/styles"
# .pipe gulpIf PROD, rev.manifest opts.rev
# .pipe gulpIf PROD, gulp.dest paths.root
.pipe gulpIf DEV, browserSync.reload
stream: true
# clean stylesheets
gulp.task 'clean:styles', (done) ->
del "#{paths.dist}/styles/**/*.*", done
# watch LESS
gulp.task 'watch:styles', ->
gulp.watch "#{paths.src}/styles/**/*.less", ['styles']
### SRC: SCRIPTS ###
# compile, bundle and minify scripts
# see: https://medium.com/@sogko/gulp-browserify-the-gulp-y-way-bb359b3f9623
gulp.task 'scripts', ['clean:scripts', 'lint'], ->
browserified = transform (filename) ->
browserify
entries: filename
extensions: ['.coffee']
debug: true
.bundle()
gulp
.src "#{paths.src}/scripts/index.coffee"
.pipe plumber handleError
.pipe browserified
.pipe gulpIf PROD, uglify opts.uglify
# .pipe gulpIf PROD, rev()
.pipe rename
extname: '.min.js'
.pipe size opts.size
.pipe gulp.dest "#{paths.dist}/scripts"
# .pipe gulpIf PROD, rev.manifest opts.rev
# .pipe gulpIf PROD, gulp.dest paths.root
# clean compiled scripts
gulp.task 'clean:scripts', (done) ->
del "#{paths.dist}/scripts/**/*.*", done
# watch scripts
gulp.task 'watch:scripts', ->
gulp.watch "#{paths.src}/scripts/**/*.coffee", ['scripts', browserSync.reload]
### SRC: IMAGES ###
# compress images
# see: https://github.com/sindresorhus/gulp-imagemin
gulp.task 'images', ->
gulp
.src "images/**",
cwd: "#{paths.src}/**"
.pipe plumber handleError
.pipe cache 'images'
.pipe imageMin
progressive: true
svgoPlugins: [
{
removeViewBox: false
}
]
use: [
pngCrush()
]
.pipe gulp.dest paths.dist
# clean image output
gulp.task 'clean:images', (done) ->
del "#{paths.dist}/images/**/*.*", done
# watch images
gulp.task 'watch:images', ->
gulp.watch "#{paths.src}/images/**/*", ['images', browserSync.reload]
### SRC: ICONS ###
# SVG icon sprite
# see: http://css-tricks.com/svg-sprites-use-better-icon-fonts/
gulp.task 'icons', ->
gulp
.src "#{paths.src}/icons/**/*.svg"
.pipe plumber handleError
.pipe svgSprite
shape:
id:
generator: 'icon-'
mode:
symbol:
inline: true
example: DEV and { dest: 'example/icons.html' }
dest: 'svg'
sprite: 'icons.svg'
.pipe gulp.dest paths.dist
# clean icon output
gulp.task 'clean:icons', (done) ->
del "#{paths.dist}/icons/**/*.*", done
# watch icons
gulp.task 'watch:icons', ->
gulp.watch "#{paths.src}/icons/**/*", ['jade-html', 'jade-js', browserSync.reload]
### SRC: JADE (TO JS) ###
# compile Jade templates to JS
# see: https://github.com/muraken720/nancle/blob/master/gulpfile.coffee
# TODO: find/request (or build) gulp-templatizer (stream support)
# TODO: don't compile back into src/ (seems wrong)
# TODO: can we replace this with gulp-jade compile to JS? (see: https://www.npmjs.com/package/gulp-jade)
# TODO: concat this with other scripts
# TODO: provide service for manifest URLs
gulp.task 'jade-js', ['icons'], ->
templatizer "#{paths.src}/jade/templates/js", "#{paths.src}/scripts/!tmpl.js"
# clean rendered Jade file
gulp.task 'clean:jade-js', (done) ->
del "#{paths.src}/scripts/!tmpl.js", done
# watch Jade files
gulp.task 'watch:jade-js', ->
gulp.watch [
"#{paths.src}/jade/layouts/js/**/*.jade"
"#{paths.src}/jade/templates/js/**/*.jade"
], ['jade-js', 'scripts', browserSync.reload]
### SRC: JADE (TO HTML) ###
# render Jade to HTML
# TODO: provide service for manifest URLs
gulp.task 'jade-html', ['icons'], ->
# if PROD
# manifest = JSON.parse fs.readFileSync "#{paths.root}/rev-manifest.json", 'utf8'
gulp
.src "*.jade",
cwd: "#{paths.src}/jade/pages/**"
.pipe plumber handleError
.pipe cache 'jade-html'
.pipe jade _.merge {}, opts.jade,
locals:
# script: if manifest? then "scripts/#{manifest['index.coffee']}" else 'scripts/index.min.js'
# style: if manifest? then "styles/#{manifest['index.css']}" else 'styles/index.min.css'
script: 'scripts/index.min.js'
style: 'styles/index.min.css'
# .pipe htmlify() # add data- prefixes to non-HTML5-valid attributes
.pipe gulp.dest paths.dist
# clean rendered Jade files
gulp.task 'clean:jade-html', (done) ->
del "#{paths.dist}/*.html", done
# watch Jade files
gulp.task 'watch:jade-html', ->
gulp.watch [
"#{paths.src}/jade/layouts/html/**/*.jade"
"#{paths.src}/jade/mixins/**/*.jade"
"#{paths.src}/jade/pages/**/*.jade"
"#{paths.src}/jade/svg/**/*.jade"
"#{paths.src}/icons/**/*.jade"
], ['jade-html', browserSync.reload]
### SRC: ANGULAR VIEWS ###
# render Angular views from Jade
gulp.task 'ng-views', ->
gulp
.src "*.jade",
cwd: "#{paths.src}/jade/views/**"
.pipe plumber handleError
.pipe cache 'ng-views'
.pipe jade opts.jade
# .pipe htmlify() # add data- prefixes to non-HTML5-valid attributes
.pipe gulp.dest "#{paths.dist}/views"
# clean Angular view output
gulp.task 'clean:ng-views', ->
del "#{paths.dist}/views/**/*.*", done
# watch Angular views
gulp.task 'watch:ng-views', ->
gulp.watch [
"#{paths.src}/jade/views/**/*.jade"
"#{paths.src}/jade/partials/**/*.jade"
], ['ng-views', browserSync.reload]
### SRC: ANGULAR TEMPLATES ###
# render Angular templates from Jade
gulp.task 'ng-html', ->
gulp
.src "*.jade",
cwd: "#{paths.src}/jade/templates/html/**"
.pipe plumber handleError
.pipe cache 'ng-html'
.pipe jade opts.jade
# .pipe htmlify() # add data- prefixes to non-HTML5-valid attributes
# .pipe templateCache() # convert to JS strings and place in Angular template cache # TODO: figure this out (see: http://david.nowinsky.net/gulp-book/example/angular-templates.html)
.pipe gulp.dest "#{paths.dist}/templates"
# clean Angular template output
gulp.task 'clean:ng-html', ->
del "#{paths.dist}/templates/**/*.*", done
# watch Angular templates
gulp.task 'watch:ng-html', ->
gulp.watch "#{paths.src}/jade/templates/html/**/*.jade", ['ng-html', browserSync.reload]
### CORE TASKS ###
# development build & watch
gulp.task 'dev', buildTasks, ->
gulp.run [
'hobo'
'serve'
'watch'
]
# production build
gulp.task 'prod', buildTasks, ->
gulp.run 'hobo'
### MAIN CLI TASKS ###
# build: call with 'gulp build' on command line
# use 'gulp build --prod' to prepare assets for production use (minify, etc.)
gulp.task 'build', ['clean'], ->
gulp.run 'prod'
# develop: call with 'gulp' on command line
gulp.task 'default', ['clean'], ->
gulp.run 'dev'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment