SlideShare a Scribd company logo
@jayharris

#dethroningGrunt
SIMPLE AND EFFECTIVE BUILDS
W I T H G U L P. J S
what is a
taskrunner?
Dethroning Grunt: Simple and Effective Builds with gulp.js
that is a lot of things to do
task runners simplify to one command
 grunt

 gulp
focusing on five tasks
demo code
 queenseight.com
 aranasoft/queenseight
//	
  Project	
  Specific	
  Tasks
grunt.loadNpmTasks('grunt-­‐bower-­‐task');
grunt.loadNpmTasks('grunt-­‐coffeelint');
grunt.loadNpmTasks('grunt-­‐contrib-­‐clean');
grunt.loadNpmTasks('grunt-­‐contrib-­‐coffee');
grunt.loadNpmTasks('grunt-­‐contrib-­‐concat');
grunt.loadNpmTasks('grunt-­‐contrib-­‐connect');
grunt.loadNpmTasks('grunt-­‐contrib-­‐copy');
grunt.loadNpmTasks('grunt-­‐contrib-­‐cssmin');
grunt.loadNpmTasks('grunt-­‐contrib-­‐jade');
grunt.loadNpmTasks('grunt-­‐contrib-­‐jshint');
grunt.loadNpmTasks('grunt-­‐contrib-­‐less');
grunt.loadNpmTasks('grunt-­‐contrib-­‐uglify');
grunt.loadNpmTasks('grunt-­‐contrib-­‐watch');
//	
  General-­‐Purpose	
  Tasks
grunt.loadNpmTasks('grunt-­‐bower-­‐task');
grunt.loadNpmTasks('grunt-­‐coffeelint');
grunt.loadNpmTasks('grunt-­‐contrib-­‐clean');
grunt.loadNpmTasks('grunt-­‐contrib-­‐coffee');
grunt.loadNpmTasks('grunt-­‐contrib-­‐concat');
grunt.loadNpmTasks('grunt-­‐contrib-­‐connect');
grunt.loadNpmTasks('grunt-­‐contrib-­‐copy');
grunt.loadNpmTasks('grunt-­‐contrib-­‐cssmin');
grunt.loadNpmTasks('grunt-­‐contrib-­‐jade');
grunt.loadNpmTasks('grunt-­‐contrib-­‐jshint');
grunt.loadNpmTasks('grunt-­‐contrib-­‐less');
grunt.loadNpmTasks('grunt-­‐contrib-­‐uglify');
grunt.loadNpmTasks('grunt-­‐contrib-­‐watch');
//	
  13	
  tasks	
  in	
  all
grunt.loadNpmTasks('grunt-­‐bower-­‐task');
grunt.loadNpmTasks('grunt-­‐coffeelint');
grunt.loadNpmTasks('grunt-­‐contrib-­‐clean');
grunt.loadNpmTasks('grunt-­‐contrib-­‐coffee');
grunt.loadNpmTasks('grunt-­‐contrib-­‐concat');
grunt.loadNpmTasks('grunt-­‐contrib-­‐connect');
grunt.loadNpmTasks('grunt-­‐contrib-­‐copy');
grunt.loadNpmTasks('grunt-­‐contrib-­‐cssmin');
grunt.loadNpmTasks('grunt-­‐contrib-­‐jade');
grunt.loadNpmTasks('grunt-­‐contrib-­‐jshint');
grunt.loadNpmTasks('grunt-­‐contrib-­‐less');
grunt.loadNpmTasks('grunt-­‐contrib-­‐uglify');
grunt.loadNpmTasks('grunt-­‐contrib-­‐watch');
gruntfile.coffee
timer	
  =	
  require	
  "grunt-­‐timer"
fs	
  =	
  require	
  'fs'
path	
  =	
  require	
  'path'
server	
  =	
  require	
  './config/server'
urlrouter	
  =	
  require	
  'urlrouter'
module.exports	
  =	
  (grunt)	
  -­‐>
	
  	
  timer.init	
  grunt
	
  	
  #	
  Project	
  configuration.
	
  	
  grunt.initConfig
	
  	
  	
  	
  pkg:	
  grunt.file.readJSON	
  'package.json'
	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  coffee:
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/js/**/*.coffee"
	
  	
  	
  	
  	
  	
  	
  	
  generated:	
  "generated/js/app.coffee.js"
	
  	
  
	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  vendor:	
  "vendor/css/**/*.css"
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/css/**/*.css"
	
  	
  	
  	
  	
  	
  	
  	
  concatenated:	
  "generated/css/app.css"
	
  	
  	
  	
  	
  	
  	
  	
  minified:	
  "dist/css/app.css"
	
  	
  	
  	
  	
  	
  	
  	
  minifiedWebRelative:	
  "css/app.css"
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  img:
	
  	
  	
  	
  	
  	
  	
  	
  root:	
  "img"
	
  	
  	
  	
  	
  	
  jade:
	
  	
  	
  	
  	
  	
  	
  	
  pages:	
  "**/*.jade"
	
  	
  	
  	
  	
  	
  	
  	
  pageRoot:	
  "app/pages/"
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/js/**/*.js"
	
  	
  	
  	
  	
  	
  	
  	
  vendor:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/components/jquery/jquery.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/components/underscore/underscore.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/components/angular/angular.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/js/**/*.js"
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  concatenatedVendor:	
  "generated/js/vendor.js"
	
  	
  	
  	
  	
  	
  	
  	
  minifiedVendor:	
  "dist/js/vendor.js"
	
  	
  	
  	
  	
  	
  	
  	
  minifiedVendorWebRelative:	
  "js/vendor.js"
	
  	
  	
  	
  	
  	
  	
  	
  concatenated:	
  "generated/js/app.js"
	
  	
  	
  	
  	
  	
  	
  	
  minified:	
  "dist/js/app.js"
	
  	
  	
  	
  	
  	
  	
  	
  minifiedWebRelative:	
  "js/app.js"	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  less:
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/css/app.less"
	
  	
  	
  	
  	
  	
  	
  	
  vendor:	
  "vendor/css/**/*.less"
	
  	
  	
  	
  	
  	
  	
  	
  generatedApp:	
  "generated/css/app.less.css"
	
  	
  	
  	
  	
  	
  	
  	
  generatedVendor:	
  "generated/css/vendor.less.css"
	
  	
  	
  	
  	
  	
  	
  	
  watch:	
  "app/css/**/*.less"
	
  	
  	
  	
  	
  	
  webfonts:
	
  	
  	
  	
  	
  	
  	
  	
  root:	
  "fonts"
	
  	
  	
  	
  bower:
	
  	
  	
  	
  	
  	
  install:
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  copy:	
  false
	
  	
  	
  	
  coffee:
	
  	
  	
  	
  	
  	
  compile:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.coffee.generated	
  %>":	
  "<%=	
  files.coffee.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  coffeelint:
	
  	
  	
  	
  	
  	
  app:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.coffee.app	
  %>"
	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  concat:
	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedVendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.css.vendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedApp	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.css.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "<%=	
  files.css.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.coffee.generated	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.js.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "<%=	
  files.js.concatenated	
  %>"

	
  	
  	
  	
  	
  	
  jsVendor:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  ["<%=	
  files.js.vendor	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "<%=	
  files.js.concatenatedVendor	
  %>"
	
  	
  	
  	
  connect:
	
  	
  	
  	
  	
  	
  server:
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  port:	
  8000
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  base:	
  'generated'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  open:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middleware:	
  (connect,	
  options)	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares	
  =	
  [];
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (!Array.isArray(options.base))
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  options.base	
  =	
  [options.base]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  directory	
  =	
  options.directory	
  ||	
  options.base[options.base.length	
  -­‐	
  1]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  options.base.forEach	
  (base)	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  #	
  Serve	
  static	
  files.
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares.push(connect.static(base))
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares.push	
  urlrouter(server.drawRoutes)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  #	
  Make	
  directory	
  browse-­‐able.
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares.push	
  connect.directory(directory)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares
	
  	
  	
  	
  copy:
	
  	
  	
  	
  	
  	
  imagesDev:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/img/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/img/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  imagesDist:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/img/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/img/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  staticDev:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/static"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  'generated'
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  staticDist:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/static"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  'dist'
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  webfontsDev:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/webfonts/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/components/font-­‐awesome/fonts/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  webfontsDist:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/webfonts/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }

	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/components/font-­‐awesome/fonts/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  cssmin:
	
  	
  	
  	
  	
  	
  compress:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.css.minified	
  %>":	
  "<%=	
  files.css.concatenated	
  %>"

	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.css.vendor	
  %>",	
  "<%=	
  files.css.app	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["concat:css"]

	
  	
  	
  	
  jade:
	
  	
  	
  	
  	
  	
  dev:
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pretty:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  data:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  js:	
  "<%=	
  files.js.minifiedWebRelative	
  %>"	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  jsVendor:	
  "<%=	
  files.js.minifiedVendorWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  css:	
  "<%=	
  files.css.minifiedWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pkg:	
  "<%=	
  pkg	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.jade.pages	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "<%=	
  files.jade.pageRoot	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ext:	
  ".html"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  dist:
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  data:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  js:	
  "<%=	
  minifiedWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  jsVendor:	
  "<%=	
  minifiedVendorWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  css:	
  "<%=	
  files.css.minifiedWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pkg:	
  "<%=	
  pkg	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.jade.pages	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "<%=	
  files.jade.pageRoot	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ext:	
  ".html"
	
  	
  	
  	
  	
  	
  	
  	
  }]

	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.js.vendor	
  %>",	
  "<%=	
  files.js.app	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["concat:js"]

	
  	
  	
  	
  jshint:
	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.js.app	
  %>"]
	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  #	
  enforcing	
  options
	
  	
  	
  	
  	
  	
  	
  	
  curly:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  eqeqeq:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  latedef:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  newcap:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  noarg:	
  true
	
  	
  	
  	
  	
  	
  #	
  relaxing	
  options
	
  	
  	
  	
  	
  	
  	
  	
  boss:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  eqnull:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  sub:	
  true
	
  	
  	
  	
  	
  	
  #	
  environment/globals
	
  	
  	
  	
  	
  	
  	
  	
  browser:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  less:
	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  paths:	
  ["app/css",	
  "vendor/css"]
	
  	
  	
  	
  	
  	
  compile:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedVendor	
  %>":	
  "<%=	
  files.less.vendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedApp	
  %>":	
  "<%=	
  files.less.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  uglify:
	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  banner:	
  '/*!	
  <%=	
  pkg.name	
  %>	
  <%=	
  grunt.template.today("yyyy-­‐mm-­‐dd")	
  %>	
  */n'
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.js.minified	
  %>":	
  "<%=	
  files.js.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  jsVendor:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.js.minifiedVendor	
  %>":	
  "<%=	
  files.js.concatenatedVendor	
  %>"
	
  	
  	
  	
  clean:
	
  	
  	
  	
  	
  	
  bower:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  bowerDirectory	
  grunt
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.js.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.css.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  dist:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  ["dist",	
  "generated"]
	
  	
  	
  	
  watch:
	
  	
  	
  	
  	
  	
  coffee:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  "<%=	
  files.coffee.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["coffeelint",	
  "coffee",	
  "concat:js"]

	
  	
  	
  	
  	
  	
  images:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["app/img/**/*.*",	
  "vendor/img/**/*.*"]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["copy:imagesDev"]
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  jade:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.jade.pageRoot	
  %>/<%=	
  files.jade.pages	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["jade:dev"]

	
  	
  	
  	
  	
  	
  less:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.vendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.watch	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["less",	
  "concat:css"]
	
  	
  
	
  	
  	
  	
  	
  	
  lint:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  "<%=	
  files.js.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["jshint"]
	
  	
  
	
  	
  	
  	
  	
  	
  webfonts:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["vendor/webfonts/**/*.*",	
  "vendor/components/font-­‐awesome/fonts/**/*.*"]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["copy:webfontsDev"]
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  livereload:
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  livereload:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  "dist/**/*.*"
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐bower-­‐task'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐coffeelint'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐clean'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐coffee'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐concat'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐connect'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐copy'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐cssmin'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐jshint'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐less'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐jade'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐uglify'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐watch'
	
  	
  grunt.registerTask	
  'default',	
  [
	
  	
  	
  	
  'common'
	
  	
  	
  	
  'dev'
	
  	
  ]
	
  	
  grunt.registerTask	
  'common',	
  [
	
  	
  	
  	
  'bower'
	
  	
  	
  	
  'coffeelint'
	
  	
  	
  	
  'jshint'
	
  	
  	
  	
  'coffee'
	
  	
  	
  	
  'less'
	
  	
  	
  	
  'concat'
	
  	
  	
  	
  'copy:staticDev'
	
  	
  	
  	
  'copy:imagesDev'
	
  	
  	
  	
  'copy:webfontsDev'
	
  	
  	
  	
  'jade:dev'
	
  	
  ]
	
  	
  grunt.registerTask	
  'dev',	
  [
	
  	
  	
  	
  'connect'
	
  	
  	
  	
  'watch'
	
  	
  ]
	
  	
  grunt.registerTask	
  'dist',	
  [
	
  	
  	
  	
  'uglify'
	
  	
  	
  	
  'cssmin'
	
  	
  	
  	
  'copy:staticDist'
	
  	
  	
  	
  'copy:imagesDist'
	
  	
  	
  	
  'copy:webfontsDist'
	
  	
  	
  	
  'jade:dist'
	
  	
  ]
bowerDirectory	
  =	
  (grunt)	
  -­‐>
	
  	
  bowerrc	
  =	
  path.join(process.cwd(),	
  ".bowerrc")
	
  	
  bowerConfig	
  =	
  grunt.file.readJSON(bowerrc)	
  unless	
  !fs.existsSync(bowerrc)
	
  	
  bowerConfig?.directory	
  ||	
  "vendor/components"
├──	
  css
│	
  	
  	
  ├──	
  app.less
│	
  	
  	
  ├──	
  mixins.less
│	
  	
  	
  └──	
  variables.less
├──	
  img
│	
  	
  	
  ├──	
  arana-­‐software.png
│	
  	
  	
  ├──	
  arana-­‐software@2x.png
│	
  	
  	
  ├──	
  banner-­‐lg.png
│	
  	
  	
  ├──	
  banner-­‐md.png
│	
  	
  	
  ├──	
  banner-­‐sm.png
│	
  	
  	
  ├──	
  crown.png
│	
  	
  	
  ├──	
  leather@1x.jpg
│	
  	
  	
  ├──	
  leather@2x.jpg
│	
  	
  	
  └──	
  wood.png
├──	
  js
│	
  	
  	
  ├──	
  app.coffee
│	
  	
  	
  ├──	
  controllers
│	
  	
  	
  │	
  	
  	
  └──	
  board.coffee
│	
  	
  	
  ├──	
  directives
│	
  	
  	
  │	
  	
  	
  └──	
  board.js
│	
  	
  	
  └──	
  templates
│	
  	
  	
  	
  	
  	
  	
  └──	
  board.coffee
├──	
  pages
│	
  	
  	
  └──	
  index.jade
└──	
  static
	
  	
  	
  	
  └──	
  favicon.ico

gruntfile.coffee
timer	
  =	
  require	
  "grunt-­‐timer"
fs	
  =	
  require	
  'fs'
path	
  =	
  require	
  'path'
server	
  =	
  require	
  './config/server'
urlrouter	
  =	
  require	
  'urlrouter'

	
  	
  	
  	
  	
  	
  jsVendor:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  ["<%=	
  files.js.vendor	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "<%=	
  files.js.concatenatedVendor	
  %>"

	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.css.vendor	
  %>",	
  "<%=	
  files.css.app	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/components/font-­‐awesome/fonts/"
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["concat:css"]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  images:
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["app/img/**/*.*",	
  "vendor/img/**/*.*"]
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["copy:imagesDev"]
	
  	
  	
  	
  cssmin:
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  compress:
	
  	
  	
  	
  	
  	
  jade:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.jade.pageRoot	
  %>/<%=	
  files.jade.pages	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.css.minified	
  %>":	
  "<%=	
  files.css.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["jade:dev"]

	
  	
  	
  	
  connect:
	
  	
  	
  	
  	
  	
  server:
module.exports	
  =	
  (grunt)	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  timer.init	
  grunt
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  port:	
  8000
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  base:	
  'generated'
	
  	
  #	
  Project	
  configuration.
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  open:	
  true
	
  	
  grunt.initConfig
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middleware:	
  (connect,	
  options)	
  -­‐>
	
  	
  	
  	
  pkg:	
  grunt.file.readJSON	
  'package.json'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares	
  =	
  [];
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (!Array.isArray(options.base))
	
  	
  	
  	
  jade:
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  options.base	
  =	
  [options.base]
	
  	
  	
  	
  	
  	
  dev:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.js.vendor	
  %>",	
  "<%=	
  files.js.app	
  %>"]
	
  	
  	
  	
  	
  	
  coffee:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["concat:js"]
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/js/**/*.coffee"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  directory	
  =	
  options.directory	
  ||	
  options.base[options.base.length	
  -­‐	
  1]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pretty:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  generated:	
  "generated/js/app.coffee.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  options.base.forEach	
  (base)	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  data:
	
  	
  	
  	
  	
  	
  less:
	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  #	
  Serve	
  static	
  files.
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  js:	
  "<%=	
  files.js.minifiedWebRelative	
  %>"	
  
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [
	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares.push(connect.static(base))
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  jsVendor:	
  "<%=	
  files.js.minifiedVendorWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.vendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  vendor:	
  "vendor/css/**/*.css"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  css:	
  "<%=	
  files.css.minifiedWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.watch	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/css/**/*.css"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares.push	
  urlrouter(server.drawRoutes)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pkg:	
  "<%=	
  pkg	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  concatenated:	
  "generated/css/app.css"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  #	
  Make	
  directory	
  browse-­‐able.
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["less",	
  "concat:css"]
	
  	
  	
  	
  	
  	
  	
  	
  minified:	
  "dist/css/app.css"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares.push	
  connect.directory(directory)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  minifiedWebRelative:	
  "css/app.css"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.jade.pages	
  %>"
	
  	
  	
  	
  	
  	
  lint:
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "<%=	
  files.jade.pageRoot	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  "<%=	
  files.js.app	
  %>"
	
  	
  	
  	
  	
  	
  img:
	
  	
  	
  	
  copy:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/"
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["jshint"]
	
  	
  	
  	
  	
  	
  	
  	
  root:	
  "img"
	
  	
  	
  	
  	
  	
  imagesDev:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ext:	
  ".html"
	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  webfonts:
	
  	
  	
  	
  	
  	
  jade:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  dist:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["vendor/webfonts/**/*.*",	
  "vendor/components/font-­‐awes
	
  	
  	
  	
  	
  	
  	
  	
  pages:	
  "**/*.jade"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/img/"
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["copy:webfontsDev"]
	
  	
  	
  	
  	
  	
  	
  	
  pageRoot:	
  "app/pages/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  data:
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  js:	
  "<%=	
  minifiedWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  livereload:
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  jsVendor:	
  "<%=	
  minifiedVendorWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/js/**/*.js"
	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  css:	
  "<%=	
  files.css.minifiedWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  livereload:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  vendor:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pkg:	
  "<%=	
  pkg	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  "dist/**/*.*"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/components/jquery/jquery.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/img/"
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/components/underscore/underscore.js"	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐bower-­‐task'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/components/angular/angular.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.jade.pages	
  %>"
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐coffeelint'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/js/**/*.js"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "<%=	
  files.jade.pageRoot	
  %>"
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐clean'
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  imagesDist:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/"
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐coffee'
	
  	
  	
  	
  	
  	
  	
  	
  concatenatedVendor:	
  "generated/js/vendor.js" 	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ext:	
  ".html"
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐concat'
	
  	
  	
  	
  	
  	
  	
  	
  minifiedVendor:	
  "dist/js/vendor.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐connect'
	
  	
  	
  	
  	
  	
  	
  	
  minifiedVendorWebRelative:	
  "js/vendor.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/img/"
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐copy'
	
  	
  	
  	
  	
  	
  	
  	
  concatenated:	
  "generated/js/app.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  jshint:
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐cssmin'
	
  	
  	
  	
  	
  	
  	
  	
  minified:	
  "dist/js/app.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.js.app	
  %>"]
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐jshint'
	
  	
  	
  	
  	
  	
  	
  	
  minifiedWebRelative:	
  "js/app.js"	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  options:
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐less'
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  #	
  enforcing	
  options
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐jade'
	
  	
  	
  	
  	
  	
  less:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  curly:	
  true
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐uglify'
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/css/app.less"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/img/"
	
  	
  	
  	
  	
  	
  	
  	
  eqeqeq:	
  true
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐watch'
	
  	
  	
  	
  	
  	
  	
  	
  vendor:	
  "vendor/css/**/*.less"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  latedef:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  generatedApp:	
  "generated/css/app.less.css"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  newcap:	
  true
	
  	
  grunt.registerTask	
  'default',	
  [
	
  	
  	
  	
  	
  	
  	
  	
  generatedVendor:	
  "generated/css/vendor.less.css"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  	
  	
  noarg:	
  true
	
  	
  	
  	
  'common'
	
  	
  	
  	
  	
  	
  	
  	
  watch:	
  "app/css/**/*.less"
	
  	
  	
  	
  	
  	
  staticDev:
	
  	
  	
  	
  	
  	
  #	
  relaxing	
  options
	
  	
  	
  	
  'dev'
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  boss:	
  true
	
  	
  ]
	
  	
  	
  	
  	
  	
  webfonts:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  eqnull:	
  true
	
  	
  grunt.registerTask	
  'common',	
  [
	
  	
  	
  	
  	
  	
  	
  	
  root:	
  "fonts"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/static"
	
  	
  	
  	
  	
  	
  	
  	
  sub:	
  true
	
  	
  	
  	
  'bower'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  #	
  environment/globals
	
  	
  	
  	
  'coffeelint'
	
  	
  	
  	
  bower:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  'generated'
	
  	
  	
  	
  	
  	
  	
  	
  browser:	
  true
	
  	
  	
  	
  'jshint'
	
  	
  	
  	
  	
  	
  install:
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  'coffee'
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  staticDist:
	
  	
  	
  	
  less:
	
  	
  	
  	
  'less'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  copy:	
  false
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [
	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  'concat'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  paths:	
  ["app/css",	
  "vendor/css"]
	
  	
  	
  	
  'copy:staticDev'
	
  	
  	
  	
  coffee:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/static"
	
  	
  	
  	
  	
  	
  compile:
	
  	
  	
  	
  'copy:imagesDev'
	
  	
  	
  	
  	
  	
  compile:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  'copy:webfontsDev'
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  'dist'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedVendor	
  %>":	
  "<%=	
  files.less.vendor	
  %>"
	
  	
  	
  	
  'jade:dev'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.coffee.generated	
  %>":	
  "<%=	
  files.coffee.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedApp	
  %>":	
  "<%=	
  files.less.app	
  %>"
	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  webfontsDev:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  grunt.registerTask	
  'dev',	
  [
	
  	
  	
  	
  coffeelint:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  uglify:
	
  	
  	
  	
  'connect'
	
  	
  	
  	
  	
  	
  app:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  'watch'
	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.coffee.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/webfonts/"
	
  	
  	
  	
  	
  	
  	
  	
  banner:	
  '/*!	
  <%=	
  pkg.name	
  %>	
  <%=	
  grunt.template.today("yyyy-­‐mm-­‐dd")	
  %>	
  */n'
	
  	
  ]
	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  js:
	
  	
  grunt.registerTask	
  'dist',	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  'uglify'
	
  	
  	
  	
  concat:
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.js.minified	
  %>":	
  "<%=	
  files.js.concatenated	
  %>"
	
  	
  	
  	
  'cssmin'
	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  jsVendor:
	
  	
  	
  	
  'copy:staticDist'
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  'copy:imagesDist'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedVendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/components/font-­‐awesome/fonts/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.js.minifiedVendor	
  %>":	
  "<%=	
  files.js.concatenatedVendor	
  %>"
	
  	
  	
  	
  'copy:webfontsDist'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.css.vendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  'jade:dist'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedApp	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  clean:
	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.css.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  bower:
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  bowerDirectory	
  grunt
bowerDirectory	
  =	
  (grunt)	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "<%=	
  files.css.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  webfontsDist:
	
  	
  	
  	
  	
  	
  js:
	
  	
  bowerrc	
  =	
  path.join(process.cwd(),	
  ".bowerrc")
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.js.concatenated	
  %>"
	
  	
  bowerConfig	
  =	
  grunt.file.readJSON(bowerrc)	
  unless	
  !fs.existsSync(bow
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  bowerConfig?.directory	
  ||	
  "vendor/components"
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/webfonts/"
	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.css.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.coffee.generated	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.js.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  dist:
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  ["dist",	
  "generated"]
	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "<%=	
  files.js.concatenated	
  %>"
	
  	
  	
  	
  watch:
	
  	
  	
  	
  	
  	
  coffee:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  "<%=	
  files.coffee.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["coffeelint",	
  "coffee",	
  "concat:js"]
'use	
  strict';
var	
  util	
  =	
  require('util');
var	
  Orchestrator	
  =	
  require('orchestrator');
var	
  gutil	
  =	
  require('gulp-­‐util');
var	
  deprecated	
  =	
  require('deprecated');
var	
  vfs	
  =	
  require('vinyl-­‐fs');
function	
  Gulp(){
	
  	
  Orchestrator.call(this);
}
util.inherits(Gulp,	
  Orchestrator);
Gulp.prototype.task	
  =	
  Gulp.prototype.add;
Gulp.prototype.run	
  =	
  function(){
	
  	
  //	
  run()	
  is	
  deprecated	
  as	
  of	
  3.5	
  and	
  will	
  be	
  removed	
  in	
  4.0
	
  	
  //	
  use	
  task	
  dependencies	
  instead
	
  	
  //	
  impose	
  our	
  opinion	
  of	
  "default"	
  tasks	
  onto	
  orchestrator
	
  	
  var	
  tasks	
  =	
  arguments.length	
  ?	
  arguments	
  :	
  ['default'];
	
  	
  this.start.apply(this,	
  tasks);
};
Gulp.prototype.src	
  =	
  vfs.src;
Gulp.prototype.dest	
  =	
  vfs.dest;
Gulp.prototype.watch	
  =	
  function	
  (glob,	
  opt,	
  fn)	
  {
	
  	
  if	
  (!fn)	
  {
	
  	
  	
  	
  fn	
  =	
  opt;
	
  	
  	
  	
  opt	
  =	
  null;
	
  	
  }
	
  	
  //	
  array	
  of	
  tasks	
  given
	
  	
  if	
  (Array.isArray(fn))	
  {
	
  	
  	
  	
  return	
  vfs.watch(glob,	
  opt,	
  function(){
	
  	
  	
  	
  	
  	
  this.start.apply(this,	
  fn);
	
  	
  	
  	
  }.bind(this));
	
  	
  }
	
  	
  return	
  vfs.watch(glob,	
  opt,	
  fn);
};
//	
  let	
  people	
  use	
  this	
  class	
  from	
  our	
  instance
Gulp.prototype.Gulp	
  =	
  Gulp;
//	
  deprecations
deprecated.field('gulp.env	
  has	
  been	
  deprecated.	
  Use	
  gulp-­‐util.env	
  or	
  your	
  own	
  CLI	
  parser	
  instead.',	
  console.log,	
  
Gulp.prototype,	
  'env',	
  gutil.env);
Gulp.prototype.run	
  =	
  deprecated.method('gulp.run()	
  has	
  been	
  deprecated.	
  Use	
  task	
  dependencies	
  or	
  gulp.watch	
  task	
  
triggering	
  instead.',	
  console.log,	
  Gulp.prototype.run);
var	
  inst	
  =	
  new	
  Gulp();
module.exports	
  =	
  inst;
Dethroning Grunt: Simple and Effective Builds with gulp.js
.src(globs[, options])
.dest(path)
.task(name[, deps], fn)
.watch(glob [, options], tasks)
.pipe(destination)
 level up

grok streams






a task: read, concatenate, write







additional steps add overhead







extraneous disk I/O









extraneous configuration







streams pipe from task to task







additional steps without overhead
 level up

the first gulp
 npm install -g gulp
npm install -D gulp
touch gulpfile.js
//gulpfile.js
var	
  gulp	
  	
  	
  =	
  require('gulp');
var	
  coffee	
  =	
  require('gulp-­‐coffee');
var	
  concat	
  =	
  require('gulp-­‐concat');
var	
  uglify	
  =	
  require('gulp-­‐uglify');
gulp.src('app/js/**/*.coffee')


gulp.src('app/js/**/*.coffee')
	
  	
  	
  	
  .pipe(gulp.dest('dist/js'));


gulp.src('app/js/**/*.coffee')
	
  	
  	
  	
  .pipe(coffee())
.pipe(concat('app.js'))
.pipe(uglify())
.pipe(gulp.dest('dist/js'));







gulp.src('app/js/**/*.coffee')
	
  	
  	
  	
  .pipe(coffee())
.pipe(concat('app.js'))
.pipe(gulp.dest('test/js'))
.pipe(uglify())
.pipe(gulp.dest('dist/js'));







gulp.task('coffee',	
  function()	
  {
	
  	
  gulp.src('app/js/**/*.coffee')
	
  	
  	
  	
  	
  	
  .pipe(coffee())
	
  	
  .pipe(concat('app.js'))
	
  	
  .pipe(gulp.dest('test/js'))
	
  	
  .pipe(uglify())
	
  	
  .pipe(gulp.dest('dist/js'));
});
gulp.task('watch',	
  function()	
  {
gulp.watch('app/js/**/*.coffee',
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ['coffee']);
});


gulp.task('default',
	
  	
  	
  	
  	
  ['coffee','watch']);








 level up

dependencies
gulp.task('css',
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  function()	
  {
	
  	
  gulp.src('app/css/app.less')
	
  	
  	
  	
  	
  	
  .pipe(less())
	
  	
  .pipe(cssmin())
	
  	
  .pipe(gulp.dest('dist/css'));
});



var	
  bower	
  =	
  require('gulp-­‐bower');
gulp.task('install',	
  function()	
  {
	
  	
  bower();
});


gulp.task('css',	
  ['install'],
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  function()	
  {
	
  	
  gulp.src('app/css/app.less')
	
  	
  	
  	
  	
  	
  .pipe(less())
	
  	
  .pipe(cssmin())
	
  	
  .pipe(gulp.dest('dist/css'));
});





var	
  bower	
  =	
  require('gulp-­‐bower');
gulp.task('install',	
  function()	
  {
	
  	
  bower();
});
//	
  Doesn't	
  work	
  as	
  expected


our five tasks
┌
│
┤
│
└

┬
│
└

─

expected dependency tree
┌
│
├
│
┼
│
├
│
└

actual tree
gulp.task('stuff',	
  function()	
  {
	
  	
  doStuff();
	
  	
  });
//	
  Option	
  1:	
  Callback
gulp.task('stuff',	
  function(done)	
  {
	
  	
  doSyncStuff()
	
  	
  done(err);
});
var	
  Q	
  =	
  require('q');
//	
  Option	
  2:	
  Promise
gulp.task('stuff',	
  function()	
  {
	
  	
  var	
  deferred	
  =	
  Q.defer();
	
  	
  doAsyncStuff(deferred.resolve);
	
  	
  return	
  deferred.promise;
});
//	
  Option	
  3:	
  Return	
  stream
gulp.task('stuff',	
  function()	
  {
	
  	
  var	
  stream	
  =	
  doStreamStuff();
	
  	
  return	
  stream;
});
gulp.task	
  'stuff',	
  ()	
  -­‐>
	
  	
  doStreamStuff()
#	
  Get	
  return	
  stream	
  for	
  free!
gulp.task	
  'stuff',	
  ()	
  -­‐>
	
  	
  doStreamStuff()
gulp.task('stuff',	
  function()	
  {
	
  	
  return	
  doStreamStuff();
	
  	
  });
var	
  bower	
  =	
  require('gulp-­‐bower');
gulp.task('install',	
  function()	
  {
	
  	
  bower();
});


var	
  bower	
  =	
  require('gulp-­‐bower');
gulp.task('install',	
  function()	
  {
	
  	
  return	
  bower();	
  //	
  Win!
});


//	
  Back	
  to	
  where	
  we	
  were
gulp.task('css',
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  function()	
  {
	
  	
  gulp.src('app/css/app.less')
	
  	
  	
  	
  	
  	
  .pipe(less())
	
  	
  .pipe(cssmin())
	
  	
  .pipe(gulp.dest('dist/css'));
});



gulp.task('css',	
  ['install'],
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  function()	
  {
	
  	
  gulp.src('app/css/app.less')
	
  	
  	
  	
  	
  	
  .pipe(less())
	
  	
  .pipe(cssmin())
	
  	
  .pipe(gulp.dest('dist/css'));
});


 level up

using coffee
//gulpfile.js
gulp.task('css',	
  ['install'],
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  function()	
  {
	
  	
  gulp.src('app/css/app.less')
	
  	
  	
  	
  	
  	
  .pipe(less())
	
  	
  .pipe(cssmin())
	
  	
  .pipe(gulp.dest('dist/css'));
});


#	
  gulpfile.coffee
gulp.task	
  'css',	
  ['install'],	
  ()	
  -­‐>
	
  	
  gulp.src	
  'app/css/app.less'
	
  	
  	
  	
  	
  	
  .pipe	
  less()
	
  	
  .pipe	
  cssmin()	
  
	
  	
  .pipe	
  gulp.dest('dist/css')


 gulp --require coffee-script/register
 more gulpfile.js
//gulpfile.js
require('coffee-­‐script');
require('./gulpfile.coffee');
 gulp
 level up

merging streams














gulp.task	
  'js',	
  ()	
  -­‐>
	
  	
  gulp.src	
  files.coffee
	
  	
  	
  	
  	
  	
  .pipe	
  coffee()
	
  	
  	
  	
  	
  	
  .pipe	
  concat('app.js')
	
  	
  	
  	
  	
  	
  .pipe	
  uglify()
	
  	
  	
  	
  	
  	
  .pipe	
  gulp.dest('dist/js')







evtstream	
  =	
  require	
  'event-­‐stream'
	
  	
  	
  #	
  and/or
streamq	
  	
  	
  =	
  require	
  'streamqueue'
gulp.task	
  'js',	
  ()	
  -­‐>
	
  	
  gulp.src(files.coffee)
	
  	
  	
  	
  	
  	
  .pipe(coffee())
	
  	
  	
  	
  	
  	
  .pipe	
  concat('app.js')
	
  	
  	
  	
  	
  	
  .pipe	
  uglify()
	
  	
  	
  	
  	
  	
  .pipe	
  gulp.dest('dist/js')







gulp.task	
  'js',	
  ()	
  -­‐>
	
  	
  evtstream.concat(
	
  	
  	
  	
  gulp.src(files.coffee)
	
  	
  	
  	
  	
  	
  	
  	
  .pipe(coffee()),
	
  	
  	
  	
  gulp.src(files.js))
	
  	
  	
  	
  	
  	
  .pipe	
  concat('app.js')
	
  	
  	
  	
  	
  	
  .pipe	
  uglify()
	
  	
  	
  	
  	
  	
  .pipe	
  gulp.dest('dist/js')








gulp.task	
  'js',	
  ()	
  -­‐>
	
  	
  es.concat(
	
  	
  	
  	
  gulp.src(files.coffee)
	
  	
  	
  	
  	
  	
  	
  	
  .pipe(coffee()),
	
  	
  	
  	
  gulp.src(files.js))
	
  	
  	
  	
  	
  	
  .pipe	
  concat('app.js')
	
  	
  	
  	
  	
  	
  .pipe	
  uglify()
	
  	
  	
  	
  	
  	
  .pipe	
  gulp.dest('dist/js')








gulp.task	
  'js',	
  ()	
  -­‐>
	
  	
  sq	
  =	
  streamq	
  {objectmode:true}
	
  	
  sq.queue	
  gulp.src(files.coffee)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  .pipe(coffee()
	
  	
  sq.queue	
  gulp.src(files.js)
	
  	
  sq.done().pipe	
  concat('app.js')
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  .pipe	
  uglify()
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  .pipe	
  gulp.dest('dist/js')









 level up

error handling
gulp.task	
  'css',	
  ['install'],	
  ()	
  -­‐>
	
  	
  gulp.src	
  files.less
	
  	
  	
  	
  	
  	
  .pipe	
  less()	
  
	
  	
  .pipe	
  cssmin()
	
  	
  .pipe	
  gulp.dest('dist/css')


//	
  app.less
.mayhem	
  {
	
  	
  font-­‐weight:	
  bold;
	
  	
  color:	
  	
  	
  	
  	
  	
  	
  @red;
}
}	
  //	
  too	
  many	
  '{'	
  ===	
  BOOM!


[gulp]	
  Running	
  'css'...

events.js:72
	
  	
  	
  	
  	
  	
  	
  	
  throw	
  er;	
  //	
  Unhandled	
  'error'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ^
Error:	
  missing	
  opening	
  `{`	
  in	
  file	
  ./c



gulp.task	
  'css',	
  ['install'],	
  ()	
  -­‐>
	
  	
  gulp.src	
  files.less
	
  	
  	
  	
  	
  	
  .pipe	
  less()	
  
	
  	
  .pipe	
  cssmin()
	
  	
  .pipe	
  gulp.dest('dist/css')


gulp.task	
  'css',	
  ['install'],	
  ()	
  -­‐>
	
  	
  gulp.src	
  files.less
	
  	
  	
  	
  	
  	
  .pipe	
  less().on('error',(err)-­‐>
	
  	
  	
  	
  	
  	
  	
  	
  console.log(''+err)	
  if	
  err
	
  	
  	
  	
  	
  	
  )	
  #	
  Ick.
	
  	
  .pipe	
  cssmin()
	
  	
  .pipe	
  gulp.dest('dist/css')


plumber	
  =	
  require	
  'gulp-­‐plumber'
gulp.task	
  'css',	
  ['install'],	
  ()	
  -­‐>
	
  	
  gulp.src	
  files.less
	
  	
  	
  	
  	
  	
  .pipe	
  plumber()	
  #Win!
	
  	
  	
  	
  	
  	
  .pipe	
  less()	
  
	
  	
  .pipe	
  cssmin()
	
  	
  .pipe	
  gulp.dest('dist/css')


[gulp]	
  Running	
  'css'...
[gulp]	
  Error	
  in	
  plugin	
  'gulp-­‐less':
	
  	
  missing	
  opening	
  `{`	
  in	
  file	
  app.less
[gulp]	
  Finished	
  'css'	
  in	
  21	
  ms


 level up

master class
gutil	
  =	
  require	
  'gulp-­‐util'


gulp.src	
  'app/css/*.css'
	
  	
  .pipe	
  concat('app.css')
	
  	
  .pipe(if	
  gutil.env.dest	
  ==	
  'prod'
	
  	
  	
  	
  	
  	
  	
  	
  then	
  cssmin()
	
  	
  	
  	
  	
  	
  	
  	
  else	
  gutil.noop())
	
  	
  .pipe	
  gulp.dest('dist/css')










gulp.src	
  'app/css/*.css'
	
  	
  .pipe	
  concat('app.css')
	
  	
  .pipe(if	
  gutil.env.dest	
  ==	
  'prod'
	
  	
  	
  	
  	
  	
  	
  	
  then	
  cssmin()
	
  	
  	
  	
  	
  	
  	
  	
  else	
  gutil.noop())
	
  	
  .pipe	
  gulp.dest('dist/css')










 gulp	
  -­‐-­‐port=8000	
  -­‐-­‐dest=prod

gutil.env.port	
  ===	
  8000
gutil.env.dest	
  ===	
  'prod'




 echo	
  Total	
  Files:	
  $(	
  	
  
	
  find	
  .	
  -­‐type	
  f	
  -­‐print
	
  |	
  wc	
  -­‐l)

Total	
  Files:	
  1000
 echo	
  watch	
  will	
  vomit
 level up

comparison
gruntfile.coffee
timer	
  =	
  require	
  "grunt-­‐timer"
fs	
  =	
  require	
  'fs'
path	
  =	
  require	
  'path'
server	
  =	
  require	
  './config/server'
urlrouter	
  =	
  require	
  'urlrouter'
module.exports	
  =	
  (grunt)	
  -­‐>
	
  	
  timer.init	
  grunt
	
  	
  #	
  Project	
  configuration.
	
  	
  grunt.initConfig
	
  	
  	
  	
  pkg:	
  grunt.file.readJSON	
  'package.json'
	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  coffee:
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/js/**/*.coffee"
	
  	
  	
  	
  	
  	
  	
  	
  generated:	
  "generated/js/app.coffee.js"
	
  	
  
	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  vendor:	
  "vendor/css/**/*.css"
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/css/**/*.css"
	
  	
  	
  	
  	
  	
  	
  	
  concatenated:	
  "generated/css/app.css"
	
  	
  	
  	
  	
  	
  	
  	
  minified:	
  "dist/css/app.css"
	
  	
  	
  	
  	
  	
  	
  	
  minifiedWebRelative:	
  "css/app.css"
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  img:
	
  	
  	
  	
  	
  	
  	
  	
  root:	
  "img"
	
  	
  	
  	
  	
  	
  jade:
	
  	
  	
  	
  	
  	
  	
  	
  pages:	
  "**/*.jade"
	
  	
  	
  	
  	
  	
  	
  	
  pageRoot:	
  "app/pages/"
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/js/**/*.js"
	
  	
  	
  	
  	
  	
  	
  	
  vendor:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/components/jquery/jquery.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/components/underscore/underscore.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/components/angular/angular.js"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "vendor/js/**/*.js"
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  concatenatedVendor:	
  "generated/js/vendor.js"
	
  	
  	
  	
  	
  	
  	
  	
  minifiedVendor:	
  "dist/js/vendor.js"
	
  	
  	
  	
  	
  	
  	
  	
  minifiedVendorWebRelative:	
  "js/vendor.js"
	
  	
  	
  	
  	
  	
  	
  	
  concatenated:	
  "generated/js/app.js"
	
  	
  	
  	
  	
  	
  	
  	
  minified:	
  "dist/js/app.js"
	
  	
  	
  	
  	
  	
  	
  	
  minifiedWebRelative:	
  "js/app.js"	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  less:
	
  	
  	
  	
  	
  	
  	
  	
  app:	
  "app/css/app.less"
	
  	
  	
  	
  	
  	
  	
  	
  vendor:	
  "vendor/css/**/*.less"
	
  	
  	
  	
  	
  	
  	
  	
  generatedApp:	
  "generated/css/app.less.css"
	
  	
  	
  	
  	
  	
  	
  	
  generatedVendor:	
  "generated/css/vendor.less.css"
	
  	
  	
  	
  	
  	
  	
  	
  watch:	
  "app/css/**/*.less"
	
  	
  	
  	
  	
  	
  webfonts:
	
  	
  	
  	
  	
  	
  	
  	
  root:	
  "fonts"
	
  	
  	
  	
  bower:
	
  	
  	
  	
  	
  	
  install:
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  copy:	
  false
	
  	
  	
  	
  coffee:
	
  	
  	
  	
  	
  	
  compile:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.coffee.generated	
  %>":	
  "<%=	
  files.coffee.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  coffeelint:
	
  	
  	
  	
  	
  	
  app:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.coffee.app	
  %>"
	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  concat:
	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedVendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.css.vendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedApp	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.css.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "<%=	
  files.css.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.coffee.generated	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.js.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "<%=	
  files.js.concatenated	
  %>"

	
  	
  	
  	
  	
  	
  jsVendor:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  ["<%=	
  files.js.vendor	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "<%=	
  files.js.concatenatedVendor	
  %>"
	
  	
  	
  	
  connect:
	
  	
  	
  	
  	
  	
  server:
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  port:	
  8000
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  base:	
  'generated'
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  open:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middleware:	
  (connect,	
  options)	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares	
  =	
  [];
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (!Array.isArray(options.base))
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  options.base	
  =	
  [options.base]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  directory	
  =	
  options.directory	
  ||	
  options.base[options.base.length	
  -­‐	
  1]
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  options.base.forEach	
  (base)	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  #	
  Serve	
  static	
  files.
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares.push(connect.static(base))
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares.push	
  urlrouter(server.drawRoutes)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  #	
  Make	
  directory	
  browse-­‐able.
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares.push	
  connect.directory(directory)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  middlewares
	
  	
  	
  	
  copy:
	
  	
  	
  	
  	
  	
  imagesDev:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/img/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/img/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  imagesDist:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/img/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/img/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.img.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  staticDev:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/static"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  'generated'
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  staticDist:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "app/static"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  'dist'
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  webfontsDev:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/webfonts/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/components/font-­‐awesome/fonts/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  webfontsDist:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/webfonts/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }

	
  	
  	
  	
  	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "vendor/components/font-­‐awesome/fonts/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "**"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/<%=	
  files.webfonts.root	
  %>/"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  cssmin:
	
  	
  	
  	
  	
  	
  compress:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.css.minified	
  %>":	
  "<%=	
  files.css.concatenated	
  %>"

	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.css.vendor	
  %>",	
  "<%=	
  files.css.app	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["concat:css"]

	
  	
  	
  	
  jade:
	
  	
  	
  	
  	
  	
  dev:
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pretty:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  data:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  js:	
  "<%=	
  files.js.minifiedWebRelative	
  %>"	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  jsVendor:	
  "<%=	
  files.js.minifiedVendorWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  css:	
  "<%=	
  files.css.minifiedWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pkg:	
  "<%=	
  pkg	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.jade.pages	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "<%=	
  files.jade.pageRoot	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "generated/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ext:	
  ".html"
	
  	
  	
  	
  	
  	
  	
  	
  }]
	
  	
  	
  	
  	
  	
  dist:
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  data:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  js:	
  "<%=	
  minifiedWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  jsVendor:	
  "<%=	
  minifiedVendorWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  css:	
  "<%=	
  files.css.minifiedWebRelative	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pkg:	
  "<%=	
  pkg	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [{
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  expand:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.jade.pages	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  cwd:	
  "<%=	
  files.jade.pageRoot	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dest:	
  "dist/"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ext:	
  ".html"
	
  	
  	
  	
  	
  	
  	
  	
  }]

	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.js.vendor	
  %>",	
  "<%=	
  files.js.app	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["concat:js"]

	
  	
  	
  	
  jshint:
	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.js.app	
  %>"]
	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  #	
  enforcing	
  options
	
  	
  	
  	
  	
  	
  	
  	
  curly:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  eqeqeq:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  latedef:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  newcap:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  noarg:	
  true
	
  	
  	
  	
  	
  	
  #	
  relaxing	
  options
	
  	
  	
  	
  	
  	
  	
  	
  boss:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  eqnull:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  sub:	
  true
	
  	
  	
  	
  	
  	
  #	
  environment/globals
	
  	
  	
  	
  	
  	
  	
  	
  browser:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  less:
	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  paths:	
  ["app/css",	
  "vendor/css"]
	
  	
  	
  	
  	
  	
  compile:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedVendor	
  %>":	
  "<%=	
  files.less.vendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.generatedApp	
  %>":	
  "<%=	
  files.less.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  uglify:
	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  banner:	
  '/*!	
  <%=	
  pkg.name	
  %>	
  <%=	
  grunt.template.today("yyyy-­‐mm-­‐dd")	
  %>	
  */n'
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.js.minified	
  %>":	
  "<%=	
  files.js.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  jsVendor:
	
  	
  	
  	
  	
  	
  	
  	
  files:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.js.minifiedVendor	
  %>":	
  "<%=	
  files.js.concatenatedVendor	
  %>"
	
  	
  	
  	
  clean:
	
  	
  	
  	
  	
  	
  bower:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  bowerDirectory	
  grunt
	
  	
  	
  	
  	
  	
  js:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.js.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  css:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  "<%=	
  files.css.concatenated	
  %>"
	
  	
  	
  	
  	
  	
  dist:
	
  	
  	
  	
  	
  	
  	
  	
  src:	
  ["dist",	
  "generated"]
	
  	
  	
  	
  watch:
	
  	
  	
  	
  	
  	
  coffee:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  "<%=	
  files.coffee.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["coffeelint",	
  "coffee",	
  "concat:js"]

	
  	
  	
  	
  	
  	
  images:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["app/img/**/*.*",	
  "vendor/img/**/*.*"]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["copy:imagesDev"]
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  jade:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["<%=	
  files.jade.pageRoot	
  %>/<%=	
  files.jade.pages	
  %>"]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["jade:dev"]

	
  	
  	
  	
  	
  	
  less:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  [
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.vendor	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  "<%=	
  files.less.watch	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  ]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["less",	
  "concat:css"]
	
  	
  
	
  	
  	
  	
  	
  	
  lint:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  "<%=	
  files.js.app	
  %>"
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["jshint"]
	
  	
  
	
  	
  	
  	
  	
  	
  webfonts:
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  ["vendor/webfonts/**/*.*",	
  "vendor/components/font-­‐awesome/fonts/**/*.*"]
	
  	
  	
  	
  	
  	
  	
  	
  tasks:	
  ["copy:webfontsDev"]
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  livereload:
	
  	
  	
  	
  	
  	
  	
  	
  options:
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  livereload:	
  true
	
  	
  	
  	
  	
  	
  	
  	
  files:	
  "dist/**/*.*"
	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐bower-­‐task'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐coffeelint'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐clean'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐coffee'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐concat'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐connect'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐copy'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐cssmin'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐jshint'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐less'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐jade'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐uglify'
	
  	
  grunt.loadNpmTasks	
  'grunt-­‐contrib-­‐watch'
	
  	
  grunt.registerTask	
  'default',	
  [
	
  	
  	
  	
  'common'
	
  	
  	
  	
  'dev'
	
  	
  ]
	
  	
  grunt.registerTask	
  'common',	
  [
	
  	
  	
  	
  'bower'
	
  	
  	
  	
  'coffeelint'
	
  	
  	
  	
  'jshint'
	
  	
  	
  	
  'coffee'
	
  	
  	
  	
  'less'
	
  	
  	
  	
  'concat'
	
  	
  	
  	
  'copy:staticDev'
	
  	
  	
  	
  'copy:imagesDev'
	
  	
  	
  	
  'copy:webfontsDev'
	
  	
  	
  	
  'jade:dev'
	
  	
  ]
	
  	
  grunt.registerTask	
  'dev',	
  [
	
  	
  	
  	
  'connect'
	
  	
  	
  	
  'watch'
	
  	
  ]
	
  	
  grunt.registerTask	
  'dist',	
  [
	
  	
  	
  	
  'uglify'
	
  	
  	
  	
  'cssmin'
	
  	
  	
  	
  'copy:staticDist'
	
  	
  	
  	
  'copy:imagesDist'
	
  	
  	
  	
  'copy:webfontsDist'
	
  	
  	
  	
  'jade:dist'
	
  	
  ]
bowerDirectory	
  =	
  (grunt)	
  -­‐>
	
  	
  bowerrc	
  =	
  path.join(process.cwd(),	
  ".bowerrc")
	
  	
  bowerConfig	
  =	
  grunt.file.readJSON(bowerrc)	
  unless	
  !fs.existsSync(bowerrc)
	
  	
  bowerConfig?.directory	
  ||	
  "vendor/components"
gulpfile.coffee
gulp	
  =	
  require	
  'gulp'
gutil	
  =	
  require	
  'gulp-­‐util'
fs	
  =	
  require	
  'fs'
path	
  =	
  require	
  'path'
bower	
  =	
  require	
  'gulp-­‐bower'
clean	
  =	
  require	
  'gulp-­‐clean'
coffee	
  =	
  require	
  'gulp-­‐coffee'
coffeelint	
  =	
  require	
  'gulp-­‐coffeelint'
concat	
  =	
  require	
  'gulp-­‐concat'
jade	
  =	
  require	
  'gulp-­‐jade'
jslint	
  =	
  require	
  'gulp-­‐jshint'
jslintReporter	
  =	
  require	
  'jshint-­‐stylish'
less	
  =	
  require	
  'gulp-­‐less'
cssmin	
  =	
  require	
  'gulp-­‐minify-­‐css'
connect	
  =	
  require	
  'gulp-­‐connect'
uglify	
  =	
  require	
  'gulp-­‐uglify'
es	
  =	
  require	
  'event-­‐stream'
pkg	
  =	
  require	
  './package.json'
server	
  =	
  require	
  './config/server'
urlrouter	
  =	
  require	
  'urlrouter'
output	
  =
	
  	
  css:	
  	
  	
  	
  	
  	
  'css/app.css'
	
  	
  jsApp:	
  	
  	
  	
  'js/app.js'
	
  	
  jsVendor:	
  'js/vendor.js'
files	
  =
	
  	
  coffee:	
  	
  	
  'app/js/**/*.coffee'
	
  	
  img:	
  	
  	
  	
  	
  	
  'app/img/**/*.*'
	
  	
  static:	
  	
  	
  'app/static/**/*.*'
	
  	
  webfonts:	
  [
	
  	
  	
  	
  'vendor/webfonts/**/*.*'
	
  	
  	
  	
  'vendor/components/font-­‐awesome/fonts/**/*.*'
	
  	
  ]
	
  	
  jade:	
  	
  	
  	
  	
  'app/pages/**/*.jade'
	
  	
  js:
	
  	
  	
  	
  app:	
  	
  	
  	
  ['app/js/**/*.js']
	
  	
  	
  	
  vendor:	
  [
	
  	
  	
  	
  	
  	
  'vendor/components/jquery/jquery.min.js'
	
  	
  	
  	
  	
  	
  'vendor/components/underscore/underscore-­‐min.js'
	
  	
  	
  	
  	
  	
  'vendor/components/angular/angular.min.js'
	
  	
  	
  	
  	
  	
  'vendor/js/**/*.js'
	
  	
  	
  	
  ]
	
  	
  less:
	
  	
  	
  	
  app:	
  	
  	
  	
  'app/css/app.less'
	
  	
  	
  	
  watch:	
  	
  [
	
  	
  	
  	
  	
  	
  'app/css/**'
	
  	
  	
  	
  	
  	
  'vendor/components/bootstrap/less/**'
	
  	
  	
  	
  ]
config	
  =
	
  	
  jshint:
	
  	
  	
  	
  #	
  enforcing	
  options
	
  	
  	
  	
  curly:	
  true
	
  	
  	
  	
  eqeqeq:	
  true
	
  	
  	
  	
  latedef:	
  true
	
  	
  	
  	
  newcap:	
  true
	
  	
  	
  	
  noarg:	
  true
	
  	
  	
  	
  #	
  relaxing	
  options
	
  	
  	
  	
  boss:	
  true
	
  	
  	
  	
  eqnull:	
  true
	
  	
  	
  	
  sub:	
  true
	
  	
  	
  	
  #	
  environment/globals
	
  	
  	
  	
  browser:	
  true
	
  	
  jade:
	
  	
  	
  	
  pretty:	
  true
	
  	
  	
  	
  data:
	
  	
  	
  	
  	
  	
  js:	
  output.jsApp
	
  	
  	
  	
  	
  	
  jsVendor:	
  output.jsVendor
	
  	
  	
  	
  	
  	
  css:	
  output.css
	
  	
  	
  	
  	
  	
  pkg:	
  pkg
	
  	
  server:
	
  	
  	
  	
  port:	
  8000
	
  	
  	
  	
  base:	
  'generated'
	
  	
  	
  	
  livereload:	
  true
	
  	
  	
  	
  open:	
  true
	
  	
  	
  	
  middleware:	
  (connect,	
  options)	
  -­‐>
	
  	
  	
  	
  	
  	
  middlewares	
  =	
  [];
	
  	
  	
  	
  	
  	
  if	
  (!Array.isArray(options.base))
	
  	
  	
  	
  	
  	
  	
  	
  options.base	
  =	
  [options.base]
	
  	
  
	
  	
  	
  	
  	
  	
  directory	
  =	
  options.directory	
  ||	
  options.base[options.base.length	
  -­‐	
  1]
	
  	
  	
  	
  	
  	
  options.base.forEach	
  (base)	
  -­‐>
	
  	
  	
  	
  	
  	
  	
  	
  #	
  Serve	
  static	
  files.
	
  	
  	
  	
  	
  	
  	
  	
  middlewares.push(connect.static(base))
	
  	
  
	
  	
  	
  	
  	
  	
  middlewares.push	
  urlrouter(server.drawRoutes)
	
  	
  	
  	
  	
  	
  #	
  Make	
  directory	
  browse-­‐able.
	
  	
  	
  	
  	
  	
  middlewares.push	
  connect.directory(directory)
	
  	
  	
  	
  	
  	
  middlewares

gulp.task	
  'default',	
  ['lint','build']
gulp.task	
  'run',	
  ['lint','build','server','watch']
gulp.task	
  'build',	
  [
	
  	
  	
  	
  'install'
	
  	
  	
  	
  'js'
	
  	
  	
  	
  'css'
	
  	
  	
  	
  'jade'
	
  	
  	
  	
  'copy'
	
  	
  ]
gulp.task	
  'install',	
  ()	
  -­‐>
	
  	
  bower()
gulp.task	
  'lint',	
  ['coffeelint','jslint']
gulp.task	
  'coffeelint',	
  ()	
  -­‐>
	
  	
  gulp.src(files.coffee)
	
  	
  	
  	
  .pipe(coffeelint())
	
  	
  	
  	
  .pipe(coffeelint.reporter())
gulp.task	
  'jslint',	
  ()	
  -­‐>
	
  	
  gulp.src(files.js.app)
	
  	
  	
  	
  .pipe(jslint(config.jshint))
	
  	
  	
  	
  .pipe(jslint.reporter(jslintReporter))
	
  	
  
gulp.task	
  'jade',	
  ()	
  -­‐>
	
  	
  gulp.src(files.jade)
	
  	
  	
  	
  .pipe(jade(config.jade))
	
  	
  	
  	
  .pipe(gulp.dest('./generated'))
	
  	
  	
  	
  .pipe(gulp.dest('./dist'))
gulp.task	
  'jsApp',	
  ()	
  -­‐>
	
  	
  es.concat(
	
  	
  	
  	
  	
  	
  gulp.src(files.coffee).pipe(coffee()),
	
  	
  	
  	
  	
  	
  gulp.src(files.js.app)
	
  	
  	
  	
  ).pipe(concat(output.jsApp))
	
  	
  	
  	
  .pipe(gulp.dest('./generated'))
	
  	
  	
  	
  .pipe(uglify())
	
  	
  	
  	
  .pipe(gulp.dest('./dist'))
	
  	
  
gulp.task	
  'jsVendor',	
  ['install'],	
  ()	
  -­‐>
	
  	
  gulp.src(files.js.vendor)
	
  	
  	
  	
  .pipe(concat(output.jsVendor))
	
  	
  	
  	
  .pipe(gulp.dest('./generated'))
	
  	
  	
  	
  .pipe(gulp.dest('./dist'))
	
  	
  
gulp.task	
  'js',	
  ['jsApp','jsVendor']
	
  	
  
gulp.task	
  'css',	
  ['install'],	
  ()	
  -­‐>
	
  	
  gulp.src(files.less.app)
	
  	
  	
  	
  .pipe(plumber())
	
  	
  	
  	
  .pipe(less())
	
  	
  	
  	
  .pipe(concat(output.css))
	
  	
  	
  	
  .pipe(gulp.dest('./generated'))
	
  	
  	
  	
  .pipe(cssmin())
	
  	
  	
  	
  .pipe(gulp.dest('./dist'))
	
  	
  
gulp.task	
  'clean',	
  ()	
  -­‐>
	
  	
  gulp.src(['./dist','./generated',	
  bowerDirectory()])
	
  	
  	
  	
  .pipe(clean())
gulp.task	
  'copy',	
  ['install'],	
  ()	
  -­‐>
	
  	
  es.concat(
	
  	
  	
  	
  gulp.src(files.img)
	
  	
  	
  	
  	
  	
  .pipe(gulp.dest('./generated/img'))
	
  	
  	
  	
  	
  	
  .pipe(gulp.dest('./dist/img')),
	
  	
  	
  	
  gulp.src(files.static)
	
  	
  	
  	
  	
  	
  .pipe(gulp.dest('./generated/'))
	
  	
  	
  	
  	
  	
  .pipe(gulp.dest('./dist/')),
	
  	
  	
  	
  gulp.src(files.webfonts)
	
  	
  	
  	
  	
  	
  .pipe(gulp.dest('./generated/fonts'))
	
  	
  	
  	
  	
  	
  .pipe(gulp.dest('./dist/fonts'))
	
  	
  )
gulp.task	
  'watch',	
  ()	
  -­‐>
	
  	
  gulp.watch	
  files.coffee,	
  	
  	
  	
  	
  	
  ['coffeelint','jsApp']
	
  	
  gulp.watch	
  files.js.app,	
  	
  	
  	
  	
  	
  ['jslint','jsApp']
	
  	
  gulp.watch	
  files.js.vendor,	
  	
  	
  ['jsVendor']
	
  	
  gulp.watch	
  files.jade.pages,	
  	
  ['jade']
	
  	
  gulp.watch	
  files.less.watch,	
  	
  ['css']
	
  	
  gulp.watch	
  [files.img,	
  files.webfonts,	
  files.static],	
  	
  ['copy']
	
  	
  
gulp.task	
  'server',	
  ['build'],	
  connect.server(config.server)
bowerDirectory	
  =	
  ()	
  -­‐>
	
  	
  bowerpath	
  =	
  path.join(process.cwd(),	
  ".bowerrc")
	
  	
  bowerrc	
  =	
  fs.readFileSync(bowerpath)	
  unless	
  !fs.existsSync	
  bowerpath	
  
	
  	
  bowerConfig	
  =	
  JSON.parse(bowerrc)	
  if	
  bowerrc?
	
  	
  bowerConfig?.directory	
  ||	
  "vendor/components"
grunt.loadNpmTasks('grunt-­‐bower-­‐task');
grunt.loadNpmTasks('grunt-­‐coffeelint');
grunt.loadNpmTasks('grunt-­‐contrib-­‐clean');
grunt.loadNpmTasks('grunt-­‐contrib-­‐coffee');
grunt.loadNpmTasks('grunt-­‐contrib-­‐concat');
grunt.loadNpmTasks('grunt-­‐contrib-­‐connect');
grunt.loadNpmTasks('grunt-­‐contrib-­‐copy');
grunt.loadNpmTasks('grunt-­‐contrib-­‐cssmin');
grunt.loadNpmTasks('grunt-­‐contrib-­‐jade');
grunt.loadNpmTasks('grunt-­‐contrib-­‐jshint');
grunt.loadNpmTasks('grunt-­‐contrib-­‐less');
grunt.loadNpmTasks('grunt-­‐contrib-­‐uglify');
grunt.loadNpmTasks('grunt-­‐contrib-­‐watch');
bower	
  	
  	
  	
  	
  	
  =	
  require	
  'gulp-­‐bower'
coffeelint	
  =	
  require	
  'gulp-­‐coffeelint'
clean	
  	
  	
  	
  	
  	
  =	
  require	
  'gulp-­‐clean'
coffee	
  	
  	
  	
  	
  =	
  require	
  'gulp-­‐coffee'
concat	
  	
  	
  	
  	
  =	
  require	
  'gulp-­‐concat'
connect	
  	
  	
  	
  =	
  require	
  'gulp-­‐connect'
	
  	
  #	
  	
  	
  	
  	
  copy	
  included	
  via	
  .dest
cssmin	
  	
  	
  	
  	
  =	
  require	
  'gulp-­‐minify-­‐css'
jade	
  	
  	
  	
  	
  	
  	
  =	
  require	
  'gulp-­‐jade'
jslint	
  	
  	
  	
  	
  =	
  require	
  'gulp-­‐jshint'
less	
  	
  	
  	
  	
  	
  	
  =	
  require	
  'gulp-­‐less'
uglify	
  	
  	
  	
  	
  =	
  require	
  'gulp-­‐uglify'
	
  	
  #	
  	
  	
  	
  watch	
  included	
  via	
  .watch
 git	
  co	
  grunt
 time	
  grunt	
  >	
  /dev/null
real	
  0m5.114s
user	
  0m4.802s
sys	
  	
  0m0.214s
 git	
  co	
  grunt
 time	
  grunt	
  >	
  /dev/null
real	
  0m5.114s
user	
  0m4.802s
sys	
  	
  0m0.214s
 git	
  co	
  gulp
 time	
  gulp	
  >	
  /dev/null
real	
  0m2.811s
user	
  0m2.601s
sys	
  	
  0m0.241s

learn more
 gulpjs.com
 gulpjs/gulp
 gulpjs
demo code
 queenseight.com
 aranasoft/queenseight
 git checkout grunt
 git checkout gulp
NEXT STEPS

npm install gulp
dethrone grunt
@jayharris
#dethroningGrunt

jay@aranasoft.com
@jayharris
#dethroningGrunt

thank you

More Related Content

What's hot (20)

PDF
WebcampZG - Rails 4
shnikola
 
PDF
Keeping the frontend under control with Symfony and Webpack
Ignacio Martín
 
PPTX
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
D
 
PPTX
Things Your Mother Didnt Tell You About Bundle Configurations - Symfony Live…
D
 
PPT
Creating the interfaces of the future with the APIs of today
gerbille
 
PPTX
Angular Tutorial Freshers and Experienced
rajkamaltibacademy
 
PDF
Laravel 로 배우는 서버사이드 #5
성일 한
 
PDF
FamilySearch Reference Client
Dallan Quass
 
PDF
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Ryan Weaver
 
PDF
WCLA12 JavaScript
Jeffrey Zinn
 
PDF
WordPress Admin UI - Future Proofing Your Admin Pages
Brandon Dove
 
PDF
Symfony tips and tricks
Javier Eguiluz
 
PDF
Rails 3.1 Asset Pipeline
eallam
 
PDF
Introduction to Vue.js
Meir Rotstein
 
PDF
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
Fabio Akita
 
PDF
YUI on the go
Christian Heilmann
 
KEY
Deploying
soon
 
PDF
Sane Async Patterns
TrevorBurnham
 
PDF
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Ryan Weaver
 
PDF
Realize mais com HTML 5 e CSS 3 - 16 EDTED - RJ
Leonardo Balter
 
WebcampZG - Rails 4
shnikola
 
Keeping the frontend under control with Symfony and Webpack
Ignacio Martín
 
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
D
 
Things Your Mother Didnt Tell You About Bundle Configurations - Symfony Live…
D
 
Creating the interfaces of the future with the APIs of today
gerbille
 
Angular Tutorial Freshers and Experienced
rajkamaltibacademy
 
Laravel 로 배우는 서버사이드 #5
성일 한
 
FamilySearch Reference Client
Dallan Quass
 
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
Ryan Weaver
 
WCLA12 JavaScript
Jeffrey Zinn
 
WordPress Admin UI - Future Proofing Your Admin Pages
Brandon Dove
 
Symfony tips and tricks
Javier Eguiluz
 
Rails 3.1 Asset Pipeline
eallam
 
Introduction to Vue.js
Meir Rotstein
 
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
Fabio Akita
 
YUI on the go
Christian Heilmann
 
Deploying
soon
 
Sane Async Patterns
TrevorBurnham
 
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Ryan Weaver
 
Realize mais com HTML 5 e CSS 3 - 16 EDTED - RJ
Leonardo Balter
 

Similar to Dethroning Grunt: Simple and Effective Builds with gulp.js (20)

KEY
Brunch With Coffee
Sébastien Gruhier
 
ZIP
Rails 3.1 Asset Pipeline
James Daniels
 
PDF
Grails for hipsters
Robert Fletcher
 
PDF
Bundling Client Side Assets
Timothy Oxley
 
PDF
Javascript is your (Auto)mate
Codemotion
 
PDF
How to quickly make REST APIs with CompoundJS
Frank Rousseau
 
KEY
Richard rodger-appgen-2012-lxjs-lisbon
Richard Rodger
 
PDF
Front-end tools
Gleb Vinnikov
 
PDF
Npm scripts
정윤 김
 
PDF
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
Alessandro Molina
 
PDF
Heroku pop-behind-the-sense
Ben Lin
 
PDF
Quest for the Perfect Workflow for McrFRED
Andi Smith
 
PDF
Hitchhiker's guide to the front end development
정윤 김
 
KEY
Expressを使ってみた
Atsuhiro Takiguchi
 
PDF
Building and deploying React applications
Astrails
 
KEY
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
PDF
ParisJS #10 : RequireJS
Julien Cabanès
 
PDF
Let Grunt do the work, focus on the fun!
Dirk Ginader
 
PDF
Resource registries plone conf 2014
Ramon Navarro
 
KEY
Full-Stack CakePHP Deployment
Jose Diaz-Gonzalez
 
Brunch With Coffee
Sébastien Gruhier
 
Rails 3.1 Asset Pipeline
James Daniels
 
Grails for hipsters
Robert Fletcher
 
Bundling Client Side Assets
Timothy Oxley
 
Javascript is your (Auto)mate
Codemotion
 
How to quickly make REST APIs with CompoundJS
Frank Rousseau
 
Richard rodger-appgen-2012-lxjs-lisbon
Richard Rodger
 
Front-end tools
Gleb Vinnikov
 
Npm scripts
정윤 김
 
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
Alessandro Molina
 
Heroku pop-behind-the-sense
Ben Lin
 
Quest for the Perfect Workflow for McrFRED
Andi Smith
 
Hitchhiker's guide to the front end development
정윤 김
 
Expressを使ってみた
Atsuhiro Takiguchi
 
Building and deploying React applications
Astrails
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
ParisJS #10 : RequireJS
Julien Cabanès
 
Let Grunt do the work, focus on the fun!
Dirk Ginader
 
Resource registries plone conf 2014
Ramon Navarro
 
Full-Stack CakePHP Deployment
Jose Diaz-Gonzalez
 
Ad

More from Jay Harris (7)

PDF
Bullets Kill People: Building Effective Presentations
Jay Harris
 
PDF
OrchardCMS module development
Jay Harris
 
PDF
Test driven node.js
Jay Harris
 
PDF
node.js Module Development
Jay Harris
 
PPT
The Geek's Guide to SEO
Jay Harris
 
PDF
Going for Speed: Testing for Performance
Jay Harris
 
PPT
Dev Basics: The ASP.NET Page Life Cycle
Jay Harris
 
Bullets Kill People: Building Effective Presentations
Jay Harris
 
OrchardCMS module development
Jay Harris
 
Test driven node.js
Jay Harris
 
node.js Module Development
Jay Harris
 
The Geek's Guide to SEO
Jay Harris
 
Going for Speed: Testing for Performance
Jay Harris
 
Dev Basics: The ASP.NET Page Life Cycle
Jay Harris
 
Ad

Recently uploaded (20)

PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PPTX
cloud computing vai.pptx for the project
vaibhavdobariyal79
 
PDF
Research-Fundamentals-and-Topic-Development.pdf
ayesha butalia
 
PPTX
AVL ( audio, visuals or led ), technology.
Rajeshwri Panchal
 
PPTX
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
PDF
The Future of Mobile Is Context-Aware—Are You Ready?
iProgrammer Solutions Private Limited
 
PDF
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
PDF
How ETL Control Logic Keeps Your Pipelines Safe and Reliable.pdf
Stryv Solutions Pvt. Ltd.
 
PDF
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
PPTX
The Future of AI & Machine Learning.pptx
pritsen4700
 
PPTX
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
PPTX
Agile Chennai 18-19 July 2025 Ideathon | AI Powered Microfinance Literacy Gui...
AgileNetwork
 
PDF
NewMind AI Weekly Chronicles – July’25, Week III
NewMind AI
 
PDF
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
PDF
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
PDF
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
PPTX
Agile Chennai 18-19 July 2025 | Emerging patterns in Agentic AI by Bharani Su...
AgileNetwork
 
PPTX
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
PPTX
Simple and concise overview about Quantum computing..pptx
mughal641
 
PPTX
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
cloud computing vai.pptx for the project
vaibhavdobariyal79
 
Research-Fundamentals-and-Topic-Development.pdf
ayesha butalia
 
AVL ( audio, visuals or led ), technology.
Rajeshwri Panchal
 
What-is-the-World-Wide-Web -- Introduction
tonifi9488
 
The Future of Mobile Is Context-Aware—Are You Ready?
iProgrammer Solutions Private Limited
 
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
How ETL Control Logic Keeps Your Pipelines Safe and Reliable.pdf
Stryv Solutions Pvt. Ltd.
 
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
The Future of AI & Machine Learning.pptx
pritsen4700
 
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
Agile Chennai 18-19 July 2025 Ideathon | AI Powered Microfinance Literacy Gui...
AgileNetwork
 
NewMind AI Weekly Chronicles – July’25, Week III
NewMind AI
 
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
Agile Chennai 18-19 July 2025 | Emerging patterns in Agentic AI by Bharani Su...
AgileNetwork
 
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
Simple and concise overview about Quantum computing..pptx
mughal641
 
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 

Dethroning Grunt: Simple and Effective Builds with gulp.js

  • 4. that is a lot of things to do task runners simplify to one command
  • 7. demo code  queenseight.com  aranasoft/queenseight
  • 8. //  Project  Specific  Tasks grunt.loadNpmTasks('grunt-­‐bower-­‐task'); grunt.loadNpmTasks('grunt-­‐coffeelint'); grunt.loadNpmTasks('grunt-­‐contrib-­‐clean'); grunt.loadNpmTasks('grunt-­‐contrib-­‐coffee'); grunt.loadNpmTasks('grunt-­‐contrib-­‐concat'); grunt.loadNpmTasks('grunt-­‐contrib-­‐connect'); grunt.loadNpmTasks('grunt-­‐contrib-­‐copy'); grunt.loadNpmTasks('grunt-­‐contrib-­‐cssmin'); grunt.loadNpmTasks('grunt-­‐contrib-­‐jade'); grunt.loadNpmTasks('grunt-­‐contrib-­‐jshint'); grunt.loadNpmTasks('grunt-­‐contrib-­‐less'); grunt.loadNpmTasks('grunt-­‐contrib-­‐uglify'); grunt.loadNpmTasks('grunt-­‐contrib-­‐watch');
  • 10. //  13  tasks  in  all grunt.loadNpmTasks('grunt-­‐bower-­‐task'); grunt.loadNpmTasks('grunt-­‐coffeelint'); grunt.loadNpmTasks('grunt-­‐contrib-­‐clean'); grunt.loadNpmTasks('grunt-­‐contrib-­‐coffee'); grunt.loadNpmTasks('grunt-­‐contrib-­‐concat'); grunt.loadNpmTasks('grunt-­‐contrib-­‐connect'); grunt.loadNpmTasks('grunt-­‐contrib-­‐copy'); grunt.loadNpmTasks('grunt-­‐contrib-­‐cssmin'); grunt.loadNpmTasks('grunt-­‐contrib-­‐jade'); grunt.loadNpmTasks('grunt-­‐contrib-­‐jshint'); grunt.loadNpmTasks('grunt-­‐contrib-­‐less'); grunt.loadNpmTasks('grunt-­‐contrib-­‐uglify'); grunt.loadNpmTasks('grunt-­‐contrib-­‐watch');
  • 11. gruntfile.coffee timer  =  require  "grunt-­‐timer" fs  =  require  'fs' path  =  require  'path' server  =  require  './config/server' urlrouter  =  require  'urlrouter' module.exports  =  (grunt)  -­‐>    timer.init  grunt    #  Project  configuration.    grunt.initConfig        pkg:  grunt.file.readJSON  'package.json'        files:            coffee:                app:  "app/js/**/*.coffee"                generated:  "generated/js/app.coffee.js"                css:                vendor:  "vendor/css/**/*.css"                app:  "app/css/**/*.css"                concatenated:  "generated/css/app.css"                minified:  "dist/css/app.css"                minifiedWebRelative:  "css/app.css"                            img:                root:  "img"            jade:                pages:  "**/*.jade"                pageRoot:  "app/pages/"            js:                app:  "app/js/**/*.js"                vendor:  [                    "vendor/components/jquery/jquery.js"                    "vendor/components/underscore/underscore.js"                    "vendor/components/angular/angular.js"                    "vendor/js/**/*.js"                ]                concatenatedVendor:  "generated/js/vendor.js"                minifiedVendor:  "dist/js/vendor.js"                minifiedVendorWebRelative:  "js/vendor.js"                concatenated:  "generated/js/app.js"                minified:  "dist/js/app.js"                minifiedWebRelative:  "js/app.js"                                            less:                app:  "app/css/app.less"                vendor:  "vendor/css/**/*.less"                generatedApp:  "generated/css/app.less.css"                generatedVendor:  "generated/css/vendor.less.css"                watch:  "app/css/**/*.less"            webfonts:                root:  "fonts"        bower:            install:                options:                    copy:  false        coffee:            compile:                files:                    "<%=  files.coffee.generated  %>":  "<%=  files.coffee.app  %>"                            coffeelint:            app:  [                "<%=  files.coffee.app  %>"            ]        concat:            css:                src:  [                    "<%=  files.less.generatedVendor  %>"                    "<%=  files.css.vendor  %>"                    "<%=  files.less.generatedApp  %>"                    "<%=  files.css.app  %>"                ]                dest:  "<%=  files.css.concatenated  %>"            js:                src:  [                    "<%=  files.coffee.generated  %>"                    "<%=  files.js.app  %>"                ]                dest:  "<%=  files.js.concatenated  %>"            jsVendor:                src:  ["<%=  files.js.vendor  %>"]                dest:  "<%=  files.js.concatenatedVendor  %>"        connect:            server:                options:                    port:  8000                    base:  'generated'                    open:  true                    middleware:  (connect,  options)  -­‐>                        middlewares  =  [];                        if  (!Array.isArray(options.base))                            options.base  =  [options.base]                                                directory  =  options.directory  ||  options.base[options.base.length  -­‐  1]                        options.base.forEach  (base)  -­‐>                            #  Serve  static  files.                            middlewares.push(connect.static(base))                        middlewares.push  urlrouter(server.drawRoutes)                        #  Make  directory  browse-­‐able.                        middlewares.push  connect.directory(directory)                        middlewares        copy:            imagesDev:                files:  [{                    expand:  true                    cwd:  "app/img/"                    src:  "**"                    dest:  "generated/<%=  files.img.root  %>/"                }                {                    expand:  true                    cwd:  "vendor/img/"                    src:  "**"                    dest:  "generated/<%=  files.img.root  %>/"                }]            imagesDist:                files:  [{                    expand:  true                    cwd:  "app/img/"                    src:  "**"                    dest:  "dist/<%=  files.img.root  %>/"                }                {                    expand:  true                    cwd:  "vendor/img/"                    src:  "**"                    dest:  "dist/<%=  files.img.root  %>/"                }]            staticDev:                files:  [                    expand:  true                    cwd:  "app/static"                    src:  "**"                    dest:  'generated'                ]            staticDist:                files:  [                    expand:  true                    cwd:  "app/static"                    src:  "**"                    dest:  'dist'                ]            webfontsDev:                files:  [{                    expand:  true                    cwd:  "vendor/webfonts/"                    src:  "**"                    dest:  "generated/<%=  files.webfonts.root  %>/"                }                {                    expand:  true                    cwd:  "vendor/components/font-­‐awesome/fonts/"                    src:  "**"                    dest:  "generated/<%=  files.webfonts.root  %>/"                }]            webfontsDist:                files:  [{                    expand:  true                    cwd:  "vendor/webfonts/"                    src:  "**"                    dest:  "dist/<%=  files.webfonts.root  %>/"                }                {                    expand:  true                    cwd:  "vendor/components/font-­‐awesome/fonts/"                    src:  "**"                    dest:  "dist/<%=  files.webfonts.root  %>/"                }]                        cssmin:            compress:                files:                    "<%=  files.css.minified  %>":  "<%=  files.css.concatenated  %>"            css:                files:  ["<%=  files.css.vendor  %>",  "<%=  files.css.app  %>"]                tasks:  ["concat:css"]        jade:            dev:                options:                    pretty:  true                    data:                        js:  "<%=  files.js.minifiedWebRelative  %>"                          jsVendor:  "<%=  files.js.minifiedVendorWebRelative  %>"                        css:  "<%=  files.css.minifiedWebRelative  %>"                        pkg:  "<%=  pkg  %>"                files:  [{                    expand:  true                    src:  "<%=  files.jade.pages  %>"                    cwd:  "<%=  files.jade.pageRoot  %>"                    dest:  "generated/"                    ext:  ".html"                }]            dist:                options:                    data:                        js:  "<%=  minifiedWebRelative  %>"                        jsVendor:  "<%=  minifiedVendorWebRelative  %>"                        css:  "<%=  files.css.minifiedWebRelative  %>"                        pkg:  "<%=  pkg  %>"                files:  [{                    expand:  true                    src:  "<%=  files.jade.pages  %>"                    cwd:  "<%=  files.jade.pageRoot  %>"                    dest:  "dist/"                    ext:  ".html"                }]            js:                files:  ["<%=  files.js.vendor  %>",  "<%=  files.js.app  %>"]                tasks:  ["concat:js"]        jshint:            files:  ["<%=  files.js.app  %>"]            options:            #  enforcing  options                curly:  true                eqeqeq:  true                latedef:  true                newcap:  true                noarg:  true            #  relaxing  options                boss:  true                eqnull:  true                sub:  true            #  environment/globals                browser:  true                        less:            options:                paths:  ["app/css",  "vendor/css"]            compile:                files:                    "<%=  files.less.generatedVendor  %>":  "<%=  files.less.vendor  %>"                    "<%=  files.less.generatedApp  %>":  "<%=  files.less.app  %>"                            uglify:            options:                banner:  '/*!  <%=  pkg.name  %>  <%=  grunt.template.today("yyyy-­‐mm-­‐dd")  %>  */n'            js:                files:                    "<%=  files.js.minified  %>":  "<%=  files.js.concatenated  %>"            jsVendor:                files:                    "<%=  files.js.minifiedVendor  %>":  "<%=  files.js.concatenatedVendor  %>"        clean:            bower:                src:  bowerDirectory  grunt            js:                src:  "<%=  files.js.concatenated  %>"            css:                src:  "<%=  files.css.concatenated  %>"            dist:                src:  ["dist",  "generated"]        watch:            coffee:                files:  "<%=  files.coffee.app  %>"                tasks:  ["coffeelint",  "coffee",  "concat:js"]            images:                files:  ["app/img/**/*.*",  "vendor/img/**/*.*"]                tasks:  ["copy:imagesDev"]                            jade:                files:  ["<%=  files.jade.pageRoot  %>/<%=  files.jade.pages  %>"]                tasks:  ["jade:dev"]            less:                files:  [                    "<%=  files.less.vendor  %>"                    "<%=  files.less.watch  %>"                ]                tasks:  ["less",  "concat:css"]                lint:                files:  "<%=  files.js.app  %>"                tasks:  ["jshint"]                webfonts:                files:  ["vendor/webfonts/**/*.*",  "vendor/components/font-­‐awesome/fonts/**/*.*"]                tasks:  ["copy:webfontsDev"]                            livereload:                options:                    livereload:  true                files:  "dist/**/*.*"                    grunt.loadNpmTasks  'grunt-­‐bower-­‐task'    grunt.loadNpmTasks  'grunt-­‐coffeelint'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐clean'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐coffee'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐concat'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐connect'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐copy'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐cssmin'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐jshint'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐less'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐jade'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐uglify'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐watch'    grunt.registerTask  'default',  [        'common'        'dev'    ]    grunt.registerTask  'common',  [        'bower'        'coffeelint'        'jshint'        'coffee'        'less'        'concat'        'copy:staticDev'        'copy:imagesDev'        'copy:webfontsDev'        'jade:dev'    ]    grunt.registerTask  'dev',  [        'connect'        'watch'    ]    grunt.registerTask  'dist',  [        'uglify'        'cssmin'        'copy:staticDist'        'copy:imagesDist'        'copy:webfontsDist'        'jade:dist'    ] bowerDirectory  =  (grunt)  -­‐>    bowerrc  =  path.join(process.cwd(),  ".bowerrc")    bowerConfig  =  grunt.file.readJSON(bowerrc)  unless  !fs.existsSync(bowerrc)    bowerConfig?.directory  ||  "vendor/components"
  • 12. ├──  css │      ├──  app.less │      ├──  mixins.less │      └──  variables.less ├──  img │      ├──  arana-­‐software.png │      ├──  arana-­‐[email protected] │      ├──  banner-­‐lg.png │      ├──  banner-­‐md.png │      ├──  banner-­‐sm.png │      ├──  crown.png │      ├──  [email protected] │      ├──  [email protected] │      └──  wood.png ├──  js │      ├──  app.coffee │      ├──  controllers │      │      └──  board.coffee │      ├──  directives │      │      └──  board.js │      └──  templates │              └──  board.coffee ├──  pages │      └──  index.jade └──  static        └──  favicon.ico gruntfile.coffee timer  =  require  "grunt-­‐timer" fs  =  require  'fs' path  =  require  'path' server  =  require  './config/server' urlrouter  =  require  'urlrouter'            jsVendor:                src:  ["<%=  files.js.vendor  %>"]                dest:  "<%=  files.js.concatenatedVendor  %>"                {            css:                    expand:  true                files:  ["<%=  files.css.vendor  %>",  "<%=  files.css.app  %>"]                    cwd:  "vendor/components/font-­‐awesome/fonts/"                tasks:  ["concat:css"]                    src:  "**"                    dest:  "dist/<%=  files.webfonts.root  %>/"            images:                }]                files:  ["app/img/**/*.*",  "vendor/img/**/*.*"]                                tasks:  ["copy:imagesDev"]        cssmin:                            compress:            jade:                files:                files:  ["<%=  files.jade.pageRoot  %>/<%=  files.jade.pages  %>"]                    "<%=  files.css.minified  %>":  "<%=  files.css.concatenated  %>"                tasks:  ["jade:dev"]        connect:            server: module.exports  =  (grunt)  -­‐>                options:    timer.init  grunt                    port:  8000                    base:  'generated'    #  Project  configuration.                    open:  true    grunt.initConfig                    middleware:  (connect,  options)  -­‐>        pkg:  grunt.file.readJSON  'package.json'                        middlewares  =  [];                        if  (!Array.isArray(options.base))        jade:            js:        files:                            options.base  =  [options.base]            dev:                files:  ["<%=  files.js.vendor  %>",  "<%=  files.js.app  %>"]            coffee:                                        options:                tasks:  ["concat:js"]                app:  "app/js/**/*.coffee"                        directory  =  options.directory  ||  options.base[options.base.length  -­‐  1]                    pretty:  true                generated:  "generated/js/app.coffee.js"                        options.base.forEach  (base)  -­‐>                    data:            less:                                #  Serve  static  files.                        js:  "<%=  files.js.minifiedWebRelative  %>"                  files:  [            css:                            middlewares.push(connect.static(base))                        jsVendor:  "<%=  files.js.minifiedVendorWebRelative  %>"                    "<%=  files.less.vendor  %>"                vendor:  "vendor/css/**/*.css"                        css:  "<%=  files.css.minifiedWebRelative  %>"                    "<%=  files.less.watch  %>"                app:  "app/css/**/*.css"                        middlewares.push  urlrouter(server.drawRoutes)                        pkg:  "<%=  pkg  %>"                ]                concatenated:  "generated/css/app.css"                        #  Make  directory  browse-­‐able.                files:  [{                tasks:  ["less",  "concat:css"]                minified:  "dist/css/app.css"                        middlewares.push  connect.directory(directory)                    expand:  true                    minifiedWebRelative:  "css/app.css"                        middlewares                    src:  "<%=  files.jade.pages  %>"            lint:                                    cwd:  "<%=  files.jade.pageRoot  %>"                files:  "<%=  files.js.app  %>"            img:        copy:                    dest:  "generated/"                tasks:  ["jshint"]                root:  "img"            imagesDev:                    ext:  ".html"                    files:  [{                }]            webfonts:            jade:                    expand:  true            dist:                files:  ["vendor/webfonts/**/*.*",  "vendor/components/font-­‐awes                pages:  "**/*.jade"                    cwd:  "app/img/"                options:                tasks:  ["copy:webfontsDev"]                pageRoot:  "app/pages/"                    src:  "**"                    data:                                    dest:  "generated/<%=  files.img.root  %>/"                        js:  "<%=  minifiedWebRelative  %>"            livereload:            js:                }                        jsVendor:  "<%=  minifiedVendorWebRelative  %>"                options:                app:  "app/js/**/*.js"                {                        css:  "<%=  files.css.minifiedWebRelative  %>"                    livereload:  true                vendor:  [                    expand:  true                        pkg:  "<%=  pkg  %>"                files:  "dist/**/*.*"                    "vendor/components/jquery/jquery.js"                    cwd:  "vendor/img/"                files:  [{                                    "vendor/components/underscore/underscore.js"                    src:  "**"                    expand:  true    grunt.loadNpmTasks  'grunt-­‐bower-­‐task'                    "vendor/components/angular/angular.js"                    dest:  "generated/<%=  files.img.root  %>/"                    src:  "<%=  files.jade.pages  %>"    grunt.loadNpmTasks  'grunt-­‐coffeelint'                    "vendor/js/**/*.js"                }]                    cwd:  "<%=  files.jade.pageRoot  %>"    grunt.loadNpmTasks  'grunt-­‐contrib-­‐clean'                ]            imagesDist:                    dest:  "dist/"    grunt.loadNpmTasks  'grunt-­‐contrib-­‐coffee'                concatenatedVendor:  "generated/js/vendor.js"                files:  [{                    ext:  ".html"    grunt.loadNpmTasks  'grunt-­‐contrib-­‐concat'                minifiedVendor:  "dist/js/vendor.js"                    expand:  true                }]    grunt.loadNpmTasks  'grunt-­‐contrib-­‐connect'                minifiedVendorWebRelative:  "js/vendor.js"                    cwd:  "app/img/"    grunt.loadNpmTasks  'grunt-­‐contrib-­‐copy'                concatenated:  "generated/js/app.js"                    src:  "**"        jshint:    grunt.loadNpmTasks  'grunt-­‐contrib-­‐cssmin'                minified:  "dist/js/app.js"                    dest:  "dist/<%=  files.img.root  %>/"            files:  ["<%=  files.js.app  %>"]    grunt.loadNpmTasks  'grunt-­‐contrib-­‐jshint'                minifiedWebRelative:  "js/app.js"                                }            options:    grunt.loadNpmTasks  'grunt-­‐contrib-­‐less'                                {            #  enforcing  options    grunt.loadNpmTasks  'grunt-­‐contrib-­‐jade'            less:                    expand:  true                curly:  true    grunt.loadNpmTasks  'grunt-­‐contrib-­‐uglify'                app:  "app/css/app.less"                    cwd:  "vendor/img/"                eqeqeq:  true    grunt.loadNpmTasks  'grunt-­‐contrib-­‐watch'                vendor:  "vendor/css/**/*.less"                    src:  "**"                latedef:  true                generatedApp:  "generated/css/app.less.css"                    dest:  "dist/<%=  files.img.root  %>/"                newcap:  true    grunt.registerTask  'default',  [                generatedVendor:  "generated/css/vendor.less.css"                }]                noarg:  true        'common'                watch:  "app/css/**/*.less"            staticDev:            #  relaxing  options        'dev'                files:  [                boss:  true    ]            webfonts:                    expand:  true                eqnull:  true    grunt.registerTask  'common',  [                root:  "fonts"                    cwd:  "app/static"                sub:  true        'bower'                    src:  "**"            #  environment/globals        'coffeelint'        bower:                    dest:  'generated'                browser:  true        'jshint'            install:                ]                        'coffee'                options:            staticDist:        less:        'less'                    copy:  false                files:  [            options:        'concat'                    expand:  true                paths:  ["app/css",  "vendor/css"]        'copy:staticDev'        coffee:                    cwd:  "app/static"            compile:        'copy:imagesDev'            compile:                    src:  "**"                files:        'copy:webfontsDev'                files:                    dest:  'dist'                    "<%=  files.less.generatedVendor  %>":  "<%=  files.less.vendor  %>"        'jade:dev'                    "<%=  files.coffee.generated  %>":  "<%=  files.coffee.app  %>"                ]                    "<%=  files.less.generatedApp  %>":  "<%=  files.less.app  %>"    ]                                webfontsDev:                        grunt.registerTask  'dev',  [        coffeelint:                files:  [{        uglify:        'connect'            app:  [                    expand:  true            options:        'watch'                "<%=  files.coffee.app  %>"                    cwd:  "vendor/webfonts/"                banner:  '/*!  <%=  pkg.name  %>  <%=  grunt.template.today("yyyy-­‐mm-­‐dd")  %>  */n'    ]            ]                    src:  "**"            js:    grunt.registerTask  'dist',  [                    dest:  "generated/<%=  files.webfonts.root  %>/"                files:        'uglify'        concat:                }                    "<%=  files.js.minified  %>":  "<%=  files.js.concatenated  %>"        'cssmin'            css:                {            jsVendor:        'copy:staticDist'                src:  [                    expand:  true                files:        'copy:imagesDist'                    "<%=  files.less.generatedVendor  %>"                    cwd:  "vendor/components/font-­‐awesome/fonts/"                    "<%=  files.js.minifiedVendor  %>":  "<%=  files.js.concatenatedVendor  %>"        'copy:webfontsDist'                    "<%=  files.css.vendor  %>"                    src:  "**"        'jade:dist'                    "<%=  files.less.generatedApp  %>"                    dest:  "generated/<%=  files.webfonts.root  %>/"        clean:    ]                    "<%=  files.css.app  %>"                }]            bower:                ]                src:  bowerDirectory  grunt bowerDirectory  =  (grunt)  -­‐>                dest:  "<%=  files.css.concatenated  %>"            webfontsDist:            js:    bowerrc  =  path.join(process.cwd(),  ".bowerrc")                files:  [{                src:  "<%=  files.js.concatenated  %>"    bowerConfig  =  grunt.file.readJSON(bowerrc)  unless  !fs.existsSync(bow                    expand:  true    bowerConfig?.directory  ||  "vendor/components"            js:                    cwd:  "vendor/webfonts/"            css:                src:  [                    src:  "**"                src:  "<%=  files.css.concatenated  %>"                    "<%=  files.coffee.generated  %>"                    dest:  "dist/<%=  files.webfonts.root  %>/"                    "<%=  files.js.app  %>"                }            dist:                ]                src:  ["dist",  "generated"]                dest:  "<%=  files.js.concatenated  %>"        watch:            coffee:                files:  "<%=  files.coffee.app  %>"                tasks:  ["coffeelint",  "coffee",  "concat:js"]
  • 13. 'use  strict'; var  util  =  require('util'); var  Orchestrator  =  require('orchestrator'); var  gutil  =  require('gulp-­‐util'); var  deprecated  =  require('deprecated'); var  vfs  =  require('vinyl-­‐fs'); function  Gulp(){    Orchestrator.call(this); } util.inherits(Gulp,  Orchestrator); Gulp.prototype.task  =  Gulp.prototype.add; Gulp.prototype.run  =  function(){    //  run()  is  deprecated  as  of  3.5  and  will  be  removed  in  4.0    //  use  task  dependencies  instead    //  impose  our  opinion  of  "default"  tasks  onto  orchestrator    var  tasks  =  arguments.length  ?  arguments  :  ['default'];    this.start.apply(this,  tasks); }; Gulp.prototype.src  =  vfs.src; Gulp.prototype.dest  =  vfs.dest; Gulp.prototype.watch  =  function  (glob,  opt,  fn)  {    if  (!fn)  {        fn  =  opt;        opt  =  null;    }    //  array  of  tasks  given    if  (Array.isArray(fn))  {        return  vfs.watch(glob,  opt,  function(){            this.start.apply(this,  fn);        }.bind(this));    }    return  vfs.watch(glob,  opt,  fn); }; //  let  people  use  this  class  from  our  instance Gulp.prototype.Gulp  =  Gulp; //  deprecations deprecated.field('gulp.env  has  been  deprecated.  Use  gulp-­‐util.env  or  your  own  CLI  parser  instead.',  console.log,   Gulp.prototype,  'env',  gutil.env); Gulp.prototype.run  =  deprecated.method('gulp.run()  has  been  deprecated.  Use  task  dependencies  or  gulp.watch  task   triggering  instead.',  console.log,  Gulp.prototype.run); var  inst  =  new  Gulp(); module.exports  =  inst;
  • 20.  level up grok streams
  • 21.    a task: read, concatenate, write
  • 27.  level up the first gulp
  • 28.  npm install -g gulp npm install -D gulp touch gulpfile.js
  • 29. //gulpfile.js var  gulp      =  require('gulp'); var  coffee  =  require('gulp-­‐coffee'); var  concat  =  require('gulp-­‐concat'); var  uglify  =  require('gulp-­‐uglify');
  • 31. gulp.src('app/js/**/*.coffee')        .pipe(gulp.dest('dist/js')); 
  • 32. gulp.src('app/js/**/*.coffee')        .pipe(coffee()) .pipe(concat('app.js')) .pipe(uglify()) .pipe(gulp.dest('dist/js'));    
  • 33. gulp.src('app/js/**/*.coffee')        .pipe(coffee()) .pipe(concat('app.js')) .pipe(gulp.dest('test/js')) .pipe(uglify()) .pipe(gulp.dest('dist/js'));    
  • 34. gulp.task('coffee',  function()  {    gulp.src('app/js/**/*.coffee')            .pipe(coffee())    .pipe(concat('app.js'))    .pipe(gulp.dest('test/js'))    .pipe(uglify())    .pipe(gulp.dest('dist/js')); });
  • 35. gulp.task('watch',  function()  { gulp.watch('app/js/**/*.coffee',                      ['coffee']); }); 
  • 36. gulp.task('default',          ['coffee','watch']);     
  • 38. gulp.task('css',                    function()  {    gulp.src('app/css/app.less')            .pipe(less())    .pipe(cssmin())    .pipe(gulp.dest('dist/css')); });  
  • 39. var  bower  =  require('gulp-­‐bower'); gulp.task('install',  function()  {    bower(); }); 
  • 40. gulp.task('css',  ['install'],                    function()  {    gulp.src('app/css/app.less')            .pipe(less())    .pipe(cssmin())    .pipe(gulp.dest('dist/css')); });   
  • 41. var  bower  =  require('gulp-­‐bower'); gulp.task('install',  function()  {    bower(); }); //  Doesn't  work  as  expected 
  • 45. gulp.task('stuff',  function()  {    doStuff();    });
  • 46. //  Option  1:  Callback gulp.task('stuff',  function(done)  {    doSyncStuff()    done(err); });
  • 47. var  Q  =  require('q'); //  Option  2:  Promise gulp.task('stuff',  function()  {    var  deferred  =  Q.defer();    doAsyncStuff(deferred.resolve);    return  deferred.promise; });
  • 48. //  Option  3:  Return  stream gulp.task('stuff',  function()  {    var  stream  =  doStreamStuff();    return  stream; });
  • 49. gulp.task  'stuff',  ()  -­‐>    doStreamStuff()
  • 50. #  Get  return  stream  for  free! gulp.task  'stuff',  ()  -­‐>    doStreamStuff() gulp.task('stuff',  function()  {    return  doStreamStuff();    });
  • 51. var  bower  =  require('gulp-­‐bower'); gulp.task('install',  function()  {    bower(); }); 
  • 52. var  bower  =  require('gulp-­‐bower'); gulp.task('install',  function()  {    return  bower();  //  Win! }); 
  • 53. //  Back  to  where  we  were gulp.task('css',                    function()  {    gulp.src('app/css/app.less')            .pipe(less())    .pipe(cssmin())    .pipe(gulp.dest('dist/css')); });  
  • 54. gulp.task('css',  ['install'],                    function()  {    gulp.src('app/css/app.less')            .pipe(less())    .pipe(cssmin())    .pipe(gulp.dest('dist/css')); }); 
  • 56. //gulpfile.js gulp.task('css',  ['install'],                    function()  {    gulp.src('app/css/app.less')            .pipe(less())    .pipe(cssmin())    .pipe(gulp.dest('dist/css')); }); 
  • 57. #  gulpfile.coffee gulp.task  'css',  ['install'],  ()  -­‐>    gulp.src  'app/css/app.less'            .pipe  less()    .pipe  cssmin()      .pipe  gulp.dest('dist/css') 
  • 58.  gulp --require coffee-script/register
  • 63. gulp.task  'js',  ()  -­‐>    gulp.src  files.coffee            .pipe  coffee()            .pipe  concat('app.js')            .pipe  uglify()            .pipe  gulp.dest('dist/js')    
  • 64. evtstream  =  require  'event-­‐stream'      #  and/or streamq      =  require  'streamqueue'
  • 65. gulp.task  'js',  ()  -­‐>    gulp.src(files.coffee)            .pipe(coffee())            .pipe  concat('app.js')            .pipe  uglify()            .pipe  gulp.dest('dist/js')    
  • 66. gulp.task  'js',  ()  -­‐>    evtstream.concat(        gulp.src(files.coffee)                .pipe(coffee()),        gulp.src(files.js))            .pipe  concat('app.js')            .pipe  uglify()            .pipe  gulp.dest('dist/js')     
  • 67. gulp.task  'js',  ()  -­‐>    es.concat(        gulp.src(files.coffee)                .pipe(coffee()),        gulp.src(files.js))            .pipe  concat('app.js')            .pipe  uglify()            .pipe  gulp.dest('dist/js')     
  • 68. gulp.task  'js',  ()  -­‐>    sq  =  streamq  {objectmode:true}    sq.queue  gulp.src(files.coffee)                              .pipe(coffee()    sq.queue  gulp.src(files.js)    sq.done().pipe  concat('app.js')                      .pipe  uglify()                      .pipe  gulp.dest('dist/js')     
  • 69.  level up error handling
  • 70. gulp.task  'css',  ['install'],  ()  -­‐>    gulp.src  files.less            .pipe  less()      .pipe  cssmin()    .pipe  gulp.dest('dist/css') 
  • 71. //  app.less .mayhem  {    font-­‐weight:  bold;    color:              @red; } }  //  too  many  '{'  ===  BOOM! 
  • 72. [gulp]  Running  'css'... events.js:72                throw  er;  //  Unhandled  'error'                            ^ Error:  missing  opening  `{`  in  file  ./c  
  • 73. gulp.task  'css',  ['install'],  ()  -­‐>    gulp.src  files.less            .pipe  less()      .pipe  cssmin()    .pipe  gulp.dest('dist/css') 
  • 74. gulp.task  'css',  ['install'],  ()  -­‐>    gulp.src  files.less            .pipe  less().on('error',(err)-­‐>                console.log(''+err)  if  err            )  #  Ick.    .pipe  cssmin()    .pipe  gulp.dest('dist/css') 
  • 75. plumber  =  require  'gulp-­‐plumber' gulp.task  'css',  ['install'],  ()  -­‐>    gulp.src  files.less            .pipe  plumber()  #Win!            .pipe  less()      .pipe  cssmin()    .pipe  gulp.dest('dist/css') 
  • 76. [gulp]  Running  'css'... [gulp]  Error  in  plugin  'gulp-­‐less':    missing  opening  `{`  in  file  app.less [gulp]  Finished  'css'  in  21  ms 
  • 78. gutil  =  require  'gulp-­‐util' 
  • 79. gulp.src  'app/css/*.css'    .pipe  concat('app.css')    .pipe(if  gutil.env.dest  ==  'prod'                then  cssmin()                else  gutil.noop())    .pipe  gulp.dest('dist/css')      
  • 80. gulp.src  'app/css/*.css'    .pipe  concat('app.css')    .pipe(if  gutil.env.dest  ==  'prod'                then  cssmin()                else  gutil.noop())    .pipe  gulp.dest('dist/css')      
  • 81.  gulp  -­‐-­‐port=8000  -­‐-­‐dest=prod gutil.env.port  ===  8000 gutil.env.dest  ===  'prod' 
  • 82.   echo  Total  Files:  $(      find  .  -­‐type  f  -­‐print  |  wc  -­‐l) Total  Files:  1000  echo  watch  will  vomit
  • 84. gruntfile.coffee timer  =  require  "grunt-­‐timer" fs  =  require  'fs' path  =  require  'path' server  =  require  './config/server' urlrouter  =  require  'urlrouter' module.exports  =  (grunt)  -­‐>    timer.init  grunt    #  Project  configuration.    grunt.initConfig        pkg:  grunt.file.readJSON  'package.json'        files:            coffee:                app:  "app/js/**/*.coffee"                generated:  "generated/js/app.coffee.js"                css:                vendor:  "vendor/css/**/*.css"                app:  "app/css/**/*.css"                concatenated:  "generated/css/app.css"                minified:  "dist/css/app.css"                minifiedWebRelative:  "css/app.css"                            img:                root:  "img"            jade:                pages:  "**/*.jade"                pageRoot:  "app/pages/"            js:                app:  "app/js/**/*.js"                vendor:  [                    "vendor/components/jquery/jquery.js"                    "vendor/components/underscore/underscore.js"                    "vendor/components/angular/angular.js"                    "vendor/js/**/*.js"                ]                concatenatedVendor:  "generated/js/vendor.js"                minifiedVendor:  "dist/js/vendor.js"                minifiedVendorWebRelative:  "js/vendor.js"                concatenated:  "generated/js/app.js"                minified:  "dist/js/app.js"                minifiedWebRelative:  "js/app.js"                                            less:                app:  "app/css/app.less"                vendor:  "vendor/css/**/*.less"                generatedApp:  "generated/css/app.less.css"                generatedVendor:  "generated/css/vendor.less.css"                watch:  "app/css/**/*.less"            webfonts:                root:  "fonts"        bower:            install:                options:                    copy:  false        coffee:            compile:                files:                    "<%=  files.coffee.generated  %>":  "<%=  files.coffee.app  %>"                            coffeelint:            app:  [                "<%=  files.coffee.app  %>"            ]        concat:            css:                src:  [                    "<%=  files.less.generatedVendor  %>"                    "<%=  files.css.vendor  %>"                    "<%=  files.less.generatedApp  %>"                    "<%=  files.css.app  %>"                ]                dest:  "<%=  files.css.concatenated  %>"            js:                src:  [                    "<%=  files.coffee.generated  %>"                    "<%=  files.js.app  %>"                ]                dest:  "<%=  files.js.concatenated  %>"            jsVendor:                src:  ["<%=  files.js.vendor  %>"]                dest:  "<%=  files.js.concatenatedVendor  %>"        connect:            server:                options:                    port:  8000                    base:  'generated'                    open:  true                    middleware:  (connect,  options)  -­‐>                        middlewares  =  [];                        if  (!Array.isArray(options.base))                            options.base  =  [options.base]                                                directory  =  options.directory  ||  options.base[options.base.length  -­‐  1]                        options.base.forEach  (base)  -­‐>                            #  Serve  static  files.                            middlewares.push(connect.static(base))                        middlewares.push  urlrouter(server.drawRoutes)                        #  Make  directory  browse-­‐able.                        middlewares.push  connect.directory(directory)                        middlewares        copy:            imagesDev:                files:  [{                    expand:  true                    cwd:  "app/img/"                    src:  "**"                    dest:  "generated/<%=  files.img.root  %>/"                }                {                    expand:  true                    cwd:  "vendor/img/"                    src:  "**"                    dest:  "generated/<%=  files.img.root  %>/"                }]            imagesDist:                files:  [{                    expand:  true                    cwd:  "app/img/"                    src:  "**"                    dest:  "dist/<%=  files.img.root  %>/"                }                {                    expand:  true                    cwd:  "vendor/img/"                    src:  "**"                    dest:  "dist/<%=  files.img.root  %>/"                }]            staticDev:                files:  [                    expand:  true                    cwd:  "app/static"                    src:  "**"                    dest:  'generated'                ]            staticDist:                files:  [                    expand:  true                    cwd:  "app/static"                    src:  "**"                    dest:  'dist'                ]            webfontsDev:                files:  [{                    expand:  true                    cwd:  "vendor/webfonts/"                    src:  "**"                    dest:  "generated/<%=  files.webfonts.root  %>/"                }                {                    expand:  true                    cwd:  "vendor/components/font-­‐awesome/fonts/"                    src:  "**"                    dest:  "generated/<%=  files.webfonts.root  %>/"                }]            webfontsDist:                files:  [{                    expand:  true                    cwd:  "vendor/webfonts/"                    src:  "**"                    dest:  "dist/<%=  files.webfonts.root  %>/"                }                {                    expand:  true                    cwd:  "vendor/components/font-­‐awesome/fonts/"                    src:  "**"                    dest:  "dist/<%=  files.webfonts.root  %>/"                }]                        cssmin:            compress:                files:                    "<%=  files.css.minified  %>":  "<%=  files.css.concatenated  %>"            css:                files:  ["<%=  files.css.vendor  %>",  "<%=  files.css.app  %>"]                tasks:  ["concat:css"]        jade:            dev:                options:                    pretty:  true                    data:                        js:  "<%=  files.js.minifiedWebRelative  %>"                          jsVendor:  "<%=  files.js.minifiedVendorWebRelative  %>"                        css:  "<%=  files.css.minifiedWebRelative  %>"                        pkg:  "<%=  pkg  %>"                files:  [{                    expand:  true                    src:  "<%=  files.jade.pages  %>"                    cwd:  "<%=  files.jade.pageRoot  %>"                    dest:  "generated/"                    ext:  ".html"                }]            dist:                options:                    data:                        js:  "<%=  minifiedWebRelative  %>"                        jsVendor:  "<%=  minifiedVendorWebRelative  %>"                        css:  "<%=  files.css.minifiedWebRelative  %>"                        pkg:  "<%=  pkg  %>"                files:  [{                    expand:  true                    src:  "<%=  files.jade.pages  %>"                    cwd:  "<%=  files.jade.pageRoot  %>"                    dest:  "dist/"                    ext:  ".html"                }]            js:                files:  ["<%=  files.js.vendor  %>",  "<%=  files.js.app  %>"]                tasks:  ["concat:js"]        jshint:            files:  ["<%=  files.js.app  %>"]            options:            #  enforcing  options                curly:  true                eqeqeq:  true                latedef:  true                newcap:  true                noarg:  true            #  relaxing  options                boss:  true                eqnull:  true                sub:  true            #  environment/globals                browser:  true                        less:            options:                paths:  ["app/css",  "vendor/css"]            compile:                files:                    "<%=  files.less.generatedVendor  %>":  "<%=  files.less.vendor  %>"                    "<%=  files.less.generatedApp  %>":  "<%=  files.less.app  %>"                            uglify:            options:                banner:  '/*!  <%=  pkg.name  %>  <%=  grunt.template.today("yyyy-­‐mm-­‐dd")  %>  */n'            js:                files:                    "<%=  files.js.minified  %>":  "<%=  files.js.concatenated  %>"            jsVendor:                files:                    "<%=  files.js.minifiedVendor  %>":  "<%=  files.js.concatenatedVendor  %>"        clean:            bower:                src:  bowerDirectory  grunt            js:                src:  "<%=  files.js.concatenated  %>"            css:                src:  "<%=  files.css.concatenated  %>"            dist:                src:  ["dist",  "generated"]        watch:            coffee:                files:  "<%=  files.coffee.app  %>"                tasks:  ["coffeelint",  "coffee",  "concat:js"]            images:                files:  ["app/img/**/*.*",  "vendor/img/**/*.*"]                tasks:  ["copy:imagesDev"]                            jade:                files:  ["<%=  files.jade.pageRoot  %>/<%=  files.jade.pages  %>"]                tasks:  ["jade:dev"]            less:                files:  [                    "<%=  files.less.vendor  %>"                    "<%=  files.less.watch  %>"                ]                tasks:  ["less",  "concat:css"]                lint:                files:  "<%=  files.js.app  %>"                tasks:  ["jshint"]                webfonts:                files:  ["vendor/webfonts/**/*.*",  "vendor/components/font-­‐awesome/fonts/**/*.*"]                tasks:  ["copy:webfontsDev"]                            livereload:                options:                    livereload:  true                files:  "dist/**/*.*"                    grunt.loadNpmTasks  'grunt-­‐bower-­‐task'    grunt.loadNpmTasks  'grunt-­‐coffeelint'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐clean'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐coffee'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐concat'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐connect'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐copy'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐cssmin'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐jshint'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐less'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐jade'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐uglify'    grunt.loadNpmTasks  'grunt-­‐contrib-­‐watch'    grunt.registerTask  'default',  [        'common'        'dev'    ]    grunt.registerTask  'common',  [        'bower'        'coffeelint'        'jshint'        'coffee'        'less'        'concat'        'copy:staticDev'        'copy:imagesDev'        'copy:webfontsDev'        'jade:dev'    ]    grunt.registerTask  'dev',  [        'connect'        'watch'    ]    grunt.registerTask  'dist',  [        'uglify'        'cssmin'        'copy:staticDist'        'copy:imagesDist'        'copy:webfontsDist'        'jade:dist'    ] bowerDirectory  =  (grunt)  -­‐>    bowerrc  =  path.join(process.cwd(),  ".bowerrc")    bowerConfig  =  grunt.file.readJSON(bowerrc)  unless  !fs.existsSync(bowerrc)    bowerConfig?.directory  ||  "vendor/components"
  • 85. gulpfile.coffee gulp  =  require  'gulp' gutil  =  require  'gulp-­‐util' fs  =  require  'fs' path  =  require  'path' bower  =  require  'gulp-­‐bower' clean  =  require  'gulp-­‐clean' coffee  =  require  'gulp-­‐coffee' coffeelint  =  require  'gulp-­‐coffeelint' concat  =  require  'gulp-­‐concat' jade  =  require  'gulp-­‐jade' jslint  =  require  'gulp-­‐jshint' jslintReporter  =  require  'jshint-­‐stylish' less  =  require  'gulp-­‐less' cssmin  =  require  'gulp-­‐minify-­‐css' connect  =  require  'gulp-­‐connect' uglify  =  require  'gulp-­‐uglify' es  =  require  'event-­‐stream' pkg  =  require  './package.json' server  =  require  './config/server' urlrouter  =  require  'urlrouter' output  =    css:            'css/app.css'    jsApp:        'js/app.js'    jsVendor:  'js/vendor.js' files  =    coffee:      'app/js/**/*.coffee'    img:            'app/img/**/*.*'    static:      'app/static/**/*.*'    webfonts:  [        'vendor/webfonts/**/*.*'        'vendor/components/font-­‐awesome/fonts/**/*.*'    ]    jade:          'app/pages/**/*.jade'    js:        app:        ['app/js/**/*.js']        vendor:  [            'vendor/components/jquery/jquery.min.js'            'vendor/components/underscore/underscore-­‐min.js'            'vendor/components/angular/angular.min.js'            'vendor/js/**/*.js'        ]    less:        app:        'app/css/app.less'        watch:    [            'app/css/**'            'vendor/components/bootstrap/less/**'        ] config  =    jshint:        #  enforcing  options        curly:  true        eqeqeq:  true        latedef:  true        newcap:  true        noarg:  true        #  relaxing  options        boss:  true        eqnull:  true        sub:  true        #  environment/globals        browser:  true    jade:        pretty:  true        data:            js:  output.jsApp            jsVendor:  output.jsVendor            css:  output.css            pkg:  pkg    server:        port:  8000        base:  'generated'        livereload:  true        open:  true        middleware:  (connect,  options)  -­‐>            middlewares  =  [];            if  (!Array.isArray(options.base))                options.base  =  [options.base]                directory  =  options.directory  ||  options.base[options.base.length  -­‐  1]            options.base.forEach  (base)  -­‐>                #  Serve  static  files.                middlewares.push(connect.static(base))                middlewares.push  urlrouter(server.drawRoutes)            #  Make  directory  browse-­‐able.            middlewares.push  connect.directory(directory)            middlewares gulp.task  'default',  ['lint','build'] gulp.task  'run',  ['lint','build','server','watch'] gulp.task  'build',  [        'install'        'js'        'css'        'jade'        'copy'    ] gulp.task  'install',  ()  -­‐>    bower() gulp.task  'lint',  ['coffeelint','jslint'] gulp.task  'coffeelint',  ()  -­‐>    gulp.src(files.coffee)        .pipe(coffeelint())        .pipe(coffeelint.reporter()) gulp.task  'jslint',  ()  -­‐>    gulp.src(files.js.app)        .pipe(jslint(config.jshint))        .pipe(jslint.reporter(jslintReporter))     gulp.task  'jade',  ()  -­‐>    gulp.src(files.jade)        .pipe(jade(config.jade))        .pipe(gulp.dest('./generated'))        .pipe(gulp.dest('./dist')) gulp.task  'jsApp',  ()  -­‐>    es.concat(            gulp.src(files.coffee).pipe(coffee()),            gulp.src(files.js.app)        ).pipe(concat(output.jsApp))        .pipe(gulp.dest('./generated'))        .pipe(uglify())        .pipe(gulp.dest('./dist'))     gulp.task  'jsVendor',  ['install'],  ()  -­‐>    gulp.src(files.js.vendor)        .pipe(concat(output.jsVendor))        .pipe(gulp.dest('./generated'))        .pipe(gulp.dest('./dist'))     gulp.task  'js',  ['jsApp','jsVendor']     gulp.task  'css',  ['install'],  ()  -­‐>    gulp.src(files.less.app)        .pipe(plumber())        .pipe(less())        .pipe(concat(output.css))        .pipe(gulp.dest('./generated'))        .pipe(cssmin())        .pipe(gulp.dest('./dist'))     gulp.task  'clean',  ()  -­‐>    gulp.src(['./dist','./generated',  bowerDirectory()])        .pipe(clean()) gulp.task  'copy',  ['install'],  ()  -­‐>    es.concat(        gulp.src(files.img)            .pipe(gulp.dest('./generated/img'))            .pipe(gulp.dest('./dist/img')),        gulp.src(files.static)            .pipe(gulp.dest('./generated/'))            .pipe(gulp.dest('./dist/')),        gulp.src(files.webfonts)            .pipe(gulp.dest('./generated/fonts'))            .pipe(gulp.dest('./dist/fonts'))    ) gulp.task  'watch',  ()  -­‐>    gulp.watch  files.coffee,            ['coffeelint','jsApp']    gulp.watch  files.js.app,            ['jslint','jsApp']    gulp.watch  files.js.vendor,      ['jsVendor']    gulp.watch  files.jade.pages,    ['jade']    gulp.watch  files.less.watch,    ['css']    gulp.watch  [files.img,  files.webfonts,  files.static],    ['copy']     gulp.task  'server',  ['build'],  connect.server(config.server) bowerDirectory  =  ()  -­‐>    bowerpath  =  path.join(process.cwd(),  ".bowerrc")    bowerrc  =  fs.readFileSync(bowerpath)  unless  !fs.existsSync  bowerpath      bowerConfig  =  JSON.parse(bowerrc)  if  bowerrc?    bowerConfig?.directory  ||  "vendor/components"
  • 87. bower            =  require  'gulp-­‐bower' coffeelint  =  require  'gulp-­‐coffeelint' clean            =  require  'gulp-­‐clean' coffee          =  require  'gulp-­‐coffee' concat          =  require  'gulp-­‐concat' connect        =  require  'gulp-­‐connect'    #          copy  included  via  .dest cssmin          =  require  'gulp-­‐minify-­‐css' jade              =  require  'gulp-­‐jade' jslint          =  require  'gulp-­‐jshint' less              =  require  'gulp-­‐less' uglify          =  require  'gulp-­‐uglify'    #        watch  included  via  .watch
  • 88.  git  co  grunt  time  grunt  >  /dev/null real  0m5.114s user  0m4.802s sys    0m0.214s
  • 89.  git  co  grunt  time  grunt  >  /dev/null real  0m5.114s user  0m4.802s sys    0m0.214s  git  co  gulp  time  gulp  >  /dev/null real  0m2.811s user  0m2.601s sys    0m0.241s
  • 91. learn more  gulpjs.com  gulpjs/gulp  gulpjs
  • 92. demo code  queenseight.com  aranasoft/queenseight  git checkout grunt  git checkout gulp