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
380
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
The One Slide Deck
zastrow
0
5
The 4-Slide Deck
zastrow
0
7
Mixin It Up
zastrow
1
84
Designing Responsively from Mobile to HD
zastrow
6
280
Pushing Pixels to Cranking Code
zastrow
3
1.9k
Other Decks in Programming
See All in Programming
AIコーディング道場勉強会#2 君(エンジニア)たちはどう生きるか
misakiotb
1
160
Using AI Tools Around Software Development
inouehi
0
1.2k
try-catchを使わないエラーハンドリング!? PHPでResult型の考え方を取り入れてみよう
kajitack
3
500
C++20 射影変換
faithandbrave
0
440
TypeScript LSP の今までとこれから
quramy
1
500
Go1.25からのGOMAXPROCS
kuro_kurorrr
0
220
Javaのルールをねじ曲げろ!禁断の操作とその代償から学ぶメタプログラミング入門 / A Guide to Metaprogramming: Lessons from Forbidden Techniques and Their Price
nrslib
3
1.9k
Haskell でアルゴリズムを抽象化する / 関数型言語で競技プログラミング
naoya
17
4.3k
データベースコネクションプール(DBCP)の変遷と理解
fujikawa8
1
250
ReadMoreTextView
fornewid
1
370
Prism.parseで 300本以上あるエンドポイントに 接続できる権限の一覧表を作ってみた
hatsu38
1
110
Cursor AI Agentと伴走する アプリケーションの高速リプレイス
daisuketakeda
1
110
Featured
See All Featured
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
16
920
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
181
53k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
35
2.3k
Why Our Code Smells
bkeepers
PRO
337
57k
Producing Creativity
orderedlist
PRO
346
40k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
331
22k
Automating Front-end Workflow
addyosmani
1370
200k
Faster Mobile Websites
deanohume
307
31k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
8
650
Making the Leap to Tech Lead
cromwellryan
134
9.3k
Optimizing for Happiness
mojombo
379
70k
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]