What's in a Build Tool?
A build tools range from simple to entirely complex. You could use a
Makefile (yes people do use those) or a simple rake task that
concatenates all source files. The tool may compile CoffeeScript
Build tools have many responsibilities. All the tools do roughly the
same thing: enable you to use CoffeeScript/SCSS/insert other compile
to JS or CSS language here, a choice of templating library
(Handlebars/Jade), and handle deployment scenarios in some way.
Most tools simply compile and concatenate all the
assets and then minify. This does not mean deploying to servers, but
- Yeoman (Node): arguably the most popular. It should be easy to dominate when you are Google backed project. Uses grunt.
- Brunch (Node): a simple tool focused on elegance and simplicity.
- Iridium (Ruby): rake-pipeline based. Highly configurable and designed for heavy duty use and complex applications.
All there will be compared in these areas
- Compilable Language Support
- Module Support
- Vendored Code
- Package Management
- Deployment Packaging
Brunch calls itself a "HTML5 Application Assember". It's opinionated and is extendable via plugins. It‘s agnostic to frameworks, libraries, programming, stylesheet & templating languages and backend technology.
Compilable Language Support
Many languages are supported via plugins. There are plugins for all the popular ones (CoffeeScript & SCSS of course). There are also plugins for Less and LiveScript. You may have to configure these yourself. Brunch may not support your choices out of the box. CoffeeScript and Stylus are the defaults. Its easy to add plugins after a new application is generated. More on this in the skeletons section.
Brunch supports a different module formats. CommonJS is the
default. You can change this to AMD, none, or write your own. Brunch
also registers a global
All the major templating libraries are supported via plugins. They may also be precompiled. Templates are registered as modules. Require them like normal modules when required.
`brunch test runs headless tests with mocha and JSDom. I'm very skeptical of JSDom. I'm concerned about the performance and about how well it mimics a real DOM. The pure headless slant concerns me. Headless testing is nice, but at the end of the day you eventually have to run tests in the browsers themselves. I'd rather see build tools embrace this then walk around it.
Brunch is fast. It's very fast. It's impressive fast. Brunch also sends notifications to the Notification Center on OSX. This means you'll see compile errors or other warnings the second you hit save. I read about this but I didn't expect it to work. It worked out of the box! I'm not sure how useful it is, but I'm sure others will find it useful.
Development is built around file watching. The final site is compiled
everytime a file changes. Brunch does include a server, although
starting it weird. You can start a server with:
Brunch has a live reloading plugin. This will automatically refresh the browser when code changes. This is handy for the "refresh, alt-tab, reload" workflow.
Brunch includes a
vendor directory. You can also configure a load
order for vendor code. This is extremely important. This means you can
configure jquery-ui to load after jquery. Vendored code is not wrapped
in modules. It's simply available. You don't have to require code in
Brunch does not handle package management. Simply download the source files
you need and drop them into
vendor/. Package management support
via Bower is planned for the next major release.
Packaging the app for deployment happens via:
--optimize flag uses a minifier (if the plugin
is installed). Plugins can also tie into the optimize flag. There is a
plugin for optimizing images.
brunch build compiles all the files
public/. Now it's your responsibility to serve the files. The
readme describes how you can host the app on various systems. However,
Brunch does none of this for you. All of this your responsibility.
Liniting is supported via plugins. There are plugins for JSLint and JSHint.
Yeoman is arguably the most popular build tool. It was introduced at Google IO. Google is behind. Addy Osamni is involved with it as well other other big names like Paul Irish. It's powered by Grunt and Bower.
Compilable Language Support
CoffeeScript and SASS are supported out of the box. Other languages
are supported by installing a plugin and then updating the
Yeoman uses AMD. Yeoman goes through a setup wizard when generating a new app. You can select ECMAScript 6 module support in the wizard.
Yeoman does not support a templating language out of the box. This is a glaring failure. I wanted to write Handlebars templates. There is a plugin for that. However, annoying configuration is required--just like most Grunt tasks. This also required customizing the server task to run the handlebars task. The watch task also had to be updated. All in all it was a very annoying and frustrating experience.
Mocha and PhantomJS are used for testing. You may also open
tests/index.html in the browser.
yeoman test opens
tests/index.html with PhantomJS and reports the results. Results are
also sent to growl if you like that sort of thing.
The development cycle happens very quickly. Run
yeoman server and a
preview server starts. The server is very fast. No complaints here.
My complaint is with Grunt. Developers have to pay attention to their application setup. Concatenation order must be specified. Compile orders must be specified. There is a fair amount of configuration that must be kept up to date. Development happens quickly after that's worked out.
Yeoman has supports few skeltons out of the box. The big three are
supported: Ember, Backbone, and Angular. You can generate a new ember
yeoman init ember. I recommend using a skeleton
instead of trying to setup all the plugins yourself.
There is a
vendor folder inside the
scripts folder for vendored
mistake. You can add a vendor folder for CSS by updating the
Yeoman does have package management. Bower is tightly integrated into
Yeoman. Dependencies are specified in
component.json. The format is
package.json in NPM. Yeoman also exposes serval commands
for package management.
yeoman install jquery and
are the most important. The files are placed into the correct places
so they can be required with require.js. You'll like Yeoman's package
management if you like Bower.
yeoman build compiles the application for deployment. It runs your
code through require.js's optimizer. It will also minify your code and
run images through an optimizer. Yeoman is not involved in the
deployment process, it simply makes assets ready for deployment.
There no linting support baked in. There might a plugin.
Disclaimer: I wrote Iridium after finding nothing sufficient in either Node or Ruby.
Iridium focuses on doing one thing extremely well: developing browser applications. It makes optimizations to achieve that goal. Iridium also includes many other things that don't fit directly into this article. Here is a big one: different environments. People coming from a Rails background take this for granted. Iridium configures three environments: development, test, and production. You can configure builds in each environment. Do you need to include some code only in production? You can do that.
Iridium is arguably the most complex of all the tools. Its also the most powerful. Iridium is built on two main things: rake-pipeline and hydrogen. Hydrogen makes Iridium extendable with components (just like engines/railties in rails). Rake-Pipeline is a library for defining a set of input files and filters. Filters can be chained together to generate the final output files.
Compilable Language Support
Iridium generates CoffeeScript and SCSS (or SASS) by default. You
can also use Less by modifying the
Assetfile. Vanilla CSS and
Iridium implements a simple solution for module support. It does not
use CommonJS or any other more complex solution. It uses
minispade to wrap source files
in named functions. Simply
require the name of the file where you
Handlebars is the only supported templating language. This is an opinionated choice. Only supporting handlebars enables complete integration. Individual and inline templates are precompiled.
Iridium has two pipelines: one for application code and
one for test code. All the test code is compiled down to
You can open
test.html in any browser. It is also framework
agnostic. PhantomJS is also supported. Running
tests.html in PhantomJS and reports results (all headless).
The PhantomJS runner works with QUnit and Jasmine.
Iridium is "refresh" friendly. Edit your source files and hit refresh
in your browser. There is a bundled development server as well. Run
iridium server to start developing.
The initially generated project is framework agnostic. Skeletons
support common frameworks. Skeletons come in as generators from
engines. There is only one engine at this time: iridium-ember.
iridium g ember:application. You can write your
own skeleton by writing an engine and defining generators.
Vendored code is treated differently then application code. Vendored
code is not wrapped in modules. It is simply available. There are
specified. All the vendored code is inserted above application code
in the final
Iridium does not support package management in anyway. If you want to
update jQuery/Ember/Handlebars/etc simply replace the file in
via an engine.
Iridium supports multiple environments: development, test, and
production. Compiling in the production environment is deployment
Individual and inline Handlebars templates are precompiled. A HTML5
cache manifest is also generated. All files are compiled into the
site/ directory. You can simply put this directory on your
web server. Iridium also includes a production ready rack server.
Applications can be deployed to Heroku for free right out of the box.
The production server will also handle caching correctly so users only
download the code when it changes (via the cache manifest and HTTP
be integrated into CI.
Sometimes it's easier to know what's not good instead of what is. I
think this way about Yeoman. Yeoman is built on top of Grunt. This is
a problem. Writing and maintain
Grunfiles is a pain. Installing
plugins also requires configuration. Doing this for every plugin is
The package management is nice, but what does it really add? How often are you managing dependencies? Is it really nicer than simply downloading the individual files? Bower does not support all use cases. Packages that have to built do not work. Ember-Data is a perfect example.
Overall it seems that Yeoman does not have great developer ergonomics. It doesn't support a templating language out of the box. All in all, Yeoman feels like a thin wrapper around grunt. I recommend you look at other options before using Yeoman.
Brunch and Iridium are much better options. Brunch is very fast and
and opinonated. Brunch' default stack is optimized for Backbone. This
is easily solved by using a different generator. Ember developers will
have no problem with Brunch. Brunch does not use Grunt. This is a
wonderful choice. Brunch plugins configure themselves. Place your
package.json and go to work. There is minimal
configuration. Developing with Brunch was a pleasant experience.
Iridium is another excellent choice. Iridium uses some of Rail's best ideas. Convention of configuration is the biggest one. Developers will do little or no configuration to get started. It's a full stack solution. Iridium supports TDD, compilation, and deployment right of the box.
Here are links to get you started:
— Adam Hawkins