Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Grunting Maintainability
Search
Philip Zastrow
April 02, 2014
Programming
1
370
Grunting Maintainability
Overview of using the Grunt JS task runner and working with some useful Grunt Plugins.
Philip Zastrow
April 02, 2014
Tweet
Share
More Decks by Philip Zastrow
See All by Philip Zastrow
Mixin It Up
zastrow
1
71
Designing Responsively from Mobile to HD
zastrow
6
270
Pushing Pixels to Cranking Code
zastrow
3
1.8k
Other Decks in Programming
See All in Programming
これでLambdaが不要に?!Step FunctionsのJSONata対応について
iwatatomoya
2
3.6k
range over funcの使い道と非同期N+1リゾルバーの夢 / about a range over func
mackee
0
110
Webエンジニア主体のモバイルチームの 生産性を高く保つためにやったこと
igreenwood
0
330
RWC 2024 DICOM & ISO/IEC 2022
m_seki
0
210
CQRS+ES の力を使って効果を感じる / Feel the effects of using the power of CQRS+ES
seike460
PRO
0
120
ドメインイベント増えすぎ問題
h0r15h0
1
230
103 Early Hints
sugi_0000
1
230
CSC305 Lecture 25
javiergs
PRO
0
130
LLM Supervised Fine-tuningの理論と実践
datanalyticslabo
3
1.1k
Haze - Real time background blurring
chrisbanes
1
510
KubeCon + CloudNativeCon NA 2024 Overviewat Kubernetes Meetup Tokyo #68 / amsy810_k8sjp68
masayaaoyama
0
250
Stackless и stackful? Корутины и асинхронность в Go
lamodatech
0
700
Featured
See All Featured
The Cost Of JavaScript in 2023
addyosmani
45
7k
Designing Experiences People Love
moore
138
23k
A Modern Web Designer's Workflow
chriscoyier
693
190k
Optimising Largest Contentful Paint
csswizardry
33
3k
Six Lessons from altMBA
skipperchong
27
3.5k
Docker and Python
trallard
42
3.1k
Git: the NoSQL Database
bkeepers
PRO
427
64k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
Faster Mobile Websites
deanohume
305
30k
KATA
mclloyd
29
14k
Designing for humans not robots
tammielis
250
25k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
Transcript
Philip Zastrow GRUNTING MAINTAINABILITY @zastrow
ROBOTS A CHILDHOOD MEMORY OF
THERE WAS A ROBOT AT MY GRAMPA’S WORKPLACE
THE ARM HELPED MAKE COMPUTER PROCESSORS
MY GRAMPA DIDN’T DESIGN THE ROBOT
None
HIS PART TURNED MANY SMALL FUNCTIONS INTO A ROBOT
GRUNTING MAINTAINABILITY FRONTEND TOOLS
HTML CSS JS WHAT WE BUILD
HBS SCSS COFFEE HOW WE BUILD
sass input.scss output.css sass watch SCSS CSS
coffee --compile coffee --watch COFFEE JS
ONE COMMAND ONE FUNCTION
WE NEED A FRONTEND ROBOT
None
None
grunt grunt watch COFFEE JS SCSS CSS
ONE COMMAND MANY FUNCTIONS
WHAT IS GRUNT?
Grunt is a tool that binds your other tools together
GRUNT IS A TASK RUNNER
THERE IS A BUFFET OF TASK RUNNERS
HELPS AUTOMATE TEDIOUS WORK GRUNT IS A TASK RUNNER
GRUNT AUTOMATES RUNNING TESTS
GRUNT AUTOMATES RUNNING TESTS FILE CONVERSION
GRUNT AUTOMATES RUNNING TESTS FILE CONVERSION CONCATENATION
nodejs.org brew install node
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
HOW DOES GRUNT WORK?
gruntjs.com/getting-started npm install -g grunt-cli GRUNT CLI
grunt
package.json Node devDependencies i.e. plugins
{ "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" } }
npm install
npm install grunt-plugin --save-dev
.js or .coffee GRUNTFILE The list of instructions for each
plugin
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
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
24ways.org/2013/grunt-is-not-weird-and-hard gruntjs.com
GRUNTING MAINTAINABILITY BUILDING MAINTAINABLE WEBSITES WITH GRUNT
FRONTEND DEVELOPMENT AND HOW WE BUILD SITES
Focus primarily on HTML, CSS, and JS; Not a CMS
Any one teammate could jump on any project at anytime
Grunt helps us collaborate with each other and client dev
teams
We use Grunt on our own website seesparkbox.com
We like improving workflow, so all tools are eligible for
replacement
We like improving workflow, so all tools are eligible for
replacement …including Grunt
Frontend projects start with a Grunt scaffolding
Grunt Project coffee data dist features grunt public Gemfile Gruntfile
config.rb package.json .gitignore bower.json .bowerrc sass specs templates
Grunt Project coffee data dist features grunt public Gemfile Gruntfile
config.rb package.json .gitignore bower.json .bowerrc sass specs templates
Grunt Project coffee data dist public sass templates
GRUNT PLUGINS SPARKBOX USES
Grunt plugins are Grunt-wrapped preprocessors
Grunt Project coffee data dist public sass templates ASSEMBLE HTML
npm install assemble --save-dev assemble.io
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'
HANDLEBARS HTML STRUCTURE handlebarsjs.com
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'
Grunt Project coffee data dist public sass templates
templates layouts pages partials
templates layouts pages partials layoutdir: "templates/layouts/"
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'
layout default.hbs contact.hbs layout: ['default.hbs']
<!doctype html> <html> <head> <title> Sample Site </title> <head> <body>
{{> _site--header }} {{> body }} {{> _site--footer }} </body> </html>
<!doctype html> <html> <head> <title> Sample Site </title> <head> <body>
{{> _site--header }} {{> body }} {{! Loads in Page Content }} {{> _site--footer }} </body> </html>
<!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>
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'
templates layout pages partials cwd: 'templates/pages'
pages index.hbs about.hbs contact.hbs
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'
index.hbs about.hbs contact.hbs cwd: 'templates/pages' src: ['*.hbs'] dest: './dist/' index.html
about.html contact.html
<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 }}
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'
templates layout pages partials partials: "templates/partials/*"
partials _site--aside.hbs _site--footer.hbs _site--header.hbs _site--navigation.hbs
<header class="site_header"> <h1 class="site_header--title">Sample Site</h1> {{> _site--navigation }} <header>
<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>
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'
YAML HTML CONTENT yaml.org
YAML YAML Ain’t Markup Language yaml.org
Grunt Project coffee data dist public sass templates data: "data/*.yml"
data index.yml about.yml site-info.yml site-nav.yml
nav-list: - nav_item: Home target: "/" - nav_item: About target:
"about.html" - nav_item: Blog target: "blog.html" - nav_item: Contact target: "contact.html"
<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>
<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>
<!doctype html> <html> <head> <title> Sample Site </title> <head> <body>
{{> _site-header }} {{> body }} {{> _site-footer }} </body> </html>
<!doctype html> <html> <head> <title> Sample Site </title> <head> <body>
{{> _site-header }} {{> body }} {{> _site-footer }} </body> </html>
<!doctype html> <html> <head> <title> Sample Site{{#if page_title}} | {{page_title}}{{/if}}
</title> <head> <body> {{> _site-header }} {{> body }} {{> _site-footer }} </body> </html>
YAML FRONT MATTER
--- 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 }}
<!doctype html> <html> <head> <title> Sample Site{{#if page_title}} | {{page_title}}{{/if}}
</title> <head> <body> {{> _site-header }} {{> body }} {{> _site-footer }} </body> </html>
<!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">
Grunt Project coffee data dist public sass templates SASS with
COMPASS CSS
npm install grunt-contrib-compass --save-dev github.com/gruntjs/grunt-contrib-compass
module.exports = (grunt) -> grunt.config "compass", dev: options: environment: "dev"
dist: options: environment: "production" grunt.loadNpmTasks "grunt-contrib-compass"
sass _general-extends.scss _general-mixins.scss _general-variables.scss _site--header.scss _site--navigation.scss mq-base.scss nomq-base.scss
Grunt Project coffee data dist public sass templates COFFEESCRIPT JAVASCRIPT
npm install grunt-contrib-coffee --save-dev github.com/gruntjs/grunt-contrib-coffee
module.exports = (grunt) -> grunt.config "coffee", compile: files: "dist/js/app.js": "coffee/app.coffee"
grunt.loadNpmTasks "grunt-contrib-coffee"
Grunt Project coffee data dist public sass templates
Grunt Project coffee data dist public sass templates
Grunt Project coffee data dist public sass templates CLEANED OUT
BEFORE THE SITE GENERATES
npm install grunt-contrib-clean --save-dev github.com/gruntjs/grunt-contrib-clean
module.exports = (grunt) -> grunt.config "clean", all: src: "dist/*" dot:
true #clean hidden files as well ! grunt.loadNpmTasks 'grunt-contrib-clean'
Grunt Project coffee data dist public sass templates STATIC FILES
NO PREPROCESSORS
npm install grunt-contrib-copy --save-dev github.com/gruntjs/grunt-contrib-copy
module.exports = (grunt) -> grunt.config "copy", main: files: [ expand:
true cwd: "public/" src: ["**"] dest: "dist/" ] ! grunt.loadNpmTasks 'grunt-contrib-copy'
Keep files short and let Grunt string them together
GRUNT PLUGIN ONE MORE THING!
Grunt Project coffee data dist public sass templates grunticon SVG
WITH PNG FALLBACK
npm install grunt-grunticon --save-dev github.com/filamentgroup/grunticon
module.exports = (grunt) -> grunt.config "grunticon", icons: files: [ expand:
true, cwd: "grunticon/src", src: ["*.svg"], dest: "dist/grunticon" ] ! grunt.loadNpmTasks "grunt-grunticon"
grunticon src
grunticon sample-logo.svg
grunticon png src grunticon.loader.txt icons.data.png.css icons.data.svg.css icons.fallback.css preview.html
.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%
.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
.icon-sample-logo { background-image: url(‘png/sample-logo.png'); background-repeat: no-repeat; }
data URI
Make sure SVG files are optimized github.com/svg/svgo
A Bit About SVG seesparkbox.com/foundry/a_bit_about_svg
GRUNTING MAINTAINABILITY REVIEW
None
GRUNT PLUGINS
ASSEMBLE HTML GENERATOR assemble.io npm install assemble --save-dev
SASS/COMPASS CSS GENERATOR github.com/gruntjs/contrib-grunt-compass npm install contrib-grunt-compass --save-dev
COFFEESCRIPT JS GENERATOR github.com/gruntjs/contrib-grunt-coffee npm install contrib-grunt-coffee --save-dev
CLEAN REMOVES ALL THE THINGS github.com/gruntjs/contrib-grunt-clean npm install contrib-grunt-clean --save-dev
COPY ADDS ALL THE THINGS github.com/gruntjs/contrib-grunt-copy npm install contrib-grunt-copy --save-dev
GRUNTICON SVG WITH PNG FALLBACK github.com/filamentgroup/grunticon npm install grunt-grunticon --save-dev
The goal is simplified and concise files
THAT’S GRUNTING MAINTAINABILITY
THANKS! @zastrow
[email protected]