SlideShare a Scribd company logo
1 of 130
Download to read offline
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
http://nodejs.org
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
$ 
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 */
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
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...
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'], 
} 
} 
}
Gruntfile.js 
grunt.registerTask('css', 
[ 
'clean:revcss', 
'concat:css', 
'cssmin:css', 
'clean:combinedcss', 
'rev:css', 
'clean:mincss', 
'injector:css' 
]);
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
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
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
Thank you! 
Matt Gifford 
@coldfumonkeh 
monkehworks.com

More Related Content

What's hot

Zero Downtime Deployment with Ansible
Zero Downtime Deployment with AnsibleZero Downtime Deployment with Ansible
Zero Downtime Deployment with AnsibleStein Inge Morisbak
 
Jenkins and Groovy
Jenkins and GroovyJenkins and Groovy
Jenkins and GroovyKiyotaka Oku
 
MeaNstack on Docker
MeaNstack on DockerMeaNstack on Docker
MeaNstack on DockerDaniel Ku
 
Zero Downtime Deployment with Ansible
Zero Downtime Deployment with AnsibleZero Downtime Deployment with Ansible
Zero Downtime Deployment with AnsibleStein Inge Morisbak
 
Big query - Command line tools and Tips - (MOSG)
Big query - Command line tools and Tips - (MOSG)Big query - Command line tools and Tips - (MOSG)
Big query - Command line tools and Tips - (MOSG)Soshi Nemoto
 
10 Cool Facts about Gradle
10 Cool Facts about Gradle10 Cool Facts about Gradle
10 Cool Facts about GradleEvgeny Goldin
 
“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.“warpdrive”, making Python web application deployment magically easy.
“warpdrive”, making Python web application deployment magically easy.Graham Dumpleton
 
Introduction to zc.buildout
Introduction to zc.buildoutIntroduction to zc.buildout
Introduction to zc.buildoutRicardo Newbery
 
From Dev to DevOps
From Dev to DevOpsFrom Dev to DevOps
From Dev to DevOpsAgile Spain
 
DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)Soshi Nemoto
 
The State of JavaScript (2015)
The State of JavaScript (2015)The State of JavaScript (2015)
The State of JavaScript (2015)Domenic Denicola
 
Augeas, swiss knife resources for your puppet tree
Augeas, swiss knife resources for your puppet treeAugeas, swiss knife resources for your puppet tree
Augeas, swiss knife resources for your puppet treeJulien Pivotto
 
Create your very own Development Environment with Vagrant and Packer
Create your very own Development Environment with Vagrant and PackerCreate your very own Development Environment with Vagrant and Packer
Create your very own Development Environment with Vagrant and Packerfrastel
 
Let Grunt do the work, focus on the fun!
Let Grunt do the work, focus on the fun!Let Grunt do the work, focus on the fun!
Let Grunt do the work, focus on the fun!Dirk Ginader
 
Devenez le plus heureux des Front-end avec Gulp.js
Devenez le plus heureux des Front-end avec Gulp.jsDevenez le plus heureux des Front-end avec Gulp.js
Devenez le plus heureux des Front-end avec Gulp.jsRémy Savard
 
Docker workshop 0507 Taichung
Docker workshop 0507 Taichung Docker workshop 0507 Taichung
Docker workshop 0507 Taichung Paul Chao
 
How to Develop Puppet Modules: From Source to the Forge With Zero Clicks
How to Develop Puppet Modules: From Source to the Forge With Zero ClicksHow to Develop Puppet Modules: From Source to the Forge With Zero Clicks
How to Develop Puppet Modules: From Source to the Forge With Zero ClicksCarlos Sanchez
 

What's hot (20)

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

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

Get Grulping with Javascript task runners
Get Grulping with Javascript task runnersGet Grulping with Javascript task runners
Get Grulping with Javascript task runnersdevObjective
 
Automating Front-End Workflow
Automating Front-End WorkflowAutomating Front-End Workflow
Automating Front-End WorkflowDimitris Tsironis
 
Workflow para desenvolvimento Web & Mobile usando grunt.js
Workflow para desenvolvimento Web & Mobile usando grunt.jsWorkflow para desenvolvimento Web & Mobile usando grunt.js
Workflow para desenvolvimento Web & Mobile usando grunt.jsDavidson Fellipe
 
Javascript is your (Auto)mate
Javascript is your (Auto)mateJavascript is your (Auto)mate
Javascript is your (Auto)mateCodemotion
 
2015 - Basta! 2015, DE: JavaScript und build
2015 - Basta! 2015, DE: JavaScript und build2015 - Basta! 2015, DE: JavaScript und build
2015 - Basta! 2015, DE: JavaScript und buildDaniel Fisher
 
Single Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle StorySingle Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle StoryKon Soulianidis
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
What makes me "Grunt"?
What makes me "Grunt"? What makes me "Grunt"?
What makes me "Grunt"? Fabien Doiron
 
The Fairy Tale of the One Command Build Script
The Fairy Tale of the One Command Build ScriptThe Fairy Tale of the One Command Build Script
The Fairy Tale of the One Command Build ScriptDocker, Inc.
 
Automating WordPress Theme Development
Automating WordPress Theme DevelopmentAutomating WordPress Theme Development
Automating WordPress Theme DevelopmentHardeep Asrani
 
Gradleintroduction 111010130329-phpapp01
Gradleintroduction 111010130329-phpapp01Gradleintroduction 111010130329-phpapp01
Gradleintroduction 111010130329-phpapp01Tino Isnich
 
Antons Kranga Building Agile Infrastructures
Antons Kranga   Building Agile InfrastructuresAntons Kranga   Building Agile Infrastructures
Antons Kranga Building Agile InfrastructuresAntons Kranga
 
Workshop 3: JavaScript build tools
Workshop 3: JavaScript build toolsWorkshop 3: JavaScript build tools
Workshop 3: JavaScript build toolsVisual Engineering
 
Guide to Node.js: Basic to Advanced
Guide to Node.js: Basic to AdvancedGuide to Node.js: Basic to Advanced
Guide to Node.js: Basic to AdvancedEspeo Software
 

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

Get Grulping with Javascript task runners
Get Grulping with Javascript task runnersGet Grulping with Javascript task runners
Get Grulping with Javascript task runners
 
Automating Front-End Workflow
Automating Front-End WorkflowAutomating Front-End Workflow
Automating Front-End Workflow
 
Workflow para desenvolvimento Web & Mobile usando grunt.js
Workflow para desenvolvimento Web & Mobile usando grunt.jsWorkflow para desenvolvimento Web & Mobile usando grunt.js
Workflow para desenvolvimento Web & Mobile usando grunt.js
 
Javascript is your (Auto)mate
Javascript is your (Auto)mateJavascript is your (Auto)mate
Javascript is your (Auto)mate
 
2015 - Basta! 2015, DE: JavaScript und build
2015 - Basta! 2015, DE: JavaScript und build2015 - Basta! 2015, DE: JavaScript und build
2015 - Basta! 2015, DE: JavaScript und build
 
Single Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle StorySingle Page JavaScript WebApps... A Gradle Story
Single Page JavaScript WebApps... A Gradle Story
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
Grunt to automate JS build
Grunt to automate JS buildGrunt to automate JS build
Grunt to automate JS build
 
GruntJS + Wordpress
GruntJS + WordpressGruntJS + Wordpress
GruntJS + Wordpress
 
What makes me "Grunt"?
What makes me "Grunt"? What makes me "Grunt"?
What makes me "Grunt"?
 
The Fairy Tale of the One Command Build Script
The Fairy Tale of the One Command Build ScriptThe Fairy Tale of the One Command Build Script
The Fairy Tale of the One Command Build Script
 
Automating WordPress Theme Development
Automating WordPress Theme DevelopmentAutomating WordPress Theme Development
Automating WordPress Theme Development
 
Npm scripts
Npm scriptsNpm scripts
Npm scripts
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
 
Gradleintroduction 111010130329-phpapp01
Gradleintroduction 111010130329-phpapp01Gradleintroduction 111010130329-phpapp01
Gradleintroduction 111010130329-phpapp01
 
Grunt.js introduction
Grunt.js introductionGrunt.js introduction
Grunt.js introduction
 
GradleFX
GradleFXGradleFX
GradleFX
 
Antons Kranga Building Agile Infrastructures
Antons Kranga   Building Agile InfrastructuresAntons Kranga   Building Agile Infrastructures
Antons Kranga Building Agile Infrastructures
 
Workshop 3: JavaScript build tools
Workshop 3: JavaScript build toolsWorkshop 3: JavaScript build tools
Workshop 3: JavaScript build tools
 
Guide to Node.js: Basic to Advanced
Guide to Node.js: Basic to AdvancedGuide to Node.js: Basic to Advanced
Guide to Node.js: Basic to Advanced
 

More from Future Insights

The Human Body in the IoT. Tim Cannon + Ryan O'Shea
The Human Body in the IoT. Tim Cannon + Ryan O'SheaThe Human Body in the IoT. Tim Cannon + Ryan O'Shea
The Human Body in the IoT. Tim Cannon + Ryan O'SheaFuture Insights
 
Pretty pictures - Brandon Satrom
Pretty pictures - Brandon SatromPretty pictures - Brandon Satrom
Pretty pictures - Brandon SatromFuture Insights
 
Putting real time into practice - Saul Diez-Guerra
Putting real time into practice - Saul Diez-GuerraPutting real time into practice - Saul Diez-Guerra
Putting real time into practice - Saul Diez-GuerraFuture Insights
 
Surviving the enterprise storm - @RianVDM
Surviving the enterprise storm - @RianVDMSurviving the enterprise storm - @RianVDM
Surviving the enterprise storm - @RianVDMFuture Insights
 
Exploring Open Date with BigQuery: Jenny Tong
Exploring Open Date with BigQuery: Jenny TongExploring Open Date with BigQuery: Jenny Tong
Exploring Open Date with BigQuery: Jenny TongFuture Insights
 
A Universal Theory of Everything, Christopher Murphy
A Universal Theory of Everything, Christopher MurphyA Universal Theory of Everything, Christopher Murphy
A Universal Theory of Everything, Christopher MurphyFuture Insights
 
Horizon Interactive Awards, Mike Sauce & Jeff Jahn
Horizon Interactive Awards, Mike Sauce & Jeff JahnHorizon Interactive Awards, Mike Sauce & Jeff Jahn
Horizon Interactive Awards, Mike Sauce & Jeff JahnFuture Insights
 
Reading Your Users’ Minds: Empiricism, Design, and Human Behavior, Shane F. B...
Reading Your Users’ Minds: Empiricism, Design, and Human Behavior, Shane F. B...Reading Your Users’ Minds: Empiricism, Design, and Human Behavior, Shane F. B...
Reading Your Users’ Minds: Empiricism, Design, and Human Behavior, Shane F. B...Future Insights
 
Front End Development Transformation at Scale, Damon Deaner
Front End Development Transformation at Scale, Damon DeanerFront End Development Transformation at Scale, Damon Deaner
Front End Development Transformation at Scale, Damon DeanerFuture Insights
 
Structuring Data from Unstructured Things. Sean Lorenz
Structuring Data from Unstructured Things. Sean LorenzStructuring Data from Unstructured Things. Sean Lorenz
Structuring Data from Unstructured Things. Sean LorenzFuture Insights
 
Cinematic UX, Brad Weaver
Cinematic UX, Brad WeaverCinematic UX, Brad Weaver
Cinematic UX, Brad WeaverFuture Insights
 
The Future is Modular, Jonathan Snook
The Future is Modular, Jonathan SnookThe Future is Modular, Jonathan Snook
The Future is Modular, Jonathan SnookFuture Insights
 
Designing an Enterprise CSS Framework is Hard, Stephanie Rewis
Designing an Enterprise CSS Framework is Hard, Stephanie RewisDesigning an Enterprise CSS Framework is Hard, Stephanie Rewis
Designing an Enterprise CSS Framework is Hard, Stephanie RewisFuture Insights
 
Accessibility Is More Than What Lies In The Code, Jennison Asuncion
Accessibility Is More Than What Lies In The Code, Jennison AsuncionAccessibility Is More Than What Lies In The Code, Jennison Asuncion
Accessibility Is More Than What Lies In The Code, Jennison AsuncionFuture Insights
 
Sunny with a Chance of Innovation: A How-To for Product Managers and Designer...
Sunny with a Chance of Innovation: A How-To for Product Managers and Designer...Sunny with a Chance of Innovation: A How-To for Product Managers and Designer...
Sunny with a Chance of Innovation: A How-To for Product Managers and Designer...Future Insights
 
Designing for Dyslexia, Andrew Zusman
Designing for Dyslexia, Andrew ZusmanDesigning for Dyslexia, Andrew Zusman
Designing for Dyslexia, Andrew ZusmanFuture Insights
 
Beyond Measure, Erika Hall
Beyond Measure, Erika HallBeyond Measure, Erika Hall
Beyond Measure, Erika HallFuture Insights
 
Real Artists Ship, Haraldur Thorleifsson
Real Artists Ship, Haraldur ThorleifssonReal Artists Ship, Haraldur Thorleifsson
Real Artists Ship, Haraldur ThorleifssonFuture Insights
 
Ok Computer. Peter Gasston
Ok Computer. Peter GasstonOk Computer. Peter Gasston
Ok Computer. Peter GasstonFuture Insights
 
Digital Manuscripts Toolkit, using IIIF and JavaScript. Monica Messaggi Kaya
Digital Manuscripts Toolkit, using IIIF and JavaScript. Monica Messaggi KayaDigital Manuscripts Toolkit, using IIIF and JavaScript. Monica Messaggi Kaya
Digital Manuscripts Toolkit, using IIIF and JavaScript. Monica Messaggi KayaFuture Insights
 

More from Future Insights (20)

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

Recently uploaded

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 

Recently uploaded (20)

Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 

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
  • 8.
  • 9.
  • 10.
  • 12.
  • 15. 0.4.x
  • 16. http://gruntjs.com/plugins 2,954 as of 8:30am 5th June 2014
  • 17. YOU NEED package.json Gruntfile.js
  • 18.
  • 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 */
  • 42.
  • 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
  • 49.
  • 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...
  • 67.
  • 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'], } } }
  • 93.
  • 94. Gruntfile.js grunt.registerTask('css', [ 'clean:revcss', 'concat:css', 'cssmin:css', 'clean:combinedcss', 'rev:css', 'clean:mincss', 'injector:css' ]);
  • 95.
  • 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
  • 104.
  • 106. http://gulpjs.com/plugins/ 635 as of 8:30am 5th June 2014
  • 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')); });
  • 118.
  • 119.
  • 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
  • 126.
  • 127.
  • 128.
  • 129.
  • 130. Thank you! Matt Gifford @coldfumonkeh monkehworks.com