AngularJS vs. Ember.js vs. Backbone.js

66
@markbates

description

The world of JavaScript client-side frameworks is overflowing with contenders vying for the crown, but which one do you choose for your next project? Which one has what it takes? In this talk we’ll look at the “Big 3”, AngularJS, Ember.js, and Backbone.js. We’ll compare them head to head, toe to toe. We’ll look at the pros and cons of each one. How do they handle form bindings? Talking to APIs? Code organization? Routing? Etc? Who’ll come out victorious in this battle of the JavaScript frameworks, or will we all just come out bloodied and bruised on the other side? Guess we’ll find out!

Transcript of AngularJS vs. Ember.js vs. Backbone.js

Page 1: AngularJS vs. Ember.js vs. Backbone.js

@markbates

Page 2: AngularJS vs. Ember.js vs. Backbone.js

hire me* (for rent, not sale)

Page 3: AngularJS vs. Ember.js vs. Backbone.js
Page 4: AngularJS vs. Ember.js vs. Backbone.js
Page 5: AngularJS vs. Ember.js vs. Backbone.js
Page 6: AngularJS vs. Ember.js vs. Backbone.js

KODIO13www.metacasts.tv

Page 7: AngularJS vs. Ember.js vs. Backbone.js

AngularJS vs. Ember vs. Backbone.js

Page 8: AngularJS vs. Ember.js vs. Backbone.js

Knockout.js

Page 9: AngularJS vs. Ember.js vs. Backbone.js

philosophies

Page 10: AngularJS vs. Ember.js vs. Backbone.js

Backbone.js

“minimal set of data-structure and view primitives for building web application with JavaScript”

Page 11: AngularJS vs. Ember.js vs. Backbone.js

Backbone.js

do what you want, however you want to do it

(we won’t tell anyone)

Page 12: AngularJS vs. Ember.js vs. Backbone.js

Ember

“framework for creating ambitious web applications”

Page 13: AngularJS vs. Ember.js vs. Backbone.js

Ember

convention over configuration

Page 14: AngularJS vs. Ember.js vs. Backbone.js

AngularJS

“Toolset for building the framework most suited to your application development”

Page 15: AngularJS vs. Ember.js vs. Backbone.js

AngularJS

plain old JavaScript

Page 16: AngularJS vs. Ember.js vs. Backbone.js
Page 17: AngularJS vs. Ember.js vs. Backbone.js
Page 18: AngularJS vs. Ember.js vs. Backbone.js
Page 19: AngularJS vs. Ember.js vs. Backbone.js

Round 1

Page 20: AngularJS vs. Ember.js vs. Backbone.js

weight

Page 21: AngularJS vs. Ember.js vs. Backbone.js

“production” versions (minified) w/ required dependencies

Page 22: AngularJS vs. Ember.js vs. Backbone.js

AngularJS Ember Backbone.js

base 81kb 235kb 6.4kb

templating language built-in73kb

(handlebars) ??

data adapter built-in210kb

(ember-data)32kb

(jQuery)

support N/A32kb

(jQuery)

17kb (json2.js)

4.9kb (underscore.js)

81kb 550kb 60.3kb

Page 23: AngularJS vs. Ember.js vs. Backbone.js

Round 2

Page 24: AngularJS vs. Ember.js vs. Backbone.js

“basic” models

Page 25: AngularJS vs. Ember.js vs. Backbone.js

Backbone.js

class  App.Beer  extends  Backbone.Model      class  App.Beers  extends  Backbone.Collection  !

 model:  Beer

Page 26: AngularJS vs. Ember.js vs. Backbone.js

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")

Page 27: AngularJS vs. Ember.js vs. Backbone.js

AngularJS

App.Beer  =  {}

Page 28: AngularJS vs. Ember.js vs. Backbone.js

“remote” models

Page 29: AngularJS vs. Ember.js vs. Backbone.js

Backbone.jsclass  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

Page 30: AngularJS vs. Ember.js vs. Backbone.js

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")

Page 31: AngularJS vs. Ember.js vs. Backbone.js

EmberDS.RESTAdapter.reopen      namespace:  'api/v1'      App.Store  =  DS.Store.extend      revision:  11      adapter:  DS.RESTAdapter.create()

Page 32: AngularJS vs. Ember.js vs. Backbone.js

AngularJS

App.factory  "Beer",  ($resource)  -­‐>      return  $resource  "/api/v1/beers/:id",                                        {id:  "@id"},                                        {update:  {method:  "PUT"}}

Page 33: AngularJS vs. Ember.js vs. Backbone.js

Round 3

Page 34: AngularJS vs. Ember.js vs. Backbone.js

routers

Page 35: AngularJS vs. Ember.js vs. Backbone.js

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)

Page 36: AngularJS vs. Ember.js vs. Backbone.js

Ember

App.Router.map  -­‐>      @resource  "brewery",  {path:  "brewery/:brewery_id"}

Page 37: AngularJS vs. Ember.js vs. Backbone.js

Ember

App.BreweryRoute  =  Ember.Route.extend      model:  (params)-­‐>          App.Brewery.find(params.brewery_id)

Page 38: AngularJS vs. Ember.js vs. Backbone.js

AngularJSApp.config  ($routeProvider)  -­‐>          $routeProvider          .when("/breweries/:id",  {              templateUrl:  "/assets/brewery.html",              controller:  "BreweryController"          })          .when("/breweries/:id/edit",  {              templateUrl:  "/assets/edit_brewery.html",              controller:  "EditBreweryController"          })

Page 39: AngularJS vs. Ember.js vs. Backbone.js

Round 4

Page 40: AngularJS vs. Ember.js vs. Backbone.js

controllers/views

Page 41: AngularJS vs. Ember.js vs. Backbone.js

Backbone.jsclass  @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

Page 42: AngularJS vs. Ember.js vs. Backbone.js

Ember

App.BreweryController  =  Ember.ObjectController.extend        save:  -­‐>          @store.commit()          #  further  code  omitted

Page 43: AngularJS vs. Ember.js vs. Backbone.js

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

Page 44: AngularJS vs. Ember.js vs. Backbone.js

Round 5

Page 45: AngularJS vs. Ember.js vs. Backbone.js

templates

Page 46: AngularJS vs. Ember.js vs. Backbone.js

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>

Page 47: AngularJS vs. Ember.js vs. Backbone.js

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'>

Page 48: AngularJS vs. Ember.js vs. Backbone.js

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>

Page 49: AngularJS vs. Ember.js vs. Backbone.js

<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

Page 50: AngularJS vs. Ember.js vs. Backbone.js

<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'}}

Page 51: AngularJS vs. Ember.js vs. Backbone.js

<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>

Page 52: AngularJS vs. Ember.js vs. Backbone.js

<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

Page 53: AngularJS vs. Ember.js vs. Backbone.js

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'>

Page 54: AngularJS vs. Ember.js vs. Backbone.js

<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>

Page 55: AngularJS vs. Ember.js vs. Backbone.js

Round 6

Page 56: AngularJS vs. Ember.js vs. Backbone.js

pros/cons

Page 57: AngularJS vs. Ember.js vs. Backbone.js

Backbone.js

• Too simple

• Not opinionated enough

• “Memory” management

• Unstructured

• Spaghetti code

• Lightweight

• Not opinionated

• Simple

• Easy to read source

• “widget” development

Pros Cons

Page 58: AngularJS vs. Ember.js vs. Backbone.js

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

Page 59: AngularJS vs. Ember.js vs. Backbone.js

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

Page 60: AngularJS vs. Ember.js vs. Backbone.js

Summary

Page 61: AngularJS vs. Ember.js vs. Backbone.js

think before you choose

Page 62: AngularJS vs. Ember.js vs. Backbone.js

don’t cargo cult

Page 63: AngularJS vs. Ember.js vs. Backbone.js

don’t use Backbone.js!

Page 64: AngularJS vs. Ember.js vs. Backbone.js

play with them all

Page 65: AngularJS vs. Ember.js vs. Backbone.js

watch the metacasts.tv episodes on them ;)

Page 66: AngularJS vs. Ember.js vs. Backbone.js

@markbates http://www.metacasts.tv