How (and how not) to build JavaScript With Node.js

How Flite moved from Ant to Grunt

Clay Smith, Flite Inc.

@smithclay

There was a time when we didn't need JavaScript build tools

But we keep writing more JavaScript...

Flite started writing a lot more front-end JavaScript

We needed a way to manage the mess.

We wanted

  1. Concatenation
  2. Minification

*graphic from a great @paulirish talk about tools.

Build Version 0 (Winter 2012)

Do all the things in Java!

Tools

  1. Concatenation: combiner.jar (circa 2009 fake sprockets in Java)
  2. Minification: Closure Compiler

using ant...

Problem

Ant is ugly.

More observations

  1. It's hard to find your way around ant if you're new.
  2. Ant is hard to extend.
  3. Ant just isn't designed for front-end engineering.
  4. Sometimes you just want a scripting language.

Build Version 1 (Spring 2012)

Do (some) things node.js!

We used jake

jake is a JavaScript build tool, similar to Make or Rake. Built to work with Node.js.

jake is a step in the right direction.

We started writing lots of jake tasks


desc('This is the default task.');
task('default', function (params) {
  console.log('This is the default task.');
});
						
There's also a CoffeeScript version called cake.

We started using lots of npm packages

This makes writing build tasks easier.

Problem

We ended up with a 1000+ line Jakefile we couldn't reuse.

Build Version 2 (Summer 2012)

Do all the things in node.js!

We couldn't help but notice this thing called grunt.js

We weren't the only ones.

grunt was doing all the stuff we were doing

In 5 lines of code

grunt.initConfig({
  min: {
    dist: {
      src: ['src/source1.js', 'src/source2.js'],
      dest: 'dist/built.min.js'
    }
  }
});
						

"Configuration over Scripting"

grunt favors the “configuration” approach for tasks for one simple reason: people seem to prefer a more declarative “configuration” style approach to a “scripting” approach.
-grunt.js author @cowboy (Ben Alman)

Grunt is balanced

Lots of common tasks and plugins that you can configure in a JSON object, but you also can script with the full power of node.js.

Grunt can load NPM plugins!


// Load some grunt tasks we’ve developed from the npm package grunt-barkeep.
grunt.loadNpmTasks('grunt-barkeep');
// Load grunt-shell
grunt.loadNpmTasks('grunt-shell');
// Load grunt-jasmine
grunt.loadNpmTasks('grunt-jasmine');
						

It's easy to create your own plugins.

Check out gruntjs.com

Plugins we use (and like)

**there's headless grunt tasks for testing in almost any framework.

It's easy to create custom tasks in grunt.

It bundles underscore, async, logging, console coloring, file utilities, and more.

var js = grunt.file.expandFiles(task.file.src);
// Hey, async is available in grunt.utils.
grunt.utils.async.forEach(js, function (fn, callback) {
    // ...
    if (err) {
    	// Fatal error logging
    	grunt.fail.fatal(err);
    }
});
						

The Future: grunt 0.4.0

Coming soon?
  • Requires node > 0.8.0
  • Externalizes a lot of plugins in the gruntjs github repository
  • Lots of bug fixes and new features

Build Version 3 (?)

rm -rf *.js

THE END

Summary: