Slide 1

Slide 1 text

#dethroningGrunt S I M P L E A N D E F F E C T I V E B U I L D S W I T H G U L P. J S @ j a y h a r r i s

Slide 2

Slide 2 text

what is a taskrunner?

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

that is a lot of things to do task runners simplify to one command

Slide 5

Slide 5 text

gulp   grunt

Slide 6

Slide 6 text

focusing on five tasks

Slide 7

Slide 7 text

demo code  queenseight.com  aranasoft/queenseight

Slide 8

Slide 8 text

//  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');

Slide 9

Slide 9 text

//  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');

Slide 10

Slide 10 text

//  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');

Slide 11

Slide 11 text

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  %>"        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"                }]        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"]            css:                files:  ["<%=  files.css.vendor  %>",  "<%=  files.css.app  %>"]                tasks:  ["concat:css"]            images:                files:  ["app/img/**/*.*",  "vendor/img/**/*.*"]                tasks:  ["copy:imagesDev"]                            jade:                files:  ["<%=  files.jade.pageRoot  %>/<%=  files.jade.pages  %>"]                tasks:  ["jade:dev"]            js:                files:  ["<%=  files.js.vendor  %>",  "<%=  files.js.app  %>"]                tasks:  ["concat:js"]            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" gruntfile.coffee

Slide 12

Slide 12 text

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  %>"        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"                }]        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"]            css:                files:  ["<%=  files.css.vendor  %>",  "<%=  files.css.app  %>"]                tasks:  ["concat:css"]            images:                files:  ["app/img/**/*.*",  "vendor/img/**/*.*"]                tasks:  ["copy:imagesDev"]                            jade:                files:  ["<%=  files.jade.pageRoot  %>/<%=  files.jade.pages  %>"]                tasks:  ["jade:dev"]            js:                files:  ["<%=  files.js.vendor  %>",  "<%=  files.js.app  %>"]                tasks:  ["concat:js"]            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-­‐awes                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(bow    bowerConfig?.directory  ||  "vendor/components" gruntfile.coffee ├──  css │      ├──  app.less │      ├──  mixins.less │      └──  variables.less ├──  img │      ├──  arana-­‐software.png │      ├──  arana-­‐[email protected] │      ├──  banner-­‐lg.png │      ├──  banner-­‐md.png │      ├──  banner-­‐sm.png │      ├──  crown.png │      ├──  [email protected] │      ├──  [email protected] │      └──  wood.png ├──  js │      ├──  app.coffee │      ├──  controllers │      │      └──  board.coffee │      ├──  directives │      │      └──  board.js │      └──  templates │              └──  board.coffee ├──  pages │      └──  index.jade └──  static        └──  favicon.ico

Slide 13

Slide 13 text

'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;

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

.src(globs[, options])

Slide 16

Slide 16 text

.dest(path)

Slide 17

Slide 17 text

.task(name[, deps], fn)

Slide 18

Slide 18 text

.watch(glob [, options], tasks)

Slide 19

Slide 19 text

.pipe(destination)

Slide 20

Slide 20 text

 level up grok streams

Slide 21

Slide 21 text

   a task: read, concatenate, write

Slide 22

Slide 22 text

        additional steps add overhead

Slide 23

Slide 23 text

        extraneous disk I/O

Slide 24

Slide 24 text

            extraneous configuration

Slide 25

Slide 25 text

     streams pipe from task to task

Slide 26

Slide 26 text

       additional steps without overhead

Slide 27

Slide 27 text

 level up the first gulp

Slide 28

Slide 28 text

npm install -g gulp npm install -D gulp touch gulpfile.js 

Slide 29

Slide 29 text

//gulpfile.js var  gulp      =  require('gulp'); var  coffee  =  require('gulp-­‐coffee'); var  concat  =  require('gulp-­‐concat'); var  uglify  =  require('gulp-­‐uglify');

Slide 30

Slide 30 text

gulp.src('app/js/**/*.coffee') 

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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')); });

Slide 35

Slide 35 text

gulp.task('watch',  function()  { gulp.watch('app/js/**/*.coffee',                      ['coffee']); }); 

Slide 36

Slide 36 text

gulp.task('default',          ['coffee','watch']);       

Slide 37

Slide 37 text

 level up dependencies

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

our five tasks

Slide 43

Slide 43 text

┌ │ ┤ │ └ ┬ │ └ ─ expected dependency tree

Slide 44

Slide 44 text

┌ │ ├ │ ┼ │ ├ │ └ actual tree

Slide 45

Slide 45 text

gulp.task('stuff',  function()  {    doStuff();    });

Slide 46

Slide 46 text

//  Option  1:  Callback gulp.task('stuff',  function(done)  {    doSyncStuff()    done(err); });

Slide 47

Slide 47 text

var  Q  =  require('q'); //  Option  2:  Promise gulp.task('stuff',  function()  {    var  deferred  =  Q.defer();    doAsyncStuff(deferred.resolve);    return  deferred.promise; });

Slide 48

Slide 48 text

//  Option  3:  Return  stream gulp.task('stuff',  function()  {    var  stream  =  doStreamStuff();    return  stream; });

Slide 49

Slide 49 text

gulp.task  'stuff',  ()  -­‐>    doStreamStuff()

Slide 50

Slide 50 text

#  Get  return  stream  for  free! gulp.task  'stuff',  ()  -­‐>    doStreamStuff() gulp.task('stuff',  function()  {    return  doStreamStuff();    });

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

 level up using coffee

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

gulp --require coffee-script/register 

Slide 59

Slide 59 text

//gulpfile.js require('coffee-­‐script'); require('./gulpfile.coffee'); gulp  more gulpfile.js 

Slide 60

Slide 60 text

 level up merging streams

Slide 61

Slide 61 text

      

Slide 62

Slide 62 text

        

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

evtstream  =  require  'event-­‐stream'      #  and/or streamq      =  require  'streamqueue'

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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')      

Slide 67

Slide 67 text

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')      

Slide 68

Slide 68 text

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')      

Slide 69

Slide 69 text

 level up error handling

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

[gulp]  Running  'css'... events.js:72                throw  er;  //  Unhandled  'error'                            ^ Error:  missing  opening  `{`  in  file  ./c   

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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')      

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

[gulp]  Running  'css'... [gulp]  Error  in  plugin  'gulp-­‐less':    missing  opening  `{`  in  file  app.less [gulp]  Finished  'css'  in  21  ms  

Slide 77

Slide 77 text

 level up master class

Slide 78

Slide 78 text

gutil  =  require  'gulp-­‐util' 

Slide 79

Slide 79 text

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')       

Slide 80

Slide 80 text

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')       

Slide 81

Slide 81 text

gulp  -­‐-­‐port=8000  -­‐-­‐dest=prod gutil.env.port  ===  8000 gutil.env.dest  ===  'prod'  

Slide 82

Slide 82 text

 echo  Total  Files:  $(    \  find  .  -­‐type  f  -­‐print\  |  wc  -­‐l) Total  Files:  1000 echo  watch  will  vomit  

Slide 83

Slide 83 text

 level up comparison

Slide 84

Slide 84 text

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  %>"        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"                }]        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"]            css:                files:  ["<%=  files.css.vendor  %>",  "<%=  files.css.app  %>"]                tasks:  ["concat:css"]            images:                files:  ["app/img/**/*.*",  "vendor/img/**/*.*"]                tasks:  ["copy:imagesDev"]                            jade:                files:  ["<%=  files.jade.pageRoot  %>/<%=  files.jade.pages  %>"]                tasks:  ["jade:dev"]            js:                files:  ["<%=  files.js.vendor  %>",  "<%=  files.js.app  %>"]                tasks:  ["concat:js"]            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" gruntfile.coffee

Slide 85

Slide 85 text

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" gulpfile.coffee

Slide 86

Slide 86 text

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');

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

  git  co  grunt time  grunt  >  /dev/null real  0m5.114s user  0m4.802s sys    0m0.214s

Slide 89

Slide 89 text

git  co  gulp time  gulp  >  /dev/null real  0m2.811s user  0m2.601s sys    0m0.241s     git  co  grunt time  grunt  >  /dev/null real  0m5.114s user  0m4.802s sys    0m0.214s

Slide 90

Slide 90 text

  

Slide 91

Slide 91 text

learn more  gulpjs.com  gulpjs/gulp  gulpjs

Slide 92

Slide 92 text

demo code  queenseight.com  aranasoft/queenseight  git checkout grunt  git checkout gulp

Slide 93

Slide 93 text

npm install gulp N E X T S T E P S

Slide 94

Slide 94 text

dethrone grunt

Slide 95

Slide 95 text

[email protected] @ j a y h a r r i s # d e t h r o n i n g G r u n t

Slide 96

Slide 96 text

thank you @ j a y h a r r i s # d e t h r o n i n g G r u n t