Building multiple folders with Grunt.

Jun 30, 2015

At Intracto we use Bamboo to automate building and deployment of our web projects. All our projects have a comparable directory structure with a Gruntfile in the same location. There’s a task in bamboo that knows to run npm install and grunt build from the root folder to build all the styles and assets.

A project that we’re currently working on has multiple web-heads so it needs to have styles and assets compiled for each of those heads. We could either change the setup of bamboo and create a GruntFile for each different design or create one file that builds everything at once. The latter is the easiest solution for this particular project, so that’s what we went for.

I’m going to share how we’ve set up the GruntFile, for demo purposes let’s assume this project needs to build for /web/jediBundle/ and /web/sithBundle.

module.exports = function (grunt) {
    grunt.initConfig({

        folderName: 'jediBundle',

        globalConfig: {
            src: 'web/<%= folderName %>/',
            pub: 'web/<%= folderName %>/public',
            dest: 'src/<%= folderName %>/public'
        },

        sass: {
            //Production version (triggers on $ grunt build)
            dist: {
                options: {
                    includePaths: require('node-neat').includePaths,
                    //Disables the sourcemaps as they are not needed on production
                    sourceMap: false
                    },
                files: {
                    '<%= globalConfig.dest %>/tmp/main.css': '<%= globalConfig.pub %>/scss/main.scss'
                }
            }
        },

        cssshrink: {
            your_target: {
                files: {
                    '<%= globalConfig.dest %>/tmp/': ['<%= globalConfig.dest %>/tmp/main.css']
                }
            }
        },
    });
}

This is an example of what a basic gruntfile looks like for us. This gruntfile will make sure Sass will be built (with production settings) and css will be shrunk.

Near the bottom of the gruntfile we usually register the build task that triggers the needed modules. grunt.registerTask('build', ['sass:dist', 'cssshrink']);. A simple call to grunt build will trigger both tasks defined, assets’ll be built and everyone is happy.

In this case however, that won’t work. Instead we’ve registered a task per website that needs to be built and made sure that the build task will run the other defined tasks

grunt.registerTask('build-jedi', function() {
    // set up configuration to build for the jedi and run tasks.
    grunt.config.set('folderName', 'jediBundle');
    grunt.task.run(['sass:dist', 'cssshrink']);
});

grunt.registerTask('build-sith', function() {
    // Set up configuration to build for the dark side and run tasks.
    grunt.config.set('folderName', 'sithBundle');
    grunt.task.run(['sass:dist', 'cssshrink']);
});

grunt.registerTask('build', function() {
    grunt.task.run('build-jedi');
    grunt.task.run('build-sith');
});

There are other ways to set up this kind of workflow, but this one was easy enough to implement without having to change other parts of our workflow.