SlideShare a Scribd company logo
Get Grulping with JavaScript Task Runners 
Matt Gifford 
@coldfumonkeh 
monkehworks.com
OBLIGATORY QUOTE 
FROM HISTORICAL FIGURE 
COMING UP
“life is really simple, 
but we insist on making 
it complicated” 
Confucius
WTF?
IT HURTS
almost all quality improvement comes via 
simplification of design, manufacturing, layout, 
processes and procedures. 
Tom Peters
almost all quality improvement comes via 
simplification of design, manufacturing, layout, 
processes and procedures. 
Tom Peters
Get Grulping with JavaScript Task Runners (Matt Gifford)
Get Grulping with JavaScript Task Runners (Matt Gifford)
Get Grulping with JavaScript Task Runners (Matt Gifford)
http://nodejs.org
Get Grulping with JavaScript Task Runners (Matt Gifford)
https://github.com/tvooo/sublime-grunt
http://gruntjs.com 
@gruntjs
0.4.x
http://gruntjs.com/plugins 
2,954 
as of 8:30am 5th June 2014
YOU NEED 
package.json 
Gruntfile.js
Get Grulping with JavaScript Task Runners (Matt Gifford)
$ 
npm init 
This utility will walk you through creating a 
package.json file. 
It only covers the most common items, 
and tries to guess sane defaults. 
Press ^C at any time to quit. 
name: (grunt_project) 
grunting_away 
version: (0.0.0) 
description: 
entry point: (index.js) 
test command: 
.... etc 
0.0.1
package.json 
{ 
"name": "grunting_away", 
"version": "0.0.1", 
"description": "", 
"main": "index.js", 
"author": "Matt Gifford", 
"license": "ISC" 
}
package.json 
{ 
"name": "grunting_away", 
"version": "0.0.1" 
}
INSTALLING GRUNT 
Use npm to install the required modules 
$ npm install < whatever the module name is > 
You may need sudo or Administrative rights
INSTALLING GRUNT 
Grunt 0.3 requires a global install of the library 
Grunt 0.4 changed... a lot (for the better) 
Now has the ability to run different local versions 
$ npm install grunt-cli -g 
-g installs the CLI package globally. Good times
INSTALLING GRUNT 
We have the global CLI. Now we need a local Grunt 
$ npm install grunt --save-dev
$ 
grunt --version 
grunt-cli v0.1.13 
grunt v0.4.5
package.json 
{ 
"name": "grunting_away", 
"version": "0.0.1", 
"devDependencies": { 
"grunt": "^0.4.5" 
} 
}
package.json 
{ 
"name": "grunting_away", 
"version": "0.0.1", 
} 
"devDependencies": { 
"grunt": "^0.4.5" 
}
Gruntfile.js 
Lives in the root directory of your project 
Commit it into your source control repo! 
Holds your task configurations 
Can be written as Gruntfile.coffee 
(if that floats your boat)
Gruntfile.js 
module.exports = function(grunt) { 
grunt.initConfig({ 
// Pure awesomeness will live here 
}); 
};
VERSION CONTROL 
| -- package.json 
| -- Gruntfile.js 
commit these and share the wealth
TEAM GRUNTING 
$ npm install
THE CODE BASE 
| -- javascripts 
-- main.js 
-- formControls.js 
| -- stylesheets 
-- form.css 
-- main.css 
can be managed more effectively
CSS CONCATENATION 
$ npm install grunt-contrib-concat --save-dev
package.json 
{ 
"name": "grunting_away", 
"version": "0.0.1", 
"devDependencies": { 
"grunt": "^0.4.5", 
"grunt-contrib-concat": "^0.4.0" 
} 
}
Gruntfile.js 
module.exports = function(grunt) { 
grunt.initConfig({ 
// Pure awesomeness will live here 
}); 
grunt.loadNpmTasks('grunt-contrib-concat'); 
};
Gruntfile.js 
grunt.initConfig({ 
concat : { 
css: { 
files: { 
'stylesheets/engage.css' : 
['stylesheets/*.css'] 
} 
} 
} 
});
Gruntfile.js 
grunt.initConfig({ 
concat : { 
css: { 
files: { 
'stylesheets/engage.css' : 
[ 
'stylesheets/main.css', 
'stylesheets/form.css' 
] 
} 
} 
} 
});
$ grunt concat 
Running "concat:css" (concat) task 
File stylesheets/engage.css created. 
Done, without errors. 
$ grunt concat:css 
Running "concat:css" (concat) task 
File stylesheets/engage.css created. 
Done, without errors.
THE CODE BASE 
| -- stylesheets 
-- engage.css 
-- form.css 
-- main.css new file generated by Grunt
Gruntfile.js 
grunt.initConfig({ 
concat : { 
css: { 
options: { 
banner: '/* Combined CSS file */n' 
}, 
/* snip */
Gruntfile.js 
grunt.initConfig({ 
pkg: grunt.file.readJSON('package.json'), 
concat : { 
css: { 
options: { 
banner: '/* <%= pkg.name %> combined file 
generated @ 
<%= grunt.template.today("dd-mm-yyyy") %> */n' 
}, 
/* snip */
Get Grulping with JavaScript Task Runners (Matt Gifford)
CSS MINIFICATION 
$ npm install grunt-contrib-cssmin --save-dev
package.json 
{ 
"name": "grunting_away", 
"version": "0.1.0", 
"devDependencies": { 
"grunt": "^0.4.5", 
"grunt-contrib-concat": "^0.4.0", 
"grunt-contrib-cssmin": "^0.9.0" 
} 
}
Gruntfile.js 
module.exports = function(grunt) { 
grunt.initConfig({ 
// Pure awesomeness will live here 
}); 
grunt.loadNpmTasks('grunt-contrib-concat'); 
grunt.loadNpmTasks('grunt-contrib-cssmin'); 
};
Gruntfile.js 
grunt.initConfig({ 
/* snip */ 
cssmin: { 
css: { 
files: { 
'stylesheets/engage.min.css' : 
[ 'stylesheets/engage.css' ] 
} 
} 
}, 
});
$ grunt cssmin 
Running "cssmin:css" (cssmin) task 
File stylesheets/engage.min.css created: 
29.73 kB → 23.62 kB 
Done, without errors.
THE CODE BASE 
| -- stylesheets 
-- engage.css 
-- engage.min.css 
-- form.css 
minified file -- main.css
Get Grulping with JavaScript Task Runners (Matt Gifford)
CACHE BUSTING 
$ npm install grunt-rev --save-dev
Gruntfile.js 
grunt.loadNpmTasks('grunt-rev'); 
rev: { 
css: { 
files: { 
src: ['stylesheets/engage.min.css'] 
} 
} 
},
$ grunt rev:css 
Running "rev:css" (rev) task 
stylesheets/engage.min.css >> 73a5cf64.engage.min.css 
Done, without errors.
THE CODE BASE 
| -- stylesheets 
-- 73a5cf64.engage.min.css 
-- engage.css 
-- engage.min.css 
-- form.css 
-- main.css 
hashed minified file
THE CODE BASE 
| -- stylesheets 
-- 73a5cf64.engage.min.css 
-- engage.css 
-- engage.min.css 
-- form.css 
-- main.css 
we don’t need these
CLEAN UP OPERATION 
$ npm install grunt-contrib-clean --save-dev
Gruntfile.js 
grunt.loadNpmTasks('grunt-contrib-clean'); 
clean: { 
combinedcss: { 
src: ['stylesheets/engage.css'] 
}, 
mincss: { 
src: ['stylesheets/engage.min.css'] 
}, 
revcss: { 
src: ['stylesheets/*engage.min.css'] 
} 
},
TOO MANY TASKS 
We already have a load of tasks to run 
What happens when we need to run them all? 
Type each command out?
REMEMBER 
simplification of processes and procedures
Gruntfile.js 
grunt.registerTask('css', 
[ 
'clean:revcss', 
'concat:css', 
'cssmin:css', 
'clean:combinedcss', 
'rev:css', 
'clean:mincss' 
]);
$ grunt css 
Running "clean:revcss" (clean) task 
Cleaning stylesheets/73a5cf64.engage.min.css...OK 
Running "concat:css" (concat) task 
File stylesheets/engage.css created. 
Running "cssmin:css" (cssmin) task 
File stylesheets/engage.min.css created: 29.73 kB → 23.62 kB 
Running "clean:combinedcss" (clean) task 
Cleaning stylesheets/engage.css...OK 
Running "rev:css" (rev) task 
stylesheets/engage.min.css >> 73a5cf64.engage.min.css 
Running "clean:mincss" (clean) task 
Done, without errors.
THE CODE BASE 
| -- stylesheets 
-- 73a5cf64.engage.min.css 
-- form.css 
-- main.css
WATCHING... 
ALWAYS WATCHING
WATCHING FOR FILE CHANGES 
$ npm install grunt-contrib-watch --save-dev
Gruntfile.js 
grunt.loadNpmTasks('grunt-contrib-watch'); 
watch: { 
css: { 
files: [ 
'stylesheets/form.css', 
'stylesheets/main.css' 
], 
tasks: ['css'] 
} 
},
Gruntfile.js 
grunt.registerTask('default', ['watch']);
$ grunt 
Running "watch" task 
Waiting... 
>> File "stylesheets/main.css" changed. 
Running "clean:revcss" (clean) task 
Cleaning stylesheets/73a5cf64.engage.min.css...OK 
Running "concat:css" (concat) task 
File stylesheets/engage.css created. 
Running "cssmin:css" (cssmin) task 
File stylesheets/engage.min.css created: 29.73 kB → 23.62 kB 
Running "clean:combinedcss" (clean) task 
Cleaning stylesheets/engage.css...OK 
Running "rev:css" (rev) task 
stylesheets/engage.min.css >> 73a5cf64.engage.min.css 
Running "clean:mincss" (clean) task 
Done, without errors. 
Completed in 0.485s at Mon Jun 02 2014 02:26:21 GMT+0100 (BST) - Waiting...
Get Grulping with JavaScript Task Runners (Matt Gifford)
THE CODE BASE 
| -- javascripts 
-- main.js 
-- formControls.js
JAVASCRIPT MANAGEMENT 
$ npm install grunt-contrib-jshint --save-dev 
$ npm install grunt-contrib-uglify --save-dev 
$ npm install grunt-remove-logging --save-dev
GRUNTFILE.JS 
grunt.loadNpmTasks('grunt-contrib-jshint'); 
jshint: { 
options: { 
curly: true, 
eqeqeq: true, 
eqnull: true, 
browser: true, 
globals: { 
jQuery: true 
}, 
}, 
all: ['Gruntfile.js','javascripts/main.js'] 
},
GRUNTFILE.JS 
grunt.loadNpmTasks('grunt-contrib-uglify'); 
uglify : { 
js: { 
files: { 
'javascripts/engage.min.js' : 
[ 'javascripts/main.js' ] 
} 
} 
},
GRUNTFILE.JS 
grunt.loadNpmTasks('grunt-remove-logging'); 
removelogging: { 
dist: { 
src: 'javascripts/engage.min.js', 
dest: 'javascripts/engage.min.js' 
} 
},
GRUNTFILE.JS 
rev: { 
css: { 
files: { 
src: ['stylesheets/engage.min.css'] 
} 
}, 
js: { 
files: { 
src: ['javascripts/engage.min.js'] 
} 
} 
},
GRUNTFILE.JS 
rev: { 
css: { 
files: { 
src: ['stylesheets/engage.min.css'] 
} 
}, 
js: { 
files: { 
src: ['javascripts/engage.min.js'] 
} 
} 
},
REMEMBER 
simplification of processes and procedures
GRUNTFILE.JS 
grunt.registerTask('js', 
[ 
'jshint', 
'clean:jsrev', 
'uglify:js', 
'removelogging', 
'rev:js', 
'clean:minjs' 
]);
GRUNTFILE.JS 
watch: { 
js: { 
files: ['javascripts/main.js'], 
tasks: ['js'] 
}, 
css: { 
files: [ 
'stylesheets/form.css', 
'stylesheets/main.css' 
], 
tasks: ['css'] 
} 
},
GRUNTFILE.JS 
watch: { 
js: { 
files: ['javascripts/main.js'], 
tasks: ['js'] 
}, 
css: { 
files: [ 
'stylesheets/form.css', 
'stylesheets/main.css' 
], 
tasks: ['css'] 
} 
} 
},
$ grunt 
Running "watch" task 
Waiting... 
>> File "javascripts/main.js" changed. 
Running "jshint:all" (jshint) task 
javascripts/main.js 
1 |console.log('monkeh love is good love') 
^ Missing semicolon. 
>> 1 error in 2 files 
Warning: Task "jshint:all" failed. Use --force to continue. 
Aborted due to warnings. 
Completed in 2.090s at Mon Jun 02 2014 03:13:55 GMT+0100 (BST) - Waiting...
$ grunt 
Running "watch" task 
Waiting... 
>> File "javascripts/main.js" changed. 
Running "jshint:all" (jshint) task 
>> 2 files lint free. 
Running "clean:jsrev" (clean) task 
Cleaning javascripts/engage.min.js...OK 
Running "uglify:js" (uglify) task 
File javascripts/engage.min.js created: 21 B → 21 B 
Running "removelogging:dist" (removelogging) task 
Removed 1 logging statements from javascripts/engage.min.js 
Running "rev:js" (rev) task 
javascripts/engage.min.js >> 0c115107.engage.min.js 
Running "clean:minjs" (clean) task 
Done, without errors. 
Completed in 0.721s at Mon Jun 02 2014 03:14:05 GMT+0100 (BST) - Waiting...
RELOADING YOUR APP
PERFORMING HTTP REQUESTS 
$ npm install grunt-http --save-dev
Gruntfile.js 
grunt.loadNpmTasks('grunt-http'); 
http: { 
reload: { 
options: { 
url: 'http://127.0.0.1:8000/index.cfm?reload=true' 
} 
} 
},
Gruntfile.js 
grunt.initConfig({ 
pkg: grunt.file.readJSON('package.json'), 
local_settings: { 
local_url: '' 
}, 
... 
http: { 
reload: { 
options: { 
url: '<%= local_settings.local_url %>' 
} 
} 
},
Gruntfile.js 
grunt.registerTask('default', ['checklocalconf']);
Gruntfile.js 
grunt.registerTask('checklocalconf', 'Check if the local config JSON file exists', function(arg) { 
if(grunt.file.exists('grunt_local_settings.json')) { 
grunt.task.run('watch'); 
} else { 
grunt.log.errorlns(''); 
grunt.log.errorlns('The grunt_local_settings.json file does not appear to exist.'); 
grunt.log.errorlns(''); 
grunt.log.errorlns('{'); 
grunt.log.errorlns(' "local_url": "http://your_local_server/?reload"'); 
grunt.log.errorlns('}'); 
grunt.log.errorlns(''); 
grunt.fail.fatal('Please create and save the grunt_local_settings.json file.'); 
}; 
});
Gruntfile.js 
grunt.registerTask('http_watcher', 
'Set the local url before running the watch command', 
function() { 
var jsonLocalSettings = grunt.file.readJSON("grunt_local_settings.json"); 
grunt.config.set('local_settings', jsonLocalSettings); 
grunt.config.requires('local_settings'); 
grunt.task.run('http:reload'); 
});
Gruntfile.js 
watch: { 
js: { 
files: ['javascripts/main.js'], 
tasks: ['js'] 
}, 
css: { 
files: [ 
'stylesheets/form.css', 
'stylesheets/main.css' 
], 
tasks: ['css'] 
}, 
cfcs: { 
files: ['cfcs/*.cfc'], 
tasks: ['http_watcher'] 
} 
},
$ grunt 
Running "checklocalconf" task 
Waiting... 
>> 
>> The grunt_local_settings.json file does not appear to exist. 
>> Please create it in this directory with the following content (the URL 
>> for your local app with reload action): 
>> 
>> { 
>> "local_url": "http://your_local_server/?reload" 
>> } 
>> 
Fatal error: Please create and save the grunt_local_settings.json file then 
re-run this command.
$ grunt 
Running "checklocalconf" task 
Running "watch" task 
Waiting... 
>> File "cfcs/test.cfc" changed. 
Running "http_watcher" task 
Running "http:reload" (http) task 
>> 200 
Done, without errors. 
Completed in 2.061s at Tue Jun 03 2014 12:01:44 GMT+0100 (BST) - Waiting...
INJECTING ASSETS 
$ npm install grunt-injector --save-dev
Gruntfile.js 
grunt.loadNpmTasks('grunt-injector'); 
injector: { 
options: {}, 
css: { 
files: { 
'layout.cfm': ['stylesheets/*engage.min.css'], 
} 
}, 
js: { 
files: { 
'layout.cfm': ['javascripts/*engage.min.js'], 
} 
} 
}
Get Grulping with JavaScript Task Runners (Matt Gifford)
Gruntfile.js 
grunt.registerTask('css', 
[ 
'clean:revcss', 
'concat:css', 
'cssmin:css', 
'clean:combinedcss', 
'rev:css', 
'clean:mincss', 
'injector:css' 
]);
Get Grulping with JavaScript Task Runners (Matt Gifford)
TIDY UP 
There are no limits to the number 
of plugins you can use 
You may also be duplicating file paths a lot 
Your Gruntfile could get messy quickly
Gruntfile.js 
grunt.loadNpmTasks('grunt-contrib-clean'); 
grunt.loadNpmTasks('grunt-contrib-concat'); 
grunt.loadNpmTasks('grunt-contrib-csslint'); 
grunt.loadNpmTasks('grunt-contrib-cssmin'); 
grunt.loadNpmTasks('grunt-http'); 
grunt.loadNpmTasks('grunt-injector'); 
grunt.loadNpmTasks('grunt-contrib-jshint'); 
grunt.loadNpmTasks('grunt-contrib-uglify'); 
grunt.loadNpmTasks('grunt-contrib-watch'); 
grunt.loadNpmTasks('grunt-remove-logging'); 
grunt.loadNpmTasks('grunt-rev'); 
grunt.loadNpmTasks('grunt-notify');
TIDY UP 
$ npm install matchdep --save-dev
Gruntfile.js 
require('matchdep') 
.filterDev('grunt-*') 
.forEach(grunt.loadNpmTasks);
ASSIGN VARIABLES 
Use the variable system to reduce duplicate text
Gruntfile.js 
grunt.initConfig({ 
pkg: grunt.file.readJSON('package.json'), 
minCSS: 'stylesheets/engage.min.css', 
}); 
cssmin: { 
css: { 
files: { 
'<%= minCSS %>' : [ 'stylesheets/engage.css' ] 
} 
} 
}, 
clean: { 
mincss: { 
src: ['<%= minCSS %>'] 
} 
}
WHAT ELSE CAN IT DO? 
image optimisation and resizing 
git integration 
run unit tests (e.g. Jasmine) 
templating 
...
WHAT ELSE CAN IT DO? 
pretty much anything you want it to 
http://gruntjs.com/plugins
Get Grulping with JavaScript Task Runners (Matt Gifford)
http://gulpjs.com 
@gulpjs
http://gulpjs.com/plugins/ 
635 
as of 8:30am 5th June 2014
INSTALLING GULP 
As a system wide module 
$ npm install gulp -g
INSTALLING GULP 
Getting a local gulp version for the project 
$ npm install gulp --save-dev
gulpfile.js 
Lives in the root directory of your project 
Commit it into your source control repo! 
Holds your task configurations 
Lowercase file name!
gulpfile.js 
// Include gulp 
var gulp = require('gulp'); 
gulp.task('default', function() { 
// place code for your default task here 
});
PIPES AND STREAMS
GRUNT 
GULP
gulpfile.js 
// Include gulp 
var gulp = require('gulp'); 
// Include Our Plugins 
var jshint = require('gulp-jshint'); 
var concat = require('gulp-concat'); 
var uglify = require('gulp-uglify'); 
var rename = require('gulp-rename'); 
var header = require('gulp-header');
gulpfile.js 
// Default Task 
gulp.task('default', ['watch']); 
// Watch Files For Changes 
gulp.task('watch', function() { 
gulp.watch('js/*.js', ['lint', 'scripts']); 
});
gulpfile.js 
// Lint Task 
gulp.task('lint', function() { 
return gulp.src('js/*.js') 
.pipe(jshint()) 
.pipe(jshint.reporter('default')); 
});
gulpfile.js 
// Concatenate & Minify JS 
gulp.task('scripts', function() { 
var headerValue = "Evaluated by gulp.n"; 
return gulp.src('js/*.js') 
.pipe(concat('combined.js')) 
.pipe(header(headerValue)) 
.pipe(gulp.dest('dist')) 
.pipe(rename('combined.min.js')) 
.pipe(uglify()) 
.pipe(header(headerValue)) 
.pipe(gulp.dest('dist')); 
});
http://gulpfiction.divshot.io
Get Grulping with JavaScript Task Runners (Matt Gifford)
Get Grulping with JavaScript Task Runners (Matt Gifford)
Streaming and piping give speed enhancements 
Code over configuration 
Still early adoption - plugins limited 
JS / Node exposure beneficial (?)
Sub tasks easily managed 
Impressive number of plugins and extensions 
I/O issues and speed (in comparison) 
Configuration could get messy
ITS NOT A CONTEST
HAPPY
FINAL WORDS 
Save your config files (repo) 
Use skeleton variation across your projects 
Create 
Employ 
Refine 
Relax
FINAL WORDS 
Has the potential to be addictive 
Check for updates and improved methods 
Use your time wisely
Get Grulping with JavaScript Task Runners (Matt Gifford)
Get Grulping with JavaScript Task Runners (Matt Gifford)
Get Grulping with JavaScript Task Runners (Matt Gifford)
Get Grulping with JavaScript Task Runners (Matt Gifford)
Thank you! 
Matt Gifford 
@coldfumonkeh 
monkehworks.com

More Related Content

PDF
Get Gulping with Javascript Task Runners
PDF
Get Grulping with JavaScript Task Runners
PDF
Grunt All Day
PDF
Grunt & Front-end Workflow
PDF
Front-end tools
PDF
Introduction to Express and Grunt
PDF
Let Grunt do the work, focus on the fun! [Open Web Camp 2013]
PPTX
Tribal Nova Docker workshop
Get Gulping with Javascript Task Runners
Get Grulping with JavaScript Task Runners
Grunt All Day
Grunt & Front-end Workflow
Front-end tools
Introduction to Express and Grunt
Let Grunt do the work, focus on the fun! [Open Web Camp 2013]
Tribal Nova Docker workshop

What's hot (19)

PDF
Zero Downtime Deployment with Ansible
PDF
Jenkins and Groovy
PDF
MeaNstack on Docker
PDF
Zero Downtime Deployment with Ansible
PDF
Big query - Command line tools and Tips - (MOSG)
PPTX
Grunt and Bower
PDF
10 Cool Facts about Gradle
PDF
“warpdrive”, making Python web application deployment magically easy.
PDF
Stupid Buildout Tricks
PDF
Introduction to zc.buildout
PDF
From Dev to DevOps
PDF
DevOps(4) : Ansible(2) - (MOSG)
PPTX
The State of JavaScript (2015)
PDF
Create your very own Development Environment with Vagrant and Packer
PDF
Let Grunt do the work, focus on the fun!
PDF
5.node js
PDF
Devenez le plus heureux des Front-end avec Gulp.js
PDF
Docker workshop 0507 Taichung
PDF
How to Develop Puppet Modules: From Source to the Forge With Zero Clicks
Zero Downtime Deployment with Ansible
Jenkins and Groovy
MeaNstack on Docker
Zero Downtime Deployment with Ansible
Big query - Command line tools and Tips - (MOSG)
Grunt and Bower
10 Cool Facts about Gradle
“warpdrive”, making Python web application deployment magically easy.
Stupid Buildout Tricks
Introduction to zc.buildout
From Dev to DevOps
DevOps(4) : Ansible(2) - (MOSG)
The State of JavaScript (2015)
Create your very own Development Environment with Vagrant and Packer
Let Grunt do the work, focus on the fun!
5.node js
Devenez le plus heureux des Front-end avec Gulp.js
Docker workshop 0507 Taichung
How to Develop Puppet Modules: From Source to the Forge With Zero Clicks
Ad

Similar to Get Grulping with JavaScript Task Runners (Matt Gifford) (20)

PDF
Get Grulping with Javascript task runners
PDF
Automating Front-End Workflow
PDF
Workflow para desenvolvimento Web & Mobile usando grunt.js
PDF
Javascript is your (Auto)mate
PPTX
2015 - Basta! 2015, DE: JavaScript und build
PPTX
Single Page JavaScript WebApps... A Gradle Story
KEY
Railsconf2011 deployment tips_for_slideshare
PPTX
Grunt to automate JS build
PDF
GruntJS + Wordpress
PDF
What makes me "Grunt"?
PDF
The Fairy Tale of the One Command Build Script
PDF
Automating WordPress Theme Development
PDF
Npm scripts
PDF
Gradleintroduction 111010130329-phpapp01
PDF
Gradle Introduction
PDF
Grunt.js introduction
PPTX
PDF
Antons Kranga Building Agile Infrastructures
PDF
Workshop 3: JavaScript build tools
PDF
Having Fun with Play
Get Grulping with Javascript task runners
Automating Front-End Workflow
Workflow para desenvolvimento Web & Mobile usando grunt.js
Javascript is your (Auto)mate
2015 - Basta! 2015, DE: JavaScript und build
Single Page JavaScript WebApps... A Gradle Story
Railsconf2011 deployment tips_for_slideshare
Grunt to automate JS build
GruntJS + Wordpress
What makes me "Grunt"?
The Fairy Tale of the One Command Build Script
Automating WordPress Theme Development
Npm scripts
Gradleintroduction 111010130329-phpapp01
Gradle Introduction
Grunt.js introduction
Antons Kranga Building Agile Infrastructures
Workshop 3: JavaScript build tools
Having Fun with Play
Ad

More from Future Insights (20)

PDF
The Human Body in the IoT. Tim Cannon + Ryan O'Shea
PDF
Pretty pictures - Brandon Satrom
PDF
Putting real time into practice - Saul Diez-Guerra
PDF
Surviving the enterprise storm - @RianVDM
PDF
Exploring Open Date with BigQuery: Jenny Tong
PDF
A Universal Theory of Everything, Christopher Murphy
PDF
Horizon Interactive Awards, Mike Sauce & Jeff Jahn
PDF
Reading Your Users’ Minds: Empiricism, Design, and Human Behavior, Shane F. B...
PDF
Front End Development Transformation at Scale, Damon Deaner
PDF
Structuring Data from Unstructured Things. Sean Lorenz
PDF
Cinematic UX, Brad Weaver
PDF
The Future is Modular, Jonathan Snook
PDF
Designing an Enterprise CSS Framework is Hard, Stephanie Rewis
PDF
Accessibility Is More Than What Lies In The Code, Jennison Asuncion
PDF
Sunny with a Chance of Innovation: A How-To for Product Managers and Designer...
PDF
Designing for Dyslexia, Andrew Zusman
PDF
Beyond Measure, Erika Hall
PDF
Real Artists Ship, Haraldur Thorleifsson
PDF
Ok Computer. Peter Gasston
PDF
Digital Manuscripts Toolkit, using IIIF and JavaScript. Monica Messaggi Kaya
The Human Body in the IoT. Tim Cannon + Ryan O'Shea
Pretty pictures - Brandon Satrom
Putting real time into practice - Saul Diez-Guerra
Surviving the enterprise storm - @RianVDM
Exploring Open Date with BigQuery: Jenny Tong
A Universal Theory of Everything, Christopher Murphy
Horizon Interactive Awards, Mike Sauce & Jeff Jahn
Reading Your Users’ Minds: Empiricism, Design, and Human Behavior, Shane F. B...
Front End Development Transformation at Scale, Damon Deaner
Structuring Data from Unstructured Things. Sean Lorenz
Cinematic UX, Brad Weaver
The Future is Modular, Jonathan Snook
Designing an Enterprise CSS Framework is Hard, Stephanie Rewis
Accessibility Is More Than What Lies In The Code, Jennison Asuncion
Sunny with a Chance of Innovation: A How-To for Product Managers and Designer...
Designing for Dyslexia, Andrew Zusman
Beyond Measure, Erika Hall
Real Artists Ship, Haraldur Thorleifsson
Ok Computer. Peter Gasston
Digital Manuscripts Toolkit, using IIIF and JavaScript. Monica Messaggi Kaya

Recently uploaded (20)

DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPT
Teaching material agriculture food technology
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Modernizing your data center with Dell and AMD
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
NewMind AI Monthly Chronicles - July 2025
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Electronic commerce courselecture one. Pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
A Presentation on Artificial Intelligence
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Approach and Philosophy of On baking technology
PDF
Encapsulation theory and applications.pdf
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Encapsulation_ Review paper, used for researhc scholars
The AUB Centre for AI in Media Proposal.docx
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
MYSQL Presentation for SQL database connectivity
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Teaching material agriculture food technology
Advanced methodologies resolving dimensionality complications for autism neur...
Modernizing your data center with Dell and AMD
Spectral efficient network and resource selection model in 5G networks
NewMind AI Monthly Chronicles - July 2025
Dropbox Q2 2025 Financial Results & Investor Presentation
Electronic commerce courselecture one. Pdf
Network Security Unit 5.pdf for BCA BBA.
A Presentation on Artificial Intelligence
Building Integrated photovoltaic BIPV_UPV.pdf
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Approach and Philosophy of On baking technology
Encapsulation theory and applications.pdf
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Encapsulation_ Review paper, used for researhc scholars

Get Grulping with JavaScript Task Runners (Matt Gifford)

  • 1. Get Grulping with JavaScript Task Runners Matt Gifford @coldfumonkeh monkehworks.com
  • 2. OBLIGATORY QUOTE FROM HISTORICAL FIGURE COMING UP
  • 3. “life is really simple, but we insist on making it complicated” Confucius
  • 6. almost all quality improvement comes via simplification of design, manufacturing, layout, processes and procedures. Tom Peters
  • 7. almost all quality improvement comes via simplification of design, manufacturing, layout, processes and procedures. Tom Peters
  • 15. 0.4.x
  • 17. YOU NEED package.json Gruntfile.js
  • 19. $ npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sane defaults. Press ^C at any time to quit. name: (grunt_project) grunting_away version: (0.0.0) description: entry point: (index.js) test command: .... etc 0.0.1
  • 20. package.json { "name": "grunting_away", "version": "0.0.1", "description": "", "main": "index.js", "author": "Matt Gifford", "license": "ISC" }
  • 21. package.json { "name": "grunting_away", "version": "0.0.1" }
  • 22. INSTALLING GRUNT Use npm to install the required modules $ npm install < whatever the module name is > You may need sudo or Administrative rights
  • 23. INSTALLING GRUNT Grunt 0.3 requires a global install of the library Grunt 0.4 changed... a lot (for the better) Now has the ability to run different local versions $ npm install grunt-cli -g -g installs the CLI package globally. Good times
  • 24. INSTALLING GRUNT We have the global CLI. Now we need a local Grunt $ npm install grunt --save-dev
  • 25. $ grunt --version grunt-cli v0.1.13 grunt v0.4.5
  • 26. package.json { "name": "grunting_away", "version": "0.0.1", "devDependencies": { "grunt": "^0.4.5" } }
  • 27. package.json { "name": "grunting_away", "version": "0.0.1", } "devDependencies": { "grunt": "^0.4.5" }
  • 28. Gruntfile.js Lives in the root directory of your project Commit it into your source control repo! Holds your task configurations Can be written as Gruntfile.coffee (if that floats your boat)
  • 29. Gruntfile.js module.exports = function(grunt) { grunt.initConfig({ // Pure awesomeness will live here }); };
  • 30. VERSION CONTROL | -- package.json | -- Gruntfile.js commit these and share the wealth
  • 31. TEAM GRUNTING $ npm install
  • 32. THE CODE BASE | -- javascripts -- main.js -- formControls.js | -- stylesheets -- form.css -- main.css can be managed more effectively
  • 33. CSS CONCATENATION $ npm install grunt-contrib-concat --save-dev
  • 34. package.json { "name": "grunting_away", "version": "0.0.1", "devDependencies": { "grunt": "^0.4.5", "grunt-contrib-concat": "^0.4.0" } }
  • 35. Gruntfile.js module.exports = function(grunt) { grunt.initConfig({ // Pure awesomeness will live here }); grunt.loadNpmTasks('grunt-contrib-concat'); };
  • 36. Gruntfile.js grunt.initConfig({ concat : { css: { files: { 'stylesheets/engage.css' : ['stylesheets/*.css'] } } } });
  • 37. Gruntfile.js grunt.initConfig({ concat : { css: { files: { 'stylesheets/engage.css' : [ 'stylesheets/main.css', 'stylesheets/form.css' ] } } } });
  • 38. $ grunt concat Running "concat:css" (concat) task File stylesheets/engage.css created. Done, without errors. $ grunt concat:css Running "concat:css" (concat) task File stylesheets/engage.css created. Done, without errors.
  • 39. THE CODE BASE | -- stylesheets -- engage.css -- form.css -- main.css new file generated by Grunt
  • 40. Gruntfile.js grunt.initConfig({ concat : { css: { options: { banner: '/* Combined CSS file */n' }, /* snip */
  • 41. Gruntfile.js grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat : { css: { options: { banner: '/* <%= pkg.name %> combined file generated @ <%= grunt.template.today("dd-mm-yyyy") %> */n' }, /* snip */
  • 43. CSS MINIFICATION $ npm install grunt-contrib-cssmin --save-dev
  • 44. package.json { "name": "grunting_away", "version": "0.1.0", "devDependencies": { "grunt": "^0.4.5", "grunt-contrib-concat": "^0.4.0", "grunt-contrib-cssmin": "^0.9.0" } }
  • 45. Gruntfile.js module.exports = function(grunt) { grunt.initConfig({ // Pure awesomeness will live here }); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-cssmin'); };
  • 46. Gruntfile.js grunt.initConfig({ /* snip */ cssmin: { css: { files: { 'stylesheets/engage.min.css' : [ 'stylesheets/engage.css' ] } } }, });
  • 47. $ grunt cssmin Running "cssmin:css" (cssmin) task File stylesheets/engage.min.css created: 29.73 kB → 23.62 kB Done, without errors.
  • 48. THE CODE BASE | -- stylesheets -- engage.css -- engage.min.css -- form.css minified file -- main.css
  • 50. CACHE BUSTING $ npm install grunt-rev --save-dev
  • 51. Gruntfile.js grunt.loadNpmTasks('grunt-rev'); rev: { css: { files: { src: ['stylesheets/engage.min.css'] } } },
  • 52. $ grunt rev:css Running "rev:css" (rev) task stylesheets/engage.min.css >> 73a5cf64.engage.min.css Done, without errors.
  • 53. THE CODE BASE | -- stylesheets -- 73a5cf64.engage.min.css -- engage.css -- engage.min.css -- form.css -- main.css hashed minified file
  • 54. THE CODE BASE | -- stylesheets -- 73a5cf64.engage.min.css -- engage.css -- engage.min.css -- form.css -- main.css we don’t need these
  • 55. CLEAN UP OPERATION $ npm install grunt-contrib-clean --save-dev
  • 56. Gruntfile.js grunt.loadNpmTasks('grunt-contrib-clean'); clean: { combinedcss: { src: ['stylesheets/engage.css'] }, mincss: { src: ['stylesheets/engage.min.css'] }, revcss: { src: ['stylesheets/*engage.min.css'] } },
  • 57. TOO MANY TASKS We already have a load of tasks to run What happens when we need to run them all? Type each command out?
  • 58. REMEMBER simplification of processes and procedures
  • 59. Gruntfile.js grunt.registerTask('css', [ 'clean:revcss', 'concat:css', 'cssmin:css', 'clean:combinedcss', 'rev:css', 'clean:mincss' ]);
  • 60. $ grunt css Running "clean:revcss" (clean) task Cleaning stylesheets/73a5cf64.engage.min.css...OK Running "concat:css" (concat) task File stylesheets/engage.css created. Running "cssmin:css" (cssmin) task File stylesheets/engage.min.css created: 29.73 kB → 23.62 kB Running "clean:combinedcss" (clean) task Cleaning stylesheets/engage.css...OK Running "rev:css" (rev) task stylesheets/engage.min.css >> 73a5cf64.engage.min.css Running "clean:mincss" (clean) task Done, without errors.
  • 61. THE CODE BASE | -- stylesheets -- 73a5cf64.engage.min.css -- form.css -- main.css
  • 63. WATCHING FOR FILE CHANGES $ npm install grunt-contrib-watch --save-dev
  • 64. Gruntfile.js grunt.loadNpmTasks('grunt-contrib-watch'); watch: { css: { files: [ 'stylesheets/form.css', 'stylesheets/main.css' ], tasks: ['css'] } },
  • 66. $ grunt Running "watch" task Waiting... >> File "stylesheets/main.css" changed. Running "clean:revcss" (clean) task Cleaning stylesheets/73a5cf64.engage.min.css...OK Running "concat:css" (concat) task File stylesheets/engage.css created. Running "cssmin:css" (cssmin) task File stylesheets/engage.min.css created: 29.73 kB → 23.62 kB Running "clean:combinedcss" (clean) task Cleaning stylesheets/engage.css...OK Running "rev:css" (rev) task stylesheets/engage.min.css >> 73a5cf64.engage.min.css Running "clean:mincss" (clean) task Done, without errors. Completed in 0.485s at Mon Jun 02 2014 02:26:21 GMT+0100 (BST) - Waiting...
  • 68. THE CODE BASE | -- javascripts -- main.js -- formControls.js
  • 69. JAVASCRIPT MANAGEMENT $ npm install grunt-contrib-jshint --save-dev $ npm install grunt-contrib-uglify --save-dev $ npm install grunt-remove-logging --save-dev
  • 70. GRUNTFILE.JS grunt.loadNpmTasks('grunt-contrib-jshint'); jshint: { options: { curly: true, eqeqeq: true, eqnull: true, browser: true, globals: { jQuery: true }, }, all: ['Gruntfile.js','javascripts/main.js'] },
  • 71. GRUNTFILE.JS grunt.loadNpmTasks('grunt-contrib-uglify'); uglify : { js: { files: { 'javascripts/engage.min.js' : [ 'javascripts/main.js' ] } } },
  • 72. GRUNTFILE.JS grunt.loadNpmTasks('grunt-remove-logging'); removelogging: { dist: { src: 'javascripts/engage.min.js', dest: 'javascripts/engage.min.js' } },
  • 73. GRUNTFILE.JS rev: { css: { files: { src: ['stylesheets/engage.min.css'] } }, js: { files: { src: ['javascripts/engage.min.js'] } } },
  • 74. GRUNTFILE.JS rev: { css: { files: { src: ['stylesheets/engage.min.css'] } }, js: { files: { src: ['javascripts/engage.min.js'] } } },
  • 75. REMEMBER simplification of processes and procedures
  • 76. GRUNTFILE.JS grunt.registerTask('js', [ 'jshint', 'clean:jsrev', 'uglify:js', 'removelogging', 'rev:js', 'clean:minjs' ]);
  • 77. GRUNTFILE.JS watch: { js: { files: ['javascripts/main.js'], tasks: ['js'] }, css: { files: [ 'stylesheets/form.css', 'stylesheets/main.css' ], tasks: ['css'] } },
  • 78. GRUNTFILE.JS watch: { js: { files: ['javascripts/main.js'], tasks: ['js'] }, css: { files: [ 'stylesheets/form.css', 'stylesheets/main.css' ], tasks: ['css'] } } },
  • 79. $ grunt Running "watch" task Waiting... >> File "javascripts/main.js" changed. Running "jshint:all" (jshint) task javascripts/main.js 1 |console.log('monkeh love is good love') ^ Missing semicolon. >> 1 error in 2 files Warning: Task "jshint:all" failed. Use --force to continue. Aborted due to warnings. Completed in 2.090s at Mon Jun 02 2014 03:13:55 GMT+0100 (BST) - Waiting...
  • 80. $ grunt Running "watch" task Waiting... >> File "javascripts/main.js" changed. Running "jshint:all" (jshint) task >> 2 files lint free. Running "clean:jsrev" (clean) task Cleaning javascripts/engage.min.js...OK Running "uglify:js" (uglify) task File javascripts/engage.min.js created: 21 B → 21 B Running "removelogging:dist" (removelogging) task Removed 1 logging statements from javascripts/engage.min.js Running "rev:js" (rev) task javascripts/engage.min.js >> 0c115107.engage.min.js Running "clean:minjs" (clean) task Done, without errors. Completed in 0.721s at Mon Jun 02 2014 03:14:05 GMT+0100 (BST) - Waiting...
  • 82. PERFORMING HTTP REQUESTS $ npm install grunt-http --save-dev
  • 83. Gruntfile.js grunt.loadNpmTasks('grunt-http'); http: { reload: { options: { url: 'http://127.0.0.1:8000/index.cfm?reload=true' } } },
  • 84. Gruntfile.js grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), local_settings: { local_url: '' }, ... http: { reload: { options: { url: '<%= local_settings.local_url %>' } } },
  • 86. Gruntfile.js grunt.registerTask('checklocalconf', 'Check if the local config JSON file exists', function(arg) { if(grunt.file.exists('grunt_local_settings.json')) { grunt.task.run('watch'); } else { grunt.log.errorlns(''); grunt.log.errorlns('The grunt_local_settings.json file does not appear to exist.'); grunt.log.errorlns(''); grunt.log.errorlns('{'); grunt.log.errorlns(' "local_url": "http://your_local_server/?reload"'); grunt.log.errorlns('}'); grunt.log.errorlns(''); grunt.fail.fatal('Please create and save the grunt_local_settings.json file.'); }; });
  • 87. Gruntfile.js grunt.registerTask('http_watcher', 'Set the local url before running the watch command', function() { var jsonLocalSettings = grunt.file.readJSON("grunt_local_settings.json"); grunt.config.set('local_settings', jsonLocalSettings); grunt.config.requires('local_settings'); grunt.task.run('http:reload'); });
  • 88. Gruntfile.js watch: { js: { files: ['javascripts/main.js'], tasks: ['js'] }, css: { files: [ 'stylesheets/form.css', 'stylesheets/main.css' ], tasks: ['css'] }, cfcs: { files: ['cfcs/*.cfc'], tasks: ['http_watcher'] } },
  • 89. $ grunt Running "checklocalconf" task Waiting... >> >> The grunt_local_settings.json file does not appear to exist. >> Please create it in this directory with the following content (the URL >> for your local app with reload action): >> >> { >> "local_url": "http://your_local_server/?reload" >> } >> Fatal error: Please create and save the grunt_local_settings.json file then re-run this command.
  • 90. $ grunt Running "checklocalconf" task Running "watch" task Waiting... >> File "cfcs/test.cfc" changed. Running "http_watcher" task Running "http:reload" (http) task >> 200 Done, without errors. Completed in 2.061s at Tue Jun 03 2014 12:01:44 GMT+0100 (BST) - Waiting...
  • 91. INJECTING ASSETS $ npm install grunt-injector --save-dev
  • 92. Gruntfile.js grunt.loadNpmTasks('grunt-injector'); injector: { options: {}, css: { files: { 'layout.cfm': ['stylesheets/*engage.min.css'], } }, js: { files: { 'layout.cfm': ['javascripts/*engage.min.js'], } } }
  • 94. Gruntfile.js grunt.registerTask('css', [ 'clean:revcss', 'concat:css', 'cssmin:css', 'clean:combinedcss', 'rev:css', 'clean:mincss', 'injector:css' ]);
  • 96. TIDY UP There are no limits to the number of plugins you can use You may also be duplicating file paths a lot Your Gruntfile could get messy quickly
  • 97. Gruntfile.js grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-csslint'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-http'); grunt.loadNpmTasks('grunt-injector'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-remove-logging'); grunt.loadNpmTasks('grunt-rev'); grunt.loadNpmTasks('grunt-notify');
  • 98. TIDY UP $ npm install matchdep --save-dev
  • 100. ASSIGN VARIABLES Use the variable system to reduce duplicate text
  • 101. Gruntfile.js grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), minCSS: 'stylesheets/engage.min.css', }); cssmin: { css: { files: { '<%= minCSS %>' : [ 'stylesheets/engage.css' ] } } }, clean: { mincss: { src: ['<%= minCSS %>'] } }
  • 102. WHAT ELSE CAN IT DO? image optimisation and resizing git integration run unit tests (e.g. Jasmine) templating ...
  • 103. WHAT ELSE CAN IT DO? pretty much anything you want it to http://gruntjs.com/plugins
  • 107. INSTALLING GULP As a system wide module $ npm install gulp -g
  • 108. INSTALLING GULP Getting a local gulp version for the project $ npm install gulp --save-dev
  • 109. gulpfile.js Lives in the root directory of your project Commit it into your source control repo! Holds your task configurations Lowercase file name!
  • 110. gulpfile.js // Include gulp var gulp = require('gulp'); gulp.task('default', function() { // place code for your default task here });
  • 113. gulpfile.js // Include gulp var gulp = require('gulp'); // Include Our Plugins var jshint = require('gulp-jshint'); var concat = require('gulp-concat'); var uglify = require('gulp-uglify'); var rename = require('gulp-rename'); var header = require('gulp-header');
  • 114. gulpfile.js // Default Task gulp.task('default', ['watch']); // Watch Files For Changes gulp.task('watch', function() { gulp.watch('js/*.js', ['lint', 'scripts']); });
  • 115. gulpfile.js // Lint Task gulp.task('lint', function() { return gulp.src('js/*.js') .pipe(jshint()) .pipe(jshint.reporter('default')); });
  • 116. gulpfile.js // Concatenate & Minify JS gulp.task('scripts', function() { var headerValue = "Evaluated by gulp.n"; return gulp.src('js/*.js') .pipe(concat('combined.js')) .pipe(header(headerValue)) .pipe(gulp.dest('dist')) .pipe(rename('combined.min.js')) .pipe(uglify()) .pipe(header(headerValue)) .pipe(gulp.dest('dist')); });
  • 120. Streaming and piping give speed enhancements Code over configuration Still early adoption - plugins limited JS / Node exposure beneficial (?)
  • 121. Sub tasks easily managed Impressive number of plugins and extensions I/O issues and speed (in comparison) Configuration could get messy
  • 122. ITS NOT A CONTEST
  • 123. HAPPY
  • 124. FINAL WORDS Save your config files (repo) Use skeleton variation across your projects Create Employ Refine Relax
  • 125. FINAL WORDS Has the potential to be addictive Check for updates and improved methods Use your time wisely
  • 130. Thank you! Matt Gifford @coldfumonkeh monkehworks.com