Upgrade to Pro — share decks privately, control downloads, hide ads and more …

grunt.js - automate all the things!1!!

grunt.js - automate all the things!1!!

Talk from the second stahlstadt.js meetup

http://www.meetup.com/stahlstadt-js/events/143609572/

Clemens Müller

December 11, 2013
Tweet

More Decks by Clemens Müller

Other Decks in Programming

Transcript

  1. SE PROBLEM • remove debug statements like console.log • concatenate

    and minify JS files • run tests, JSHint • compile SASS, minify images, sprites, … • …
  2. APPROACHES manually • use existing infrastructure, like Rails Asset Pipeline,

    … • Makefile, Shell Scripts • Ant, Maven, Jake, Rake, …
  3. APPROACHES manually • use existing infrastructure, like Rails Asset Pipeline,

    … • Makefile, Shell Scripts • Ant, Maven, Jake, Rake, … • Grunt
  4. • The JavaScript Task Runner • node.js • Configuration over

    scripting • Plugins, which are mostly wrappers around existing libs WHAT IS GRUNT?
  5. npm install grunt --save-dev 1 { 2 "name": "stahlstadtjs_grunt", 3

    "version": "0.0.1", 4 "author": "Thomas Brezina", 5 "devDependencies": { 6 "grunt": "~0.4.2" 7 } 8 }
  6. // Gruntfile.js 1 module.exports = function(grunt) { 2 } $

    grunt Warning: Task "default" not found. Use --force to continue. Aborted due to warnings.
  7. // src/app.js 1 App = function() {} 2 App.prototype.greet =

    function(name) { 3 console.log("hello " + name) 4 }
  8. JSHINT npm install grunt-contrib-jshint --save-dev 1 { 2 "name": "stahlstadtjs_grunt",

    3 "version": "0.0.1", 4 "author": "Thomas Brezina", 5 "devDependencies": { 6 "grunt": "~0.4.2", 7 "grunt-contrib-jshint": "~0.7.2" 8 } 9 }
  9. 1 module.exports = function(grunt) { 2 grunt.initConfig({ 3 jshint: {

    4 all: ["src/*.js"] 5 } 6 }); 7 8 grunt.loadNpmTask("grunt-contrib-jshint"); 9 10 grunt.registerTask("default", ["jshint"]); 11 } JSHINT
  10. 1 module.exports = function(grunt) { 2 grunt.initConfig({ 3 jshint: {

    4 all: ["src/*.js"] 5 } 6 }); 7 8 grunt.loadNpmTask("grunt-contrib-jshint"); 9 10 grunt.registerTask("default", ["jshint"]); 11 } JSHINT
  11. JSHINT $ grunt Running "jshint:all" (jshint) task Linting src/app.js ...ERROR

    [L3:C31] W033: Missing semicolon. console.log("hello " + name) Warning: Task "jshint:all" failed. Use --force to continue. Aborted due to warnings.
  12. // src/app.js 1 App = function() {} 2 App.prototype.greet =

    function(name) { 3 console.log("hello " + name) 4 }
  13. // src/app.js 1 App = function() {} 2 App.prototype.greet =

    function(name) { 3 console.log("hello " + name) ; 4 }
  14. JSHINT $ grunt jshint Running "jshint:all" (jshint) task >> 1

    file lint free. Done, without errors. ProTip™ http://jslinterrors.com/
  15. UGLIFY npm install grunt-contrib-uglify --save-dev 1 { 2 "name": "stahlstadtjs_grunt",

    3 "version": "0.0.1", 4 "author": "Thomas Brezina", 5 "devDependencies": { 6 "grunt": "~0.4.2", 7 "grunt-contrib-jshint": "~0.7.2", 8 "grunt-contrib-uglify": "~0.2.7" 9 } 10 }
  16. 1 module.exports = function(grunt) { 2 grunt.initConfig({ 3 jshint: {

    }, 4 uglify: { 5 debug: { 6 src: "src/app.js", 7 dest: "dist/app.js", 8 options: { beautify: true } 9 }, 10 minified: { 11 src: "src/app.js", 12 dest: "dist/app.min.js", 13 options: { mangle: true, compress: true } 14 } 15 } 16 }); 17 18 grunt.registerTask("default", ["jshint", "uglify"]); 19 20 grunt.loadNpmTasks("grunt-contrib-uglify"); 21 grunt.loadNpmTasks("grunt-contrib-jshint"); 22 }
  17. 1 module.exports = function(grunt) { 2 grunt.initConfig({ 3 jshint: {

    }, 4 uglify: { 5 debug: { 6 src: "src/app.js", 7 dest: "dist/app.js", 8 options: { beautify: true } 9 }, 10 minified: { 11 src: "src/app.js", 12 dest: "dist/app.min.js", 13 options: { mangle: true, compress: true } 14 } 15 } 16 }); 17 18 grunt.registerTask("default", ["jshint", "uglify"]); 19 20 grunt.loadNpmTasks("grunt-contrib-uglify"); 21 grunt.loadNpmTasks("grunt-contrib-jshint"); 22 }
  18. UGLIFY $ grunt uglify:minified Running "uglify: minified" (uglify) task File

    "dist/app.min.js" created. Done, without errors.
  19. UGLIFY $ grunt uglify Running "uglify:debug" (uglify) task File "dist/app.js"

    created. Running "uglify:minified" (uglify) task File "dist/app.min.js" created. Done, without errors.
  20. UGLIFY . !"" Gruntfile.js !"" package.json #"" dist $ !""

    app.js $ #"" app.min.js #"" src #"" app.js
  21. 1 module.exports = function(grunt) { 2 grunt.initConfig({ 3 pkg: grunt.file.readJSON("package.json"),

    4 jshint: {}, 5 uglify: { 6 debug: { 7 src: "src/app.js", 8 dest: "dist/app-<%= pkg.version %>.js", 9 options: { beautify: true } 10 }, 11 minified: { 12 src: "src/app.js", 13 dest: "dist/app-<%= pkg.version %>.min.js", 14 options: { mangle: true, compress: true } 15 } 16 } 17 }); 18 19 grunt.registerTask("default", ["jshint", "uglify"]); 20 21 grunt.loadNpmTasks("grunt-contrib-uglify"); 22 grunt.loadNpmTasks("grunt-contrib-jshint"); 23 }
  22. 1 module.exports = function(grunt) { 2 grunt.initConfig({ 3 pkg: grunt.file.readJSON("package.json"),

    4 jshint: {}, 5 uglify: { 6 debug: { 7 src: "src/app.js", 8 dest: "dist/app-<%= pkg.version %>.js", 9 options: { beautify: true } 10 }, 11 minified: { 12 src: "src/app.js", 13 dest: "dist/app-<%= pkg.version %>.min.js", 14 options: { mangle: true, compress: true } 15 } 16 } 17 }); 18 19 grunt.registerTask("default", ["jshint", "uglify"]); 20 21 grunt.loadNpmTasks("grunt-contrib-uglify"); 22 grunt.loadNpmTasks("grunt-contrib-jshint"); 23 }
  23. UGLIFY $ grunt uglify Running "uglify:debug" (uglify) task File "dist/app-0.0.1.js"

    created. Running "uglify:minified" (uglify) task File "dist/app-0.0.1.min.js" created. Done, without errors.
  24. UGLIFY . !"" Gruntfile.js !"" package.json #"" dist $ !""

    app-0.0.1.js $ !"" app-0.0.1.min.js $ !"" app.js $ #"" app.min.js #"" src #"" app.js
  25. CLEAN npm install grunt-contrib-clean --save-dev 1 { 2 "name": "stahlstadtjs_grunt",

    3 "version": "0.0.1", 4 "author": "Thomas Brezina", 5 "devDependencies": { 6 "gruntnt": "~0.4.2", 7 "grunt-contrib-jshint": "~0.7.2", 8 "grunt-contrib-uglify": "~0.2.7" 9 "grunt-contrib-clean": "~0.5.0" 10 } 11 }
  26. CLEAN 1 module.exports = function(grunt) { 2 grunt.initConfig({ 3 pkg:

    …, 4 jshint: { … }, 5 uglify: { … }, 6 clean: ["dist"] 7 }); 8 9 grunt.registerTask("default", ["jshint", "clean", "uglify"]); 10 11 grunt.loadNpmTasks("grunt-contrib-clean"); 12 grunt.loadNpmTasks("grunt-contrib-uglify"); 13 grunt.loadNpmTasks("grunt-contrib-jshint"); 14 }
  27. ALLE 3 ZUSAMMEN $ grunt Running "jshint:all" (jshint) task >>

    1 file lint free. Running "clean:0" (clean) task Cleaning dist...OK Running "uglify:debug" (uglify) task File "dist/app-0.0.1.js" created. Running "uglify:minified" (uglify) task File "dist/app-0.0.1.min.js" created. Done, without errors.
  28. MOAR PLUGINS • currently 1931 plugins • almost all start

    with grunt- • grunt-contrib-* are official plugins supported by core team • tip top README’s
  29. LOAD-GRUNT-TASKS 1 module.exports = function(grunt) { 2 grunt.loadNpmTasks("grunt-shell"); 3 grunt.loadNpmTasks("grunt-sass");

    4 grunt.loadNpmTasks("grunt-recess"); 5 grunt.loadNpmTasks("grunt-sizediff"); 6 grunt.loadNpmTasks("grunt-svgmin"); 7 grunt.loadNpmTasks("grunt-styl"); 8 grunt.loadNpmTasks("grunt-php"); 9 grunt.loadNpmTasks("grunt-eslint"); 10 grunt.loadNpmTasks("grunt-concurrent"); 11 grunt.loadNpmTasks("grunt-bower-requirejs"); 12 }
  30. LOAD-GRUNT-TASKS 1 module.exports = function(grunt) { 2 // load all

    grunt tasks matching the `grunt-*` pattern 3 require("load-grunt-tasks")(grunt); 4 }
  31. GRUNT-CONTRIB-CONCAT 1 grunt.initConfig({ 2 concat: { 3 dist: { 4

    src: ["src/main.js", "src/**/*.js"], 5 dest: "dist/app.js" 6 } 7 } 8 });
  32. GRUNT-NEUTER // a.js require("b"); new B(); // b.js require("c"); B

    = function() { new C(); } // c.js C = function() {} // d.js D = function() {}
  33. GRUNT-NEUTER // a.js require("b"); new B(); // b.js require("c"); B

    = function() { new C(); } // c.js C = function() {} // d.js D = function() {} // Gruntfile.js neuter: { src: ["a.js"], dest: "dist/app.js" } +
  34. GRUNT-NEUTER // a.js require("b"); new B(); // b.js require("c"); B

    = function() { new C(); } // c.js C = function() {} // d.js D = function() {} // dist/app.js C = function() {} B = function() { new C(); } new B(); // Gruntfile.js neuter: { src: ["a.js"], dest: "dist/app.js" } + =
  35. GRUNT-NEUTER // a.js require("b"); new B(); // b.js require("c"); B

    = function() { new C(); } // c.js C = function() {} // d.js D = function() {} // dist/app.js C = function() {} B = function() { new C(); } new B(); D = function() {} // Gruntfile.js neuter: { src: ["a.js", “*.js”], dest: "dist/app.js" } + =
  36. GRUNT-CONTRIB-WATCH grunt.initConfig({ watch: { gruntfile: { files: "Gruntfile.js", tasks: ["jshint:gruntfile"],

    }, src: { files: ["lib/*.js", "css/**/*.scss", "!lib/dontwatch.js"], tasks: ["default"], } } });
  37. GRUNT-CONTRIB-CONNECT grunt.initConfig({ connect: { server: { options: { port: 8000,

    base: "dist" } }, test: { options: { port: 8001, base: "test" } } } });
  38. OTHER USEFUL PLUGINS • grunt-s3 • grunt-release • grunt-parallel, grunt-newer

    • grunt-remove-logging • mincss, uncss, csslint • imagemin, spritesmith • responsive-images • qunit, mocha, jasmine, CasperJS, SlimerJS, ... • http://gruntjs.com/plugins
  39. CUSTOM TASKS 1 module.exports = function(grunt) { 2 grunt.initConfig({ 3

    watch: { ... }, 4 connect: { 5 test: { ... } 6 } 7 }); 8 9 grunt.registerTask("test", ["connect:test", "watch"]); 10 }
  40. WRITING YOUR OWN TASK 1 module.exports = function(grunt) { 2

    grunt.registerTask("random", "a random number", function() { 3 var math = require("fast-random-number-NPM-module"); 4 grunt.log.writeln( math.random() ); 5 }); 6 }
  41. WRITING YOUR OWN TASK 1 module.exports = function(grunt) { 2

    grunt.registerTask("random", "a random number", function() { 3 var math = require("fast-random-number-NPM-module"); 4 grunt.log.writeln( math.random() ); 5 }); 6 }
  42. 1 module.exports = function(grunt) { 2 // load needed grunt

    tasks from package.json 3 grunt.loadNpmTasks("grunt-contrib-clean"); 4 ...
  43. 1 module.exports = function(grunt) { 2 // load needed grunt

    tasks from package.json 3 grunt.loadNpmTasks("grunt-contrib-clean"); 4 ... 5 6 // configure the tasks 7 grunt.initConfig({ 8 jshint: { ... }, 9 ... 10 });
  44. 1 module.exports = function(grunt) { 2 // load needed grunt

    tasks from package.json 3 grunt.loadNpmTasks("grunt-contrib-clean"); 4 ... 5 6 // configure the tasks 7 grunt.initConfig({ 8 jshint: { ... }, 9 ... 10 }); 11 12 // specify default and custom tasks 13 grunt.registerTask("default", ["dist"]); 14 grunt.registerTask("dist", ["clean", "uglify"]); 15 grunt.registerTask("test", ["watch", "connect"]); 16 }
  45. 1 module.exports = function(grunt) { 2 // load needed grunt

    tasks from package.json 3 grunt.loadNpmTasks("grunt-contrib-clean"); 4 ... 5 6 // configure the tasks 7 grunt.initConfig({ 8 jshint: { ... }, 9 ... 10 }); 11 12 // specify default and custom tasks 13 grunt.registerTask("default", ["dist"]); 14 grunt.registerTask("dist", ["clean", "uglify"]); 15 grunt.registerTask("test", ["watch", "connect"]); 16 }
  46. 0.5.0 • split configurations since Gruntfile can get big #989

    • load-grunt-tasks, load-grunt-config • interactive CLI #949 • Make task file compilation more intelligent #927 • …
  47. POSSIBLE NEXT TALK’S • by YOU?!!!! • split options for

    tasks into separate files • more examples • live reload, across browsers • requirejs, grunt-neuter • grunt & yeoman & bower • project scaffolding • grunt advanced patterns • tips’n’tricks • grunt in the wild