Integrating Grunt with Roots Theme

Using Grunt with Roots will help you automate your workflow and build WordPress themes more efficiently.

I pushed up a Grunt branch to the Roots repository that will show you how I’ve used grunt in my projects lately. The Roots Gruntfile will:

  1. Validate your JavaScript with JSHint
  2. Compile Bootstrap’s bootstrap.less & responsive.less along with your site-specific app.less to main.css
  3. Concatenate all your JavaScript plugins and site-specific JS to scripts.js
  4. Minify scripts.js to scripts.min.js & main.css to main.min.css
  5. Update lib/scripts.php’s wp_enqueue_style and wp_enqueue_script calls to update the version based off the md5 of the files (to bust cache)

Benefits

  • Easily compile LESS files
  • Minification and concatenation without plugins
  • Fewer requests made to the server (one CSS file, one main JS file besides Modernizr and jQuery)
  • Ensures valid JavaScript
  • Others working on your project are able to use the same build script and have a unified development process
  • Code is optimized for production use

The Gruntfile.js file

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

  grunt.initConfig({
    jshint: {
      options: {
        jshintrc: '.jshintrc'
      },
      all: [
        'Gruntfile.js',
        'assets/js/*.js',
        'assets/js/plugins/*.js',
        '!assets/js/scripts.min.js'
      ]
    },
    recess: {
      dist: {
        options: {
          compile: true,
          compress: true
        },
        files: {
          'assets/css/main.min.css': [
            'assets/css/less/bootstrap/bootstrap.less',
            'assets/css/less/bootstrap/responsive.less',
            'assets/css/less/app.less'
          ]
        }
      }
    },
    uglify: {
      dist: {
        files: {
          'assets/js/scripts.min.js': [
            'assets/js/plugins/bootstrap/bootstrap-transition.js',
            'assets/js/plugins/bootstrap/bootstrap-alert.js',
            'assets/js/plugins/bootstrap/bootstrap-button.js',
            'assets/js/plugins/bootstrap/bootstrap-carousel.js',
            'assets/js/plugins/bootstrap/bootstrap-collapse.js',
            'assets/js/plugins/bootstrap/bootstrap-dropdown.js',
            'assets/js/plugins/bootstrap/bootstrap-modal.js',
            'assets/js/plugins/bootstrap/bootstrap-tooltip.js',
            'assets/js/plugins/bootstrap/bootstrap-popover.js',
            'assets/js/plugins/bootstrap/bootstrap-scrollspy.js',
            'assets/js/plugins/bootstrap/bootstrap-tab.js',
            'assets/js/plugins/bootstrap/bootstrap-typehead.js',
            'assets/js/plugins/*.js',
            'assets/js/_*.js'
          ]
        }
      }
    },
    watch: {
      less: {
        files: [
          'assets/css/less/*.less',
          'assets/css/less/bootstrap/*.less'
        ],
        tasks: ['recess']
      },
      js: {
        files: [
          '<%= jshint.all %>'
        ],
        tasks: ['jshint']
      }
    },
    clean: {
      dist: [
        'assets/css/main.min.css',
        'assets/js/scripts.min.js'
      ]
    }
  });

  // Load tasks
  grunt.loadTasks('tasks');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-recess');

  // Register tasks
  grunt.registerTask('default', [
    'clean',
    'recess',
    'uglify',
    'version'
  ]);
  grunt.registerTask('dev', [
    'watch'
  ]);

};

File changes/re-organization

There have been a few changes in the grunt branch allowing better organization of your assets:

  1. All Bootstrap files have been moved into a subdirectory to assets/css/less/bootstrap/
  2. app.css has been renamed to app.less, moved to the LESS directory, and updated with some @import’s at the top of the file to use variables and mixins from Bootstrap
  3. plugins.js has been removed since you’ll be placing all of your plugins within assets/js/plugins/
  4. The minified Bootstrap JS doesn’t exist anymore and all of the Bootstrap plugins exist in assets/js/plugins/bootstrap/ — you can easily remove certain plugins from your site by editing the Gruntfile
  5. main.js has been replaced with _main.js and contains an example helpful DOM-based routing script that works off the WordPress body_class
  6. lib/scripts.php has been updated to remove all extra CSS and JS files and also places JavaScript in the footer

Installing Grunt to use with Roots

After you’ve installed grunt globally you’ll need to install the additional Grunt tasks we use. First, clone Roots from your /wp-content/themes/ directory and switch to the Grunt branch:

$ git clone https://github.com/retlehs/roots.git
$ cd roots
$ git checkout grunt

Then install the Grunt tasks (grunt-contrib, grunt-recess) used in the Roots Gruntfile by typing:

$ npm install

Now you’re ready to build. Type grunt to build. Use grunt watch to watch for updates to your LESS and JS files and Grunt will automatically re-build as you write your code.

Thanks to Stephen Jothen for the help creating the task that updates the versions for enqueued CSS and JS.