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

Grunting Maintainability

Grunting Maintainability

Overview of using the Grunt JS task runner and working with some useful Grunt Plugins.

2e0312c825c0338b1d29b4d3cfb087ae?s=128

Philip Zastrow

April 02, 2014
Tweet

More Decks by Philip Zastrow

Other Decks in Programming

Transcript

  1. Philip Zastrow GRUNTING MAINTAINABILITY @zastrow

  2. ROBOTS A CHILDHOOD MEMORY OF

  3. THERE WAS A ROBOT AT MY GRAMPA’S WORKPLACE

  4. THE ARM HELPED MAKE COMPUTER PROCESSORS

  5. MY GRAMPA DIDN’T DESIGN THE ROBOT

  6. None
  7. HIS PART TURNED MANY SMALL FUNCTIONS INTO A ROBOT

  8. GRUNTING MAINTAINABILITY FRONTEND
 TOOLS

  9. HTML CSS JS WHAT WE BUILD

  10. HBS SCSS COFFEE HOW WE BUILD

  11. sass input.scss output.css sass watch SCSS CSS

  12. coffee --compile coffee --watch COFFEE JS

  13. ONE COMMAND ONE FUNCTION

  14. WE NEED A FRONTEND ROBOT

  15. None
  16. None
  17. grunt grunt watch COFFEE JS SCSS CSS

  18. ONE COMMAND MANY FUNCTIONS

  19. WHAT IS GRUNT?

  20. Grunt is a tool that
 binds your other
 tools together

  21. GRUNT IS A TASK RUNNER

  22. THERE IS A BUFFET OF TASK RUNNERS

  23. HELPS AUTOMATE TEDIOUS WORK GRUNT IS A TASK RUNNER

  24. GRUNT AUTOMATES RUNNING TESTS

  25. GRUNT AUTOMATES RUNNING TESTS FILE CONVERSION

  26. GRUNT AUTOMATES RUNNING TESTS FILE CONVERSION CONCATENATION

  27. nodejs.org brew install node

  28. Grunt for People Who Think Things Like Grunt are Weird

    and Hard —Chris Coyier, 24 Ways 24ways.org/2013/grunt-is-not-weird-and-hard
  29. HOW DOES GRUNT WORK?

  30. gruntjs.com/getting-started npm install -g grunt-cli GRUNT CLI

  31. grunt

  32. package.json Node devDependencies i.e. plugins

  33. { "name": “sample-site", "version": "0.1.0", "devDependencies": { "grunt": "~0.4.2", "assemble":

    "~0.4.13", "grunt-contrib-clean": "~0.4.0", "grunt-contrib-coffee": "~0.6.0", "grunt-contrib-compass": "~0.1.3", "grunt-contrib-copy": "~0.4.1" } }
  34. npm install

  35. npm install grunt-plugin --save-dev

  36. .js or .coffee GRUNTFILE The list of instructions for each

    plugin
  37. module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'),

    uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } }); // Load the plugin that provides the “uglify" task. grunt.loadNpmTasks('grunt-contrib-uglify'); // Default task(s). grunt.registerTask('default', ['uglify']); }; Example code from gruntjs.com
  38. module.exports = (grunt) -> # Project configuration. grunt.initConfig pkg: require("package.json")

    uglify: options: banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' build: src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' ! # Load the plugin that provides the “uglify" task. grunt.loadNpmTasks 'grunt-contrib-uglify' # Default task(s). grunt.registerTask 'default', ['uglify'] Example code from gruntjs.com
  39. 24ways.org/2013/grunt-is-not-weird-and-hard gruntjs.com

  40. GRUNTING MAINTAINABILITY BUILDING MAINTAINABLE WEBSITES
 WITH GRUNT

  41. FRONTEND DEVELOPMENT AND HOW WE BUILD SITES

  42. Focus primarily on HTML, CSS, and JS; Not a CMS

  43. Any one teammate could jump on any project at anytime

  44. Grunt helps us collaborate with each other and
 client dev

    teams
  45. We use Grunt on our own website seesparkbox.com

  46. We like improving workflow, so all tools are eligible for

    replacement
  47. We like improving workflow, so all tools are eligible for

    replacement …including Grunt
  48. Frontend projects start with a Grunt scaffolding

  49. Grunt Project coffee data dist features grunt public Gemfile Gruntfile

    config.rb package.json .gitignore bower.json .bowerrc sass specs templates
  50. Grunt Project coffee data dist features grunt public Gemfile Gruntfile

    config.rb package.json .gitignore bower.json .bowerrc sass specs templates
  51. Grunt Project coffee data dist public sass templates

  52. GRUNT PLUGINS SPARKBOX USES

  53. Grunt plugins are Grunt-wrapped preprocessors

  54. Grunt Project coffee data dist public sass templates ASSEMBLE HTML

  55. npm install assemble --save-dev assemble.io

  56. module.exports = (grunt) -> grunt.config "assemble", options: partials: "templates/partials/*" data:

    "data/*.yml" layoutdir: "templates/layouts/" layout: ['default.hbs'] files: expand: true cwd: 'templates/pages' src: ['*.hbs'] dest: './dist/' ! grunt.loadNpmTasks 'assemble'
  57. HANDLEBARS HTML STRUCTURE handlebarsjs.com

  58. module.exports = (grunt) -> grunt.config "assemble", options: partials: "templates/partials/*" data:

    "data/*.yml" layoutdir: "templates/layouts/" layout: ['default.hbs'] files: expand: true cwd: 'templates/pages' src: ['*.hbs'] dest: './dist/' ! grunt.loadNpmTasks 'assemble'
  59. Grunt Project coffee data dist public sass templates

  60. templates layouts pages partials

  61. templates layouts pages partials layoutdir: "templates/layouts/"

  62. module.exports = (grunt) -> grunt.config "assemble", options: partials: "templates/partials/*" data:

    "data/*.yml" layoutdir: "templates/layouts/" layout: ['default.hbs'] files: expand: true cwd: 'templates/pages' src: ['*.hbs'] dest: './dist/' ! grunt.loadNpmTasks 'assemble'
  63. layout default.hbs contact.hbs layout: ['default.hbs']

  64. <!doctype html> <html> <head> <title> Sample Site </title> <head> <body>

    {{> _site--header }} {{> body }} {{> _site--footer }} </body> </html>
  65. <!doctype html> <html> <head> <title> Sample Site </title> <head> <body>

    {{> _site--header }} {{> body }} {{! Loads in Page Content }} {{> _site--footer }} </body> </html>
  66. <!doctype html> <html> <head> <title> Sample Site </title> <head> <body>

    {{> _site--header }} {{! Loads Site Header Partial }} {{> body }} {{> _site--footer }} {{! Loads Site Footer Partial }} </body> </html>
  67. module.exports = (grunt) -> grunt.config "assemble", options: partials: "templates/partials/*" data:

    "data/*.yml" layoutdir: "templates/layouts/" layout: ['default.hbs'] files: expand: true cwd: 'templates/pages' src: ['*.hbs'] dest: './dist/' ! grunt.loadNpmTasks 'assemble'
  68. templates layout pages partials cwd: 'templates/pages'

  69. pages index.hbs about.hbs contact.hbs

  70. module.exports = (grunt) -> grunt.config "assemble", options: partials: "templates/partials/*" data:

    "data/*.yml" layoutdir: "templates/layouts/" layout: ['default.hbs'] files: expand: true cwd: 'templates/pages' src: ['*.hbs'] dest: './dist/' ! grunt.loadNpmTasks 'assemble'
  71. index.hbs about.hbs contact.hbs cwd: 'templates/pages' src: ['*.hbs'] dest: './dist/' index.html

    about.html contact.html
  72. <div class="main_content"> <article class="main_content--article"> <header class="main_content--header"> <h1 class="main_content--title">Our Homepage</h1> <header>

    <div class="article_content"> <p>This is the main content for our page.</p> </div> </article> </div> ! {{> _site--aside }}
  73. module.exports = (grunt) -> grunt.config "assemble", options: partials: "templates/partials/*" data:

    "data/*.yml" layoutdir: "templates/layouts/" layout: ['default.hbs'] files: expand: true cwd: 'templates/pages' src: ['*.hbs'] dest: './dist/' ! grunt.loadNpmTasks 'assemble'
  74. templates layout pages partials partials: "templates/partials/*"

  75. partials _site--aside.hbs _site--footer.hbs _site--header.hbs _site--navigation.hbs

  76. <header class="site_header"> <h1 class="site_header--title">Sample Site</h1> {{> _site--navigation }} <header>

  77. <nav class="site_nav"> <ul class="site_nav--list"> {{#each site-nav.nav-list}} <li class="site_nav--item"> <a href=“{{target}}"

    class="site_nav--link"> {{nav_item}} </a> </li> {{/each}} </ul> <nav>
  78. module.exports = (grunt) -> grunt.config "assemble", options: partials: "templates/partials/*" data:

    "data/*.yml" layoutdir: "templates/layouts/" layout: ['default.hbs'] files: expand: true cwd: 'templates/pages' src: ['*.hbs'] dest: './dist/' ! grunt.loadNpmTasks 'assemble'
  79. YAML HTML CONTENT yaml.org

  80. YAML YAML Ain’t Markup Language yaml.org

  81. Grunt Project coffee data dist public sass templates data: "data/*.yml"

  82. data index.yml about.yml site-info.yml site-nav.yml

  83. nav-list: - nav_item: Home target: "/" - nav_item: About target:

    "about.html" - nav_item: Blog target: "blog.html" - nav_item: Contact target: "contact.html"
  84. <nav class="site_nav"> <ul class="site_nav--list"> {{#each site-nav.nav-list}} <li class="site_nav--list"> <a href=“{{target}}"

    class="site_nav--list"> {{nav_item}} </a> </li> {{/each}} </ul> <nav>
  85. <nav class="site_nav"> <ul class="site_nav--list"> <li class="site_nav--list"> <a href="/" class="site_nav--list"> Home

    </a> </li> <li class="site_nav--list"> <a href="about.html" class="site_nav--list"> About </a> </li> <li class="site_nav--list"> <a href="blog.html" class="site_nav--list"> Blog </a> </li> <li class="site_nav--list"> <a href="contact.html" class="site_nav--list"> {{nav_item}} </a>
  86. <!doctype html> <html> <head> <title> Sample Site </title> <head> <body>

    {{> _site-header }} {{> body }} {{> _site-footer }} </body> </html>
  87. <!doctype html> <html> <head> <title> Sample Site </title> <head> <body>

    {{> _site-header }} {{> body }} {{> _site-footer }} </body> </html>
  88. <!doctype html> <html> <head> <title> Sample Site{{#if page_title}} | {{page_title}}{{/if}}

    </title> <head> <body> {{> _site-header }} {{> body }} {{> _site-footer }} </body> </html>
  89. YAML FRONT MATTER

  90. --- page_title: About Us --- ! <div class="main_content"> <article class="main_content--article">

    <header class="main_content--header"> <h1 class="main_content—title">{{page_title}}</h1> <header> <div class="article_content"> {{ about.page-content }} </div> </article> </div> ! {{> _site--aside }}
  91. <!doctype html> <html> <head> <title> Sample Site{{#if page_title}} | {{page_title}}{{/if}}

    </title> <head> <body> {{> _site-header }} {{> body }} {{> _site-footer }} </body> </html>
  92. <!doctype html> <html> <head> <title> Sample Site | About Us

    </title> <head> <body> <header class="site_header"> <h1 class="site_header--title">Sample Site</h1> <nav class="site_nav"> <ul class="site_nav--list"> <li class="site_nav--list"> <a href="/" class="site_nav—list"> Home </a> </li> <li class="site_nav--list"> <a href="about.html" class="site_nav--list"> About </a> </li> <li class="site_nav--list">
  93. Grunt Project coffee data dist public sass templates SASS with

    COMPASS CSS
  94. npm install grunt-contrib-compass --save-dev github.com/gruntjs/grunt-contrib-compass

  95. module.exports = (grunt) -> grunt.config "compass", dev: options: environment: "dev"

    dist: options: environment: "production" grunt.loadNpmTasks "grunt-contrib-compass"
  96. sass _general-extends.scss _general-mixins.scss _general-variables.scss _site--header.scss _site--navigation.scss mq-base.scss nomq-base.scss

  97. Grunt Project coffee data dist public sass templates COFFEESCRIPT JAVASCRIPT

  98. npm install grunt-contrib-coffee --save-dev github.com/gruntjs/grunt-contrib-coffee

  99. module.exports = (grunt) -> grunt.config "coffee", compile: files: "dist/js/app.js": "coffee/app.coffee"

    grunt.loadNpmTasks "grunt-contrib-coffee"
  100. Grunt Project coffee data dist public sass templates

  101. Grunt Project coffee data dist public sass templates

  102. Grunt Project coffee data dist public sass templates CLEANED OUT

    BEFORE THE SITE GENERATES
  103. npm install grunt-contrib-clean --save-dev github.com/gruntjs/grunt-contrib-clean

  104. module.exports = (grunt) -> grunt.config "clean", all: src: "dist/*" dot:

    true #clean hidden files as well ! grunt.loadNpmTasks 'grunt-contrib-clean'
  105. Grunt Project coffee data dist public sass templates STATIC FILES

    NO PREPROCESSORS
  106. npm install grunt-contrib-copy --save-dev github.com/gruntjs/grunt-contrib-copy

  107. module.exports = (grunt) -> grunt.config "copy", main: files: [ expand:

    true cwd: "public/" src: ["**"] dest: "dist/" ] ! grunt.loadNpmTasks 'grunt-contrib-copy'
  108. Keep files short and let Grunt string them together

  109. GRUNT PLUGIN ONE MORE THING!

  110. Grunt Project coffee data dist public sass templates grunticon SVG

    WITH PNG FALLBACK
  111. npm install grunt-grunticon --save-dev github.com/filamentgroup/grunticon

  112. module.exports = (grunt) -> grunt.config "grunticon", icons: files: [ expand:

    true, cwd: "grunticon/src", src: ["*.svg"], dest: "dist/grunticon" ] ! grunt.loadNpmTasks "grunt-grunticon"
  113. grunticon src

  114. grunticon sample-logo.svg

  115. grunticon png src grunticon.loader.txt icons.data.png.css icons.data.svg.css icons.fallback.css preview.html

  116. .icon-sample-logo { background-image: url(‘data:image/svg +xml;charset=US-ASCII,%3C%3Fxml %20version%3D %221.0%22%20encoding%3D %22UTF-8%22%20standalone%3D%22no%22%3F%3E%3Csvg %20width%3D%22302px%22%20height%3D%2266px %22%20viewBox%3D%220%200%20302%2066%22%20version%3D

    %221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org %2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F %2Fwww.w3.org%2F1999%2Fxlink%22%3E %20%20%20%20%3Ctitle%3EButton%3C%2Ftitle%3E %20%20%20%20%3Cdefs%3E%20%20%20%20%20%20%3Cstyle%3E %20%20%20%20%20%20%20%20.button--path%20%7B %20%20%20%20%20%20%20%20%20%20fill%3A%20%23D4D4D4%3B %20%20%20%20%20%20%20%20%7D%20%20%20%20%20%20%3C %2Fstyle%3E%20%20%20%20%3C%2Fdefs%3E %20%20%20%20%3Cpath%20class%3D%22button--path%22%20d %3D
 %22M244.681203%2C0%20L56.2445924%2C0%20C27.7845831%2C 0%200%2C33.8953123%200%2C33.8953123%20C0%2C33.8953123 %2026.3926138%2C65.9999996%2055.4422152%2C65.9999996% 20C137.527029%2C65.9999996%20218.318013%2C66.0000005%
  117. .icon-sample-logo { background-image: url(‘data:image/ png;base64,iVBORw0KGgoAAAANSUhEUgAAAS4AAABCCAYAAADpAT vWAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAA ACGpJREFUeJzt3XuMXGUZBvDn/Wa6uy5toS0bE2OUEly3O +eMVrZaFdRN1CbEpqYNBaHBGAtyCaigTRo0AaoxBIsXEoLIRZRU2F CQgEgpcYlJCZcRh3POzGxWCAIBQlgSUzRMpzPv6x/ uku2ys7tzPbPd5/ff5sx5v2f/

    eXL22znnCBa5IAhOBTDknDvdzNYCWG1mawCsBrDaObc83oRE7aWqJ efcuwAOq+rrzrnXALxgZhGAoFAoRNu3b6/ EHLMhEneAWgVBkHbOfR3A51X1dOfcmrgzES0mqvqOc+4pAKNm9ojv +8/ HnalWi6K4oij6NIBtqrrVOXda3HmIjjOvArgfwD7P856JO8xCdGxx BUGwSkQuBHCJiJwScxyiJUFV/ ykiv122bNmdAwMDE3HnqabjiiuXy6VU9QoR2QGgN +48REvR5D7ZPaq6N51OB3HnmaljiiuXy33GzK4D8NW4sxDRMQ6Y2R 7f9w/ FHWRK7MU1eYX1UxHZEncWIqrOzB53zv0olUo9HXeW2IqrUCicUqlU rlPV851zLq4cRFQbVb3PObfb87wX4srQ9uKKoqjLzHaZ2dXOuZ52r 09EjZvcA/ slgD2e5/2n3eu3tbjCMBwWkZsBDLRzXSJqDVV9HcD30+n0SDvXbUt
  118. .icon-sample-logo { background-image: url(‘png/sample-logo.png'); background-repeat: no-repeat; }

  119. data URI

  120. Make sure SVG files are optimized github.com/svg/svgo

  121. A Bit About SVG seesparkbox.com/foundry/a_bit_about_svg

  122. GRUNTING MAINTAINABILITY REVIEW

  123. None
  124. GRUNT PLUGINS

  125. ASSEMBLE HTML GENERATOR assemble.io npm install assemble --save-dev

  126. SASS/COMPASS CSS GENERATOR github.com/gruntjs/contrib-grunt-compass npm install contrib-grunt-compass --save-dev

  127. COFFEESCRIPT JS GENERATOR github.com/gruntjs/contrib-grunt-coffee npm install contrib-grunt-coffee --save-dev

  128. CLEAN REMOVES ALL THE THINGS github.com/gruntjs/contrib-grunt-clean npm install contrib-grunt-clean --save-dev

  129. COPY ADDS ALL THE THINGS github.com/gruntjs/contrib-grunt-copy npm install contrib-grunt-copy --save-dev

  130. GRUNTICON SVG WITH PNG FALLBACK github.com/filamentgroup/grunticon npm install grunt-grunticon --save-dev

  131. The goal is simplified and concise files

  132. THAT’S GRUNTING MAINTAINABILITY

  133. THANKS! @zastrow philip@heysparkbox.com