A simplistic guide to start GRUNT

Lets talk about GRUNT - the Task Runner today .  Now, some of you guys would be like .."Woo i am outta here " because yes, grunt has been hyped as a somewhat mysterious feature about which some people think that they are better off without it .
  But if you invest few hours of your life learning it, you will surely save few weeks at the least .
Now, what is grunt and what does it do ? It is an automating tool which is an indisposable particularly if your creating an app for production . You ask why!! because it provides a great API to do tasks like minification , concatenation and almost every task you can think of for which otherwise you would have written hundreds of lines to do  ..

Still confused ? Lets explore it a bit ..

Grunt is built upon Node . What is Node ? Node is an open source , runtime environment which uses the V8 javascipt engine, thus its applications are written in javascript.
V8 javascript engine is used in chrome browser  , so basically they have taken the browser's skill and added it to desktops and servers , so that javascript runs everywhere .
So you need to have Node installed in order to work with grunt , grunt is installed using the npm command :

 npm install grunt --save-dev

adding parameter -g(globally) will do install grunt but  it will not run grunt as you need to have a local copy of grunt for each project you have .  --save-dev will add it to your package.json file inside "devDependencies": { } . If you ask what is devDependency , follow this link

After this  you have to install grunt-cli :

 npm install -g grunt-cli

It is the command line interface for grunt . This will install grunt-cli module in /usr/local/lib/node_modules . If you want it locally in your project folder, remove the -g (globally) . The job of  grunt-cli does is that it runs the grunt installed next to your Gruntfile .  Now, if you had installed grunt-cli and not installed grunt locally , you would get the following error on typing 'grunt' in your :

Fatal error: Unable to find local grunt.

If you're seeing this message, either a Gruntfile wasn't found or grunt
hasn't been installed locally to your project. For more information about
installing and configuring grunt, please see the Getting Started guide:

Finally, you need to create a 'Gruntfile.js' manually , which will contain the grunt config and tasks and everything grunt related .
This completes the bare minimum installation task , now you will see the following files in your project directory :

node_modules
        |____grunt
        |____<other modules if you have installed>
package.json
Gruntfile.js

So, lets begin with writing grunt tasks already .  Every thing you write in grunt should be inside a wrapper function :

  module.exports=function(grunt){};

people familiar with node will instantly feel relieved , as this is the standard syntax for exposing node module  to other files . Starting with the basics , lets create a grunt task and run it . Lets create a grunt task ,that prints Hello World .
The syntax for creating a grunt task is 'grunt.registerTask(taskName,taskList)' and grunt.registerTask(taskName,taskDescription,taskFunction) , in our case we will use later one.

module.exports= function(grunt){
grunt.registerTask('firstTask','This is the very first task',function(){
      grunt.log.writeln("Hello World");
}
}


you will get the following output when you type 'grunt firstTask' in your terminal:

Running "firstTask" task
Hello World

Done, without errors.

If you specify the task name as default , the task will run if you just type 'grunt' in your terminal. 

You can also define many sub-properties and run them all using grunt.registerMultiTask . The name itself is verbose enough , we can run multiple tasks with it . Before, we discuss that ,its a good time to talk about grunt.initConfig . This takes an object, which  is used to set the configuration required for your tasks :

grunt.initConfig(configObject);


Lets assume you want to run a multi task 'routine' which has sub tasks : eat , sleep , code .

Gruntfile.js 

module.exports = function(grunt){
grunt.initConfig({
  routine: {
    eat: 'Time to eat',
    code: 'Time to code',
    sleep: 'Time to sleep',
  }
});
grunt.task.registerMultiTask('routine', 'Log stuff.', function() {
  grunt.log.writeln(this.target + ': ' + this.data);
});
}


Output:

$grunt routine

Running "routine:eat" (routine) task
eat: Time to eat

Running "routine:code" (routine) task
code: Time to code

Running "routine:sleep" (routine) task
sleep: Time to sleep

Done, without errors.

You can also read files and configure tasks using there content . For example, if you want to assign the name of your project (which is stored in the name property of your  package.json file ), to the code property of the routine task , you simply have to first read the file :

pkg=grunt.file.readJSON('path/package.json');


and assign its name property value to code 

code: '<%= pkg.name %>' 


'<%= %>' is used to evaluate the values of properties  you create.

To run tasks(plugins) from vendors, you will have to download using npm , and load them in your Gruntfile , suppose you want to use the uglify task(the task for minifying your files) 

Installation :

npm install grunt-contrib-uglify --save-dev


packages with '-contrib' in them are built by the grunt team themselves .

in your Gruntfile :

grunt.loadNpmTasks(grunt-contrib-uglify);
and configuration is to be written inside grunt.initConfig :
grunt.initConfig({
uglify: {
        files: {
          'dest/scripts/scripts.min.js': [
             'src/scripts/scripts.js'
           ]
         }
     },
})


If you want to load external libraries in your gruntfile , you can use require(' library name') , as is written in nodejs. It will find and load the library from node modules .  

Till now, i had specified only a few basic methods which are used in almost every project. All of these methods are defined in different subobjects of grunt but are also exposed to grunt object directly for convenience. Like i used grunt.initConfig , but this method actually belongs to grunt.config API , with the name  grunt.config.init . 

I will wrap up this post with a mere definition of all the APIs , you can have a detailed look at them from the grunt site .

1) grunt.config : This API lets us access and set project specific configuration in our gruntfile. We     explored the grunt.config.init(alias: grunt.initConfig) . 
2) grunt.event : This API lets us configure listeners for events . Grunt itself does not emit any events uptill now .
3) grunt.log : This API lets us output text to the console. We used one of its methods  'grunt.log.writeln' in this post 
4) grunt.fail : This API lets us display error messages when something goes wrong in our grunt tasks and and it will abort grunt . We can use --force command line option to continue running grunt if we used grunt.fail.warn 
5) grunt.file : This API exposes different methods to do file manipulation like create, read,write , copy, paste . We used one of its methods  'grunt.file.readJSON'  in this post
6) grunt.option : This is used to pass paramteres across different tasks , and also to read parameter you set on your terminal while running grunt . If you had specified  the parameter '--ranBy=Aakash' in your terminal ,  grunt.option('ranBy') will return Aakash
7) grunt.template: This API exposes methods to process template strings manually
8) grunt.task: This API registers, runs and loads tasks . We used grunt.task.loadNpmTasks (grunt.loadNpmTasks) and grunt.task.registerTask( grunt.registerTask),                     grunt.task.registerMultiTask(grunt.registerMultiTask) in this post .
9) grunt.util : This API provides miscellaneous utilities for our gruntfile and tasks .

If you could make out something from this post , then GRUNT is now a slave at your disposal :) 

2 comments: