SlideShare una empresa de Scribd logo
1 de 96
@jayharris

#dethroningGrunt
SIMPLE AND EFFECTIVE BUILDS
W I T H G U L P. J S
what is a
taskrunner?
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;
.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

Más contenido relacionado

La actualidad más candente

WebcampZG - Rails 4
WebcampZG - Rails 4WebcampZG - Rails 4
WebcampZG - Rails 4
shnikola
 
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
Things Your Mother Didn't Tell You About Bundle Configurations - Symfony Live...
D
 
Things Your Mother Didnt Tell You About Bundle Configurations - Symfony Live…
Things Your Mother Didnt Tell You About Bundle Configurations - Symfony Live…Things Your Mother Didnt Tell You About Bundle Configurations - Symfony Live…
Things Your Mother Didnt Tell You About Bundle Configurations - Symfony Live…
D
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of today
gerbille
 
WordPress Admin UI - Future Proofing Your Admin Pages
WordPress Admin UI - Future Proofing Your Admin PagesWordPress Admin UI - Future Proofing Your Admin Pages
WordPress Admin UI - Future Proofing Your Admin Pages
Brandon Dove
 
Deploying
DeployingDeploying
Deploying
soon
 

La actualidad más candente (20)

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

Similar a Dethroning Grunt: Simple and Effective Builds with gulp.js

Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
Yehuda Katz
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
Yehuda Katz
 
Head First Zend Framework - Part 1 Project & Application
Head First Zend Framework - Part 1 Project & ApplicationHead First Zend Framework - Part 1 Project & Application
Head First Zend Framework - Part 1 Project & Application
Jace Ju
 

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

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

Más de Jay Harris

Más de Jay Harris (7)

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

Último

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 

Último (20)

Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 

Dethroning Grunt: Simple and Effective Builds with gulp.js

  • 3.
  • 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;
  • 14.
  • 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