Dethroning Grunt: Simple and Effective Builds with gulp.js

1318668b99b2d5a3900f3f7758763a69?s=47 Jay Harris
February 10, 2014

Dethroning Grunt: Simple and Effective Builds with gulp.js

Grunt is king. It is the ubiquitous task runner used for most nodejs projects and has quickly expanded to conquer other software ecosystems. However, its kingdom is vulnerable. Grunt does not align well with many nodejs paradigms and is notorious for its harsh learning curve. Meet Gulp, the challenger in the taskrunner revolution. Gulp’s easy configuration produces an easy learning curve, and its alignment with nodejs paradigms eliminates the friction. Grab your ticket, your foam finger, and your team-colored face paint and witness the battle, the revolution, and the crowning of Gulp.

Author:
Jay Harris
Problem Solver | Arana Software
jay@aranasoft.com | www.aranasoft.com
www.twitter.com/jayharris

1318668b99b2d5a3900f3f7758763a69?s=128

Jay Harris

February 10, 2014
Tweet

Transcript

  1. #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
  2. what is a taskrunner?

  3. None
  4. that is a lot of things to do task runners

    simplify to one command
  5. gulp   grunt

  6. focusing on five tasks

  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');
  9. //  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');
  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. 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
  12. 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-­‐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
  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. None
  15. .src(globs[, options])

  16. .dest(path)

  17. .task(name[, deps], fn)

  18. .watch(glob [, options], tasks)

  19. .pipe(destination)

  20.  level up grok streams

  21.    a task: read, concatenate, write

  22.         additional steps

    add overhead
  23.         extraneous disk

    I/O
  24.          

      extraneous configuration
  25.      streams pipe from task to

    task
  26.        additional steps without

    overhead
  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');
  30. gulp.src('app/js/**/*.coffee') 

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

      
  37.  level up dependencies

  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 
  42. our five tasks

  43. ┌ │ ┤ │ └ ┬ │ └ ─ expected

    dependency tree
  44. ┌ │ ├ │ ┼ │ ├ │ └ actual

    tree
  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')); });     
  55.  level up using coffee

  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 

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

  60.  level up merging streams

  61.       

  62.         

  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  
  77.  level up master class

  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  
  83.  level up comparison

  84. 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
  85. 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
  86. 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');
  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  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
  90.   

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

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

     git checkout gulp
  93. npm install gulp N E X T S T E

    P S
  94. dethrone grunt

  95. jay@aranasoft.com @ j a y h a r r i

    s # d e t h r o n i n g G r u n t
  96. 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