Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Giving your Development more Grunt - FOWA Londo...
Search
Jack Franklin
October 25, 2013
Technology
5
660
Giving your Development more Grunt - FOWA London 2013
An in-depth introduction to GruntJS and some of the best plugins available.
Jack Franklin
October 25, 2013
Tweet
Share
More Decks by Jack Franklin
See All by Jack Franklin
Advanced React Meetup: Testing JavaScript
jackfranklin
1
240
Components on the Web: Frontend NE
jackfranklin
1
830
ReactiveConf: Lessons Migrating Complex Software
jackfranklin
0
500
Front Trends: Migrating complex software
jackfranklin
1
830
Migrating from Angular to React: Manc React
jackfranklin
1
200
Half Stack Fest: Webpack
jackfranklin
4
570
FullStackFest: Elm for JS Developers
jackfranklin
1
260
Codelicious: Intro to ES2015
jackfranklin
0
400
PolyConf: Elm for JS Developers
jackfranklin
0
280
Other Decks in Technology
See All in Technology
StrandsとNeptuneを使ってナレッジグラフを構築する
yakumo
1
130
We Built for Predictability; The Workloads Didn’t Care
stahnma
0
150
[CV勉強会@関東 World Model 読み会] Orbis: Overcoming Challenges of Long-Horizon Prediction in Driving World Models (Mousakhan+, NeurIPS 2025)
abemii
0
150
Codex 5.3 と Opus 4.6 にコーポレートサイトを作らせてみた / Codex 5.3 vs Opus 4.6
ama_ch
0
220
SREじゃなかった僕らがenablingを通じて「SRE実践者」になるまでのリアル / SRE Kaigi 2026
aeonpeople
6
2.6k
量子クラウドサービスの裏側 〜Deep Dive into OQTOPUS〜
oqtopus
0
150
22nd ACRi Webinar - NTT Kawahara-san's slide
nao_sumikawa
0
120
顧客との商談議事録をみんなで読んで顧客解像度を上げよう
shibayu36
0
340
私たち準委任PdEは2つのプロダクトに挑戦する ~ソフトウェア、開発支援という”二重”のプロダクトエンジニアリングの実践~ / 20260212 Naoki Takahashi
shift_evolve
PRO
2
210
コンテナセキュリティの最新事情 ~ 2026年版 ~
kyohmizu
7
2.4k
ClickHouseはどのように大規模データを活用したAIエージェントを全社展開しているのか
mikimatsumoto
0
270
SchooでVue.js/Nuxtを技術選定している理由
yamanoku
3
210
Featured
See All Featured
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
950
How to Talk to Developers About Accessibility
jct
2
140
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
330
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
0
190
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
470
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
A Soul's Torment
seathinner
5
2.3k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
0
260
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
3.6k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
117
110k
Into the Great Unknown - MozCon
thekraken
40
2.3k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.9k
Transcript
GIVING YOUR DEVELOPMENT MORE GRUNT @jack_franklin #FOWA
comp-sci student javascript / ruby author & blogger
THANKS ADDY!
None
0.4.1
PLUGINS
NODE
npm
WINDOWS
npm install grunt-cli -g installing grunt the package to install
install it globally (system wide)
mkdir my-new-project cd my-new-project new project
{ "name": "my-sample-app", "version": "0.0.0", "devDependencies": { "grunt": "0.4.1" }
} package.json
install deps npm install
module.exports = function(grunt) { grunt.initConfig({ // config goes here });
}; Gruntfile.js
Gruntfile.js package.json src/ - one.js - two.js - three.js src
files
npm install grunt-contrib-uglify --save-dev uglify plugin
{ ... "devDependencies": { "grunt": "0.4.1", "grunt-contrib-uglify": "~0.2.4" } }
package.json
module.exports = function(grunt) { grunt.initConfig({ // config goes here });
grunt.loadNpmTasks(“grunt- contrib-uglify”); }; Gruntfile.js
module.exports = function(grunt) { grunt.initConfig({ uglify: { minify: { files:
{ 'dist/out.js': ['src/*.js'] } } } }); ... }; Gruntfile.js
> grunt uglify Running "uglify:minify" (uglify) task File "dist/out.js" created.
Done, without errors. Running the task
grunt.loadNpmTasks(...); grunt.registerTask(“default”, “uglify”); Gruntfile.js > grunt # now runs the
uglify task
npm install grunt-contrib-jshint --save-dev JSHint
grunt.loadNpmTasks(“grunt-contrib- uglify”); grunt.loadNpmTasks(“grunt-contrib- jshint”); Gruntfile.js
uglify: { /* snip */ }, jshint: { all: ['Gruntfile.js',
'src/ *.js'] }, // rest of Gruntfile Gruntfile.js
> grunt jshint Running "jshint:all" (jshint) task >> 4 files
lint free. Done, without errors. Running the task
grunt.registerTask(“default”, [“jshint”, “uglify”]); Default Task
> grunt Running "jshint:all" (jshint) task >> 4 files lint
free. Running "uglify:minify" (uglify) task File "dist/out.js" created. Done, without errors. Running grunt
// JSHint won't like the missing // semi colon console.log("file
2") src/two.js
Running "jshint:all" (jshint) task Linting src/two.js ...ERROR [L2:C22] W033: Missing
semicolon. console.log("file 2") Warning: Task "jshint:all" failed. Use --force to continue. Aborted due to warnings. Running grunt
Multi Tasks lots of tasks can have different configurations
module.exports = function(grunt) { grunt.initConfig({ uglify: { minify: { files:
{ 'dist/out.js': ['src/*.js'] } } } }); ... }; Gruntfile.js
uglify: { minify: { /* snip */ }, withBanner: {
options: { banner: "/*Hello World*/" }, files: { 'dist/out.js': ['src/*.js'] } } }, // rest of Gruntfile Gruntfile.js
> grunt uglify:withBanner Running "uglify:withBanner" (uglify) task File "dist/out.js" created.
Done, without errors. Running a task
> cat dist/out.js /*Hello World*/console.log("file 1"),console.log("file 3"),console.log("file 2"); Gruntfile.js
grunt.registerTask("default", ["jshint", "uglify:withBanner"]); Gruntfile.js
npm install grunt-contrib-watch --save-dev Watching
grunt.loadNpmTasks('grunt-contrib-watch'); Watching
uglify: { /*snip*/ }, watch: { files: [‘src/*.js’, ‘Gruntfile.js’], tasks:
[‘jshint’], }, jshint: { /*snip*/ } Gruntfile.js
> grunt watch Running "watch" task Waiting...OK >> File "src/two.js"
changed. Running "jshint:all" (jshint) task >> 4 files lint free. Done, without errors. Completed in 0.470s at Wed Oct 23 2013 14:27:08 GMT+0100 (BST) - Waiting... Watching
Watching Running JSHint constantly Checking tests haven’t broken Auto compiling
Sass/Less
Notifications npm install grunt-notify --save-dev grunt.loadNpmTasks('grunt-contrib-notify');
None
Testing npm install grunt-contrib-jasmine --save- dev grunt.loadNpmTasks('grunt-contrib- jasmine');
Gruntfile.js jshint: { /* snip */ }, jasmine: { test:
{ src: 'src/*.js', options: { specs: 'spec/*.js' } } }, watch: { /*snip */ },
spec/test.js describe("my app", function() { it("passes", function() { expect(two()).toEqual(2); });
});
src/two.js window.two = function() { return 2; };
Testing > grunt jasmine Running "jasmine:test" (jasmine) task Testing jasmine
specs via phantom . 1 spec in 0.001s. >> 0 failures Done, without errors.
Default Task grunt.registerTask("default", [ "jshint", "jasmine", "uglify:withBanner" ]);
Default Task Running "jshint:all" (jshint) task >> 4 files lint
free. Running "jasmine:test" (jasmine) task Testing jasmine specs via phantom . 1 spec in 0.002s. >> 0 failures Running "uglify:withBanner" (uglify) task File "dist/out.js" created. Done, without errors.
Errors Running "jshint:all" (jshint) task >> 4 files lint free.
Running "jasmine:test" (jasmine) task Testing jasmine specs via phantom x my app:: passes: failed Expected 2 to equal 3. (1) 1 spec in 0.002s. >> 1 failures
npm install grunt-concurrent --save-dev grunt.loadNpmTasks('grunt-concurrent'); Concurrent
concurrent: { target1: ['jasmine', 'jshint'] } grunt.registerTask("default", [ "concurrent:target1", "uglify:withBanner"
]); Gruntfile.js
Running "concurrent:target1" (concurrent) task Running "jshint:all" (jshint) task >> 4
files lint free. Done, without errors. Running "jasmine:test" (jasmine) task Testing jasmine specs via phantom 1 spec in 0.001s. >> 0 failures Done, without errors. Running "uglify:withBanner" (uglify) task File "dist/out.js" created. Done, without errors.
None
"src/*.js" Tidying Up
grunt.initConfig({ srcFiles: "src/*.js", uglify: { /*snip */ }, ... });
Defining Vars
jshint: { all: [ 'Gruntfile.js', '<%= srcFiles %>' ] },
Using Vars
define once refer lots change once
grunt.initConfig({ srcFiles: "src/*.js", outFile: "dist/out.js", uglify: { /* snip */
}, ... }); More Vars
minify: { files: { '<%= outFile %>': ['<%= srcFiles %>']
} } More Vars
grunt.loadNpmTasks("grunt-contrib- uglify"); grunt.loadNpmTasks("grunt-contrib- jshint"); grunt.loadNpmTasks("grunt-contrib- watch"); grunt.loadNpmTasks("grunt-contrib- jasmine"); grunt.loadNpmTasks("grunt- notify");
Match Dep
npm install matchdep --save-dev Match Dep
// replace all the loadNpmTask() lines with: require('matchdep') .filterDev('grunt-*') .forEach(grunt.loadNpmTasks);
Match Dep
“work less, do more, make awesome” -@addyosmani
be lazy automate lessen friction
“embrace the ecosystem” -me, Generate Conf, Sept 2013
love your tools get to know them
None
setup once use again and again iterate
scratched the surface
popular jQuery BBC Twitter Adobe Bocoup Opera WordPress
700+ plugins http://gruntjs.com/plugins
700+ plugins minification image optimisation templating compiling local servers live
reloading
for more gruntjs.com @gruntjs @gruntweekly #grunt on freenode
be warned! watch out for outdated tutorials
0.4.1
any (easy) questions? speakerdeck.com/jackfranklin @jack_franklin javascriptplayground.com https://github.com/javascript-playground/fowa-grunt-talk