Skip to content
This repository has been archived by the owner on Jan 16, 2024. It is now read-only.

Working with grunt

drsm79 edited this page Aug 9, 2012 · 4 revisions

Working with grunt/bbb

grunt and bbb are neat task based tools that help you build web applications conforming to best practices (minified everything, test driven, sensible code layout etc.). Using these as helpers for your situp.py projects is desirable - since much of the grunt work (arf!) is taken care of for you.

Situp now has pre and post processors. These allow you to run commands before and after pushing to the server and are a great place to hook in tools like grunt or bbb. Consult situp.py push -h for a list of available pre/post processors.

Using grunt/bbb from a pre/post-processor

To trigger grunt or bbb you'll want to use the cmd processor, which is available both for pre and post actions:

situp.py push -d my_app -s host --pre=cmd "bbb package" -e bbb-app
situp.py push -d my_app -s host --post=cmd "bbb clean" -e bbb-app
situp.py push -d my_app -s host --pre=cmd "bbb package" --post=cmd "bbb clean" -e bbb-app

Triggering bbb package is only useful if you have the necessary task defined. The package task builds the application (e.g. cat's and minifies js/css) and copies the build artifacts and any assets into a predefined location. For use with situp.py this is the _attachments directory of your design document.

At the moment you'll need to include the following task definition and alias to enable the package task:

// Copy files and folders into a new directory structure
grunt.registerTask("relocate", "Relocate files and directories.", function(){
  // bail if release hasn't run
  grunt.task.requires('release');
  // TODO: ditch this when grunt v0.4 is released
  grunt.util = grunt.util || grunt.utils;

  var _ = grunt.util._;

  var options = _.defaults(grunt.config("relocate") || {}, {
    destination: 'bundle',
    files: ['*.html'],
    folders: {'dist': ''}
  });

  grunt.file.mkdir(options.destination);

  function recurse_expand(source, dest){
    var files = {};
    grunt.file.recurse(source, function(abspath, r, s, f){
      files[abspath] = abspath.replace(source, dest);
    });
    return files;
  }

  function copyPath(the_list){
    _.each(the_list, function(source){
      var destination = options.destination + '/' + source;
      destination = destination.replace(/\/+/g, '/');
      grunt.log.writeln('copy ' + source + ' to ' + destination);
      grunt.file.copy(source, destination);
    });
  }

  function relocateToPath(the_list){
    _.each(the_list, function(newpath, path, l){
      var destination = options.destination + '/' + newpath;
      destination = destination.replace(/\/+/g, '/');
      grunt.log.writeln('copy ' + path + ' to ' + destination);
      grunt.file.copy(path, destination);
    });
  }

  if (_.isArray(options.files)){
    // files to copy into the bundle
    _.each(options.files, function(f){
      copyPath(grunt.file.expand(f));
    });
  } else {
    // files to relocate into the bundle
    var expandedFiles = {};
    _.each(options.files, function(value, key, list){
      // grunt.file.expand returns a list, make suitable object
      _.each(grunt.file.expand(key), function(file){
        expandedFiles[file] = value + '/' + _.last(file.split('/'));
      });
    });
    relocateToPath(expandedFiles);
  }

  if (_.isArray(options.folders)){
    // directories to copy into the bundle
    _.each(options.folders, function(f){
      copyPath(recurse_expand(f, f));
    });
  } else {
    // directories to relocate into the bundle
    _.map(options.folders, function(value, key, list){
      relocateToPath(recurse_expand(key, value));
    });
  }
});
// Build a release (lint, test, minify css/js) then copy resulting
// files and all other assets into a bundle directory
grunt.registerTask("package", "release bundle");

This is then configured like:

relocate: {
  // Files to bundle up. Can be copied into same directory structure
  //files: ['*.html'],
  // or relocated into a new one:
  files: {'*.html': '',
          'dist/release/*.css': 'assets/css/',
          'dist/release/*.js': 'assets/js/libs'
         },
  // Folders to bundle up. Copy files and folders:
  folders: ['things'],
  // or relocate them:
  //folders: {'things': 'thangs'},
  // all locations are relative to the destination parameter.
  destination: '_design/my_app/_attachments/'
}

You can see a sample application, including a full grunt.js file using bbb to manage client side code here. The application is also live up on Cloudant.

Clone this wiki locally