Automated Front-end Development with Grunt

210a2116d2266c84d155f1d8a14f31ef?s=47 FEVR
October 27, 2014

Automated Front-end Development with Grunt

Preprocessors, minification, image enhancement, and then testing, deployment .. How many tasks we do every day? And how many different tools we have to use along our workflow?
Marco Solazzi gives us the solution, strictly javascript based, called Gruntjs

210a2116d2266c84d155f1d8a14f31ef?s=128

FEVR

October 27, 2014
Tweet

Transcript

  1. Automated Front-end Development with Grunt

  2. About me ▪Senior Front-end Developer @ Intesys ▪Articolista JavaScript @

    HTML.it ▪Co-founder Frontenders Verona
  3. About me ▪Senior Front-end Developer @ AQuést ▪Articolista JavaScript @

    HTML.it ▪Co-founder Frontenders Verona
  4. ▪Ottimizzare il workflow ▪Ottimizzare il codice Front-end automation

  5. Ottimizzare il workflow

  6. Back in the ‘90...

  7. Not just HTML & CSS

  8. Not just HTML & CSS

  9. None
  10. Ottimizzare il codice

  11. Performance Golden Rule: “80-90% of the end-user response time is

    spent on the frontend.” - Steve Souders (http://www.stevesouders.com/blog/2012/02/10/the-performance-golden-rule/)
  12. http://www.stevesouders.com/blog/2012/02/10/the-performance-golden-rule/ TOP 10 Alexa websites Febbraio 2012

  13. “Users expect pages to load in two seconds — and

    after three seconds, up to 40 percent will simply leave.” - Lara Hogan (http://alistapart.com/article/improving-ux-through-front-end-performance)
  14. Performance tips ▪Ridurre le richieste HTTP ▪Minificare JavaScript e CSS

    e comprimerli (gzip) ▪Ottimizzare le immagini ▪Resource hashing + Expires o Cache-Control Header ▪Utilizzare sprite https://developers.google.com/speed/docs/best-practices/rules_intro
  15. Do it by hand?!?!

  16. None
  17. Tools matter

  18. If your "build process" is the F5 key, you have

    a problem. - Jeff Atwood (http://www.codinghorror.com/blog/2007/10/the-f5-key-is-not-a-build-process.html)
  19. Some fair options

  20. Front-end friendly?

  21. Grunt to the rescue!

  22. Grunt cosa? ▪JavaScript based task runner ▪Creato da Ben Alman

    nel 2012 ▪49 Contributors ▪8500+ stars su GitHub
  23. Vantaggi ▪Scritto in Nodejs ▪Installabile come modulo npm ▪Configurazione in

    formato JSON ▪Estendibile con moduli JavaScript ▪3500+ plugins (http://gruntjs.com/plugins)
  24. Built with Grunt... ▪Adobe Brackets ▪jQuery ▪Tweetdeck ▪Bootstrap ▪Modernizr ▪Opera

    GitHub Projects ▪WordPress Build Process ▪Ghost
  25. Getting started...

  26. npm install --save-dev grunt-contrib-concat grunt-contrib-uglifyjs # concatenazione di file e

    minificazione js con uglifyjs Configurazione di base sudo npm install -g grunt-cli # -g installa globalmente 1) Installazione runtime cd grunt-demo npm init # reply to prompts... 2) Creazione file di progetto package.json npm install --save-dev grunt # --save-dev salva un riferimento alla libreria in package.json 3) Installazione delle librerie di base di grunt 4) Installazione plugins
  27. package.json { "name": "grunt-demo", "version": "0.0.1", ... "devDependencies": { "grunt":

    "~0.4.5", "grunt-contrib-concat": "~0.5.0", "grunt-contrib-uglify": "~0.6.0" } }
  28. Struttura della cartelle

  29. Struttura della cartelle Edit Here

  30. Struttura della cartelle Edit Here Build Here

  31. Struttura della cartelle Build File!

  32. Gruntfile.js Il Gruntfile è il file in cui vengono caricati

    e configurati i task installati
  33. module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { dist:

    { src: ['src/javascripts/base.js', 'src/javascripts/modules.js', 'src/javascripts/application.js'], dest: 'dist/javascripts/application.js' } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/javascripts/application.min.js': ['<%= concat.dist.dest %>'] } } } }); ['grunt-contrib-uglify', 'grunt-contrib-concat'].forEach(grunt.loadNpmTasks); grunt.registerTask('default', ['concat', 'uglify']); };
  34. module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { dist:

    { src: ['src/javascripts/base.js', 'src/javascripts/modules.js', 'src/javascripts/application.js'], dest: 'dist/javascripts/application.js' } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/javascripts/application.min.js': ['<%= concat.dist.dest %>'] } } } }); ['grunt-contrib-uglify', 'grunt-contrib-concat'].forEach(grunt.loadNpmTasks); grunt.registerTask('default', ['concat', 'uglify']);}; legge package.json e lo salva per gli altri task
  35. module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { dist:

    { src: ['src/javascripts/base.js', 'src/javascripts/modules.js', 'src/javascripts/application.js'], dest: 'dist/javascripts/application.js' } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/javascripts/application.min.js': ['<%= concat.dist.dest %>'] } } } }); ['grunt-contrib-uglify', 'grunt-contrib-concat'].forEach(grunt.loadNpmTasks); grunt.registerTask('default', ['concat', 'uglify']); }; legge i file JS e li concatena
  36. module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { dist:

    { src: ['src/javascripts/base.js', 'src/javascripts/modules.js', 'src/javascripts/application.js'], dest: 'dist/javascripts/application.js' } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/javascripts/application.min.js': ['<%= concat.dist.dest %>'] } } } }); ['grunt-contrib-uglify', 'grunt-contrib-concat'].forEach(grunt.loadNpmTasks); grunt.registerTask('default', ['concat', 'uglify']); }; minifica i sorgenti
  37. module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { dist:

    { src: ['src/javascripts/base.js', 'src/javascripts/modules.js', 'src/javascripts/application.js'], dest: 'dist/javascripts/application.js' } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/javascripts/application.min.js': ['<%= concat.dist.dest %>'] } } } }); ['grunt-contrib-uglify', 'grunt-contrib-concat'].forEach(grunt.loadNpmTasks); grunt.registerTask('default', ['concat', 'uglify']); }; commento generato dinamicamente
  38. module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { dist:

    { src: ['src/javascripts/base.js', 'src/javascripts/modules.js', 'src/javascripts/application.js'], dest: 'dist/javascripts/application.js' } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/javascripts/application.min.js': ['<%= concat.dist.dest %>'] } } } }); ['grunt-contrib-uglify', 'grunt-contrib-concat'].forEach(grunt.loadNpmTasks); grunt.registerTask('default', ['concat', 'uglify']); }; riferimenti ad altri task
  39. module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { dist:

    { src: ['src/javascripts/base.js', 'src/javascripts/modules.js', 'src/javascripts/application.js'], dest: 'dist/javascripts/application.js' } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/javascripts/application.min.js': ['<%= concat.dist.dest %>'] } } } }); ['grunt-contrib-uglify', 'grunt-contrib-concat'].forEach(grunt.loadNpmTasks); grunt.registerTask('default', ['concat', 'uglify']); }; carica i plugin/task installati
  40. module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { dist:

    { src: ['src/javascripts/base.js', 'src/javascripts/modules.js', 'src/javascripts/application.js'], dest: 'dist/javascripts/application.js' } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/javascripts/application.min.js': ['<%= concat.dist.dest %>'] } } } }); ['grunt-contrib-uglify', 'grunt-contrib-concat'].forEach(grunt.loadNpmTasks); grunt.registerTask('default', ['concat', 'uglify']); }; definisce un task di default
  41. Output del comando

  42. aLL THE tHINGS! G R U N T I F

    Y
  43. WOK https://github.com/intesys/wok “tasty website cookware”

  44. WOK is a loosely opinionated boilerplate for web development built

    with flexibility and productivity in mind.
  45. Ingredienti... ▪Sass + Compass ( + Bootstrap-Sass) ▪Ottimizzazione e minificazione

    CSS, JS e immagini ▪EJS Templating (Jade coming soon...) ▪Markdown partials, JSON data & fixtures ▪Environment specific code blocks ▪Asset filename revving ▪Analisi e build custom di Modernizr ▪Sass automated styleguide ▪Server statico locale + watch + live reload / Browsersync ▪Deploy remoto con rsync ▪Server weinre per debug mobile
  46. demo time...

  47. Thank you! @dwightjack https://github.com/dwightjack