As one of the authors of Ember.js, I frequently get asked: "Should I use Angular or Ember?"
I think the answer to that question has a lot more to do with what kind of application are you building? than is Ember better than Angular?
While there are a few superficial similarities—they both use bindings and are more helpful for writing web applications than, for example, Backbone.js—they quickly depart from one another in how they expect you to approach building apps.
Let me first discuss the inspiration for Ember.js. Starting in 2009, I worked on SproutCore while at Apple, in addition to contributing to the suite of web applications that became what you now see on iCloud. In that environment, I was surrounded by some of the best Cocoa developers in the world.
Now, here's the thing about client-side web applications: they're not really breaking new ground. The fundamental model has been around since the 80's: code running locally on a computer, fetching data from the network, and then rendering it locally and putting it on screen. Really, the only thing that's changed is that the code is running inside the sandboxed environment of the browser, and the "binary" is loaded as you need it instead of being installed by the user onto their hard drive.
To me, the obvious thing to do is to look around and ask: What have the people who have come before us done? And I think it's hard to argue with the success of frameworks like Cocoa, both on the Mac and on iOS, in aiding developers in writing apps that users love.
We want developers to be able to build ambitious web apps that are competitive with those native apps. To do that, they need both sophisticated tools and the right vocabulary of concepts to help them communicate and collaborate.
With Ember.js, we've spent a lot of time borrowing liberally from concepts introduced by native application frameworks like Cocoa. When we felt those concepts were more hindrance than help—or didn't fit within the unique constraints of the web—we turned to other popular open source projects like Ruby on Rails and Backbone.js for inspiration.
Ember.js, therefore, is a synthesis of the powerful tools of our native forebears with the lightweight sensibilities of the modern web.
Now, Angular: I actually really like Angular, Google, and all of the developers I've met on the Angular team. In fact, we had once discussed how we might unite our efforts, but—excuse my French—the synergy just wasn't there.
Angular, in my opinion, is much more of a research project than Ember.js. Just look at the terminology: Ember talks about models, views, and controllers. Angular's guide requires you to learn about things like scopes, directives and transclusion.
I am all in favor of research projects, and I wish them the best. But, as Jeremy Ashkenas always says, look at the apps in production.
Big companies have invested serious time and energy in Ember.js, and the results speak for themselves. The new version of ZenDesk has been rewritten in Ember (after they got frustrated with Backbone.js and moved off it). The entire web experience at Square is Ember, because they wanted a beautiful and responsive UI on the web and institutionally know that those can be delivered using concepts borrowed from Cocoa. Many of Groupon's mobile web apps are Ember.js. There are many, many more startups finding success with Ember.js, and in turn, contributing to it and helping grow the community.
The majority of apps that I've seen written in Angular are demos or internal Google properties.
Yehuda and I have been extremely aggressive about getting real users of Ember involved in the design and maintenance of the framework. This keeps us honest and makes sure features we add are not things we think are neat but are driven by real problems developers are hitting today.
In fact, for the past few months, the majority of the work on Ember.js proper has been done by a core group of community contributors, from different companies. If Yehuda and I got hit by a bus tomorrow, Ember would be fine. If our company went under, Ember would be fine. By making this a truly community project, instead of a "by Google" project, I believe we get an order of magnitude more man-hours contributed to it.
Back to technical details. From their own website, "AngularJS is what HTML would have been, had it been designed for building web-apps." I think that that philosophy is evident when looking at their apps. The user interface is defined by HTML tags, decorated with attributes (like `data-ng-repeat`) that have semantic meaning.
Ember.js uses Handlebars to describe the HTML that makes up your application interface. Now, aesthetically, we can argue whether you prefer Handlebars syntax (which uses, for example, the
helper) or annotating HTML with additional attributes like Angular does. I personally think that the HTML attribute approach is a little noisier and hard to read, but I think that anyone can get used to either one. If Ember.js didn't exist and I had to use a framework that uses data attributes, I wouldn't cry.
But leaving aesthetics aside, I believe that our approach to using string-based templates gives us several advantages, both now and in the future:
- String-based templates can be pre-compiled on the server. This signficantly reduces startup time (because there is effectively no computation required at app boot) and means that rendering a template is as simple as invoking a function.
- Angular requires you to traverse the entire DOM at app boot time. The bigger your app is, the slower it starts.
- String templates are easy to divide up and load lazily, if your app starts getting large.
Additionally, Handlebars only lets you bind to properties, while Angular allows you to embed arbitrary expressions that live update. Many people initially see this as a limitation of Ember, but in fact:
- Angular must recompute those expressions every time something changes, which means the more bound elements in your app, the slower it gets.
Angular, in general, relies on something called dirty checking to determine when changes have been made. Dirty checking is when you scan each object and all of its bound properties, comparing the current value to the last known value. If it changes, you go update the binding. As you can imagine, this gets very expensive the more objects you have.
The Angular guys are smart and they made this tradeoff very carefully. Their reasoning is:
Needless to say, we made the opposite decision. Miško Hevery describes the tradeoffs they made on StackOverflow: http://stackoverflow.com/a/96939….
He points out, with dirty checking, that you can never have more than 2000 bound objects at a time. (Note that only one of his three "issues with change listeners" applies to Ember.js, because of our run loop.)
I think that this illustrates best the difference in philosophies between Ember.js and Angular. Ember.js and Angular both strive for simplicity and ease-of-use. But Ember is designed so you don't have to worry about whether or not you have 2000 bindings. If you're writing large-scale apps, you've got bigger things to worry about.
Angular is great for small- to intermediate-scale applications that will never run into the limitations of their architecture. With Ember, we sometimes ask you to do a little more work—like specifying the dependencies of your computed properties—in order to make the most common operations run at O(1) instead of O(n), or worse.
We're always looking to take advantage of new browser and language features to make things easier to use. For example, once proxies land in ES6 (http://wiki.ecmascript.org/doku….), we won't require you to use
any longer. But we're not willing to give you a little bit of rope if we think you'll just end up hanging yourself with it as your app grows.
So that's why I think, if you're building ambitious apps, you should pick Ember.js.
We're not afraid to borrow liberally from our predecessors that have already learned how best to build large apps.
We've got a fantastic community that has some of the smartest web developers working on the hardest problems, and they're doing it because they're hitting those hard problems in the real world and they want to solve it correctly.
We've now locked down the 1.0 API, so you can start learning and not worry about the ground changing from under your feet.
To really get a feel for Ember, here's a screencast I put together of building an app from scratch:
There are also some great resources for learning:
If you're building ambitious apps, you should definitely check out Ember.js.