Using node.js for a build script
Lately we‘ve been amazed by how node allows you to use plain JavaScript for all your scripting needs. My coworkers still rely on Python or Ruby for those stuff, but since I’m a frontend guy, this comes in really handy for me. (Don’t get me wrong, Python and Ruby are really great languages, but I’m just too lazy to learn, when I can achieve the same thing with the language I’m using day to day).
Amazed and inspired by the many approaches the OpenSource community has towards using node for build script stuff I decided to hack my own build script for a few of my recent projects. Again, I’m being pretty lazy here. I could have just learned my way into one of the existing build scripts out there, but I wanted full flexibility and a syntax I could easily hack for different project structures. So let’s get started.
If you’re coming from the frontend like me, you’ll know that the essential part of frontend building is file concatenation and minification of assets. So that’s where I started. Concatenating files is pretty straightforward in using nodes built in filesystem-module. So my basic script workflow looks like this: Find all the files, concatenate them into a temporary file, minify the contents of the temporary file to the build target and delete that temporary file. (Lot’s of temporary going on there…)
Let’s say you have an array of files you want to concatenate that looks like this:
var paths = ['js/script1.js', 'js/script2.js', 'js/script3.js'];
You can then simply make one file from these three files using map and node’s very own filesystem module:
var _fs = require('fs');
// map the contents of all files to the array "out"
var out = paths.map(function(path) {
return _fs.readFileSync(path, 'utf8');
});
// join "out" with a linebreak and save that stuff to a temporary file
_fs.writeFileSync('tempFile', out.join('\n'), 'utf8');
It’s that simple! Next step is to minify that stuff. No need to reinvent the wheel here. Before rolling my own script I’ve been pretty happy using Google’s Closure Compiler for Javascript and YUI Compressor for CSS. Nice thing about node: It also has a child_process module, that let’s you run command line stuff from inside your scripts. So simply take the syntax you’re using on the command line and drop it inside your script. (You’ll obviously have to place the .jar files of YUI Compressor and GCC in the same folder as your node script…)
var exec = require('child_process').exec;
// ClosureCompiler
exec('java -jar google_closure_compiler-r1810.jar --js=tempFile --js_output_file=script.min.js', function (err, stdout, stderr) {
// Put some callback stuff here
});
// YUI Compressor
exec('java -jar -Xss2048k /yuicompressor-2.4.7.jar tempFile -o style.min.css', function(err, stdout, stderr) {
// Again, callback should go here
});
That’s all there is to using node for build scripts. You’ve just learned how to concatenate and minify assets with node.js. This is all you need to know to get started hacking a build script for your own project.
Rodolphe Stoclin has written a nice node module called “node-minify” to provide some great abstraction over those minification called. You can find it on github: https://github.com/srod/node-minify
At the time of writing this, “node-minify” has no ability to automatically concatenate files. So I’ve forked the module, added that stuff and sent a pull request to Rodolphe. I’ll keep you updated. In the meantime you can check out my implementation at https://github.com/lnolte/node-minify
So in the end file concatenation and minification in node becomes as simple as this:
var compressor = require('node-minify');
// This will concatenate your script files and minify them using Google Closure Compiler (gcc)
new compressor.minify({
type: 'gcc',
fileIn: ['public/js/plugins.js', 'public/js/scripts.js'],
fileOut: 'public/js/script.min.js',
callback: function(err){
console.log(err);
}
});
From now on I’ll be using node a lot more for streamlining my frontend build processes. I’m still trying to figure out a nice way to distribute the whole process, but I feel like I’m getting there.
What are your experiences with build proccesses? Please let me know. Thanks for reading!

