Angular on the edge

Exploring Angular with Websockets

The Framework Hunt

Background

Since March 2012 I have been working on launching a startup. Initially the idea was to develop for the mobile platforms and so I started researching which mobile framework to choose… In the end I decided to use Sencha Touch, since it seemed like a more mature (professional) platform than fx JQuery mobile and had good documentation and the Sencha organisation and community behind it and was built using a similar architecture as ExtJS but now with MVC included. Sencha Touch had a large suite of ready-made components suitable for most use cases and seemed “easy” to use, especially with Coffeescript.

However having used Sencha Touch for a while, it turned out it was only good as long as you stayed within its very narrow boundaries. As soon as you wanted to do something different, you were on your own. In particular we had problems with the limitations of the navigation bars. After spending 3 months with Sencha, I changed strategy and went for Rails 3, a framework I had been usng since 2009 and was comfortable with.

Developing the back-end

I started developing the back-end and various helper components for geolocation, map positioning, duration handling etc. I also spent several weeks developing a generic search component that would be easy to use to setup any complex query and had a very nice API.

By the end of 2012 I had much of the back-end and supporting components done and started working on a communication component, to allow users to initiate dialogs and communicate. It also supported system messages, a nice search API etc.

Developing the front-end

In february I had the front end design done to support the back-end I started implementing a prototype of the full app. However, as I had feared, the view side of things was very cumbersome and difficult to do “right” in Rails. I had been looking at apotomo and cells for a way to structure the views as widgets instead of partials, but they were lacking in functionality.

REST API

In the end, as Rails 4 beta was realeased, I decided that the time had come to ditch Rails for the front end and instead have the backend exposed as a REST API using the Rails API gem.

Hunt for a REST API consumer

Then I looked at some railscasts about javascript MVC frameworks and found that Ember looked promising since it was headed by @wycats the lead architect of Rails 3.

I then spend 4-6 weeks trying to dig into and understand Ember, building several small components (generators) during my learning process. In the end however, I found that the Ember was way too unstable, and the documentation was very sparse, limited and rarely up to date… Too much of a hazzle. I then looked at frameworks like Angular or Meteor and a different picture emerged. These frameworks are much more mature and stable and have much better documentation.

Web components or Web sockets?

Once again I had to change tactics. AngularJS seemed the most promising as it had the backing of Google and was closely linked to the upcoming Web Components, a key feature of the “new web” architecture… I liked Meteor since it lets you have a fully event driven app, where the app (and all clients) are auto-updated whenever the model changes. Sweet :) An even driven approach using web sockets would greatly simplify the architecture!

However, Meteor has its own “problems”, since it has its own package struture and doesn’t support “web components”. Ideally I wanted to combine the model auto-sync feature of Meteor with Angular. I didn’t really care much about how Meteor uses Handlebar templates for the UI similar to Ember (and Derby). I feel that Angular “Web Componets” are much better, as they better encapsulate UI and logic and makes it easy to design reusable components.

Hybrid approaches

I found a repo Meteor_angular, and also then discovered Derby in the process. I also found a sample Meteor project using the meteor-angular bridge. However, even the Meteor approach was limited. Looking at Derby, it used a Racer engine that employed the Operational Transformation (OT) pattern to support caching locally and then syncing the cache later as the server becomes availaible. This would be an awesome feature, and so I started looking into the possibility of using Racer with Angular instead. This would mean I could ditch my REST API for a simpler approach, perhaps using Mongoose models or directly operating on the Mongo collections, hmm…

Derby and Racer

I found that @Sebmaster had a very recent blog post, describing how he had acheived Anuglar with Racer integration for the same reasons. I was very excited!!! Then I started digging into the Racer and Derby documentation, and it turns out that Derby has its own “Web components” which supports namespaces, while using Handlebars. Pretty cool ;)

Looking deeper into the Derby/Racer architecture however, it turns out that the current versions are 0.3.x and 0.5.x coming up, both “unstable” according to semantic versioning.

They recently employed the guy behind ShareJS to redesign Racer with a new and improved ShareJS engine backing it. From comments around the web (and from dialog with the guy behind HabbitRPG), I discovered that Racer had always had its problems… Hmmm… Guess we will have to wait a while yet!

Conclusion

So in conclusion, the best path forward looks to be AngularJS, using the REST API and perhaps employing Meteor or Socket Stream (see fx ss-angular) for web socket functionality, such as chat or when server updates should be pushed and updated on clients. I think a hybrid approach will be fine. So after a year of research and much experimentation, I’m more than half way in my project and feel that I have finally found a resonable web stack.

As a side note: if I should start today, I would likely ditch Rails and go straight for Angular with a Restacular - Mongoose backend, using Coffeescript client and server side. It looks to me like the old server side MVC frameworks (and languages) will be dying…

Coffeescript, Node and Mongo are the new kings today!

Say goodbye to ages old technologies… :)