Learning GruntJS : Part 2 – Manage JavaScript Tasks

Earlier we have seen how to get started with GruntJs. This tutorial will teach you how to use Grunt for managing JavaScript tasks. We will go through a number if useful Grunt plugins for managing JavaScript tasks using GruntJs

In this series of articles we will learn Grunt basics and also explore a number of important Grunt plugins to automate your front-end workflow. This series covers following tutorials on GruntJs:

1. Learning GruntJs:Part 1 – Getting Started with GruntJs
2. Learning GruntJs:Part 2 – Manage JavaScript Tasks
3. Learning GruntJs:Part 3 – Manage CSS Tasks
4. Learning GruntJs:Part 4 – Some Useful Grunt Plugins

Grunt Concat task

Concat task allows us to concatenate more than one files into a single file. Concatenation is important when we have our JavaScript code written in multiple files. Loading multiple file can be slow down the loading of web pages. So it is always better to concat multiple files into a single file which can be then used in production.

Install Grunt Concat

$ npm install grunt-contrib-concat --save-dev

Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:

grunt.loadNpmTasks('grunt-contrib-concat');

Configure Concat Task

In your Gruntfile you can configure the concat task as below:

// Gruntfile.js
module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {
        separator: ';',
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %> */',
      },
      dist: {
        src: ['app/javascript/main.js', 'app/javascript/forms.js'],
        dest: 'app/dist/built.js',
      },
    },
  });

  // Load the plugin that provides the "concat" task.
  grunt.loadNpmTasks("grunt-contrib-concat");

  // Default task(s).
  grunt.registerTask('default', ['concat']);
};

Here the dist object takes two options. The src is an array of all files that needs to be concatenated and dest is the path of output JavaScript file that needs to be generated after concatenation.
You can see all the plugin options here.

Run Concat Task

$ grunt concat

Grunt JSCS – JavaScript Code Style Checker

JSCS allows you to check the style errors in your javascript code. JSCS enforces rules from Google, jQuery, AirBnb, Crockford and many others. JSCS enables the common conventions and styling througout a team or project so that JavaScript code remains consistent.
We have covered JSCS in detail in a separate article also.
About JSCS:

  • JSCS is a code style checker
  • Over 60 validation rules
  • Presets from popular style guides like jQuery, Google
  • Highly configurable
  • Install JSCS
$ npm install grunt-jscs --save-dev

JSCS config.json

JSCS needs a config.json which has all the settings and configurations. Here is the sample config.json file:

// config.json for JSCS

{
    "preset": "jquery",
    "fileExtensions": [ ".js", "jscs" ],

    "requireParenthesesAroundIIFE": true,
    "maximumLineLength": 120,
    "validateLineBreaks": "LF",
    "validateIndentation": 4,

    "disallowKeywords": ["with"],
    "disallowSpacesInsideObjectBrackets": null,
    "disallowImplicitTypeConversion": ["string"],

    "safeContextKeyword": "_this",

    "excludeFiles": [
      "test/data/**"
    ]
}

JSCS Grunt task

In the Gruntfile you can create the JSCS task as below:

// Gruntfile.js

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    jscs: {
      src: "src/*.js",
      options: {
          config: "config.json"
      }
    }
  });

  // Load the plugin that provides the "jscs" task.
  grunt.loadNpmTasks("grunt-jscs");

  // Default task(s).
  grunt.registerTask('default', ['jscs']);

};

Read more about JSCS configuration.

Run the JSCS task

$ grunt jscs

Here is the sample output of this task:

grunt-error

Grunt JSHint

JSHint is a community-driven tool to detect errors and potential problems in JavaScript code and to enforce your team’s coding conventions. It is very flexible so you can easily adjust it to your particular coding guidelines and the environment you expect your code to execute in. JSHint is open source and will always stay this way.

Install JSHint

$ npm install grunt-contrib-jshint --save-dev

JSHint is used with a plugin known as JSHint-stylish that outputs the result in colorful and more elegant manner.

$ npm install jshint-stylish --save-dev

JSHint Grunt task

Create the Jshint task in your Gruntfile as below:

// Gruntfile.js
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {  // a task for hinting all JS files
        src: [
          'Gruntfile.js',
          'app/javascript/{,*/}*.js'
        ]
      },
      main: { // another task for hinting specific files
        src: [
          'app/javascript/{,*/}*.js'
        ]
      }
    },
  });

  // Load the plugins
  grunt.loadNpmTasks("grunt-contrib-jshint");

  // Default task(s).
  grunt.registerTask('default', ['jshint:main']);
};

For JSHint to work we need to create a .jshintrc file at the project root. .jshintrc has all the configurations and options for JSHint and you can modify these settings to suit your project needs.
Here the src options takes all the files to be checked for errors. Multiple JSHint tasks can be created in same JSHint configuration. In above example we have created all and main sub tasks that can run independently as:

$ grunt jshint:all

$ grunt jshint:main

Here is the sample output of the JSHint task:

Jshint error
Jshint error

Grunt Uglify

Uglify is used to minify the JavaScript files. Minified files are always better for performance of your web app as you can save lot of bandwidth.

Install Uglify

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

Grunt Uglify Task

You can create the usglify task in Gruntfile as below:

// Gruntfile.js

module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
  
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %> */'
        compress: {
         drop_console: true    //removes console logs from code
        }
      },
      my_target: {
        files: {
          'dist/output.min.js': ['app/dist/built.js']
        }
      }
    }

  });

  // Load the plugins
  grunt.loadNpmTasks("grunt-contrib-uglify");

  // Default task(s).
  grunt.registerTask('default', ['uglify']);

};

You can see that we can create multiple targets in Uglify. Each target takes files options which is the key-value pair of output and input files. key is the path of minified js file. The value is an array of input files that needs to be minified.

Final JavaScreipt Task

Our final JavaScript Grunt task may look something like:

// Gruntfile.js

grunt.registerTask('js', [
  'jscs',
  'jshint',
  'concat',
  'uglify'
]);

Written by Arvind Bhardwaj

Arvind is a certified Magento 2 expert with more than 10 years of industry-wide experience.

Website: http://www.webspeaks.in/