《Web前端开发最佳实践》第九章 引用16：A Comparison of Angular, Backbone, CanJS and Ember
I have had the opportunity to use four of these frameworks: Angular, Backbone, CanJS and Ember. So I decided to create a comparison to help you decide which one to use. I will go through several factors that you might want to consider when choosing one.
To each factor I have assigned a score between 1 and 5. Where 1 is poor and 5 is great. I have tried to be impartial in my comparison, but of course my objectivity is heavily compromised as the scores are based mostly on my personal experience.
There are really important features a framework should have to provide the necessary foundation to build useful applications. Does it do view bindings? two way bindings? filters? computed properties? dirty attributes? form validation? etc. This can be a very long list. Below is a comparison of what I consider the really important features in a MVC framework:
|Two way bindings||y||–||y||y|
|Filtered list views||y||–||y||y|
Observables: Objects that can be observed for changes.
Routing: Pushing changes to the browser url hash and listening for changes to act accordingly.
View bindings: Using observable objects in views, having the views automatically refresh when the observable object change.
Two way bindings: Having the view push changes to the observable object automatically, for example a form input.
Partial views: Views that include other views.
Filtered list views: Having views that display objects filtered by a certain criteria.
Update 2014-07-08: As of version 2.0 CanJS now supports two way bindings.
So based on these features my scores are:
It is important to note that Backbone can do most of this things with a lot of manual code or with the help of plug-ins. But I am only considering the available features in the core framework.
There are hundreds of awesome plug-ins and libraries out there that do specialised things. They usually do these things better than what comes bundle with a framework. So it important to be able to integrate these libraries with the chosen MVC framework.
Backbone is the most flexible framework as it is the one with the less conventions and opinions. You are required to make a lot of decisions when using Backbone.
CanJS is almost as flexible as Backbone as it allows you to easily integrate other libraries with minimum effort. With CanJS you can even use a totally different rendering engine if you want, I have used Rivets extensively with CanJS without any issues. Although I recommend using what comes with the framework.
Ember and Angular are still flexible frameworks to some degree but you will find that you could end up fighting the framework if you don’t like the way it does certain things. There are some things that you just need to buy into when using Ember or Angular.
Learning curve and documentation
Angular has a very high wow factor at the beginning. It can do some amazing things – like two-way bindings – without having to learn much. And it looks quite easy at first sight. But after you have learnt the very basics it is quite a steep learning curve from there. It is a complex framework with lots of peculiarities. Reading the documentation is not easy as there is a lot of Angular specific jargon and a serious lack of examples.
The basic of Backbone are quite easy to learn. But soon you find that there are not enough opinions there to know how to best structure your code. You will need to watch or read a few tutorials to learn some best Backbone practices. Also you will find that you will probably need to learn another library on top of Backbone (e.g. Marionette or Thorax) to get things done. So I don’t consider Backbone the easier framework to learn.
CanJS is in comparison the easiest to learn of the bunch. Just by reading the one page website (http://canjs.us/) you will know most of what you need to be productive. There is of course more to learn, but I only had the need to reach for help in rare occasions (tutorials, forum, irc).
Ember also has a steep learning curve like Angular, I believe that learning Ember is easier than Angular but it requires a highest learning investment at the beginning to get basic things done. Angular in contrast lets you do some amazing things without learning too much. Ember lacks this early wow factor.
After you learn the framework well what really matters is how productive you are with. You know: conventions, magic, doing as much as possible quickly.
Once you know Angular well you be can very productive with it, no doubt about that. It just doesn’t get the highest score because I think that Ember has gone a step further in this category.
Backbone requires you to write a lot of boilerplate code, which I think is totally unnecessary. This is in my opinion a direct threat against developer productivity.
CanJS neither shines nor disappoints in this area. But due to the low learning curve you can be quite productive with it very early on.
Ember really shines here. Because it is full of strong conventions it does a lot of stuff automagically for you. All you need to do is learn and apply those conventions and Ember will to the right thing.
How easy is to find help, tutorials and experts?
The Backbone community is huge, there is no doubt about that. You can find dozens of tutorials about Backbone, a very active community on StackOverflow and IRC.
The Angular and Ember communities are pretty big as well. Also lots of tutorial and activity in StackOverflow and IRC, but not as much as Backbone.
The CanJS community on the other hand is small in comparison, but fortunately is quite active and helpful. I haven’t found the smaller size of the CanJS community to be a liability.
Is there an ecosystem of plug-ins and libraries?
Here again Backbone beats the others hands down. There are tons of plug-ins for it. The Angular ecosystem is getting quite interesting as well with things like Angular UI. I think that the Ember ecosystem is less developed but it should get better due to Ember’s popularity. CanJS has the smallest ecosystem if any.
This might be an important consideration, specially if you are doing mobile development.
Size library alone (no dependecies, just min)
Backbone is the smallest and people often point to this fact. But this is not the end of the story.
Size with dependencies
At 80k Angular is the only library of the bunch that doesn’t require extra libraries to work.
However all the other need other libraries to work:
Backbone needs at least Underscore and Zepto. You can use the mini-templates in underscore for rendering views, but most of the time you will want to use a nicer template engine like Mustache. This is 61K.
CanJS needs at least Zepto. This is 57K.
I don’t consider performance to be a critical factor on choosing a framework because they are all performant enough for most of the things they will be used for. But this of course depends on what you are doing with it. If you are building a game performance should be a big consideration.
I have seen and made many performance tests with these libraries e.g. this one. But I am not totally convinced on the reliability of these tests. It is really hard to be sure that the test is really testing the right things and in the right way.
However, from what I have seen and read CanJS seems to have the edge when it comes to performance, specially in rendering view bindings. On the other hand I believe that Angular is the less performant based on the fact that it does dirty checking of objects. This cannot possibly be as performant as the others. See this.
Is this a mature framework, has it been proven in production, are there many website using it?
Backbone has a ton of websites built with it. Its code base hasn’t had major changes in the lasts two year which is a great thing from the maturity perspective.
Although Ember is not that new, it has had major changes along the way, just reaching a stable form in the last couple of months. So at this time I don’t consider it to be a mature framework.
Angular seems more stable and proven than Ember. But not as much as Backbone.
Memory leak safety
This is an important consideration if you are building single page apps that are intended to stay open for a long time. You don’t want your application to leak memory, this can be a real problem. Unfortunately this can happen quite easily, specially if you are creating listeners for DOM events yourself.
Angular, CanJS and Ember will deal with this effectively as long as you follow their best practices. Backbone on the other hand requires you to do this work manually in a teardown method.
How easy is to test you code? The keys to have great testable code are modularity (have small pieces that can be tested in isolation) and dependency injection (being able to change dependencies in your tests).
You can do this with any of the frameworks if you learn the right patterns, but it is not easy and it requires you to get out of your way to apply them.
Modularity and dependency injection are core features of Angular, it actively discourages you from doing things in any other way. This usually leads to code that is easier to test. Because of this I consider Angular to has an advantage in this area.
Update 2013-05-08: Updated testability to explain better the Angular approach.
This is probably one of the biggest factors when choosing a library.
- Do you like declarative html? –> Angular
- Do you like using a template engine? –> Backbone, Can and Ember
- Do you like an opinionated framework? –> Ember
- Do you want a framework that stick closely to the original SmallTalk MVCpattern? –> None here, maybe CanJS is the closest.
- Do you want to use what seems cool at the moment? –> Ember, Angular
There is no way to score this.
Well, putting all together this is my tally. Remember this is just my opinion, please let me know if you think I have scored a library really wrong.
If you put the same weight to every factor it is a tight competition, there are no clear winners or losers. So I guess it all comes down to personal taste or how much weight you apply to each particular factor.
A note about Backbone (Impartiality ends here)
I have tried to stay impartial during my post but I cannot finish it without sharing my current opinion about Backbone.
Backbone was a great library two years ago, but I am convinced that there are better things now. I believe that many people choose Backbone just because of its popularity, it is a vicious circle.
Backbone trumps ultimate flexibility over developer convenience. But I think that it has traded too much, as it seriously lacks features and developer productivity. Yes, there are lots of plug-ins to compensate for this, but then you will be learning Backbone and something else on top.
Backbone can also be very tempting because of its big community and the ecosystem, but this advantage will disappear as the other frameworks become more popular.
Because of this I strongly feel that you should think twice before choosing Backbone for your next project.
Update 2013-04-20: Added testability. Update 2013-04-18: Made it clear that the last section is just my opinion. Removed the inflammatory “It is time to move on” statement.