Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

AngularJS vs. Ember.js vs. Backbone.js

2,553 views

Published on

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!

Published in: Technology, Business
  • Be the first to comment

AngularJS vs. Ember.js vs. Backbone.js

  1. 1. @markbates
  2. 2. hire me* (for rent, not sale)
  3. 3. www.metacasts.tv KODIO13
  4. 4. AngularJS vs. Ember vs. Backbone.js
  5. 5. Knockout.js
  6. 6. philosophies
  7. 7. Backbone.js “minimal set of data-structure and view primitives for building web application with JavaScript”
  8. 8. Backbone.js do what you want, however you want to do it (we won’t tell anyone)
  9. 9. Ember “framework for creating ambitious web applications”
  10. 10. Ember convention over configuration
  11. 11. AngularJS “Toolset for building the framework most suited to your application development”
  12. 12. AngularJS plain old JavaScript
  13. 13. Round 1
  14. 14. weight
  15. 15. “production” versions (minified) w/ required dependencies
  16. 16. AngularJS base templating language data adapter support Ember Backbone.js 81kb 235kb 6.4kb built-in 73kb (handlebars) ?? built-in 210kb (ember-data) 32kb (jQuery) N/A 32kb (jQuery) 17kb (json2.js) 4.9kb (underscore.js) 81kb 550kb 60.3kb
  17. 17. Round 2
  18. 18. “basic” models
  19. 19. Backbone.js class  App.Beer  extends  Backbone.Model       class  App.Beers  extends  Backbone.Collection   !  model:  Beer
  20. 20. 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")
  21. 21. AngularJS App.Beer  =  {}
  22. 22. “remote” models
  23. 23. 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
  24. 24. 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")
  25. 25. Ember DS.RESTAdapter.reopen      namespace:  'api/v1'       App.Store  =  DS.Store.extend      revision:  11      adapter:  DS.RESTAdapter.create()
  26. 26. AngularJS App.factory  "Beer",  ($resource)  -­‐>      return  $resource  "/api/v1/beers/:id",                                        {id:  "@id"},                                        {update:  {method:  "PUT"}}
  27. 27. Round 3
  28. 28. routers
  29. 29. 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)
  30. 30. Ember App.Router.map  -­‐>      @resource  "brewery",  {path:  "brewery/:brewery_id"}
  31. 31. Ember App.BreweryRoute  =  Ember.Route.extend      model:  (params)-­‐>          App.Brewery.find(params.brewery_id)
  32. 32. 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"          })
  33. 33. Round 4
  34. 34. controllers/views
  35. 35. 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
  36. 36. Ember App.BreweryController  =  Ember.ObjectController.extend        save:  -­‐>          @store.commit()          #  further  code  omitted
  37. 37. 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
  38. 38. Round 5
  39. 39. templates
  40. 40. 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>
  41. 41. 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>
  42. 42. 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>
  43. 43. 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>
  44. 44. 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>
  45. 45. 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>
  46. 46. 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>
  47. 47. 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>
  48. 48. 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>
  49. 49. Round 6
  50. 50. pros/cons
  51. 51. Backbone.js Pros Cons • Lightweight • Too simple • Not opinionated • Not opinionated enough • Simple • “Memory” management • Easy to read source • Unstructured • “widget” development • Spaghetti code
  52. 52. Ember Pros Cons • Too complex • Overly opinionated • Heavyweight • Structured • Highly opinionated • ember-data - not production ready “less” code • API always in flux • Buggy • Little to no mind-share outside of Rails • Difficult to read source code • • “large” apps
  53. 53. AngularJS Pros • Lightly structured • Lightly opinionated • “less” code • Plain JavaScript • Simple/Powerful • Easy to test • Lightweight • small, medium, or large apps Cons • Difficult to read source code • jQuery plugins require custom directives • Large apps requiring self-imposed structure
  54. 54. Summary
  55. 55. think before you choose
  56. 56. don’t cargo cult
  57. 57. don’t use Backbone.js!
  58. 58. play with them all
  59. 59. watch the metacasts.tv episodes on them ;)
  60. 60. @markbates http://www.metacasts.tv

×