Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
AngularJS vs. Ember.js vs. Backbone.js
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Kod.io
October 26, 2013
Programming
520
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
AngularJS vs. Ember.js vs. Backbone.js
By Mark Bates
http://kod.io
Kod.io
October 26, 2013
More Decks by Kod.io
See All by Kod.io
Our future is in our past or whatever
kodio
0
73
You should learn Go!
kodio
1
140
Daha iyi Geliştirme Ortamı için: Vagrant
kodio
0
83
Building Next-Generation iOS Apps with AFNetworking 2.0
kodio
2
400
Reactive Principles
kodio
1
160
iBeacons: Interacting with the physical world using Bluetooth LE
kodio
1
110
Go: a simple programming environment
kodio
2
180
Why I had to write a client side framework for Koding.
kodio
1
100
Sure, I could learn Objective-C but...
kodio
1
98
Other Decks in Programming
See All in Programming
PHP初心者セッション2026 〜生成AIでは見えない裏側を知る:今だからLAMPを通して仕組みを学ぶ〜
kashioka
0
930
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
660
torikago - Ruby::Boxで照らすモジュラモノリスの実行境界
se4weed
1
380
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
600
ソフトウェアエンジニアにとっての生成AI - 特性を知って使い倒す / generative ai for software enginner
kishida
5
1.4k
<title><a id="</title>君はこのHTMLをパースできるか"></a></title> #雑LT_study
pizzacat83
0
140
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
2
280
人間の目はかわらない、だからJPEGは30年もつ
yuzneri
12
18k
jsmini JavaScript Engine を作ってみた話
yosuke_furukawa
PRO
0
320
運用ダッシュボードの設計を誰も教えてくれないのだけどみなさんどうしてるんですか? - チームに監視するという文化を根付かせるための第一歩を踏みたい -
satoshi256kbyte
1
120
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
490
全PRの83%がAIレビューだけでマージできるようになった開発組織はその後どうなったか
athug
1
1.7k
Featured
See All Featured
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.7k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
380
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
990
So, you think you're a good person
axbom
PRO
2
2.1k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2.1k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
240
4 Signs Your Business is Dying
shpigford
187
23k
Ethics towards AI in product and experience design
skipperchong
2
340
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Darren the Foodie - Storyboard
khoart
PRO
3
3.6k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
Transcript
@markbates
hire me* (for rent, not sale)
None
None
None
KODIO13 www.metacasts.tv
AngularJS vs. Ember vs. Backbone.js
Knockout.js
philosophies
Backbone.js “minimal set of data-structure and view primitives for building
web application with JavaScript”
Backbone.js do what you want, however you want to do
it (we won’t tell anyone)
Ember “framework for creating ambitious web applications”
Ember convention over configuration
AngularJS “Toolset for building the framework most suited to your
application development”
AngularJS plain old JavaScript
None
None
None
Round 1
weight
“production” versions (minified) w/ required dependencies
AngularJS Ember Backbone.js base 81kb 235kb 6.4kb templating language built-in
73kb (handlebars) ?? data adapter built-in 210kb (ember-data) 32kb (jQuery) support N/A 32kb (jQuery) 17kb (json2.js) 4.9kb (underscore.js) 81kb 550kb 60.3kb
Round 2
“basic” models
Backbone.js class App.Beer extends Backbone.Model class App.Beers
extends Backbone.Collection ! model: Beer
Ember App.Beer = DS.Model.extend title: DS.attr("string")
abv: DS.attr("number") country_id: DS.attr("number") brewery_id: DS.attr("number") brewery: DS.belongsTo("App.Brewery") country: DS.belongsTo("App.Country")
AngularJS App.Beer = {}
“remote” models
Backbone.js class App.Beer extends Backbone.Model urlRoot: "/api/v1/beers"
class App.Beers extends Backbone.Collection url: -‐> if @brewery_id? return "/api/v1/breweries/#{@brewery_id}/beers" else return "/api/v1/beers" model: Beer
Ember App.Beer = DS.Model.extend title: DS.attr("string")
abv: DS.attr("number") country_id: DS.attr("number") brewery_id: DS.attr("number") brewery: DS.belongsTo("App.Brewery") country: DS.belongsTo("App.Country")
Ember DS.RESTAdapter.reopen namespace: 'api/v1' App.Store
= DS.Store.extend revision: 11 adapter: DS.RESTAdapter.create()
AngularJS App.factory "Beer", ($resource) -‐> return $resource "/api/v1/beers/:id",
{id: "@id"}, {update: {method: "PUT"}}
Round 3
routers
Backbone.js @Router = Backbone.Router.extend initialize: -‐>
@countries = new Countries() routes: "breweries/:brewery_id": "brewery" "breweries/:brewery_id/edit": "breweryEdit" brewery: (brewery_id) -‐> @changeView(new BreweryView(collection: @countries, model: new Brewery(id: brewery_id))) breweryEdit: (brewery_id) -‐> @changeView(new BreweryEditView(collection: @countries, model: new Brewery(id: brewery_id))) changeView: (view) => @currentView?.remove() @currentView = view $("#outlet").html(@currentView.el)
Ember App.Router.map -‐> @resource "brewery", {path: "brewery/:brewery_id"}
Ember App.BreweryRoute = Ember.Route.extend model: (params)-‐>
App.Brewery.find(params.brewery_id)
AngularJS App.config ($routeProvider) -‐> $routeProvider
.when("/breweries/:id", { templateUrl: "/assets/brewery.html", controller: "BreweryController" }) .when("/breweries/:id/edit", { templateUrl: "/assets/edit_brewery.html", controller: "EditBreweryController" })
Round 4
controllers/views
Backbone.js class @BreweryEditView extends Backbone.View template:
"brewery_edit" events: "click #save-‐button": "saveClicked" "keypress #brewery-‐title": "titleEdited" initialize: -‐> super @countriesView = new CountriesView(collection: @collection) @$el.html(@countriesView.el) @model.on "change", @render @model.fetch() render: => @$("#country-‐outlet").html(@renderTemplate()) return @ saveClicked: (e) => e?.preventDefault() attrs = title: @$("#brewery-‐title").val() synonyms: @$("#brewery-‐synonyms").val() address: @$("#brewery-‐address").val() @model.save attrs, success: (model, response, options) => App.navigate("/breweries/#{@model.id}", trigger: true) error: (model, xhr, options) -‐> errors = [] for key, value of xhr.responseJSON.errors errors.push "#{key}: #{value.join(", ")}" alert errors.join("\n") titleEdited: (e) => title = @$("#brewery-‐title").val() @$("h2").text(title) ! # further code omitted
Ember App.BreweryController = Ember.ObjectController.extend save: -‐>
@store.commit() # further code omitted
AngularJS @EditBreweryController = ($scope, $routeParams, $location, Brewery) -‐>
$scope.brewery = Brewery.get(id: $routeParams.id) $scope.save = -‐> success = -‐> $location.path("/breweries/#{$routeParams.id}") $scope.errors = null failure = (object)-‐> $scope.errors = object.data.errors $scope.brewery.$update {}, success, failure
Round 5
templates
Backbone.js <h2><%= @model.displayName() %></h2> <form>
<div class="control-‐group"> <label class="control-‐label" for="title">Title</label> <div class="controls"> <input type='text' class='input-‐xxlarge' value='<%= @model.get("title") %>'id='brewery-‐title'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> <input type='text' class='input-‐xxlarge' value='<%= @model.get("synonyms") %>'id='brewery-‐synonyms'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="address">Address</label> <div class="controls"> <textarea class='input-‐xxlarge' id='brewery-‐address'><%= @model.get("address") %></textarea> </div> </div> <button class='btn btn-‐primary' id='save-‐button'>Save</button> <a href="/breweries/<%= @model.id %>" class='btn'>Cancel</a> </form>
Backbone.js <h2><%= @model.displayName() %></h2> <form>
<div class="control-‐group"> <label class="control-‐label" for="title">Title</label> <div class="controls"> <input type='text' class='input-‐xxlarge' value='<%= @model.get("title") %>'id='brewery-‐title'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> <input type='text' class='input-‐xxlarge' value='<%= @model.get("synonyms") %>'id='brewery-‐synonyms'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="address">Address</label> <div class="controls"> <textarea class='input-‐xxlarge' id='brewery-‐address'><%= @model.get("address") %></textarea> </div> </div> <button class='btn btn-‐primary' id='save-‐button'>Save</button> <a href="/breweries/<%= @model.id %>" class='btn'>Cancel</a> </form> <input type='text' class='input-‐xxlarge' value='<%= @model.get("title") %>'id='brewery-‐title'>
Backbone.js <h2><%= @model.displayName() %></h2> <form>
<div class="control-‐group"> <label class="control-‐label" for="title">Title</label> <div class="controls"> <input type='text' class='input-‐xxlarge' value='<%= @model.get("title") %>'id='brewery-‐title'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> <input type='text' class='input-‐xxlarge' value='<%= @model.get("synonyms") %>'id='brewery-‐synonyms'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="address">Address</label> <div class="controls"> <textarea class='input-‐xxlarge' id='brewery-‐address'><%= @model.get("address") %></textarea> </div> </div> <button class='btn btn-‐primary' id='save-‐button'>Save</button> <a href="/breweries/<%= @model.id %>" class='btn'>Cancel</a> </form> <textarea class='input-‐xxlarge' id='brewery-‐address'><%= @model.get("address") %></textarea>
<div class='span12'> <h2>{{displayName}}</h2> <h3>
{{cityState}} {{#linkTo "country" country}} {{country.title}} {{/linkTo}} </h3> {{#if isEditing}} <form> <div class="control-‐group"> <label class="control-‐label" for="title">Title</label> <div class="controls"> {{view Ember.TextField valueBinding="title" class='input-‐xxlarge'}} </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> {{view Ember.TextField valueBinding="synonyms" class='input-‐xxlarge'}} </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> {{view Ember.TextArea valueBinding="address" class='input-‐xxlarge'}} </div> </div> <button class='btn btn-‐primary' {{action "save"}}>Save</button> </form> {{ else }} {{ partial "brewery/show" }} {{/if}} </div> Ember
<div class='span12'> <h2>{{displayName}}</h2> <h3>
{{cityState}} {{#linkTo "country" country}} {{country.title}} {{/linkTo}} </h3> {{#if isEditing}} <form> <div class="control-‐group"> <label class="control-‐label" for="title">Title</label> <div class="controls"> {{view Ember.TextField valueBinding="title" class='input-‐xxlarge'}} </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> {{view Ember.TextField valueBinding="synonyms" class='input-‐xxlarge'}} </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> {{view Ember.TextArea valueBinding="address" class='input-‐xxlarge'}} </div> </div> <button class='btn btn-‐primary' {{action "save"}}>Save</button> </form> {{ else }} {{ partial "brewery/show" }} {{/if}} </div> Ember {{view Ember.TextField valueBinding="title" class='input-‐xxlarge'}}
<div class='span12'> <h2>{{displayName}}</h2> <h3>
{{cityState}} {{#linkTo "country" country}} {{country.title}} {{/linkTo}} </h3> {{#if isEditing}} <form> <div class="control-‐group"> <label class="control-‐label" for="title">Title</label> <div class="controls"> {{view Ember.TextField valueBinding="title" class='input-‐xxlarge'}} </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> {{view Ember.TextField valueBinding="synonyms" class='input-‐xxlarge'}} </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> {{view Ember.TextArea valueBinding="address" class='input-‐xxlarge'}} </div> </div> <button class='btn btn-‐primary' {{action "save"}}>Save</button> </form> {{ else }} {{ partial "brewery/show" }} {{/if}} </div> Ember <button class='btn btn-‐primary' {{action "save"}}>Save</button>
<form> <h3>{{brewery.title}}</h3> <div ng-‐include='"/assets/_errors.html"'></div>
<div class="control-‐group"> <label class="control-‐label" for="title">Title</label> <div class="controls"> <input type='text' class='input-‐xxlarge' ng-‐model='brewery.title'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> <input type='text' class='input-‐xxlarge' ng-‐model='brewery.synonyms'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="address">Address</label> <div class="controls"> <textarea class='input-‐xxlarge' ng-‐model='brewery.address'></textarea> </div> </div> <button class='btn btn-‐primary' ng-‐click='save()'>Save</button> </form> AngularJS
AngularJS <form> <h3>{{brewery.title}}</h3> <div ng-‐include='"/assets/_errors.html"'></div>
<div class="control-‐group"> <label class="control-‐label" for="title">Title</label> <div class="controls"> <input type='text' class='input-‐xxlarge' ng-‐model='brewery.title'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> <input type='text' class='input-‐xxlarge' ng-‐model='brewery.synonyms'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="address">Address</label> <div class="controls"> <textarea class='input-‐xxlarge' ng-‐model='brewery.address'></textarea> </div> </div> <button class='btn btn-‐primary' ng-‐click='save()'>Save</button> </form> <input type='text' class='input-‐xxlarge' ng-‐model='brewery.title'>
<form> <h3>{{brewery.title}}</h3> <div ng-‐include='"/assets/_errors.html"'></div>
<div class="control-‐group"> <label class="control-‐label" for="title">Title</label> <div class="controls"> <input type='text' class='input-‐xxlarge' ng-‐model='brewery.title'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="synonyms">Synonyms</label> <div class="controls"> <input type='text' class='input-‐xxlarge' ng-‐model='brewery.synonyms'> </div> </div> <div class="control-‐group"> <label class="control-‐label" for="address">Address</label> <div class="controls"> <textarea class='input-‐xxlarge' ng-‐model='brewery.address'></textarea> </div> </div> <button class='btn btn-‐primary' ng-‐click='save()'>Save</button> </form> AngularJS <button class='btn btn-‐primary' ng-‐click='save()'>Save</button>
Round 6
pros/cons
Backbone.js • Too simple • Not opinionated enough • “Memory”
management • Unstructured • Spaghetti code • Lightweight • Not opinionated • Simple • Easy to read source • “widget” development Pros Cons
Ember • Too complex • Overly opinionated • Heavyweight •
ember-data - not production ready • API always in flux • Buggy • Little to no mind-share outside of Rails • Difficult to read source code • Structured • Highly opinionated • “less” code • “large” apps Pros Cons
AngularJS • Difficult to read source code • jQuery plugins
require custom directives • Large apps requiring self-imposed structure • Lightly structured • Lightly opinionated • “less” code • Plain JavaScript • Simple/Powerful • Easy to test • Lightweight • small, medium, or large apps Pros Cons
Summary
think before you choose
don’t cargo cult
don’t use Backbone.js!
play with them all
watch the metacasts.tv episodes on them ;)
@markbates http://www.metacasts.tv