Are you interested in learning Ember.js? I'm teaching at Embergarten in Toronto on September 13th. Come and learn how to build Ember.js applications!

Learn Ember.js with me in Toronto!

Aug 15 2014

Embergarten

If you’re interested in learning Ember.js, I’m happy to announce that I’m partnering with my friends at Unspace to teach an introductory class on Saturday September 13th here in Toronto.

We did one of these last year and it was super fun. This time around we’re just focusing on the beginner stuff, so if you or anyone you know are new to Ember.js, you should check it out.

All the information you need is on the Embergarten website!

View the full article to comment on it

Creating an Integration test in Ember.js (Screencast)

Jun 27 2014

Once upon a time it used to be difficult to create integration tests in Ember.js. Fortunately, the framework has come a long way and it’s now really easy to get integration testing working in your application. This screencast shows how to set it up with ember-cli:

There is some boilerplate code required that you’ll need at the top of your integration test files if you want to do it yourself. Here it is:

import startApp from 'vault/tests/helpers/start-app';
var App;

module('Integration - Secret', {
  setup: function() {
    App = startApp();
  },
  teardown: function() {
    Ember.run(App, 'destroy');
  }
});
View the full article to comment on it

Building Emberredit (screencast)

May 29 2014

One of my more popular blog entries is on using Ember.js without Ember Data. Recently I’ve been going through my old entries and making sure they don’t have any glaring mistakes, and I realized this would be a good opportunity to convert my emberreddit project to ember-cli.


This screencast shows how you can build an Ember.js application without using Ember Data. It starts off simple and then shows how to build advanced stuff like an identity map yourself.

It assumes some knowledge of Ember. The guides and docs for Ember.js are available at: http://emberjs.com/guides/

To install NodeJS go to: http://nodejs.org/

The excellent ember-cli is available at: http://iamstef.net/ember-cli/

And finally the code created in this screencast can be found here: https://github.com/eviltrout/emberreddit

Thanks to Stefan Penner, Jo Liss and the Ember Core team for making this amazing framework and tools. Also thanks to Erik Bryn for showing me a few tips about the model hook!


I had a lot of fun making the screencast so I will likely do more in the future. Drop me a line and let me know what future screencasts you’d like to see.

View the full article to comment on it

Getting Started with ES6 Modules

May 3 2014

Javascript is a fantastic example of how something, despite having visible warts and very poor design, can dominate the tech landscape. Nobody uses Javascript because it’s a beautiful language; they use it because it’s ubiquitous. Its warts are now well understood and most have workarounds.

An amazing omission in Javascript’s design is the lack of a built-in module system. As more projects used Javascript and shared more code, the need for a robust module system became necessary. Two contenders sprung up, Asynchronous Module Definition (AMD) and CommonJS (CJS). The former is much more popular with browser applications and the latter is much more popular with server applications written in node.js.

Having two major standards for defining modules led to a technological holy war in the Javascript community akin to the vim/emacs arguments of the editor world. It wasn’t pretty.

Fortunately, there is light at the end of the tunnel. TC39 has been hard at work on the next version of Javascript, called ES6 (short for EcmaScript 6). One of the major features of ES6 is a standard syntax for handling modules in Javascript.

A simple example of ES6 modules

By default anything you declare in a file in a ES6 project is not available outside that file. You have to use the export keyword to explicitly make it available. Here’s an example of how to export a user class:

// user.js

var localVariable = 123;  // not visible outside this file

export default function User(age) {
  this.age = age;
}; // can be imported by other files

And now if we wanted to use the User class in another file:

// user-details.js

import User from 'user';

var evilTrout = new User(35);

Pretty simple, isn’t it? There are many more examples of the syntax here if you are curious about other ways it can be used.

When will it be available in browsers?

In the past, it was very risky to use new Javascript features before they were standardized and widely available in browsers. You’d never know if someone was using an old or incompatible browser and it would cause your code to crash and burn.

These days, thanks to the Extensible Web movement, people are working hard at making it so that developers can try out advanced features before they’re compatible in all browsers.

The great news is you can use ES6 modules today! You just have to run your code through a transpiler. The transpiler will convert your ES6 modules into Javascript that browsers can understand today. In the future, when the browsers understand ES6 modules natively, you’ll be able to stop transpiling and it will just work.

The transpiler I’ve been using lately is es6-module-transpiler from Square. If you check out their build tools section you’ll see they’ve got integration stories for all the major Javascript build tools.

If you are using Rails on the server side, Dockyard has created an easy to use Gem version of it that you should be able to drop into your project.

ES6 Modules and Ember.js

The Ember community has bet big on ES6 modules. For example, if you are using Ember App Kit to structure your project, it includes ES6 module support via transpiling out of the box.

Recently, Robert Jackson converted the Ember source code to ES6 modules. This means that, if you have things set up properly in your development environment, you can import just the parts of Ember.js that you want to use and end up with a potentially smaller runtime.

ES6 modules integrate quite beautifully in an Ember project. If you’re not using ES6 modules, the standard way of making parts of your application available for discovery was by hanging them off your application’s global namespace. For example:

// app/controllers/user.js
App.UserController = Ember.ObjectController.extend({
  // ... controller code
});

Then if you transitioned to the user route, Ember would search for a UserController on your App object. This actually works quite well, but making everything available globally makes it too easy for developers to reach into components they have no business reaching into. If you make it easy for a developer to do the wrong thing, they will do it.

To contrast, if you are using Ember with an ES6 application you can define your user controller this way:

// app/controllers/user.js

export default Ember.ObjectController.extend({
  // ... controller code
});

Ember’s new resolver will then look for the module exported from the app/controllers/user path and will wire it up for you automatically.

Going Forward

I’ve found that since I started using ES6 modules in my projects that their code bases are a lot cleaner and more organized. It also just feels awesome to be using a standard before it’s widely available.

I’ve got a branch of Discourse that I am converting to ES6 modules one at a time. The bad news is that Discourse has hundreds of files to convert, so it will be some time before we are 100% on ES6. The good news is, with a little duct tape in our custom resolver, the application can run with some modules in the global Discourse namespace and some in ES6 format. I’m hoping to merge it into master shortly so our contributors can help with the converting efforts.

My advice is to not wait for browsers to implement these modules; start hacking today and put your project ahead of the curve. There are other ES6 features that can be transpiled too, and I’m excited to try some of those out too!

View the full article to comment on it

The Refresh Test

Apr 10 2014

How many times has the following happened to you?

You go to a web site and it asks you to create an account. You fill out a form with all the obvious fields and hit submit. The page refreshes and shows you the form again.

Phone Number is required

Well, that’s annoying. There was no indication that the site needed your phone number. You prefer not to give out your phone number to every web site, but this one is run by a company you trust, so you scroll down and fill it out. You submit the form again.

Password is required

What the heck!? You already entered a password! You scroll down to the form and see that the fields are now empty. It turns out that even though you filled out the password fields the first time, after you missed the phone number they were cleared. You fill them out and submit the form again.

Username is not available

At this point you’re ready to throw your computer out the window. There are fewer things more frustrating than trying to get your data into the exact shape a web site wants, especially if it clears fields every time you fail.

Another annoyance: just about every time I order something online, right after I input my credit card information, I am presented with a spinner animation and the text “Do not hit the back button or refresh your browser!” It’s terrifying that a company that is taking my money over the Internet can’t handle me refreshing the page without charging my card twice.

The sad thing is that both of these problems are totally solvable. In fact, they’ve been easy to solve for over a decade. Yet you still see them all the time.

Lessons from Live Reloading

Recently I spent some time playing with Ember App Kit. Ember App Kit is a suggested project structure for your applications built by Stefan Penner (and a bunch of other awesome developers). It’s really great and if you’ve never tried it out you should![1]

One feature Ember App Kit includes out of the box is support for connect-livereload, which automatically reloads your changes in your browser whenever you save a file.

It sounds like a minor thing, but after using it for a few hours having to manually hit Cmd-R feels like a chore. It’s a great little productivity booster.

Live Reload also has a side effect: it encourages you to make your application refresh resistant.

In my application I had a multi-step wizard where you had to enter many form fields at once, and I found it so frustrating to have all my form data pulled out from underneath me every time I hit save.

The frustration led me to persist the form data temporarily in localStorage. Once I did that, every time my application refreshed it looked exactly the same as it did before. It was probably a grand total of 10 minutes of work, and my application was much more resilient for it.

The Refresh Test

A great experiment to perform on a Javascript heavy application is to simply refresh the page and see where you end up. Does it look the same as before? Did you lose any work?

Users will put up with losing a small amount of state on refresh, for example if they’d expanded a menu and it’s suddenly collapsed, but you should never throw away what they were working on.

One thing I love about Ember.js is that its router makes you think in terms of URLs, which gives you a great head start for handling refreshes and the dreaded back button.

Many people think of URLs as files, because in the past requesting a path like profile.php?id=eviltrout meant you really wanted a file on the server called profile.php with the parameter eviltrout.

I find it’s better to think of a URL as the serialized state of your application. A path of /profiles/eviltrout should mean “I’m viewing eviltrout’s profile.”

If you’re building a Javascript application and the URL is not changing as your users navigate around, that is practically begging to give them a bad experience at some point. Not only can they be easily frustrated if they hit the back or refresh buttons, but they won’t be able to bookmark or share links with others.

I’m not suggesting that the URL contain every possible interaction a user can make; if you do that you will end up with a huge headache and a meaningless URL. Instead, you should focus on the most important things a user will want to see when the page is refreshed. For example, on Discourse we maintain a user’s scroll position in a topic by changing the URL as they scroll.

Going forward, I’m going to make sure that all my applications handle refreshing elegantly and I recommend you do too! If you’re interested in more on this topic, Tom Dale has a great talk on this called Stop Breaking the Web.


1. If you’re a fan of using bleeding edge stuff, check out Stefan Penner’s ember-cli and Jo Liss' broccoli. Ember App Kit works well today but those projects are a glimpse of the future of where Ember development is headed.

View the full article to comment on it

Embedding Discourse in Static Sites

Jan 22 2014

It’s been possible to embed comments from a Discourse forum on to other sites for a while now, but the only publishing software we supported was Wordpress.

Many people, myself included, don’t use Wordpress to run their sites. This very blog is a series of static HTML documents that are generated by Middleman. (Like Discourse itself, my blog is open source; you can find the code here so feel free to submit pull requests!).

Well… Good News Everyone! It’s now possible to embed Discourse content into any HTML document. In fact, as you can see below, the comments on this very site are now handled by a Discourse instance I set up.

How it Works

You can now configure Discourse to support embedding. Once you’ve done that, you paste a small snippet of Javascript into your site template and you’re off to the races.

Discourse will create topics for your blog entries if you provide it with an RSS or Atom feed. It’s also smart enough to update them if the content changes, say for corrections or typos. When any users of your forum post comments, they will automatically be inserted into your blog.

If your site does not have an XML feed, Discourse will create topics based on your page contents using a readability algorithm. It’s remarkably accurate for those cases when your site doesn’t have a feed.

How to Set up Embedding

  1. Install a Discourse Forum. We currently recommend using discourse_docker to do this. If you have ruby on your computer, you can even do it via a command line wizard.

  2. Navigate to the Embedding Site Settings. The URL will be something like:

    http://discourse.yourdomain.com/admin/site_settings/category/embedding

  3. Configure the settings appropriately. Here’s how it looks for my blog:

    Embedding Settings

  4. In your blog template, paste in the following snippet of Javascript and a <div> tag for where you’d like the comments to appear:

    <div id="discourse-comments"></div>
    
    <script type="text/javascript">
      var discourseUrl = "http://fishtank.eviltrout.com/",
          discourseEmbedUrl = 'http://eviltrout.com/link-to-blog-entry.html';
    
      (function() {
        var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
          d.src = discourseUrl + 'javascripts/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);
      })();
    </script>
    

    Configuration

    1. You will have to change the discourseUrl variable so it points to the root URL of your Discourse forum.
    2. Make sure discourseEmbedUrl is the canonical URL to the page where you are embedding Discourse. You will want to make sure this uniquely identifies the page. For my blog template, I use the following code to link to the article: discourseEmbedUrl = 'http://eviltrout.com<%= current_page.url %>'

  5. Reload your blog. Your blog posts should start syncing over to your forum and any comments should be imported into your blog. It’s that easy!

Going Forward

eviltrout.com has been running this set up for a few weeks now and it’s been great! Of course, like with any new feature of Discourse we’d love to hear your feedback so we can iterate on it and make it better. Let us know how it works for your use case.

View the full article to comment on it

Hiding Offscreen Content in Ember.js

Jan 4 2014

Everything you render in a browser, whether it’s a blog post or a tweet or a video, has a performance cost.

At the very least, you will be asking the browser to render a handful of tags and text elements that make up your user interface. That structure, a subtree in the browser’s DOM, can be quite complicated and memory intensive.

The more tags and elements you render, the slower the browser is going to perform, and the more memory it is going to use to do it. It follows that if you give the browser less work to do, it will do it faster.

This principle holds true even if you are using a browser application framework like Ember.js. Every data binding you make between an element and an object has a cost. If you reduce your bindings and views, your interface will feel snappier.

Long Lived Applications

Discourse makes heavy use of infinite scrolling. If a user is reading a long topic with many posts, new posts will stream in asynchronously from the server as the scroll position approaches the end of the browser’s viewport.

For shorter topics, adding all that extra content to the DOM was not a performance issue. Modern browsers, even on mobile devices, could handle rendering of hundreds of posts of formatted text without breaking a sweat.

However, as Discourse installs began to see heavy use, we found some topics had thousands of posts, and some users would read many of them in one sitting. All of those inserted posts started having a negative effect; browsers would often start to feel “choppy” and could even crash, leaving users frustrated.

Cloaking Offscreen Content

The obvious solution to this problem was to unload content from the DOM as it scrolled offscreen and render it again if it came back onscreen.

The issue with this is that if you remove an element from the DOM, the browser will reflow, and all the other content underneath it will jump back upwards. In order to prevent the browser viewport from moving, you have to replace the element with a simpler one that has the exact same height as the element it’s replacing.

One of Ember’s strengths is how it breaks down your UI into a hierarchy of views. You have your ApplicationView which contains your TopicView and a collection of PostViews and so forth.

I took advantage of this structure and implemented a CloakedView class.

The idea is any of your views can be contained in a cloak. When onscreen, the cloak renders the contained view. When offscreen, the cloak will copy the height of its rendered content and unload it.

A PostView doesn’t care if it’s cloaked or not. It should only be concerned with how to render a post. We can choose to cloak when we display a list of posts with a special helper. So instead of rendering a collection of Posts like so:

{{collection content=topic.posts itemViewClass="postView"}}

We can drop in a replacement like so:

{{cloaked-collection content=topic.posts cloakView="post"}}

ember-cloaking

After implementing cloaking, there was an immediate drop of 30% RAM usage in long Discourse topics. Scrolling also remains smooth even if many posts are browser in one sitting. We’ve been running it in production for about a month and it’s been a huge win!

I’ve extracted the cloaking logic into a library called ember-cloaking.

For now it only works with vertical scrolling, but if you are doing a large amount of horizontal scrolling I’m sure it could be adjusted to work without too much effort.

The fact that I was able to implement this functionality in a generic way without much code is a testament to Ember’s excellent design.

If your application is rendering many items in the browser at once, especially if you are implementing infinite scrolling, you should give it a shot and let me know how it works for you!

View the full article to comment on it

Internationalization Support in Ember.js

Nov 24 2013

One thing I’m really proud of is that when we launched Discourse, we had first class Internationalization (i18n) support ready to be used. Our first release only English, but thanks to our community we have 18 localizations of our software in progress! Here’s what Discourse looks like in Simplified Chinese:

Discourse in Chinese

On the server side, Discourse uses Rails' built in i18n support. It has been around for a long time and works easily so I won’t go into that. Check out the documentation for your server side framework of choice for more.

I18n in Ember.js

Our client side application is written in Ember.js, which doesn’t have built in support for i18n. However, it’s not difficult to add it in.

We use i18n-js, a project whose goal is to bring Rails translation support to Javascript. Don’t worry if you don’t use Rails on the server side. You can use all of the code in this post outside of Rails if you like. The Javascript code in 1i8n-js is all you’ll need.

Once you’ve included i18n-js in your project, you will have access to an I18n object in your javascript code to perform translations with. The first thing you’ll need to do is include a translations.js file that includes all your translations. Here’s how a simple one could look:

I18n.translations = {
  en: {
    hello: 'hello',
    cookieCount: {
      one: 'You have {{count}} cookie.',
      other: 'You have {{count}} cookies. Yum!'
    }
  },

  fr: {
    hello: 'bonjour'
    cookieCount: {
      one: 'Vous avez {{count}} biscuit.',
      other: 'Vous avez {{count}} biscuits. Le Yum!'
    }
  }
};

And then if you wanted to output a translation you can use the i18n.t function:

console.log(I18n.t('hello'));   // outputs hello because the default locale is `en`

I18n.locale = 'fr';
console.log(I18n.t('hello'));   // outputs bonjour

In an Ember app though, you’ll want to be able to access those translations in your handlebars templates. To do this, you’ll need to define a helper. You can just copy and paste this code into your app:

Ember.Handlebars.registerHelper('i18n', function(property, options) {
  var params = options.hash,
      self = this;

  // Support variable interpolation for our string
  Object.keys(params).forEach(function (key) {
    params[key] = Em.Handlebars.get(self, params[key], options);
  });

  return I18n.t(property, params);
});

Now your templates are ready to be translated:

<h1>{{i18n hello}}</h1>

<p>{{i18n cookieCount count=user.cookies.length}}</p>

Note that the I18n library is smart enough to notice when you supply a parameter named count to select the correct pluralization for a key. If the user has one cookie it won’t add that pesky “s.”

I18n support is so easy to add that I recommend it for just about every web project unless you’re absolutely sure you’ll never need it in another language. The Internet is a lot bigger than your home country, go forth and make it easier to translate!

View the full article to comment on it

Enemy of the State

Oct 5 2013

I learned very quickly while working on a large open source project is that it is important to make my code hard to break. The primary line of defense for this is a comprehensive test suite, but I think it’s also very important to create functions that are easy to use and difficult to damage.

I find I even code this way on personal projects that will never be released. Even if you never work on a team with other developers, there is a good chance you will forget a lot of implementation details of the code that you aren’t actively working on. You need to protect your code from yourself!

I think a lot about state these days. How much data should an object have, and how should it expose that to other objects? I find many bugs are related to the state and scope of data not being what you’d expect.

An Example: ActiveRecord

ActiveRecord makes it easy to retrieve all rows from database and represent them as objects:

Product.all.each do |p|
  puts p.name
end

We didn’t have to specify that we wanted the name column from the database before we outputted it; by default ActiveRecord includes all the columns in the table.

Over time, many frequently used tables in databases such as Product tend to get more columns added to them to support new features. You might find that your table that started off with 4 columns is eventually over 50!

There is overhead involved in returning all those extra columns from the database. At the very least, the database has to send more data across the wire to your application. On top of that, Rails has to deserialize all the columns into their appropriate types in the object.

When returning a single Product you will probably not notice much of a difference. However, when returning hundreds of rows at once, the overhead can add up quite a bit.

Selecting only what you need

ActiveRecord provides a method called select that can be used choose the columns returned from the database. We could write something like this:

Product.select([:id, :name]).each do |p|
  puts p.name
end

This will certainly execute faster than the Products.all query above. However, if you do this, you are exposing yourself to many bugs due to inconsistent state.

The danger here is ActiveRecord returns a mixed state instance of Product. The returned object looks like a Product. It has all of the instance methods you defined on Product, however, it is missing some of the data that is normally there.

To illustrate this, imagine you have a function that returns a product’s name, but adds an asterisk if it’s on sale:

def fancy_product_title(product)
  if product.on_sale?
    return product.name + "*"
  else
    return product.name
  end
end

In this case, our method checks the on_sale column in the database to determine whether to append the asterisk. However, if you retrieved the Product using select([:id, :name]) you would not have this column present, and even if the product was on sale your users wouldn’t know about it.

Now this might seem like a pretty easy bug to squash. Any competant programmer could adjust this code to return on_sale in the select clause if if they saw it wasn’t ever being displayed.

That is demanding a much broader knowledge of the application and the flow of data than is necessary. It takes more development time, and doesn’t scale well when your codebase grows. Also, who wants to constantly think “hey, do I have all the data I need in this object to do my work?”

Keep it Consistent

You can eliminate any entire class of bugs by never using select. You should insist that your object instances always include all their data members.

What about the performance issues? I suggest instead that you design your data structures in a different way. Rather than returning inconsistent Product models, why not create a method that returns BasicProduct objects?

All Product instances have enough data to transform into BasicProduct instances if they need to. If you like inheritance you could make a Product extend a BasicProduct. If you’re not a fan of inheritance you could create a to_basic method.

This is just one example of how easy it is to leave things in an inconsistent state, especially when considering performance. I suggest that you make an effort to keep your data in sync as much as possible, even if it involves a little data modelling. You’ll have fewer bugs, and your code will be better to use in the long run.

View the full article to comment on it

Computed Property Macros

Jul 7 2013

Computed Properties

By design, Handlebars templates don’t allow complex expressions. You are given an {{#if}} block helper, but it can only evaluate whether something is “truthy” (aka true, a non-empty string or array or other value that is not undefined or null.)

For example, you can’t do something like this:

{{#if (eyes.length == 1) && (horns.length == 1) && flies && (color == 'purple') && eatsDudes}}
  <i>It was a one-eyed, one-horned, flying purple people eater!</i>
{{/if}}

Handlebars encourages you to use a single evaluation for your logic:

{{#if purplePeopleEater}}
  <i>It was a one-eyed, one-horned, flying purple people eater!</i>
{{/if}}

I think the second example is much clearer and easier to follow. Even though some other templating languages might allow you to use more complex expressions in your templates like the first example, I’d recommend aggregating them anyway. It will make your life a lot easier.

Ember gives you a great tool out of the box to do this easily called computed properties. I’ve written about them before, but in a nutshell they allow you to create a function that transforms one or more properties into another single property. In this case, you could make one like this:

var Creature = Ember.Object.extend({

  purplePeopleEater: function() {
    return (this.get('eyes.length') === 1) &&
           (this.get('horns.length') === 1) &&
           (this.get('flies') &&
           (this.get('color') === 'purple') &&
           (this.get('eatsDudes')));
  }.property('eyes.length', 'horns.length', 'flies', 'color', 'eatsDudes')

});

By adding .property() to your function prototype, this tells Ember that it’s a computed property. The 5 arguments tell Ember to cache the result unless any of those properties change. As long as our Creature’s values don’t change, the result won’t be recalculated.

Computed Property Macros

Computed Properties are an important feature in Ember and are understood well developers. However, there is a less well known way to declare computed properties that is often a lot easier and clearer: using the Ember.computed set of functions. They are shortcuts for creating common types of computed properties. Here’s some examples:

var Creature = Ember.Object.extend({
  eyesBlue: Ember.computed.equal('eyes', 'blue'),

  hasTwoBananas: Ember.computed.gte('bananas.length', 2),

  sick: Ember.computed.not('healthy'),

  radical: Ember.computed.and('ninja', 'turtle'),

  staff: Ember.computed.or('moderator', 'admin')
});

You can find a full list of macros on the Ember API site.

Not only are the computed property macros often shorter to write, but you don’t have to specify the dependant properties for caching like you do when using the .property() method, so I find them to be less error prone. Here’s how I might re-write the purplePeopleEater property by breaking it into smaller macros:

var Creature = Ember.Object.extend({
  oneEyed: Ember.computed.equal('eyes.length', 1),
  oneHorned: Ember.computed.equal('horns.length', 1),
  purple: Ember.computed.equal('color', 'purple'),

  purplePeopleEater: Ember.computed.and('oneEyed', 'oneHorned', 'flies', 'purple', 'eatsDudes')
});

It’s a lot more DRY than the previous solution. In the first solution we had to write every property name twice, now we only write it once.

A secondary benefit of this approach is we’ve cached the internal properties such as oneEyed. If another computed property needed that comparison, we already have it available and cached.

Once you start to use these macros you won’t stop! You’ll find yourself breaking long sequences of conditionals into smaller boolean chunks that are easier to re-use and cache for performance. Have fun!

View the full article to comment on it

Adding Support for Search Engines to your Javascript Applications

Jun 19 2013

Important Update (May 25, 2014): Google has started parsing and indexing Javascript. The approach of this article is to use <noscript> tags but Google will likely ignore those now. We upgraded our site to sniff Google and other popular search engines and serve our simple content that way. However, in the future it might not be a concern as Google plan on having Javascript sites just work!


It’s a myth that if you use a client side MVC framework that your application’s content cannot be indexed by search engines. In fact, Discourse forums were indexable by Google the day we launched.

Search engine visibility does, however, require a little more work to implement. This is a real trade off you’ll have to consider before you decide to go with an MVC framework instead of an application that does its rendering on the server side.

Before you get scared off: I’d like to point out that our search engine code was done by Sam Saffron in a day! This extra work might take you less time than you thought.

Getting Started: Pretty URLs

Out of the box, most client side MVC frameworks will default to hash-based URLs that take advantage of the fact that characters in a URL after an # are not passed through to the server. Once the Javascript application boots up it looks at hash data and figures out what it has to do.

Modern browsers have a better alternative to hash-based URLs: The HTML5 History API. The History API allows your Javascript code to modify the URL without reloading the entire page. Instead of URLs like http://yoursite.com/#/users/eviltrout you can support http://yoursite.com/users/eviltrout.

There are two downsides to using the History API. The first is Internet Explorer only started supporting it IE10. If you have to support IE9, you’ll want to stick with hashes. (Note: Discourse actually works on IE9, but the URL does not update as the user goes around. We’ve accepted this trade off.)

The second downside is that you have to modify your server to serve up your Javascript application regardless of what URL is requested. You need to do this because if you change the browser URL and the user refreshes their browser the server will look for a document at that path that doesn’t exist.

Serving Content

The second downside I mentioned actually has an nice upside to it. Even if you are serving up the same Javascript code regardless of URL, there is still an opportunity for the server to do some custom work.

The trick is to serve up two things in one document: your Javascript application and the basic markup for search engines in a <noscript> tag. If you’re unfamiliar with a the <noscript> tag, it’s designed for rendering versions of a resource to a clients like search engines that don’t support Javascript.

This is really easy to do in Ruby on Rails (and probably other frameworks that I’m less familiar with!). Your application.html.erb can look like this:

<html>
  <body>
    <section id='main'></section>
    <noscript>
      <%= yield %>
    </noscript>
  </body>
  ... load your Javascript code here into #main
</html>

With this approach, if any server side route renders a simple HTML document, it will end up in the <noscript> tag for indexing. I wouldn’t spend much time on what the HTML looks like. It’s meant to be read by a robot! Just use very basic HTML. To preview what a search engine will see, you can turn off Javascript support in your browser and hit refresh.

We’ve found it advantageous to use the same URLs for our JSON API as for our routes in the Javascript application. If a URL is requested via XHR or otherwise specifies the JSON content type, it will receive JSON back.

In Rails, you can reuse the same logic for finding your objects, and then choose the JSON or HTML rendering path in the end. Here’s a simplified version of our user#show route:

def show
  @user = fetch_user_from_params

  respond_to do |format|
    format.html do
      # doing nothing here renders show.html.erb with the basic user HTML in <noscript>
    end

    format.json do
      render_json_dump(UserSerializer.new(@user))
    end
  end
end

Note that you don’t have to implement HTML views for all your routes, just the ones that you want to index. The others will just render nothing into <noscript>.

One More Thing

If you get an HTML request for a URL that also responds with JSON, there is a good chance your application is going to make a call to the same API endpoint after it loads to retrieve the data in JSON so it can be rendered.

You can avoid this unnecessary round trip by rendering the JSON result into a variable in a <script> tag. Then, when your Javascript application looks for your JSON, have it check to see if it exists in the document already. If it’s there, use it instead of making the extra request.

This approach is much faster for initial loads! If you’re interested in how it’s implemented in Discourse, check out:

View the full article to comment on it

AngularJS vs Ember

Jun 15 2013

Recently I got together with some local developers to discuss client side MVC frameworks. We ended up discussing many of the differences between AngularJS and Ember.

Discourse is an Ember application and has been since the first prototype, so I have a lot of experience with it. However, it became clear during the conversation with my peers that there was a lot about AngularJS I didn’t know.

There is evidence that AngularJS is beating out Ember in terms of developer mind share: there are more Stack Overflow questions dedicated to AngularJS. AngularJS has more stars and forks on Github. At a recent Javascript meetup in Toronto, when polled virtually every developer expressed interest in learning more about AngularJS. Clearly there is something to this framework!

I decided to take some time to seriously investigate AngularJS and see what all the fuss was about. I read through as much documentation, blog posts and guides as I could. I downloaded AngularJS and made simple applications. I reached out to local developers and pestered them with questions about the framework.

I have a good idea now why AngularJS is gaining momentum: it is simpler. There is a lot less to the framework and as a consequence it’s easier to learn. If I were to rank the amount of tools various client side MVC frameworks give you, Angular seems to exist somewhere near the half way point between Backbone and Ember.

The pitfalls of simplicity

A few years ago, many Rails developers I knew were excited about Sinatra. Sinatra is far simpler than Rails. It allocates a fraction of the objects Rails does. I observed a pattern as those developers started to build out their applications. Some were used to Rails' large toolbox of convenience functions so they included ActiveSupport. Some needed ORMs so they included ActiveRecord. At that point, what was the advantage of Sinatra? You were basically running a Rails application.

Framework simplicity is good if your application is meant to be simple. But you should be cautious when choosing simplicity if your application is ambitious and you care about supporting it for a long time.

Don’t get me wrong: if an API is convoluted and verbose, and a competing one is equally functional yet simpler to use, by all means use the competitor. However, people are far too quick to mistake simplicity for good design.

Ember has more concepts to learn and more to wrap your head around than AngularJS. Before you write off Ember due to its complexity, consider why the developers added all that extra stuff. Perhaps it’s there for a reason?

Ember is a toolbox full of concepts you will find useful if you want to build a large and maintainable application. The trade offs it has made in its API are there to help you structure your code in a sane way. As you learn Ember you will notice several philosophies and opinions that are completely absent from the AngularJS framework.

This is far better illustrated via example. In this post, I’m going to try and demonstrate a few major shortcomings in AngularJS and how the Ember approach is much better.

In pursuit of a single source of truth

Let’s say you’re working on a web application that does rendering on the server. The current page you’re working on is meant to display a list of items as rows, and if the user clicks on a row, it will change color to indicate it’s been selected.

If you were using jQuery to do this, you’d likely bind a function to the click event on each row. When fired, your function would change the CSS class of the row to highlight it.

You can’t stop there, though. Your function also has to remove the CSS class from any other rows that were previously selected. That’s a little crazy if you think about it! Changing which item is selected means we have to know everywhere that it’s been represented in our UI.

Whenever you store the same piece of data in multiple places, it is likely to go out of sync. Additionally, your code ends up being longer and more complex as it has to manage all the various updates every time it changes.

Client side MVC (Model View Controller) frameworks like Ember and AngularJS separate your data model from its presentation. Your model becomes the single source of truth. If you change it, your HTML template changes automatically. If you want to know its current value, you read it from the model instead of the DOM.

This is a a huge boon to developer productivity while simultaneously reducing the potential for errors related to out of sync data.

What’s an AngularJS Model?

AngularJS touts itself as a MVC or MVW (Model View Whatever) framework.

It’s clear where AngularJS' view layer is: you annotate regular HTML documents with ng-* attributes and handlebars style {{variable}} expressions. It’s also easy to understand where the controllers are; you link Javascript classes to elements using ng-controller attributes.

What isn’t clear, especially if you come from a server side MVC background, is what is an AngularJS model? There is no standard Model base class, nor is there a component or interface in AngularJS that defines what a model is supposed to be.

In an AngularJS controller, you are given an object called $scope. Any data you attach to it is rendered in your HTML template:

function SomeCtrl($scope) {
  $scope.countries = ['can', 'usa', 'fra', 'jap'];
  $scope.user = {name: "Evil Trout"};
  $scope.age = 34;

  // Our template now can render {{age}}, {{user.name}} and a list of countries!
}

According to the AngularJS documentation any named data in an AngularJS $scope is a model, not just Javascript objects and arrays, but primitives, too! In the above snippet, there are three models!

What’s wrong with Javascript primitives as models?

AngularJS gives you tools you need to manage a single source of truth in your templates. This is a concept known as data binding. If we created a template that has an AngularJS expression {{age}}, we can say it’s bound to the $scope.age model. If you wrote {{age}} several times in one template, and executed $scope.age = 40 in your controller, all would update simultaneously.

There is a secondary level of data binding, however, that you need if you truly want to express a single source of truth, and that is within your data model itself. In other words, AngularJS stops short by only allowing for data binding only between your $scope and template, not within the structures in your Javascript code.

In Ember, all models extend the Ember.Object base class. When you do this, you gain the ability to declare relationships within and between models. For example:

var Room = Ember.Object.extend({
  area: function() {
    return this.get('width') * this.get('height');
  }.property('width', 'height')
});

Here, we’ve created a model called Room. We’ve declared area which is known as a computed property. The property syntax you see at the end there tells Ember that the Room’s area depends on its width and height.

Creating an instance of this model is easy:

var room = Room.create({width: 10, height: 5});

Now we can create a template:

<p>Room:</p>

<p>{{width}} ft.</p>
<p>{{height}} ft.</p>
<p>{{area}} sq ft.</p>

And Ember would render the attributes correctly. In this case, it’s impossible for area to be out of sync with width and height. If either of those two properties change, area will be updated automatically.

Modeling this in AngularJS

Because AngularJS models are regular Javascript objects, AngularJS doesn’t have an equivalent to computed properties. However, you can approximate them using functions on your objects:

var Room = function(args) {
  this.width = args.width;
  this.height = args.height;
}

Room.prototype.area = function() {
  return this.width * this.height;
}

To access the area of our Room, you have to add a set of parentheses to your area() call:

<p>Room:</p>

<p>{{width}} ft.</p>
<p>{{height}} ft.</p>
<p>{{area()}} sq ft.</p>

This illustrates a key difference between Ember and AngularJS. Ember subscribes to the Uniform Access Principle. In an Ember template, regardless of whether you are accessing something that is computed or something that is a primitive, the expression looks the same. In AngularJS, functions have to be specifically demarcated.

This can cause maintainability nightmares down the road. Over time, in a large software project, you will inevitably want to replace something that was previously a primitive with a method. In Ember you can do this painlessly; in AngularJS you’ll have to update every template where that model is used.

Using getters and setters

It’s worth discussing a related trade-off you might have noticed in the Ember code above: to access properties of a model, you have to use getters and setters. This means a little extra typing, but you reap the same benefit in the Javascript code that you do in the template: replacing a primitive with a function will just work!

A secondary benefit to using getters and setters is you can chain them safely. Consider the following code:

console.log(room.inhabitant.name);

What happens if the inhabitant is not present? You’ll raise a Javascript error. In the Ember equivalent you’ll get undefined back, which makes it easier to write more resilient code:

// outputs undefined
console.log(room.get('inhabitant.name'));

Performance issues

There is another downside to using a functions instead of computed properties: it’s much slower.

In our Ember code, we expressed that area depends on width and height. In AngularJS, we didn’t do that. So how could AngularJS possibly know to re-render the area if the width or height changed? In fact, how does AngularJS ever know to re-render when things change if it’s not using special Javascript objects for models?

The answer is: it doesn’t. AngularJS uses a process called dirty checking to determine what it needs to update in the DOM. When a controller finishes executing code, AngularJS compares everything in the $scope to its previous values. If they’ve changed, it updates the DOM.

AngularJS cannot know whether it needs to execute the function again because it doesn’t know what the function does, so it executes its code every time it has to update the template. What if your function is executed hundreds or thousands of times on a template? What if the function does a non-trivial computation? That would be very slow!

I asked around how AngularJS developers get around this and apparently the best answer is to cache the result of the function yourself in a different variable. But if you do that, you’ve got more than one source of truth for that value. If you ever update the Room’s dimensions, how do we guarantee that the area property will be updated too?

I was pointed to an AngularJS function called $scope.$watch that allows you to watch an expression and execute some code when it changes. The problem is that the $watch function belongs to the $scope and NOT the Room. If you had an array of Room instances for example, you can’t watch them all without looping through them all constantly.

What if the same Room object instance existed in multiple controllers? You’d have to have the $watch in every controller which would mean a lot of unnecessary recalculations. Good luck debugging issues if you take that approach! Talk about a maintenance nightmare!

Reusing object instances

AngularJS makes it much harder to reuse object instances than Ember does. In an Ember template for example, you can link to another route using the {{linkTo}} helper:

<ul>
{{#each user in users}}
  <li>{{linkTo 'users.show' user}}Show {{username}}{{/linkTo}}</li>
{{/each}}
</ul>

Here, we’re looping through a list of users and creating a link to show that particular user. If you hovered over the link, you’d see something like /users/show/123 if your routes were set up properly. However, when you click the link, Ember actually passes the reference to the user through to your other route.

Ember’s router is smart enough to not have to resolve the user by id again if it already has the user object in memory. It just makes use of the object it already has. In AngularJS, every time you visit a route, it passes an id and has to resolve it in your controllers.

One of the great advantages of long lived browser applications is you can reuse objects as the user navigates around. AngularJS doesn’t follow this philosophy; it encourages you to throw away what you already had and find it again (probably from the server!).

Another consequence of this is that if you ever end up with two instances of the same User in memory, you’ve violated the single source of truth again!

Conclusion

I think it’s clear at this point that Angular’s focus on simplicity has some serious consequences. There are workarounds for some of these issues that you can implement yourself in your project with great discipline, but ask yourself this: are all developers on your team going to follow the same conventions? Additionally, if you add all sorts of extra constructs to AngularJS to make it work like Ember, why not just use Ember in the first place?

Due to it’s lack of conventions, I wonder how many Angular projects rely on bad practices such as AJAX calls directly within controllers? Due to dependency injection, are developers injecting router parameters into directives? Are novice AngularJS developers going to structure their code in a way that an experienced AngularJS developer believes is idiomatic?

In fact, what is idiomatic AngularJS? None of the examples or blogs I read through demonstrated how to reuse object instances, for example. Is that just not done in AngularJS applications?

Ultimately, I think you should examine your application’s goals. Do you want to build something that pushes the boundaries of what people expect from the web? Is your application going to be super simple, or do you want to add powerful features and maintain it well over time?

If you’re serious about front end development, I advise you to take the time to learn Ember properly. Once you figure out how all the pieces fit together, you’ll won’t be able to live without them.

Final Note

If you know Angular and I’ve written something wrong here, please contact me to let me know! I’d love to revisit or correct any mistakes or omissions.

View the full article to comment on it

Older Posts

Organizing Data in Long Lived Applications

May 26 2013

Ember without Ember Data

Mar 23 2013

Generating IIFEs in Rails

Feb 25 2013

Infinite Scrolling that Works

Feb 16 2013

Why Discourse uses Ember.js

Feb 10 2013

Crawling the Downvote Brigades of Reddit

Jan 16 2013

How our users exploited concurrency and how we fixed it

Jan 10 2013

Turbolinks and the Prague Café Effect

Jan 6 2013

Just because you're privileged doesn't mean you suck

Jan 3 2013

I've been programming since I was 7

Dec 30 2012

Is Penny Arcade being ghost drawn?

Sep 30 2012