GruntJS, organize, compile and minimize your javascript, css and less

Grunt JS is a task runner, and what that means is that using a command-line interface you can perform predefined tasks that you can configure in a JSON file (Gruntfile.json). These tasks can used for many things such as compiling, minify, testing, watch for file changes and others. 

The different types of functionalities are implemented via plugins. Grunt itself, the cli (the command line interface) and the plugins can be installed using NPM(which I'll briefly cover if you never used it).

Table of Contents

Installing NPM using NVM

I always go for version managers instead of just installing things such as Ruby or Node from packages or download binaries. (obviously skip this step if you already have NPM)

# First, if you are using a Debian-based distro you are going to need to have these:
$ sudo apt-get install build-essential libssl-dev

# Next step is install NVM
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh | bash

# And finally we install NPM, this is how you specify the version
$ nvm install 5.0.0

Installing Grunt and some plugins using NPM

We do this by creating or editing our package.json:

{
  "name": "Test Project",
  "version": "0.0.1",
  "devDependencies": {
    "grunt": "~0.4.5",
    "grunt-contrib-uglify": "~0.5.0",
    "grunt-contrib-concat": "~1.0.1",
    "grunt-contrib-copy": "~1.0.0",
    "grunt-contrib-cssmin": "~2.0.0"
  }
}

All plugins are named like grunt-contrib-*. And You can view a complete list of available plugins here

Before we continue lets install ALL THE THINGS:

# Insall all packages from your package.json
$ npm install

# And finally we install the grunt cli so we can use it from the command line
$ npm install -g grunt-cli

Next step is to configure Grunt and the plugins we included before.

Configuring and running Grunt

Now we need to create our config file: Gruntfile.js, "where" depends on your project but probably along side your package.json.

Bellow is the basic structure of a Gruntfile, it can be split in 3 main sections:

  1. The configuration itself: this includes a section for each of the plugins. 
  2. Tasks loading.
  3. Registering tasks.
// Gruntfile.js

/* NOTE: In the code where i wrote stuff like {plugin_name1} is where
 *       you need to put the plugins names like:  Example: uglify, cssmin, etc ... 
 */

module.exports = function(grunt) {

  /* (1) Project configuration. */
  grunt.initConfig({
    // Doing this we pick up the name from our package.json file
    pkg: grunt.file.readJSON('package.json'),

    /* Plugin configuration goes here.... */
     "plugin_name1": {
      // Plugin config here....
    },
    "plugin_name2": {
      // Another plugin config here....
    }
  });

  /* (2) Load the plugins that provides the tasks. */
  grunt.loadNpmTasks('grunt-contrib-{plugin_name1}');
  grunt.loadNpmTasks('grunt-contrib-{plugin_name2}');

  /* (3) Tasks */
  grunt.registerTask('{task_name}', ['{plugin_name1}', '{plugin_name1}']);
  grunt.registerTask('default', ['{plugin_name1}', '{plugin_name1}']);

  /* Task Examples */
  
  /*
    This registers a task named 'buildAssets' (you can use any string here)
    The second parameter is an array of which plugins you wanna to run.
   */
  grunt.registerTask('buildAssets', ['uglify', 'cssmin']);

  /*
    If we register a task 'default', it will run when you invoke grunt it without any parameters
   */
  grunt.registerTask('default', ['watch']);
};

The example provides the buildAssets task which runs the uglify and cssmin plugins.

$ grunt buildAssets

Grunt Uglify Plugin

Simple way to join/obfuscate/minify your code. Check the config section of the example bellow, the build section in particular.

I've included 3 possible cases in the build/files section:

  1. Join and minify all js from the src/frontend/ folder and create a frontend.min.js in our public directory.
  2. Same as the previous one, but on this one you need to specify each of the files you want to merge and ugilfy (as an array)
  3. The last one is similar, but the output will be several files; one for each of all the files found in the source directory. (same as the previous one but without the merge)
// Gruntfile.js
module.exports = function(grunt) {

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

    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      build: {
        files: [{
          src: 'src/frontend/*.js',
          dest: 'public/js/frontend.min.js'
        },{
          
          src: ['src/backend/script1.js', 'src/backend/script2.js'],
          dest: 'public/js/backend.min.js'
        },{
          expand: true,
          cwd: 'src/modules/',
          src: '**/*.js',
          dest: 'public/js/modules/',
        }]
      }
    }
  });

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

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

Grunt Concat Plugin

Very easy plugin to concatenate/merge files into one.

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

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

    concat: {
      frontendJS: {
        src: ['node_modules/prismjs/components/prism-ruby.min.js',
          'node_modules/prismjs/components/prism-php.min.js',
          'node_modules/prismjs/components/prism-javascript.min.js',
          'node_modules/prismjs/components/prism-c.min.js',
          'node_modules/prismjs/components/prism-css.min.js',
          'node_modules/prismjs/components/prism-bash.min.js',
          'node_modules/prismjs/components/prism-json.min.js'
        ],
        dest: 'public/js/prism.min.js'
      },
      frontendCSS: {
        // Another and/or more files here...
      }
    }
  });

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

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

Grunt Copy Plugin

Another simple one to copy files from one location to another one.

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

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

    copy: {
      main: {
        files: [
          {
            expand: true,
            cwd: 'node_modules/font-awesome/fonts/',
            src: '*.*',
            dest: 'public/assets/fonts/'
          }
        ]
      }
    }
  });

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

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

Grunt CSSMin Plugin

Very simple way to minify one or more CSS files.

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

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

    cssmin: {
      target: {
        files: {
          'public/css/styles.min.css': ['src/css/*.css']
        }
      }
    }
  });

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

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

Grunt Watch Plugin

With this plugin you can tell Grunt to execute certain tasks when files changes are detected. After the configuration is set, we can run "grunt watch", this will leave grunt in a "waiting" status and will automatically run any task you want when you modify the source files.

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

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

    cssmin: {
      target: {
        files: {
          'public/css/styles.min.css': ['src/css/*.css']
        }
      }
    },

    watch: {
      css: {
        files: ['src/css/*.css'],
        tasks: ['cssmin'],
        options: {
          spawn: false,
        }
      }
    }
  });

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

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

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

Grunt Less Plugin

Plugin to compile your less files. Config is super easy, so i also included the watch plugin to make things easier during development.  The only "new" thing here is the options/path configuration var that we use to specify where less scans for @import directives files.

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

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

    less: {
      development: {
        options: {
          paths: ['src/less/inc/']
        },
        files: {
          'public/css/site.css': 'src/less/*.less'
        }
      }
    },

    watch: {
      css: {
        files: ['src/less/*.less'],
        tasks: ['less'],
        options: {
          spawn: false,
        }
      }
    }
  });

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

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

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

All plugins have many options, this post covers just the most basic ones.

About
Related Posts
  • No related articles have been found, for now
Comments
The comments are closed on this section.
Hire me!

I'm currently open for new projects or join pretty much any project i may fit in, let me know!

Read about what I do, or contact me for details.