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
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
72
You should learn Go!
kodio
1
140
Daha iyi Geliştirme Ortamı için: Vagrant
kodio
0
81
Building Next-Generation iOS Apps with AFNetworking 2.0
kodio
2
400
Reactive Principles
kodio
1
150
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
97
Other Decks in Programming
See All in Programming
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
150
AI駆動開発を妨げる技術的負債の解消アプローチ / ai-refactoring-approach
minodriven
17
9.2k
광주소프트웨어마이스터고등학교 DevFest 특강 - 바이브 코딩 시대에서 주니어 개발자로 살아남는 방법
utilforever
1
150
1年で人数1.5倍、PR数5.5倍増。 品質とアウトカムはどうなったか、 何が効いたか
ike002jp
0
140
【SRE NEXT 2026 Lunch Session】一人目専任SREの立ち上げを加速する ― AIと進めたオンボーディングで2分を0.04秒にした話
pkshadeck
PRO
0
2.9k
AIが無かった頃の素敵な出会いの話
codmoninc
1
170
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
350
AIキャラアプリkaiwaの低遅延音声通話基盤をどう作ったか - AWS Gravitonで支える低遅延・低コストAI Agent基盤
mogamit
0
180
使用 Meilisearch 建立新聞搜尋工具
johnroyer
0
160
SREは、MCPとSRE Agentをこう使え!
kazumax55
0
150
分散システム、なんですぐ死んでしまうん?耐障害性を高めたいあなたのためのレジリエンスパターン入門
mshibuya
7
6.7k
AIを活用したE2Eテスト実装効率化のあゆみ / ebisu-mobile-14-kotetu
kotetuco
0
180
Featured
See All Featured
SEO for Brand Visibility & Recognition
aleyda
0
4.6k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
HDC tutorial
michielstock
2
750
Marketing to machines
jonoalderson
1
5.6k
AI: The stuff that nobody shows you
jnunemaker
PRO
9
840
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
220
A designer walks into a library…
pauljervisheath
211
24k
sira's awesome portfolio website redesign presentation
elsirapls
0
300
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.9k
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