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

PDF
Introducing Assetic: Asset Management for PHP 5.3
PDF
20130528 solution linux_frousseau_nopain_webdev
PDF
AnkaraJUG Kasım 2012 - PrimeFaces
PDF
Fisl 11 - Dicas de Desenvolvimento Web com Ruby
PPTX
How to Build SPA with Vue Router 2.0
PPT
Gradle: The Build system you have been waiting for
PDF
WebGUI Developers Workshop
PDF
Web Frontend development: tools and good practices to (re)organize the chaos
Introducing Assetic: Asset Management for PHP 5.3
20130528 solution linux_frousseau_nopain_webdev
AnkaraJUG Kasım 2012 - PrimeFaces
Fisl 11 - Dicas de Desenvolvimento Web com Ruby
How to Build SPA with Vue Router 2.0
Gradle: The Build system you have been waiting for
WebGUI Developers Workshop
Web Frontend development: tools and good practices to (re)organize the chaos

What's hot (20)

PDF
WebcampZG - Rails 4
PDF
Keeping the frontend under control with Symfony and Webpack
PPTX
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
 
PPTX
Things Your Mother Didnt Tell You About Bundle Configurations - Symfony Live…
 
PPT
Creating the interfaces of the future with the APIs of today
PPTX
Angular Tutorial Freshers and Experienced
PDF
Laravel 로 배우는 서버사이드 #5
PDF
FamilySearch Reference Client
PDF
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
PDF
WCLA12 JavaScript
PDF
WordPress Admin UI - Future Proofing Your Admin Pages
PDF
Symfony tips and tricks
PDF
Rails 3.1 Asset Pipeline
PDF
Introduction to Vue.js
PDF
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
PDF
YUI on the go
KEY
Deploying
PDF
Sane Async Patterns
PDF
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
PDF
Realize mais com HTML 5 e CSS 3 - 16 EDTED - RJ
WebcampZG - Rails 4
Keeping the frontend under control with Symfony and Webpack
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
 
Things Your Mother Didnt Tell You About Bundle Configurations - Symfony Live…
 
Creating the interfaces of the future with the APIs of today
Angular Tutorial Freshers and Experienced
Laravel 로 배우는 서버사이드 #5
FamilySearch Reference Client
Symfony Guard Authentication: Fun with API Token, Social Login, JWT and more
WCLA12 JavaScript
WordPress Admin UI - Future Proofing Your Admin Pages
Symfony tips and tricks
Rails 3.1 Asset Pipeline
Introduction to Vue.js
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
YUI on the go
Deploying
Sane Async Patterns
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Realize mais com HTML 5 e CSS 3 - 16 EDTED - RJ
Ad

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

PDF
Rails 3: Dashing to the Finish
PDF
Burn down the silos! Helping dev and ops gel on high availability websites
PDF
Having Fun with Play
PDF
Rails 3 overview
PDF
Javascript is your (Auto)mate
PDF
Building and deploying React applications
PDF
Head First Zend Framework - Part 1 Project & Application
PPTX
Single Page JavaScript WebApps... A Gradle Story
PDF
Deploying configurable frontend web application containers
PPTX
Nodejs.meetup
PDF
Refresh Austin - Intro to Dexy
KEY
[Coscup 2012] JavascriptMVC
PDF
Django at the Disco
PDF
QConSP 2015 - Dicas de Performance para Aplicações Web
PDF
实战Ecos
PDF
以Vue開發電子商務網站
架構與眉角
PPT
Maven
PPT
PPTX
Google app engine by example
PDF
What makes me "Grunt"?
Rails 3: Dashing to the Finish
Burn down the silos! Helping dev and ops gel on high availability websites
Having Fun with Play
Rails 3 overview
Javascript is your (Auto)mate
Building and deploying React applications
Head First Zend Framework - Part 1 Project & Application
Single Page JavaScript WebApps... A Gradle Story
Deploying configurable frontend web application containers
Nodejs.meetup
Refresh Austin - Intro to Dexy
[Coscup 2012] JavascriptMVC
Django at the Disco
QConSP 2015 - Dicas de Performance para Aplicações Web
实战Ecos
以Vue開發電子商務網站
架構與眉角
Maven
Google app engine by example
What makes me "Grunt"?
Ad

More from Jay Harris (7)

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

Recently uploaded (20)

PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PPTX
Cloud computing and distributed systems.
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
PDF
cuic standard and advanced reporting.pdf
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Approach and Philosophy of On baking technology
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Empathic Computing: Creating Shared Understanding
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
GamePlan Trading System Review: Professional Trader's Honest Take
PDF
Advanced Soft Computing BINUS July 2025.pdf
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Cloud computing and distributed systems.
Review of recent advances in non-invasive hemoglobin estimation
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
CIFDAQ's Market Insight: SEC Turns Pro Crypto
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
cuic standard and advanced reporting.pdf
“AI and Expert System Decision Support & Business Intelligence Systems”
The Rise and Fall of 3GPP – Time for a Sabbatical?
Approach and Philosophy of On baking technology
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
NewMind AI Weekly Chronicles - August'25 Week I
Chapter 3 Spatial Domain Image Processing.pdf
Empathic Computing: Creating Shared Understanding
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
GamePlan Trading System Review: Professional Trader's Honest Take
Advanced Soft Computing BINUS July 2025.pdf
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows

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-­‐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"]
  • 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