How to start-up with grunt?? – Beginners Tutorial

Hi Pals,

Lets walk through the beginners tutorial of grunt. I would like to thank Brain P.Hogan for his detail explanation in “Automate with grunt” book.

Note: I just followed and simplifed Hogan theory for grunt.

Pre-requisites:

1. Editor like sublime text/brackets

2. Node.js in your machine

What is Grunt? Why it is needed?

Grunt is a task runner, designed to be more configuration than code. if you know JavaScript, Grunt becomes a
very powerful automation tool for many types of projects. If you have a manual repetitive task you run as part of your development or deployment process, chances are there’s a way to automate that process with Grunt.

Installing & Configuring Grunt

Before we can do anything with Grunt, we have to install the Grunt commandline tool. Grunt is written in Node.js, and to install it we use npm, the tool Node uses to download and manage dependencies. Open a new Terminal and
type the following command:
$ npm install -g grunt-cli

The grunt-cli tool we installed globally on our system will then work with the version of grunt within our project. Let’s create a simple project folder and set everything up. Create a new folder called kicking_tires and navigate into that folder in your Terminal:
$ mkdir kicking_tires
$ cd kicking_tires

we can add Grunt as a development dependency in current project like this:
$ npm install grunt –save-dev // this allows grunt to install only in current project
Grunt will be installed into the node_modules/ subfolder of the current folder, and it’ll be added to the package.json file as a development dependency.

The –save-dev command also saves the version number into the package.json file, and it uses the tilde in front of the version number to signify that any version. The node_modules folder contains all of the libraries our project depends on. This means you have a copy of the Grunt library itself in the node_modules folder.

Adding things as development dependencies allows new people who want to work on our project to easily download all of the dependencies we specify by issuing the npm install command in the folder that contains the package.json file. In fact, let’s try this now. Remove the node_modules folder and then run npm install. You’ll see that npm fetches Grunt again, creating a new node_modules folder.

With Grunt installed, we can test things out by running it from the command line:
$ grunt
This fires off the grunt-cli library we installed globally, which then uses the grunt library we installed in our project’s node_modules folder.

Grunt is telling us that we need something called a Gruntfile in our project. A Gruntfile is a JavaScript file that specifies and configures the tasks you want to be able to run for your project.Grunt is specifically looking for a file called Gruntfile.js in the current working directory and it can’t find one, so let’s create a Gruntfile.

Every Gruntfile starts out with some boilerplate code. Create a new file called Gruntfile.js and add this:
path: basics/kicking_tires/Gruntfile.js

code:

module.exports = function(grunt){
// Your tasks go here
}

Here you’re defining a Node.js module that receives a grunt object. You’ll use that object and its methods throughout your configuration files. Now, within the curly braces, define the following task, which prints some text to the screen:
grunt.registerTask(‘default’, function(){
console.log(‘Hello from Grunt.’);
});

We use grunt.registerTask() to create a new Grunt task. We pass in a task name followed by an associated callback function. Whatever we put in the callback function is executed when we invoke the task. To see it in action, run this new task from the Terminal:
$ grunt
You’ll see the following output:
Running “default” task
Hello from Grunt.
Done, without errors.

In this task we’ve used Node’s console.log function, but we really should use
Grunt’s grunt.log() object instead.

So, change the following:
console.log(‘Hello from Grunt.’);
to
grunt.log.writeln(‘Hello from Grunt.’);
and rerun the task with
$ grunt
You shouldn’t see anything different.

Let’s create another rather silly task that adds some numbers together. In the Gruntfile, add this task:
basics/kicking_tires/Gruntfile.js
grunt.registerTask(‘addNumbers’, function(first, second){
var answer = Number(first) + Number(second);
grunt.log.writeln(first + ‘ + ‘ + second + ‘ is ‘ + answer);
});
To run this task, we have to supply both numbers as arguments to the task,and we do that using colons, like this:
$ grunt addNumbers:1:2
And when we do that, we see this result:
Running “addNumbers:1:2” (addNumbers) task
1 + 2 is 3.

Handling Errors:

we’ll want to log error messages. We can do that with grunt.log().In our addNumbers() task, let’s check to make sure the first argument is a number. If it isn’t, we’ll print an error on the screen:
basics/kicking_tires/Gruntfile.js
if(isNaN(Number(first))){
grunt.warn(‘The first argument must be a number.’);
}
Now run this with
$ grunt addNumbers:a:2
and you’ll see an interesting response from Grunt:

Running “addNumbers:a:2” (addNumbers) task
Warning: The first argument must be a number. Use –force to continue.

Running our task with the –force option. Let’s try that:
$ grunt addNumbers:a:2 –force
Running “addNumbers:a:2” (addNumbers) task
Warning: The first argument must be a number. Used –force, continuing.
a + 2 is NaN
Done, but with warnings.

Run Multile Tasks as one:

Grunt offers the ability to create one task that fires off other tasks. Grunt refers to this as an alias.
To make a task like this we use registerTask() and pass it an array of tasks instead of a callback function.
basics/kicking_tires/Gruntfile.js
grunt.registerTask(‘all’, [‘default’, ‘greet:Brian’, ‘addNumbers:2:3’]);
Notice that when we do this we pass these task names as strings, which means we can pass arguments as well.

We’ve called this task all, but if we renamed it to default we’d be able to run this task by running grunt with no arguments. The default task is commonly used to run the test suite for a project.

Adding text description to your tasks:

Let’s define a simple task called praise() that makes Grunt say some words of encouragement to you.
basics/kicking_tires/Gruntfile.js
grunt.registerTask(‘praise’,
‘Have Grunt say nice things about you.’, function(){
var praise = [
“You’re awesome.”,
“You’re the best developer ever!”,
“You are extremely attractive.”,
“Everyone loves you!”
]
var pick = praise[(Math.floor(Math.random() * praise.length))];
grunt.log.writeln(pick);
});
Now type this:
$ grunt –help
This shows Grunt’s basic help page, but in the middle of the output you’ll see this:
Available tasks
default Custom task.
greet Custom task.
addNumbers Custom task.
all Alias for “default”, “greet:Brian”, “addNumbers:2:3” tasks.
praise Have Grunt say nice things about you.
All the tasks we didn’t document just say “Custom task,” but our praise() task shows its description.

1st chapter – creating a basic project

Let’s create a project folder called deployment and then navigate into it:
$ mkdir deployment
$ cd deployment
$ npm init
Fill in the basic information or leave it at its default values. Alternatively, create your own package.json file that contains this:
{
“name”: “deploying”,
“version”: “0.0.0”,
“description”: “A simple project to copy files for deployment.”
}
Next, we add Grunt as a dependency:
$ npm install grunt –save-dev
Now we’ll create a basic Gruntfile.js with the following content:

files/simple/deploying/Gruntfile.js
module.exports = function(grunt){
}
Now let’s create a few simple files and folders in this project. First, create an index.html file with a default HTML5 template:
files/simple/deploying/index.html
<!DOCTYPE html>
<html lang=”en-US”>
<head>
<meta charset=”utf-8″>
<title>Test page</title>
<link rel=”stylesheet” href=”stylesheets/style.css”>
</head>
<body>
<h1>Test page</h1>
</body>
</html>
Then create the folders stylesheets and javascripts:
$ mkdir stylesheets
$ mkdir javascripts
After that, create a stylesheets/style.css file with the following contents:
files/simple/deploying/stylesheets/style.css
h1{color: #F00;}

Finally, create the file javascripts/app.js, which looks like this:
files/simple/deploying/javascripts/app.js
var app = {};
app.name = ‘Hello’;
With the setup out of the way, let’s jump into how we work with these files in Grunt tasks.

Create a copy of files into another directory where build runs with these copied files

Grunt provides many options like watchers(if you save in any html/js file, automatically page reloads), working copy directory for your build etc etc.

Here we will see, how grunt helps in copying your files to working copy folder:

Grunt provides grunt.config.init(), which lets us define the configuration for our Grunt tasks by passing in a JavaScript object with the properties and values for our tasks.
files/simple/deploying/Gruntfile.js
grunt.config.init({
});

Our target is to add a copyFiles property in this config file..

A best practice for creating configuration options for a task is to place all options within an options property.

We need a way to specify the destination folder that we’ll copy our files to, so we’ll create an option for the workingDirectory:
files/simple/deploying/Gruntfile.js
copyFiles: {
options: {
workingDirectory: ‘working’,
}
}

So, did you understood what exactly grunt is??

Well, in simple words..its pretty a task runner that runs with your own commands(which you creates as tasks).

Let me brief with a very small example..now i wanna create a folder/delete a folder with my own commands in grunt..so my commands would be something like

$grunt createFolder // this creates a folder in some specified path

$grunt clean// Deletes the working folder and its contents

Now lets explain with necessary code..

Grunt’s built-in grunt.util.mkdir() method creates folders, and so all we have to do is create a task, read the name of the directory from our configuration object, and create the folder.
Creating and Deleting Directories
files/simple/deploying/Gruntfile.js
grunt.registerTask(‘createFolder’, ‘Create the working folder’, function(){
grunt.config.requires(‘copyFiles.options.workingDirectory’);
grunt.file.mkdir(grunt.config.get(‘copyFiles.options.workingDirectory’));
});
We’re using grunt.config.requires() to ensure that the configuration property we want has been set.

We then use grunt.config.get() to fetch the value out of the object and use it to create the folder, using the same dot notation.At the command line we can run
$ grunt createFolder
and we’ll see the new working folder in our directory.

To remove the working folder, we can write a very similar task, but this time we’ll use Grunt’s grunt.file.delete() method instead. This deletes a file, or a folder and all of its contents.
files/simple/deploying/Gruntfile.js
grunt.registerTask(‘clean’,
‘Deletes the working folder and its contents’, function(){
grunt.config.requires(‘copyFiles.options.workingDirectory’);
grunt.file.delete(grunt.config.get(‘copyFiles.options.workingDirectory’));
});

Copying Files
Our project may have lots of files that we don’t want to deploy to the web server. For example, there’s no need to send up our Gruntfile.js or the node_modules folder if we’re building a basic website. So we’ll need to tell Grunt what files we want to copy over. Let’s create a new manifest property of our copyFiles configuration object, which will be an array of file paths we want to copy.

files/simple/deploying/Gruntfile.js
copyFiles: {
options: {
workingDirectory: ‘working’,
➤ manifest: [
➤ ‘index.html’, ‘stylesheets/style.css’, ‘javascripts/app.js’
➤ ]
Grunt provides grunt.file.copy(), which lets us specify a source file and a destination.

Our copyFiles task will check for the workingDirectory and manifest properties and then iterate over the files in the manifest, copying each file into the working folder.
files/simple/deploying/Gruntfile.js
grunt.registerTask(‘copyFiles’, function(){
var files, workingDirectory;
grunt.config.requires(‘copyFiles.options.manifest’);
grunt.config.requires(‘copyFiles.options.workingDirectory’);
files = grunt.config.get(‘copyFiles.options.manifest’); workingDirectory =
grunt.config.get(‘copyFiles.options.workingDirectory’);
files.forEach(function(file) {
var destination = workingDirectory + ‘/’ + file;
grunt.log.writeln(‘Copying ‘ + file + ‘ to ‘ + destination);
grunt.file.copy(file, destination);
});
});
We can run this task with
$ grunt copyFiles
Running “copyFiles” task
Copying index.html to working/index.html
Copying stylesheets/style.css to working/stylesheets/style.css
Copying javascripts/app.js to working/javascripts/app.js
Done, without errors.
and the files are copied now into our working folder.

All set, now do all at once

Now, to make this all fit together nicely, let’s create a new task that runs the clean, createFolder, and copyFiles tasks. Let’s call the task deploy, shall we?
files/simple/deploying/Gruntfile.js
grunt.registerTask(‘deploy’, ‘Deploys files’,
[‘clean’, ‘createFolder’, ‘copyFiles’]);
Creating and Deleting Directories • 15
http://www.it-ebooks.info
Run this new task:
$ grunt deploy
Running “clean” task
Running “createFolder” task
Running “copyFiles” task
Copying index.html to working/index.html
Copying stylesheets/style.css to working/stylesheets/style.css
Copying javascripts/app.js to working/javascripts/app.js
Done, without errors.

Read JSON data

Grunt provides a function called file.readJSON() that reads json data from a file and parse it into a javascript object.

files/recursive/deploying/Gruntfile.js

grunt.config.init({
pkg: grunt.file.readJSON(‘package.json’),

Fetching Client-Side Libraries with Bower

Bower is a package manager for client-side libraries, and it’s a great way to quickly grab the libraries our project needs. Bower downloads any libraries we specify into a bower_components folder in our project. First, we’ll install
Bower globally:
$ npm install -g bower
Bower uses the Git version-control system to fetch libraries, so you’ll need to install the Git command-line client on your computer.And if you’re on Windows, you’ll need to install Git so that it runs from your Windows Command Prompt, not the default “Bash shell” option.

once Bower’s all set up, we can use it to fetch Angular and the other libraries, like this:

$ bower install angular
$ bower install angular-resource
$ bower install jquery
Now, if you look under the bower_components folder, you’ll see folders for angular,angular-resource, and jquery, with the appropriate JavaScript libraries in each folder. That’s a lot easier than finding, downloading, unzipping, and moving a bunch of files around :).

Note: If we didn’t specify any version info, Bower just grabs the latest version it knows about.

Minifying JavaScript
To make our JavaScript download faster, we’re going to minify it. This process removes comments, whitespace, and line breaks, and even obfuscates code by shortening variable names. We’ll use the Uglify utility to do this by way of
the grunt-contrib-uglify plug-in.
First, we install the plug-in:
$ npm install grunt-contrib-uglify –save-dev

workflow/markdown/Gruntfile.js
grunt.loadNpmTasks(‘grunt-contrib-uglify’);
grunt.config(‘uglify’, {
scripts: {
files: {
‘assets/app.js’ : ‘tmp/app.js’
}
}
});
And that takes care of the JavaScript! Test it out by running the following:
$ grunt uglify
Running “uglify:scripts” (uglify) task
File assets/app.js created: 816.58 kB → 128.81 kB
Done, without errors.

Adding Sass to Grunt
By this point you can probably guess how this will work. There’s a plug-in called grunt-contrib-sass that we have to install and configure. So, install the plug-in with npm:
$ npm install grunt-contrib-sass –save-dev
Then add the following configuration to the Gruntfile:
workflow/markdown/Gruntfile.js
grunt.loadNpmTasks(‘grunt-contrib-sass’);
grunt.config(‘sass’, {
app: {
files: {
‘tmp/app.css’: [‘sass/style.scss’]
}
}
});
Notice that we placed the output file in the tmp folder. We’re not quite done with the stylesheet yet.

Minifying Our CSS
We’ve minified the JavaScript code in our app, and now we’ll do the same with our CSS. We’ll use the grunt-contrib-cssmin plug-in to do this, and the configuration for this is very easy. First, install the plug-in as a dependency:
$ npm install grunt-contrib-cssmin –save-dev
Then, configure it almost exactly like the uglify task for JavaScript, by reading in the tmp/app.css file that the Sass task created and placing the minified version in the assets/ folder:
workflow/markdown/Gruntfile.js
grunt.loadNpmTasks(‘grunt-contrib-cssmin’);
grunt.config(‘cssmin’, {
app: {
files: {
‘assets/app.css’: [‘tmp/app.css’]
}
}
});
Now let’s run the cssmin task to generate the assets/app.css file that our interface wants:
$ grunt sass cssmin
Running “cssmin:app” (cssmin) task
File assets/app.css created: 1 kB → 537 B
Done, without errors.
The task runs perfectly, cutting our file size nearly in half. And now we have all the components of our workflow, as well as a completely working application that you should be able to view by opening index.html in your browser.
Let’s simplify this whole process with a build task that runs all of the steps.

 Simplifying the Build

We want one task that, when called, invokes the tasks to build the JavaScript files and the CSS files.
Let’s add a build task to our Gruntfile:
workflow/markdown/Gruntfile.js
grunt.registerTask(‘build’, “Builds the application.”,
[‘coffee’, ‘concat:scripts’, ‘sass’, ‘cssmin’, ‘uglify’ ]);
When we execute this build task, the whole process runs.
$ grunt build
Running “coffee:app” (coffee) task
Running “concat:scripts” (concat) task
File “tmp/app.js” created.
Running “sass:app” (sass) task
File tmp/app.css created.

Running “cssmin:app” (cssmin) task
File assets/app.css created.
Running “uglify:scripts” (uglify) task
File assets/app.js created.
Done, without errors.
A single command builds our application, letting us take advantage of powerful preprocessors and minification tools.

Watching Files for Changes

We’ve set up a ton of tasks so far, but every time we make a change to a file we have to run Grunt manually. And we really should never have to do anything manually when it comes to task management. Let’s use the gruntcontrib-
watch plug-in to watch files for changes and run the appropriate tasks.
Install the plug-in first:
$ npm install grunt-contrib-watch –save-dev
To configure this plug-in, we specify a target, the files to watch, and the Grunt tasks that should run when those files change. For our JavaScript files, we’ll actually want to watch the CoffeeScript files for changes. When those files
change, we’ll need to run the coffee(), concat(), and uglify() tasks. Then we’ll want to watch the CSS files for changes and run the sass and cssmin tasks. So first, let’s set up the configuration to watch the JavaScript files:
workflow/markdown/Gruntfile.js
grunt.loadNpmTasks(‘grunt-contrib-watch’);
grunt.config(‘watch’, {
scripts: {
files: [‘coffeescripts/**/*.coffee’],
tasks: [‘coffee’, ‘concat:scripts’, ‘uglify’],
options: {
spawn: false
}
},
});
And then, inside of that configuration block, we’ll add another target for the Sass files:

workflow/markdown/Gruntfile.js
styles: {
files: [‘sass/**/*.scss’],
tasks: [‘sass’, ‘cssmin’],
options: {
spawn: false
}
},
To use this, we employ the grunt watch command. Unlike other tasks, Grunt doesn’t return to the command line. Instead, it stays running in a loop, watching files for changes. Open one of the Sass files or the CoffeeScript files,
make a change, save the file, and watch the changes happen.
To stop watching, press Ctrl-C

Refreshing the Browser Automatically

The grunt-contrib-watch plug-in has built-in support for LiveReload, an amazing tool that can automatically reload web pages and CSS documents in the browser whenever files change. This is incredibly useful for any web developer,
so let’s configure it.
All we have to do is add a few additional options to the configuration section for the grunt-contrib-watch plug-in. First, we’ll configure it to watch for changes to the index.html file. We won’t need to run any tasks when that file changes.
And then we’ll include the option to enable LiveReload support.
workflow/markdown/Gruntfile.js
interface: {
files: [‘index.html’]
},
options: {
livereload: true
}
To see this in action, you’ll need to download the extension for your web browser. You can get extensions for Chrome, Firefox, and Safari from the LiveReload website.6 Install the plug-in, then fire up grunt-watch in your Terminal and activate the plug-in. Then change something in the HTML or the CSS and see the page update after you save the file.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s