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
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?
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
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.
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:
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 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.
- 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
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
And an example of boot.coffee could look like this, with the code below initialising an emberjs applicaiton:
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:
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.
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.
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:
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:
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.
Sinon.js gets included in test/support as a nice opinionated default to assist with mocking out any async ajax calls.
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.