SlideShare ist ein Scribd-Unternehmen logo
1 von 51
Downloaden Sie, um offline zu lesen
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
grunt from the 

ground up
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
About me
• I build things	

• I write books	

• I teach people	

• I love code!
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Why are you here?
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
What is Grunt?
Grunt is a task runner written in JavaScript. It has advantages and disadvantages to other build tools.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
However, one of the worst ways to use Grunt is to just copy and paste people’s examples that you find online. There are lots of tutorials out there to
follow, but before you start copying configurations around, you should learn how Grunt handles things under the hood.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Prerequisites
SO to do that let’s work with Grunt from the ground up. In order to do this you’ll need two things: You’ll need NodeJS installed and you’ll need to be
comfortable with the shell. The stuff we’ll do here today is code that works on my Mac. But it’ll work everywhere.
!
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Initial Setup
$	
  npm	
  install	
  grunt-­‐cli
$	
  cd	
  yourwebsite
$	
  npm	
  init
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
The nom init command brings you through a wizard that asks a few questions about your project. The answers to these questions can be used by Grunt or
other apps later. For example, Grunt can make your application name available as a variable when it writes files. You could also use this file as the source
of your app’s version number.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
package.json
{

"name": "awesomeco",

"version": "0.0.1",

"description": "This is my basic site",

"main": "index.html",

"scripts": {

"test": "echo "Error: no test specified" && exit 1"

},

"author": "Brian Hogan",

"license": "MIT"

}

Here’s how it works. That command creates the file package.json which contains all the things we specified. And what’s really important about this is that
this file can also list the dependencies of our app.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
So if we try to run the `grunt` command we get told that it can’t find “local grunt.”
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Installing Grunt to a
project
$	
  npm	
  install	
  grunt	
  -­‐-­‐save-­‐dev
The grunt-cli command we installed earlier lets us use the grunt command. But that doesn’t actually install Grunt. It just installs a command line tool that
is designed to talk to the version of Grunt that is installed as an app dependency.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
And so we install Grunt to our project and then when we try to run Grunt again it says we need a Gruntfile.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Gruntfile.js
'use strict'

module.exports = function(grunt){



};
The Gruntfile is how we configure our tasks. Our Gruntfile looks like this.
!
The expression ‘use strict’ tells the JavaScript interpreter to be more strict on how it processes rules, raises errors, etc.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
A task
'use strict';

module.exports = function(grunt){

grunt.registerTask("hello", function(){

// your code here



});

};

This is a task declaration. We “register the task” by giving it a name and a callback function that gets run. It’s like an event listener.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
“Hello world”?
grunt.registerTask('hello', function(){

console.log("Hello World");

});
There’s a simple task. Works great!!
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Demo
Live demo
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Arguments




grunt.registerTask('greet', function(name){

grunt.log.writeln("Hello " + name);

});
Code originally shown live during talk.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Errors?
grunt.registerTask('add', function(firstNumber, secondNumber){

firstNumber = Number(firstNumber);

secondNumber = Number(secondNumber);



if(isNaN(firstNumber)) grunt.warn("Nope! Why do you fail?????");

if(isNaN(secondNumber)) grunt.warn("Nope! Why do you fail?????");



var answer = firstNumber + secondNumber;

grunt.log.writeln(answer);



});

Code originally shown live during talk.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
External
'use strict';

module.exports = function(grunt){

grunt.registerTask('praise', function(){

var praise = [

"You're awesome!",

"You are the best developer ever!",

"You deserve a raise!",

"You are good looking!",

"Everyone likes you!"

];



grunt.log.writeln(praise[Math.floor(Math.random() * praise.length)]);



});

};



Code originally shown live during talk.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Loading External Tasks
grunt.loadTasks('tasks');

Code originally shown live during talk.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Chaining
grunt.registerTask('default', ['praise', 'hello', 'greet:Brian']);

grunt.registerTask('build', ['praise', 'hello']);



Code originally shown live during talk.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Simple tasks
• grunt.registerTask	

• arguments	

• external tasks (grunt.loadTasks)	

• Task chaining	

• default tasks
So, we have the grunt.registerTask command to define a tasks. We can also define tasks that take arguments. We can have tasks defined outside of the
Gruntfile and load those in, and we can define a task that calls other tasks. We can even have a default task that gets called when we type `grunt`.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Configuration
grunt.initConfig({

mainFile: 'index.html'

});
Grunt tasks are better when they’re configured. We can set up a configuration object and add some stuff to it.
!
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
grunt.config.get
grunt.registerTask('printFile', function(){

var file = grunt.config.get('mainFile');

console.log(file); 

});
Then we use grunt.config.get to grab the value out!
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Config Demo
grunt open:index.html
Chrome Firefox Safari
Let’s use configuration to create a task that opens a page in all the browsers We’ll create a configuration for this and then write a task that launches the
browsers that we configure.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Config
grunt.initConfig({

browsers: [

'open -a Firefox',

'open -a Safari',

'open -a "Google Chrome"'

]

});
Code originally shown live during talk.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
grunt.registerTask('open', function(file){

var browsers = grunt.config.get('browsers');



var exec = require('child_process').exec;



for (var index = 0; index < browsers.length; index++) {



// tell Grunt to wait 

var done = this.async();



var command = browsers[index] + ' ' + file;

grunt.log.writeln("Running " + command);

var process = exec(command, function (error, stdout, stderr) {

if (error) {

if(error.code !== 0){

grunt.warn(stderr);

grunt.log.writeln(error.stack);



}

}

// tell Grunt to get going again.

done();

});



}

});
Code originally shown live during talk.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Multitasks
grunt build
basic version full version
Grunt’s multitasks let us build a single task that has many targets. Let’s say we’re doing our own JS framework. We want to build a basic version and a
version that includes jQuery since our library depends on that. We’ll create two versions with one task.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Our library
aquery
lib
a.js
b.js
vendor
jquery.js
So we’ll organize our code like this: our javascript files get split up into their own little files. We’ll put them in the lib/ folder. Then we’ll put jQuery in the
vendor folder.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Config
grunt.config.init({

build: {

aquery: {

src: ['lib/a.js', 'lib/b.js'],

dest: 'dist/aquery.js'

},

aqueryWithJquery: {

src: ['lib/a.js', 'lib/b.js', 'vendor/jquery.js'],

dest: 'dist/.aqueryFull.js'

}

}

});
Multitasks can look at a task’s configuration for source and destination files. Here we’re specifying both versions.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
The Task
grunt.registerMultiTask('build', 'Concatenate files.', function() {

var output = '';



this.files.forEach(function(filegroup) { 



var sources = filegroup.src.map(function(file){

return(grunt.file.read(file));

});



output = sources.join(';');

grunt.file.write(filegroup.dest, output);

}); 



});

Then we use grunt’s multitask declaration, give it the same name as the configuration. and then we can iterate over the files. Grunt has utilities we can use
to open the files, read the contents, and write new files. It’s pretty cool!
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Workflows with
plugins!
One of the things that makes Grunt so attractive is its huge library of plugins.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Our plan
sass sass/style.sass stylesheets/style.sass
cssmin stylesheets/style.sass stylesheets/style.sass
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Using A Grunt Plugin
• $ npm install grunt-contrib-whatever	

• grunt.loadNpmTasks(‘whatever');
• Add configuration.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Plugin Config
grunt.initConfig({	
// other plugin configuration

concat: {

options: {

separator: ';',

},

dist: {

src: ['src/intro.js', 'src/project.js', 'src/outro.js'],

dest: 'dist/built.js',

},

},	
// other plugin configuration.

});
Here’s an example of a plugin config. But see… the examples in all the docs just tell you to paste a bunch of config options right in the main configuration.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
grunt.config()
grunt.config('concat', {

options: {

separator: ';',

},

dist: {

src: ['src/intro.js', 'src/project.js', 'src/outro.js'],

dest: 'dist/built.js',

},

});
But instead we can use grunt.config to put the code for each plugin in its own configuration block. This makes things much easier to maintain.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Plugins we need
• grunt-contrib-sass	

• grunt-contrib-cssmin	

• grunt-contrib-watch
So here are the plugins we’ll configure.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Demo!
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Sass
grunt.loadNpmTasks('grunt-contrib-sass');



grunt.config('sass', {

app: {

files: {

'stylesheets/style.css' : ['sass/style.scss']

}

}

});
Code originally shown live during talk.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Watch for changes!
sass stylesheets/style.sass
Changes to
style.scss
We also want to watch for changes.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Watch
grunt.loadNpmTasks('grunt-contrib-watch');

	
grunt.config('watch', {

styles: {

files: ['sass/**/*.scss'],

tasks: ['sass']

}

});

Brian P. Hogan
twitter: @bphogan
www.bphogan.com
LiveReload
grunt.loadNpmTasks('grunt-contrib-watch');

grunt.config('watch', {

options: {

livereload: true

},

styles: {

files: ['sass/**/*.scss'],

tasks: ['sass']

}

});

Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Build
cssmin stylesheets/style.sass
build
sass
So then all we need to do is make a task that calls these parts. And you can do that with a task chain.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Other Plugins?
• grunt-contrib-jshint	

• grunt-contrib-less	

• grunt-contrib-concat	

• grunt-contrib-coffee	

• grunt-contrib-uglify
There are tons of Grunt plugins out there for you to work with. The JSHint plugin will scan your code for syntax and formatting issues. The Less plugin will
let you use Less, another CSS preprocesssor. Into CoffeeScript? use that! You can even make your JavaScript smaller using Uglify. Or you can write your
own Grunt plugin.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Grunt
• Simple tasks	

• Multitasks	

• Plugins
Grunt is the standard for JavaScript projects right now. Simple tasks are easy to define. Multitasks make it very easy to build a single task that builds
multiple outputs, and plugins make Grunt incredibly flexible.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Grunt is there for you, to be used to automate everything that you need. If you have to do some repetitive task, you owe it to yourself to automate
everything.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
http://pragprog.com/book/bhgrunt/
More? Here’s a shameless plug. In a couple of weeks, this book will be available for you to own. And the two best questions will get a free ebook copy
when it’s released.
Brian P. Hogan
twitter: @bphogan
www.bphogan.com
Questions?
Twitter: @bphogan

Weitere ähnliche Inhalte

Mehr von Brian Hogan

Responsive Web Design
Responsive Web DesignResponsive Web Design
Responsive Web DesignBrian Hogan
 
Web Development with CoffeeScript and Sass
Web Development with CoffeeScript and SassWeb Development with CoffeeScript and Sass
Web Development with CoffeeScript and SassBrian Hogan
 
Building A Gem From Scratch
Building A Gem From ScratchBuilding A Gem From Scratch
Building A Gem From ScratchBrian Hogan
 
Intro To Advanced Ruby
Intro To Advanced RubyIntro To Advanced Ruby
Intro To Advanced RubyBrian Hogan
 
Turning Passion Into Words
Turning Passion Into WordsTurning Passion Into Words
Turning Passion Into WordsBrian Hogan
 
HTML5 and CSS3 Today
HTML5 and CSS3 TodayHTML5 and CSS3 Today
HTML5 and CSS3 TodayBrian Hogan
 
Web Development With Ruby - From Simple To Complex
Web Development With Ruby - From Simple To ComplexWeb Development With Ruby - From Simple To Complex
Web Development With Ruby - From Simple To ComplexBrian Hogan
 
Stop Reinventing The Wheel - The Ruby Standard Library
Stop Reinventing The Wheel - The Ruby Standard LibraryStop Reinventing The Wheel - The Ruby Standard Library
Stop Reinventing The Wheel - The Ruby Standard LibraryBrian Hogan
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Brian Hogan
 
Make GUI Apps with Shoes
Make GUI Apps with ShoesMake GUI Apps with Shoes
Make GUI Apps with ShoesBrian Hogan
 
Story-driven Testing
Story-driven TestingStory-driven Testing
Story-driven TestingBrian Hogan
 
Learning To Walk In Shoes
Learning To Walk In ShoesLearning To Walk In Shoes
Learning To Walk In ShoesBrian Hogan
 
Rails and Legacy Databases - RailsConf 2009
Rails and Legacy Databases - RailsConf 2009Rails and Legacy Databases - RailsConf 2009
Rails and Legacy Databases - RailsConf 2009Brian Hogan
 

Mehr von Brian Hogan (15)

Responsive Web Design
Responsive Web DesignResponsive Web Design
Responsive Web Design
 
Web Development with CoffeeScript and Sass
Web Development with CoffeeScript and SassWeb Development with CoffeeScript and Sass
Web Development with CoffeeScript and Sass
 
Building A Gem From Scratch
Building A Gem From ScratchBuilding A Gem From Scratch
Building A Gem From Scratch
 
Intro To Advanced Ruby
Intro To Advanced RubyIntro To Advanced Ruby
Intro To Advanced Ruby
 
Turning Passion Into Words
Turning Passion Into WordsTurning Passion Into Words
Turning Passion Into Words
 
HTML5 and CSS3 Today
HTML5 and CSS3 TodayHTML5 and CSS3 Today
HTML5 and CSS3 Today
 
Web Development With Ruby - From Simple To Complex
Web Development With Ruby - From Simple To ComplexWeb Development With Ruby - From Simple To Complex
Web Development With Ruby - From Simple To Complex
 
Stop Reinventing The Wheel - The Ruby Standard Library
Stop Reinventing The Wheel - The Ruby Standard LibraryStop Reinventing The Wheel - The Ruby Standard Library
Stop Reinventing The Wheel - The Ruby Standard Library
 
Intro to Ruby
Intro to RubyIntro to Ruby
Intro to Ruby
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7
 
Make GUI Apps with Shoes
Make GUI Apps with ShoesMake GUI Apps with Shoes
Make GUI Apps with Shoes
 
The Why Of Ruby
The Why Of RubyThe Why Of Ruby
The Why Of Ruby
 
Story-driven Testing
Story-driven TestingStory-driven Testing
Story-driven Testing
 
Learning To Walk In Shoes
Learning To Walk In ShoesLearning To Walk In Shoes
Learning To Walk In Shoes
 
Rails and Legacy Databases - RailsConf 2009
Rails and Legacy Databases - RailsConf 2009Rails and Legacy Databases - RailsConf 2009
Rails and Legacy Databases - RailsConf 2009
 

Kürzlich hochgeladen

The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....ShaimaaMohamedGalal
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 

Kürzlich hochgeladen (20)

The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 

Grunt From The Ground Up

  • 1. Brian P. Hogan twitter: @bphogan www.bphogan.com grunt from the 
 ground up
  • 2. Brian P. Hogan twitter: @bphogan www.bphogan.com About me • I build things • I write books • I teach people • I love code!
  • 3. Brian P. Hogan twitter: @bphogan www.bphogan.com Why are you here?
  • 4. Brian P. Hogan twitter: @bphogan www.bphogan.com What is Grunt? Grunt is a task runner written in JavaScript. It has advantages and disadvantages to other build tools.
  • 5. Brian P. Hogan twitter: @bphogan www.bphogan.com However, one of the worst ways to use Grunt is to just copy and paste people’s examples that you find online. There are lots of tutorials out there to follow, but before you start copying configurations around, you should learn how Grunt handles things under the hood.
  • 6. Brian P. Hogan twitter: @bphogan www.bphogan.com Prerequisites SO to do that let’s work with Grunt from the ground up. In order to do this you’ll need two things: You’ll need NodeJS installed and you’ll need to be comfortable with the shell. The stuff we’ll do here today is code that works on my Mac. But it’ll work everywhere. !
  • 7. Brian P. Hogan twitter: @bphogan www.bphogan.com Initial Setup $  npm  install  grunt-­‐cli $  cd  yourwebsite $  npm  init
  • 8. Brian P. Hogan twitter: @bphogan www.bphogan.com The nom init command brings you through a wizard that asks a few questions about your project. The answers to these questions can be used by Grunt or other apps later. For example, Grunt can make your application name available as a variable when it writes files. You could also use this file as the source of your app’s version number.
  • 9. Brian P. Hogan twitter: @bphogan www.bphogan.com package.json {
 "name": "awesomeco",
 "version": "0.0.1",
 "description": "This is my basic site",
 "main": "index.html",
 "scripts": {
 "test": "echo "Error: no test specified" && exit 1"
 },
 "author": "Brian Hogan",
 "license": "MIT"
 }
 Here’s how it works. That command creates the file package.json which contains all the things we specified. And what’s really important about this is that this file can also list the dependencies of our app.
  • 10. Brian P. Hogan twitter: @bphogan www.bphogan.com So if we try to run the `grunt` command we get told that it can’t find “local grunt.”
  • 11. Brian P. Hogan twitter: @bphogan www.bphogan.com Installing Grunt to a project $  npm  install  grunt  -­‐-­‐save-­‐dev The grunt-cli command we installed earlier lets us use the grunt command. But that doesn’t actually install Grunt. It just installs a command line tool that is designed to talk to the version of Grunt that is installed as an app dependency.
  • 12. Brian P. Hogan twitter: @bphogan www.bphogan.com And so we install Grunt to our project and then when we try to run Grunt again it says we need a Gruntfile.
  • 13. Brian P. Hogan twitter: @bphogan www.bphogan.com Gruntfile.js 'use strict'
 module.exports = function(grunt){
 
 }; The Gruntfile is how we configure our tasks. Our Gruntfile looks like this. ! The expression ‘use strict’ tells the JavaScript interpreter to be more strict on how it processes rules, raises errors, etc.
  • 14. Brian P. Hogan twitter: @bphogan www.bphogan.com A task 'use strict';
 module.exports = function(grunt){
 grunt.registerTask("hello", function(){
 // your code here
 
 });
 };
 This is a task declaration. We “register the task” by giving it a name and a callback function that gets run. It’s like an event listener.
  • 15. Brian P. Hogan twitter: @bphogan www.bphogan.com “Hello world”? grunt.registerTask('hello', function(){
 console.log("Hello World");
 }); There’s a simple task. Works great!!
  • 16. Brian P. Hogan twitter: @bphogan www.bphogan.com
  • 17. Brian P. Hogan twitter: @bphogan www.bphogan.com Demo Live demo
  • 18. Brian P. Hogan twitter: @bphogan www.bphogan.com Arguments 
 
 grunt.registerTask('greet', function(name){
 grunt.log.writeln("Hello " + name);
 }); Code originally shown live during talk.
  • 19. Brian P. Hogan twitter: @bphogan www.bphogan.com Errors? grunt.registerTask('add', function(firstNumber, secondNumber){
 firstNumber = Number(firstNumber);
 secondNumber = Number(secondNumber);
 
 if(isNaN(firstNumber)) grunt.warn("Nope! Why do you fail?????");
 if(isNaN(secondNumber)) grunt.warn("Nope! Why do you fail?????");
 
 var answer = firstNumber + secondNumber;
 grunt.log.writeln(answer);
 
 });
 Code originally shown live during talk.
  • 20. Brian P. Hogan twitter: @bphogan www.bphogan.com External 'use strict';
 module.exports = function(grunt){
 grunt.registerTask('praise', function(){
 var praise = [
 "You're awesome!",
 "You are the best developer ever!",
 "You deserve a raise!",
 "You are good looking!",
 "Everyone likes you!"
 ];
 
 grunt.log.writeln(praise[Math.floor(Math.random() * praise.length)]);
 
 });
 };
 
 Code originally shown live during talk.
  • 21. Brian P. Hogan twitter: @bphogan www.bphogan.com Loading External Tasks grunt.loadTasks('tasks');
 Code originally shown live during talk.
  • 22. Brian P. Hogan twitter: @bphogan www.bphogan.com Chaining grunt.registerTask('default', ['praise', 'hello', 'greet:Brian']);
 grunt.registerTask('build', ['praise', 'hello']);
 
 Code originally shown live during talk.
  • 23. Brian P. Hogan twitter: @bphogan www.bphogan.com Simple tasks • grunt.registerTask • arguments • external tasks (grunt.loadTasks) • Task chaining • default tasks So, we have the grunt.registerTask command to define a tasks. We can also define tasks that take arguments. We can have tasks defined outside of the Gruntfile and load those in, and we can define a task that calls other tasks. We can even have a default task that gets called when we type `grunt`.
  • 24. Brian P. Hogan twitter: @bphogan www.bphogan.com Configuration grunt.initConfig({
 mainFile: 'index.html'
 }); Grunt tasks are better when they’re configured. We can set up a configuration object and add some stuff to it. !
  • 25. Brian P. Hogan twitter: @bphogan www.bphogan.com grunt.config.get grunt.registerTask('printFile', function(){
 var file = grunt.config.get('mainFile');
 console.log(file); 
 }); Then we use grunt.config.get to grab the value out!
  • 26. Brian P. Hogan twitter: @bphogan www.bphogan.com
  • 27. Brian P. Hogan twitter: @bphogan www.bphogan.com Config Demo grunt open:index.html Chrome Firefox Safari Let’s use configuration to create a task that opens a page in all the browsers We’ll create a configuration for this and then write a task that launches the browsers that we configure.
  • 28. Brian P. Hogan twitter: @bphogan www.bphogan.com Config grunt.initConfig({
 browsers: [
 'open -a Firefox',
 'open -a Safari',
 'open -a "Google Chrome"'
 ]
 }); Code originally shown live during talk.
  • 29. Brian P. Hogan twitter: @bphogan www.bphogan.com grunt.registerTask('open', function(file){
 var browsers = grunt.config.get('browsers');
 
 var exec = require('child_process').exec;
 
 for (var index = 0; index < browsers.length; index++) {
 
 // tell Grunt to wait 
 var done = this.async();
 
 var command = browsers[index] + ' ' + file;
 grunt.log.writeln("Running " + command);
 var process = exec(command, function (error, stdout, stderr) {
 if (error) {
 if(error.code !== 0){
 grunt.warn(stderr);
 grunt.log.writeln(error.stack);
 
 }
 }
 // tell Grunt to get going again.
 done();
 });
 
 }
 }); Code originally shown live during talk.
  • 30. Brian P. Hogan twitter: @bphogan www.bphogan.com Multitasks grunt build basic version full version Grunt’s multitasks let us build a single task that has many targets. Let’s say we’re doing our own JS framework. We want to build a basic version and a version that includes jQuery since our library depends on that. We’ll create two versions with one task.
  • 31. Brian P. Hogan twitter: @bphogan www.bphogan.com Our library aquery lib a.js b.js vendor jquery.js So we’ll organize our code like this: our javascript files get split up into their own little files. We’ll put them in the lib/ folder. Then we’ll put jQuery in the vendor folder.
  • 32. Brian P. Hogan twitter: @bphogan www.bphogan.com Config grunt.config.init({
 build: {
 aquery: {
 src: ['lib/a.js', 'lib/b.js'],
 dest: 'dist/aquery.js'
 },
 aqueryWithJquery: {
 src: ['lib/a.js', 'lib/b.js', 'vendor/jquery.js'],
 dest: 'dist/.aqueryFull.js'
 }
 }
 }); Multitasks can look at a task’s configuration for source and destination files. Here we’re specifying both versions.
  • 33. Brian P. Hogan twitter: @bphogan www.bphogan.com The Task grunt.registerMultiTask('build', 'Concatenate files.', function() {
 var output = '';
 
 this.files.forEach(function(filegroup) { 
 
 var sources = filegroup.src.map(function(file){
 return(grunt.file.read(file));
 });
 
 output = sources.join(';');
 grunt.file.write(filegroup.dest, output);
 }); 
 
 });
 Then we use grunt’s multitask declaration, give it the same name as the configuration. and then we can iterate over the files. Grunt has utilities we can use to open the files, read the contents, and write new files. It’s pretty cool!
  • 34. Brian P. Hogan twitter: @bphogan www.bphogan.com
  • 35. Brian P. Hogan twitter: @bphogan www.bphogan.com Workflows with plugins! One of the things that makes Grunt so attractive is its huge library of plugins.
  • 36. Brian P. Hogan twitter: @bphogan www.bphogan.com Our plan sass sass/style.sass stylesheets/style.sass cssmin stylesheets/style.sass stylesheets/style.sass
  • 37. Brian P. Hogan twitter: @bphogan www.bphogan.com Using A Grunt Plugin • $ npm install grunt-contrib-whatever • grunt.loadNpmTasks(‘whatever'); • Add configuration.
  • 38. Brian P. Hogan twitter: @bphogan www.bphogan.com Plugin Config grunt.initConfig({ // other plugin configuration
 concat: {
 options: {
 separator: ';',
 },
 dist: {
 src: ['src/intro.js', 'src/project.js', 'src/outro.js'],
 dest: 'dist/built.js',
 },
 }, // other plugin configuration.
 }); Here’s an example of a plugin config. But see… the examples in all the docs just tell you to paste a bunch of config options right in the main configuration.
  • 39. Brian P. Hogan twitter: @bphogan www.bphogan.com grunt.config() grunt.config('concat', {
 options: {
 separator: ';',
 },
 dist: {
 src: ['src/intro.js', 'src/project.js', 'src/outro.js'],
 dest: 'dist/built.js',
 },
 }); But instead we can use grunt.config to put the code for each plugin in its own configuration block. This makes things much easier to maintain.
  • 40. Brian P. Hogan twitter: @bphogan www.bphogan.com Plugins we need • grunt-contrib-sass • grunt-contrib-cssmin • grunt-contrib-watch So here are the plugins we’ll configure.
  • 41. Brian P. Hogan twitter: @bphogan www.bphogan.com Demo!
  • 42. Brian P. Hogan twitter: @bphogan www.bphogan.com Sass grunt.loadNpmTasks('grunt-contrib-sass');
 
 grunt.config('sass', {
 app: {
 files: {
 'stylesheets/style.css' : ['sass/style.scss']
 }
 }
 }); Code originally shown live during talk.
  • 43. Brian P. Hogan twitter: @bphogan www.bphogan.com Watch for changes! sass stylesheets/style.sass Changes to style.scss We also want to watch for changes.
  • 44. Brian P. Hogan twitter: @bphogan www.bphogan.com Watch grunt.loadNpmTasks('grunt-contrib-watch');
 grunt.config('watch', {
 styles: {
 files: ['sass/**/*.scss'],
 tasks: ['sass']
 }
 });

  • 45. Brian P. Hogan twitter: @bphogan www.bphogan.com LiveReload grunt.loadNpmTasks('grunt-contrib-watch');
 grunt.config('watch', {
 options: {
 livereload: true
 },
 styles: {
 files: ['sass/**/*.scss'],
 tasks: ['sass']
 }
 });

  • 46. Brian P. Hogan twitter: @bphogan www.bphogan.com Build cssmin stylesheets/style.sass build sass So then all we need to do is make a task that calls these parts. And you can do that with a task chain.
  • 47. Brian P. Hogan twitter: @bphogan www.bphogan.com Other Plugins? • grunt-contrib-jshint • grunt-contrib-less • grunt-contrib-concat • grunt-contrib-coffee • grunt-contrib-uglify There are tons of Grunt plugins out there for you to work with. The JSHint plugin will scan your code for syntax and formatting issues. The Less plugin will let you use Less, another CSS preprocesssor. Into CoffeeScript? use that! You can even make your JavaScript smaller using Uglify. Or you can write your own Grunt plugin.
  • 48. Brian P. Hogan twitter: @bphogan www.bphogan.com Grunt • Simple tasks • Multitasks • Plugins Grunt is the standard for JavaScript projects right now. Simple tasks are easy to define. Multitasks make it very easy to build a single task that builds multiple outputs, and plugins make Grunt incredibly flexible.
  • 49. Brian P. Hogan twitter: @bphogan www.bphogan.com Grunt is there for you, to be used to automate everything that you need. If you have to do some repetitive task, you owe it to yourself to automate everything.
  • 50. Brian P. Hogan twitter: @bphogan www.bphogan.com http://pragprog.com/book/bhgrunt/ More? Here’s a shameless plug. In a couple of weeks, this book will be available for you to own. And the two best questions will get a free ebook copy when it’s released.
  • 51. Brian P. Hogan twitter: @bphogan www.bphogan.com Questions? Twitter: @bphogan