Docs » Extend Grunt

Webhook uses a Javascript taskrunner called Grunt to power most of our local runserver. We use it to compile templates to HTML, deploy the site and run a whole bunch of other useful actions you likely don't realize happen behind the scenes. While you don't need to know what Grunt does to use Webhook, you might find use in extending it in your Webhook site to perform tasks like minifying your static files or preprocessing your Sass or Less files to CSS.

If you've never used Grunt before, here's a great tutorial to teach you the basics.

Changes to your Gruntfile only effect the local site

Before we begin, it's important to note that any tasks you add to your Webhook site's Gruntfile are only run locally. Once your code hits our live servers we run a seperate build operation against your site when it needs to be rebuilt (for example, when an article is saved). This means you should never use Grunt tasks to dynamically read template code, instead use it only for preproccessing tasks like minifying files, copying or cleaning directories and other more common Grunt tasks.

Customizing your Gruntfile.js and Node packages

Every Webhook site comes with a Gruntfile.js file located in its root folder. In it you are welcome to add your own tasks and perform actions as you see fit to help out your development workflow. We've siloed out our own tasks so you've got a clean area that should never be changed by our own update process.

If you do add tasks you'll likely also add to your package.json file as well. Again, you're welcome to add whatever scripts you need to help in your local environment, but know that these scripts will not be installed or run on the live build servers.

Warning!
Currently, when a wh update is run during the Webhook upgrade process we change the package.json file and re-install any Node modules. If you've made changes to these files, you might want to backup your work just in case our update script gets overzealous.

An example

The following is an example of an extended Gruntfile used in the Webhook preprocessor theme. Basically it watches for changes to the sass, less, and coffee directories and then compiles those files into .css and .js files.

First we need to add the Node modules we plan on using to our package.json file. In this case, it's the sass, less and coffee modules.

// We need to add these to the bottom of our package.json file
"grunt-contrib-sass": "~0.7.3",
"grunt-contrib-less": "~0.11.2",
"grunt-contrib-coffee": "~0.4.0"

Then we set up a Gruntfile to watch for changes.

'use strict';
module.exports = function(grunt) {

  // ----------------------------------------------------------
  // WARNING, BRAVE DEVELOPER
  // ----------------------------------------------------------
  // Webhook allows you to use local grunt tasks and files.
  // However, these tasks are ONLY RUN LOCALLY and not when
  // your live site needs to be rebuilt. This means you should
  // only use grunt for pre-processing tasks like building
  // Sass, less or coffescript files, not for reading things
  // from your templates and making dynamic changes during
  // the build process. Doing so will cause your live site
  // not to regerate.
  //
  // You have been warned!

  grunt.initConfig({
    // BUILD SASS TO CSS
    sass: {
      dev: {
        options: {
          // We used the expanded style because Webhook already minifies CSS when it deploys your site.
          style: 'expanded',

          // Uncomment the below line to include outside directories as well.
          // loadPath: ['location/of/other/sass']
        },
        files: [{
          // Files in the /sass/ directory will go to /static/css/ when processed.
          expand: true,
          cwd: 'sass',
          src: ['*.sass'],
          dest: 'static/css',
          ext: '.css'
        }]
      }
    },

    // BUILD LESS TO CSS
    less: {
      dev: {
        options: {
          // Uncomment the below line to include outside directories as well.
          // paths: ['location/of/other/less/']
        },
        files: [{
          // Files in the /less/ directory will go to /static/css/ when processed.
          expand: true,
          cwd: 'less',
          src: ['*.less'],
          dest: 'static/css',
          ext: '.css'
        }]
      }
    },

    // BUILD COFFEE TO JAVASCRIPT
    coffee: {
      compile: {
        files: {
          'static/javascript/main.js': ['coffee/*.coffee'] // compile and concat into single file
        }
      },
    },

    // WHEN FILES CHANGE, RUN THE ABOVE TASKS ALONG WITH BUILD
    watch: {
      sass : {
        files: ['sass/**/*.sass'],
        tasks: ['sass', 'build']
      },
      less : {
        files: ['less/**/*.less'],
        tasks: ['less', 'build']
      },
      coffee : {
        files: ['coffee/**/*.coffee'],
        tasks: ['coffee', 'build']
      },
    }
  });

  // THIS LOADS THE TASKS WE NEED ABOVE IN FROM OUR NPM
  // Note, that we need to have these installed through the package.json file as well
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-coffee');

  // NEVER REMOVE THESE LINES, OR ELSE YOUR PROJECT MAY NOT WORK
  require('./options/generatorOptions.js')(grunt);
  grunt.loadTasks('tasks');
};