The Software Simpleton

Nomadic cattle rustler and inventor of the electric lasso

Iridium - a Toolchain for Javascript Development

I want to give a shout out to a very new and very interesting project called iridium from Adam Hawkins who blogs at BroadcastingAdam. Iridium aims to provide some much needed tooling to the new front end javascript/coffeescript project type that is popularised by the javascript mv* space.

With more and more of the application code finding its way onto the client in the form of javascript or coffeescript, there is a necessity to make a clear separation between between the front end client code and the backend server code. With Gems like the rails-api gem stripping away all the unnecessary cruft that is not needed when serving only json from a rails application, wouldn’t it be nice if you could spin up a new javascript/coffeescript project with just a few keystrokes?

Problem 1 - Lack of Front End Project Guidance

Gone are the days (I wish) when client side code and server side code lived side by side in a one size fits all monolithic project structure. Good practice dictates that you should segregate these two distinct layers into two (or more) orthogonal projects that can evolve at their own pace.

On the server side, I can quickly create a new rails project by issuing a command like

1
rails new project_name

Rails brought conformity to the mvc pattern by creating a guaranteed project structure for every rails project. Wouldn’t it be nice if we could bring some order to the new breed of client side only project?

The Solution

Iridium aims to add some much needed tooling to the front end project space and sets out with the following goals:-

  • CLI driven interactions
  • Expose as little Ruby as possible
  • Focus on JS/CSS/HTML
  • Make JS testable

First Steps

The first thing to do is to ensure that you have casperjs installed. Casperjs is what iridium uses as its integration test framework. Full installation details can be found here. I personally used homebrew to install casperjs.

Next, you need to create a Gemfile with the following entries:

I created an instance of the above Gemfile in my ~/projects directory so that I can easily create front end projects from that location.

A quick bundle install will install the specified gems and then you can start using iridium.

Iridium solves the first problem by allowing me to spin up a new client side project with most of the initial decision making made for me.

I can now create a new front end project named sample by simply entering the following command while in the project directory.

1
bundle exec iridium app sample

Note that I am using bundle exec, do not pass go if you are not running iridium in the context of the bundle specified in the Gemfile.

The above command will create the following output:

create sample
create app/images
create app/javascripts/app.coffee
create app/javascripts/boot.coffee
create app/javascripts/controllers
create app/javascripts/models
create app/javascripts/templates
create app/javascripts/views
create app/public
create app/stylesheets/app.scss
create app/vendor/javascripts
create app/vendor/javascripts/handlebars.js
create app/vendor/javascripts/jquery.js
create app/vendor/javascripts/minispade.js
create app/vendor/stylesheets
create site
create test
create test/controllers
create test/helper.coffee
create test/integration/navigation_test.coffee
create test/models
create test/support/qunit.js
create test/support/sinon.js
create test/templates
create test/unit/truth_test.coffee
create test/views
create application.rb
create readme.md
create .gitignore

This will create the following project structure: We now have a guaranteed folder structure for every client project we create. Iridium also provides some smart defaults that will provide some much needed guidance for anybody new to this space:

  • We will be using SASS as the css framework of choice and an app.scss file is created in app/stylesheets/app.scss.
  • There is a clear separation between unit and integration tests.
  • We will be using QUnit for unit tests.
  • We will be using Casperjs for integration tests. Integration tests are often overlooked in the front end world.
  • sinon.js is injected into the test environment and is used to mock or stub out any async calls when unit testing.
  • The Rake-pipeline is used for javascript loading and for packaging assets for deployment.

The Case for the Rake-Pipeline

The rake-pipeline is a better fit for single page applications than an asynchronous module loader like requirejs because it bundles all your dependencies and individual files into a single script. The rake-pipeline does all this concatenation and minification transparently behind the scenes without you having to do anything at all. Using the rails asset pipeline eases rolling deployment for you because you still get your scripts served as individual files when in development mode but in production mode, scripts are served minified and concatenated.

I prefer the rake-pipeline over requirejs because requirejs is great in development and satisfies the requirement of being able to break the functionality up into smaller files but and I must stress the word but, it is at this time of writing, a major pain in the rear to compile requirejs out for a production build. You are going to have to use something like the r.js compiler to bundle all your dependencies into a single script.

With a combination of the Rake-pipeline, @wycat’s rake-pipeline-web-filters and minispade we can achieve the following goals:

  • Break it up: While it’s common to write smaller libraries as one big file, I like the mental separation provided by dividing the source into multiple files.
  • Inline dependency management: I’d rather define each file’s dependencies right in the code, rather than define the concatenation order in some sort of makefile.
  • Keep files separate while debugging: When we’re setting breakpoints and stepping through code in the debugger we want to see our individual source files, not have to wade through one big file.
  • A transparent solution: We need the production library to be free from dependency management code.

With the above combination, I can develop my code in separate files and then I can prefix my code with minispade require statements like below:

1
2
3
require 'app/router'
require 'app/controllers/application'
require 'app/views/application'

When you create an iridium project, the rake-pipeline is already hooked up and a copy of the latest minispade.js can be found in app/vendor/minispade.js.

The above is valid coffeescript and I can simply point to one file with all my requires.

app.coffeee and boot.coffee

A nice conventions is created for you when you create a new iridium project that really helps when it comes to testing. A file named app.coffee is created for you where you can put all your minispade require statements as was outlined above. This file is hooked up for you in both the web application itself and the test environment. No initialisation code goes into this file, just the minispade require statements. A separate file named boot.coffee is created to house any application start up code. The boot.coffee file is not referenced by the test environment, paving the way for you to unit test separate bits of the application rather than having to boot the whole thing.

An example of the app.coffee file that is referenced by both the testing environment and the actual website itself could look like this:

1
2
3
require 'app/router'
require 'app/controllers/application
require 'app/views/application'

And an example of boot.coffee could look like this, with the code below initialising an emberjs applicaiton:

1
2
require 'application/app'
Application.initialize()

Index.html

index.html is an annoying part of web development. You cannot start or serve your application without an HTML page to load your JS. Iridium has a built in index.html which loads your assets and dependencies. This will work for most simple applications. You can override this by providing your own index.html in public.

Once you have generated your application, you can run the built in development server like so:

1
bundle exec iridium server

Which will give you the following output:

$ cd sample
$ bundle exec iridium server
>> Thin web server (v1.4.1 codename Chromeo)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:9292, CTRL+C to stop

Problem 2 - Testing the client code

The rise of the client side MV* framework and the proliferation of code on the client has made the call to test, a more important one than ever. The tide does appear to be turning on testing client code with the rise of important testing frameworks like Jasmine and QUnit but adoption of this practice could be better. Part of the difficulty is getting set up. Why should I have to concern myself with wiring everything together every time I start a new project? Anybody who initially wrestled with Jasmine and the rails asset pipeline will know exactly what I mean when by wrestling.

Anybody from a rails background will be comfortable with running particular flavours of test suites (unit/integration/functional etc.) via rake’s uniform command line interface. Iridium gives you the same capabilities and makes the clear distinction between unit tests and integration tests which is not always the case in the javascript world.

The Solution - The Iridium Test Runner

When you create a new project with iridium, your project is ready to test from both the unit test side and the integration test side. No set up code is required. There is a test/unit folder and a test/integration folder which should need no explanation as to their presence.

QUnit is the default test suite for writing unit tests and casperjs the framework of choice for integration tests.

What is very nice and is the ability to run both the unit tests and the integration tests a single unified test suite.

When the following command is entered:

1
bundle exec iridium test

The above will run both the unit tests and the integrations tests and present the results as a unified test suite.

It is also possible to be more granular and run, for example only unit tests:

1
bundle exec iridium test test/unit/* --debug

Note that I am passing in the –debug switch to enable console messages to be printed to standard out.

I can also run tests against individual files.

1
bundle exec iridium test test/unit/truth_test.coffee  --debug

Sinon.js gets included in test/support as a nice opinionated default to assist with mocking out any async ajax calls.

Conclusion

The front end project space has been crying out for a project like iridium. Rails provides uniformity and opinionated guidance every time you create a project. We need the same in the front end project space.

Go check the project out on github and spread the word. There are many features I have not mentioned in this post and many that will be added in the future.

Comments