Grunt in a modular application
As a Node application grows, a modular design where features reside in neatly separated units is a must in order to keep things manageable. Node makes this relatively easy with its package management. For the application as a whole, however, there is little guidance available to help you keep things consistent.
One problem that I had to tackle over the past few days was to run all the tests in my application with a single grunt command. Because of the modular design, I have a test folder, and a grunt file, in each module, where it belongs. If I wanted to run them all, however, I had top go into each directory and grunt from there.
After some unsuccessful attempts to spin new processes, or new grunt instances, from my root grunt file, I found the grunt-run-grump package, that will spin up a new process, run grunt inside it, and integrate the results into the root’s results. That was exactly what I needed.
I built a small utility function that dynamically adds one section per module to a runGruntConfig object if it finds a grunt file in a directory:
function setupSubGrunt(root) {
var gruntPath = path.resolve(root, 'Gruntfile.js');
var isGrunt =fs.existsSync(gruntPath);
if (isGrunt) {
runGruntConfig[root] = {
src: gruntPath,
options: {
verbose: verbose,
indentLog: ' | ',
cwd: path.resolve(root)
}
};
}
return isGrunt;
}
My application can then explore itself for modules, call setupSubGrunt for each, and once it’s done, initialize the configuration, and register the global “modules” task:
grunt.config.merge({
run_grunt: runGruntConfig
});
grunt.registerTask('modules', 'Run all tasks in all modules', 'run_grunt');
Each Grunt file, in each module, can still be run individually, as there is nothing special about them, but I now also have the ability to run them all at once, but still in their own specific context. This has already proven to be a fast and clean way to manage tests across the application. All I have to do is “grunt modules”.