Grunt : The Task Runner

What is Grunt?

Grunt is a JavaScript task runner, a tool used to automatically perform frequently used tasks such as minification, compilation, unit testing, linting, etc.
The basic principle for Grunt is to give us an easy way to run tasks. A task is a set of code files and configuration files already created for you. You can get new tasks by installing Grunt plugins that you will get using npm.

How can I use it?

It uses a command-line interface (CLI) to run custom tasks defined in a file (known as a Gruntfile). Grunt is written in Node.js. It is distributed via npm.

Step 1. Create the package.json file

Use npm to init the file:
npm init
Then you will see some questions [2]. After giving those answers you will see the format of package.json [3]. Type "yes" to confirm it [4].

Step 2. Install Grunt globally and locally

At first install Grunt globally.
npm install -g grunt
Then install it locally.
npm install grunt --save-dev
Note: Do not forget the –dev part for it to be specified as a devDependencie in the package.json file.

Step 3. Create the Gruntfile.js

Here is a minimal gruntfile that only read the package.json file and create a default task which runs nothing.
 module.exports = function(grunt) {  
  // Project configuration.  
  grunt.initConfig({  
   pkg: grunt.file.readJSON('package.json'),  
  });  
  // Default task(s).  
  grunt.registerTask('default', []);  
 };  
Note: place the file in the project folder, side by side with the package.json file

Now run grunt command, you should see a message "Done.".

Step 4. Add your first task: JSHint

Now that your gruntfile is ready, the next step is to add a plugin and use it. All plugins can be found here: http://gruntjs.com/plugins. One of the common tasks performed in a gruntfile is checking if the JavaScript syntax is correct. To do that, we usually use JSHint.

If you search for JSHint on the grunt plugins page, you will find grunt-contrib-jshint (here) which corresponds to what we need! In the project folder, run:
npm install grunt-contrib-jshint --save-dev

Load the plugin

To load the plugin, use the loadNpmTasks function:
 // Load the plugin that provides the "jshint" task  
 grunt.loadNpmTasks('grunt-contrib-jshint');  

Configure the task

Add following code in grunt.initConfig section.
 jshint:{  
    files: ['*.js', '!Gruntfile.js'],  
    options: {  
      "curly": true,  
      "eqnull": true,  
      "eqeqeq": true,  
      "undef": false,  
      "globals": {  
       "jQuery": true  
      }  
    }  
   },  

Register the task

To register this task use registerTask function.
 grunt.registerTask('default', ['jshint']);  

Finally the Gruntfile.js

 module.exports = function(grunt) {  
  // Project configuration.  
  grunt.initConfig({  
   pkg: grunt.file.readJSON('package.json'),  
      jshint:{  
    files: ['*.js', '!Gruntfile.js'],  
    options: {  
      "curly": true,  
      "eqnull": true,  
      "eqeqeq": true,  
      "undef": false,  
      "globals": {  
       "jQuery": true  
      }  
    }  
   },  
  });  
   // Load the plugin that provides the "jshint" task  
  grunt.loadNpmTasks('grunt-contrib-jshint');  
  // Default task(s).  
  grunt.registerTask('default', ['jshint']);  
 };  

You can run your task by using the following command line (where you specify the task name as a parameter for grunt):
grunt jshint

Step 5. Add your second task: Minification/Compression

If you search for uglfy on the grunt plugins page, you will find grunt-contrib-uglify (here) which corresponds to what we need! In the project folder, run:
npm install grunt-contrib-uglify --save-dev

Load the plugin

To load the plugin, use the loadNpmTasks function:
 grunt.loadNpmTasks('grunt-contrib-uglify');

Configure the task

Add following code in grunt.initConfig section.
 uglify: {
   my_target: {
     files: {
       'dest/output.min.js': ['main.js', 'index.js']
     }
   }
 },

Finally the Gruntfile.js

 module.exports = function(grunt) {  
  // Project configuration.  
  grunt.initConfig({  
   pkg: grunt.file.readJSON('package.json'),  
      jshint:{  
    files: ['*.js', '!Gruntfile.js'],  
    options: {  
      "curly": true,  
      "eqnull": true,  
      "eqeqeq": true,  
      "undef": false,  
      "globals": {  
       "jQuery": true  
      }  
    }  
   },  
      uglify: {  
           my_target: {  
            files: {  
                'dest/output.min.js': ['main.js', 'index.js']  
            }  
           }  
      },  
  });  
   // Load the plugin that provides the "jshint" task  
  grunt.loadNpmTasks('grunt-contrib-jshint');  
  grunt.loadNpmTasks('grunt-contrib-uglify');  
  // Default task(s).  
  grunt.registerTask('default', ['jshint']);  
 };  

You can run your task by using the following command line (where you specify the task name as a parameter for grunt):
grunt uglify
Now, you will see  a new folder named dest. You will find output.min.js file inside this folder which is minified version of main.js and index.js.

Step 6. Use watch so you do not have to run grunt manually

Now, you are a happy developer. All you repetitive tasks are automated inside a grunt workflow and you just have to run grunt for them to execute. But that can be done even more easily. That can be done automatically. 
To do that, you can add a specific task named watch. This task will constantly inspect your working folder and, based on rules, when a file is modified, grunt will run an associated task. 

First, install watch in your project folder: 
npm install grunt-contrib-watch --save-dev

Load the plugin

To load the plugin, use the loadNpmTasks function:
 grunt.loadNpmTasks('grunt-contrib-watch');

Configure the task

The config part is a bit different here because you need to specify a configuration for each task you want to cover using watch. Add following code in grunt.initConfig section to run jshint and uglify command.
 watch: {
   scripts: {
     files: ['*.js'], // for all files in all folder: '**/*.js'
     tasks: ['jshint', 'uglify'],
     options: {
       spawn: false,
     },
   },
 },

Finally the Gruntfile.js

 module.exports = function(grunt) {  
  // Project configuration.  
  grunt.initConfig({  
   pkg: grunt.file.readJSON('package.json'),  
      jshint:{  
    files: ['*.js', '!Gruntfile.js'],  
    options: {  
      "curly": true,  
      "eqnull": true,  
      "eqeqeq": true,  
      "undef": false,  
      "globals": {  
       "jQuery": true  
      }  
    }  
   },  
      uglify: {  
           my_target: {  
            files: {  
                'dest/output.min.js': ['main.js', 'index.js']  
            }  
           }  
      },  
      watch: {  
       scripts: {  
           files: ['*.js'], // for all files in all folder: '**/*.js'  
           tasks: ['jshint', 'uglify'],  
           options: {  
            spawn: false,  
           },  
       },  
      },  
  });  
   // Load the plugin that provides the "jshint" task  
  grunt.loadNpmTasks('grunt-contrib-jshint');  
  grunt.loadNpmTasks('grunt-contrib-uglify');  
  grunt.loadNpmTasks('grunt-contrib-watch');  
  // Default task(s).  
  grunt.registerTask('default', ['jshint']);  
 };  

When you want to activate watch you only have to run the following command:
grunt watch
And it will execute tasks each time a file is changed and this file is in the scope of watched files for the specific task. 

References

Follow this link if you want to know in more details.
https://en.wikipedia.org/wiki/Grunt_(software)

Comments