Grunt - The JavaScript Task Runner

Developing for the web can be tedious sometimes. Not only do you need to develop using multiple languages you need to make things as easy for yourself as you can when it comes to deployment. One of the most basic things you can do to make your source files ready for production is to minify all of your JavaScript files. There are a few programs out there that will do it for you but today I want to show you Grunt. The great thing about Grunt is it will autocompile and minify your code even as you're developing. For example, in your templates you set the source for your scripts to the .min.js versions. Normally once you make a change to the source you'd need to manually minify the file again before refreshing the page. Grunt will do all of the minifying for you and using one of their plugins can watch your code for changes and automatically recompile when you save. I'm going to go through a basic setup for Grunt. There are many more advanced things you can do with Grunt but I'm just going to show you a basic setupd to recompile your LESS files and minify your JavaScript each time they change. The first thing you'll want to do is install Grunt. To install it you'll need NPM and Node.js. If you already have those installed skip down to step 3.
  1. sudo apt-get install npm
  2. Download Node.js from http://nodejs.org/
    1. tar xvzf node...tar.gz
    2. cd node.../
    3. sudo ./configure
    4. sudo make
    5. sudo make install
  3. npm install -g grunt-cli
  4. Go to your project folder and run grunt init to create a basic package.json file. You also need to create an empty Gruntfile.js. These need to be at the root of your project.
  5. npm install grunt --save-dev
  6. npm install grunt-contrib-watch --save-dev
  7. npm install grunt-contrib-uglify --save-dev
  8. npm install grunt-contrib-less --save-dev
Step 3 installs the Grunt command-line interface. Step 4 ensures you have the right files to install your Grunt setup. Steps 5-8 install the plugins we are going to use in this guide. Watch is the plugin to watch our files for changes and make something happen when they do. Uglify is the minification plugin. Less is what will compile our LESS files to CSS. The --save-dev automatically puts the plugins into your package.json file. Now that you have everything installed you need to set up your Gruntfile to do what you want Grunt to do. Here is a simple example Gruntfile.js.
module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    watch: {
        customers: {
            files: ['customers/static/customers/js/source/'],
            tasks: ['customers'],
        },
        customers_less: {
            files: ['customers/static/customers/less/'],
            tasks: ['customers_less'],
        },
    },
    less: {
        customers_less: {
            files: [
                {
                    expand: true,
                    cwd: 'customers/static/customers/less',
                    src: '/.less',
                    dest: 'customers/static/customers/css',
                    ext: '.css'
                }
            ]
        },
    },
    uglify: {
      options: {
        banner: '/! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      customers: {
        files: [
            {
                expand: true,
                cwd: 'customers/static/customers/js/source',
                src: '/*.js',
                dest: 'customers/static/customers/js',
                ext: '.min.js',
            }
        ]
      },
    }
  });

  // Plugins
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-less');

  // Default task(s).
  grunt.registerTask('default', ['uglify', 'less']);
  // Uglify Tasks
  grunt.registerTask('customers', ['uglify:customers']);
  // LESS Tasks
  grunt.registerTask('customers_less', ['less:customers_less']);
};
Let's walk through that file. At the top you see grunt.initConfig and in here we will put a dictionary with each key representing either a Grunt keyword or a Grunt plugin. In the example above you can see there is pkg, watch, less, and uglify. Pkg reads your package.json for information about your project. watch, less, and uglify all contain information for the various plugins to know what to compile and where to output it. I'll quickly go through each plugin and how it is setup. Watch contains a dictionary with named methods. I've labeled them after the Django app it relates to in my project but you can name them whatever. Inside of the labeled section are the keywords files and tasks. Both are lists and they define what files to watch and what tasks to perform when one of those files have been changed. Less is structured similarly to Watch but instead of triggering a task it is going to take source files and convert them to CSS files. It takes one keyword argument with a list of dictionaries with various options. To use those options you first need to set expand to true. Cwd is the relative path name to your source files. Src says where to look for and what type of file they are. Here we are checking all directories and subdirectories found at cwd for .less files to convert. Dest is where the CSS files will be outputted. Ext says what the file extension should be. Uglify looks almost exactly the same as the less section and that is because it is doing almost the exact same thing, taking source files and outputting files in a destination folder. I created a sub-folder inside my js folder to house the source files and then send the minified versions to the main js folder. This allowed me to keep most of my URLs in tact and just add .min.js to the filename. At the top of uglify there is the options keyword with banner inside of it. You can customize this to put a small bit of text at the top of your minified files. Here we have the package name and when it was compiled. Now that we have all of the plugins configured we need to activate them all. Place all the names of the plugins you are using under the Plugins section. After that you create tasks. Every Gruntfile needs a default task that will be run when you use the command grunt. I have mine set to do all the things inside of both uglify and less so it compiles all of my code in one command. Next you'll need to register the task names so watch knows what to run. Once you've done that you are good to go. Run the command grunt watch and then change any of your files. You should see that Grunt automatically redid whatever section it was told to do. Grunt is a great tool and I have only slightly scratched the surface of what it is capable of. Please head over to their website to learn more about Grunt and the great things you can do with it. If you have any tips or tricks with Grunt please comment below.