building a single-page app: backbone, node.js, and beyond
DESCRIPTION
TRANSCRIPT
![Page 1: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/1.jpg)
Building a Single-Page App: Backbone, Node.js, and Beyond
Spike Brehm, Front End [email protected]
@spikebrehmSeptember 12, 2012
Thursday, September 13, 12
![Page 2: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/2.jpg)
Past: Why Single-Page Apps
Present: How we built Wish Lists
Future: In pursuit of the Holy Grail
Thursday, September 13, 12
![Page 3: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/3.jpg)
PastWhy Single-Page Apps
Thursday, September 13, 12
![Page 4: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/4.jpg)
Thursday, September 13, 12
![Page 5: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/5.jpg)
Airbedandbreakfast.com
Thursday, September 13, 12
![Page 6: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/6.jpg)
Airbedandbreakfast.com
• Started in 2008 as a Rails 2.x app
Thursday, September 13, 12
![Page 7: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/7.jpg)
Airbedandbreakfast.com
• Started in 2008 as a Rails 2.x app
• Now Rails 3.0
Thursday, September 13, 12
![Page 8: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/8.jpg)
Airbedandbreakfast.com
• Started in 2008 as a Rails 2.x app
• Now Rails 3.0
• Still stuck in old, page-based paradigm
Thursday, September 13, 12
![Page 9: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/9.jpg)
What is a Single-Page App?
Thursday, September 13, 12
![Page 10: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/10.jpg)
What is a Single-Page App?
Thursday, September 13, 12
![Page 11: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/11.jpg)
What is a Single-Page App?
Thursday, September 13, 12
![Page 12: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/12.jpg)
What is a Single-Page App?
• Navigate in the app without page refresh
Thursday, September 13, 12
![Page 13: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/13.jpg)
What is a Single-Page App?
• Navigate in the app without page refresh
• Application logic in the client
Thursday, September 13, 12
![Page 14: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/14.jpg)
What is a Single-Page App?
• Navigate in the app without page refresh
• Application logic in the client
• Fetch data on demand
Thursday, September 13, 12
![Page 15: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/15.jpg)
Why Single-Page Apps?
Thursday, September 13, 12
![Page 16: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/16.jpg)
Why Single-Page Apps?
• Faster JavaScript runtimes
Thursday, September 13, 12
![Page 17: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/17.jpg)
Why Single-Page Apps?
• Faster JavaScript runtimes
• New browser features (pushState, localStorage, etc.)
Thursday, September 13, 12
![Page 18: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/18.jpg)
Why Single-Page Apps?
• Faster JavaScript runtimes
• New browser features (pushState, localStorage, etc.)
• Heightened user expectations
Thursday, September 13, 12
![Page 19: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/19.jpg)
Two Approaches
The Easy Way
The Hard Wayaka “The Holy Grail”
Thursday, September 13, 12
![Page 20: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/20.jpg)
The Easy Way
Thursday, September 13, 12
![Page 21: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/21.jpg)
The Easy Way
Thursday, September 13, 12
![Page 22: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/22.jpg)
The Easy Way
• JavaScript app runs entirely in client
Thursday, September 13, 12
![Page 23: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/23.jpg)
The Easy Way
• JavaScript app runs entirely in client
• Server technology agnostic
Thursday, September 13, 12
![Page 24: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/24.jpg)
The Easy Way
• JavaScript app runs entirely in client
• Server technology agnostic
• Can use Backbone to structure app
Thursday, September 13, 12
![Page 25: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/25.jpg)
The Easy Way
• JavaScript app runs entirely in client
• Server technology agnostic
• Can use Backbone to structure app
• Poor SEO -- not crawlable
Thursday, September 13, 12
![Page 26: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/26.jpg)
The Easy Way
• JavaScript app runs entirely in client
• Server technology agnostic
• Can use Backbone to structure app
• Poor SEO -- not crawlable
• Performance hit to download & evaluate JS before rendering
Thursday, September 13, 12
![Page 27: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/27.jpg)
The Easy Way
• JavaScript app runs entirely in client
• Server technology agnostic
• Can use Backbone to structure app
• Poor SEO -- not crawlable
• Performance hit to download & evaluate JS before rendering
• Good for apps behind login, or tools
Thursday, September 13, 12
![Page 28: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/28.jpg)
The Hard Wayaka “The Holy Grail”
Thursday, September 13, 12
![Page 29: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/29.jpg)
The Hard Way
Thursday, September 13, 12
![Page 30: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/30.jpg)
The Hard Way• Routing, templating, application logic, utilities run on
client and server
Thursday, September 13, 12
![Page 31: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/31.jpg)
The Hard Way• Routing, templating, application logic, utilities run on
client and server
• Navigate to any page, HTML rendered in client -- hit refresh, serves up HTML
Thursday, September 13, 12
![Page 32: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/32.jpg)
The Hard Way• Routing, templating, application logic, utilities run on
client and server
• Navigate to any page, HTML rendered in client -- hit refresh, serves up HTML
• Must render full page of HTML without access to DOM (or find a faster DOM implementation)
Thursday, September 13, 12
![Page 33: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/33.jpg)
The Hard Way• Routing, templating, application logic, utilities run on
client and server
• Navigate to any page, HTML rendered in client -- hit refresh, serves up HTML
• Must render full page of HTML without access to DOM (or find a faster DOM implementation)
• Requires JavaScript runtime on the server (or DSL that compiles down to JavaScript -- think GWT)
Thursday, September 13, 12
![Page 34: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/34.jpg)
The Hard Way• Routing, templating, application logic, utilities run on
client and server
• Navigate to any page, HTML rendered in client -- hit refresh, serves up HTML
• Must render full page of HTML without access to DOM (or find a faster DOM implementation)
• Requires JavaScript runtime on the server (or DSL that compiles down to JavaScript -- think GWT)
• Backbone not a good fit
Thursday, September 13, 12
![Page 35: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/35.jpg)
The Hard Way• Routing, templating, application logic, utilities run on
client and server
• Navigate to any page, HTML rendered in client -- hit refresh, serves up HTML
• Must render full page of HTML without access to DOM (or find a faster DOM implementation)
• Requires JavaScript runtime on the server (or DSL that compiles down to JavaScript -- think GWT)
• Backbone not a good fit
• Provides good SEO
Thursday, September 13, 12
![Page 36: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/36.jpg)
The Hard Way• Routing, templating, application logic, utilities run on
client and server
• Navigate to any page, HTML rendered in client -- hit refresh, serves up HTML
• Must render full page of HTML without access to DOM (or find a faster DOM implementation)
• Requires JavaScript runtime on the server (or DSL that compiles down to JavaScript -- think GWT)
• Backbone not a good fit
• Provides good SEO
• Better performance
Thursday, September 13, 12
![Page 37: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/37.jpg)
Performance
Improving performance on Twitter.comhttp://engineering.twitter.com/2012/05/improving-performance-on-twittercom.html
“Time to first tweet”
Thursday, September 13, 12
![Page 38: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/38.jpg)
Stops and Starts
Thursday, September 13, 12
![Page 39: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/39.jpg)
Stops and Starts
• mustache.rb: code duplication
Thursday, September 13, 12
![Page 40: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/40.jpg)
Stops and Starts
• mustache.rb: code duplication
• therubyracer: performance, stability
Thursday, September 13, 12
![Page 41: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/41.jpg)
Stops and Starts
• mustache.rb: code duplication
• therubyracer: performance, stability
• PhantomJS: slow, overly complicated
Thursday, September 13, 12
![Page 42: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/42.jpg)
PresentHow we built Wish Lists
Thursday, September 13, 12
![Page 43: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/43.jpg)
Thursday, September 13, 12
![Page 44: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/44.jpg)
Technologies
Thursday, September 13, 12
![Page 45: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/45.jpg)
Technologies• MV*: Backbone.js
Thursday, September 13, 12
![Page 46: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/46.jpg)
Technologies• MV*: Backbone.js
• Templating: Handlebars
Thursday, September 13, 12
![Page 47: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/47.jpg)
Technologies• MV*: Backbone.js
• Templating: Handlebars
• UI & Layout: Oxygen (Airbnb’s Bootstrap)
Thursday, September 13, 12
![Page 48: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/48.jpg)
Technologies• MV*: Backbone.js
• Templating: Handlebars
• UI & Layout: Oxygen (Airbnb’s Bootstrap)
• CoffeeScript
Thursday, September 13, 12
![Page 49: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/49.jpg)
Technologies• MV*: Backbone.js
• Templating: Handlebars
• UI & Layout: Oxygen (Airbnb’s Bootstrap)
• CoffeeScript
• HTML5 pushState
Thursday, September 13, 12
![Page 50: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/50.jpg)
Technologies• MV*: Backbone.js
• Templating: Handlebars
• UI & Layout: Oxygen (Airbnb’s Bootstrap)
• CoffeeScript
• HTML5 pushState
• api.airbnb.com
Thursday, September 13, 12
![Page 51: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/51.jpg)
Rails-Backbone interface: index.html.erb
<div class=”app_view”></div>
<script>!function(){ I18n.extend(<%= @phrases.to_json.html_safe %>); Airbnb.Api.config(<%= @api_config.to_json.html_safe %>);
window.WishlistsApp = new AIR.Apps.Wishlists( <%= @init_data.to_json.html_safe %> );}();</script>
Thursday, September 13, 12
![Page 52: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/52.jpg)
<div class=”app_view”></div>
<script>!function(){ I18n.extend(<%= @phrases.to_json.html_safe %>); Airbnb.Api.config(<%= @api_config.to_json.html_safe %>);
window.WishlistsApp = new AIR.Apps.Wishlists( <%= @init_data.to_json.html_safe %> );}();</script>
Rails-Backbone interface: index.html.erb
Thursday, September 13, 12
![Page 53: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/53.jpg)
<div class=”app_view”></div>
<script>!function(){ I18n.extend(<%= @phrases.to_json.html_safe %>); Airbnb.Api.config(<%= @api_config.to_json.html_safe %>);
window.WishlistsApp = new AIR.Apps.Wishlists( <%= @init_data.to_json.html_safe %> );}();</script>
Rails-Backbone interface: index.html.erb
Thursday, September 13, 12
![Page 54: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/54.jpg)
<div class=”app_view”></div>
<script>!function(){ I18n.extend(<%= @phrases.to_json.html_safe %>); Airbnb.Api.config(<%= @api_config.to_json.html_safe %>);
window.WishlistsApp = new AIR.Apps.Wishlists( <%= @init_data.to_json.html_safe %> );}();</script>
Rails-Backbone interface: index.html.erb
Thursday, September 13, 12
![Page 55: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/55.jpg)
<div class=”app_view”></div>
<script>!function(){ I18n.extend(<%= @phrases.to_json.html_safe %>); Airbnb.Api.config(<%= @api_config.to_json.html_safe %>);
window.WishlistsApp = new AIR.Apps.Wishlists( <%= @init_data.to_json.html_safe %> );}();</script>
Rails-Backbone interface: index.html.erb
Thursday, September 13, 12
![Page 56: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/56.jpg)
<div class=”app_view”></div>
<script>!function(){ I18n.extend(<%= @phrases.to_json.html_safe %>); Airbnb.Api.config(<%= @api_config.to_json.html_safe %>);
window.WishlistsApp = new AIR.Apps.Wishlists( <%= @init_data.to_json.html_safe %> );}();</script>
Rails-Backbone interface: index.html.erb
Thursday, September 13, 12
![Page 57: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/57.jpg)
<div class=”app_view”></div>
<script>!function(){ I18n.extend(<%= @phrases.to_json.html_safe %>); Airbnb.Api.config(<%= @api_config.to_json.html_safe %>);
window.WishlistsApp = new AIR.Apps.Wishlists( <%= @init_data.to_json.html_safe %> );}();</script>
Rails-Backbone interface: index.html.erb
Thursday, September 13, 12
![Page 58: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/58.jpg)
Bootstrapping the app window.WishlistsApp = new AIR.Apps.Wishlists({ “listings”: [...], “wishlists”: [...], ... });
Thursday, September 13, 12
![Page 59: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/59.jpg)
Bootstrapping the app window.WishlistsApp = new AIR.Apps.Wishlists({ “listings”: [...], “wishlists”: [...], ... });
WishlistsApp.get(‘wishlists’)
=> [Object, Object, Object, ...]
Thursday, September 13, 12
![Page 60: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/60.jpg)
Bootstrapping the app
Thursday, September 13, 12
![Page 61: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/61.jpg)
• Each action bootstraps whatever data needed on first pageload
Bootstrapping the app
Thursday, September 13, 12
![Page 62: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/62.jpg)
• Each action bootstraps whatever data needed on first pageload
• Subsequent data is requested on-demand
Bootstrapping the app
Thursday, September 13, 12
![Page 63: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/63.jpg)
App Initializeclass AIR.Apps.Wishlists extends Backbone.Model
initialize: => @wishlists = new AIR.Collections.Wishlists @get('wishlists') @listings = new AIR.Collections.Listings @get('listings') ...
new AIR.Routers.Wishlists({app: @})
Thursday, September 13, 12
![Page 64: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/64.jpg)
App Initializeclass AIR.Apps.Wishlists extends Backbone.Model
initialize: => @wishlists = new AIR.Collections.Wishlists @get('wishlists') @listings = new AIR.Collections.Listings @get('listings') ...
new AIR.Routers.Wishlists({app: @})
WishlistsApp.wishlists=> Wishlists _byCid: Object _byId: Object length: 11 models: Array[11] __proto__: ctor
Thursday, September 13, 12
![Page 65: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/65.jpg)
Backbone Router
Thursday, September 13, 12
![Page 66: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/66.jpg)
Backbone Router• Translates URL changes to method
calls
Thursday, September 13, 12
![Page 67: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/67.jpg)
Backbone Router• Translates URL changes to method
calls
• Source of global app state
Thursday, September 13, 12
![Page 68: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/68.jpg)
Backbone Router• Translates URL changes to method
calls
• Source of global app state
• Keep state out of views
Thursday, September 13, 12
![Page 69: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/69.jpg)
Backbone Router• Translates URL changes to method
calls
• Source of global app state
• Keep state out of views
• Idempotent view rendering
Thursday, September 13, 12
![Page 70: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/70.jpg)
Backbone Routerclass AIR.Routers.Wishlists extends Backbone.Router routes: 'wishlists/:id' : 'show' 'wishlists/:id/edit' : 'edit'
...
show: (id) -> @app.fetchWishlist id, (model) => view = new AIR.Views.Wishlists.ShowView {@app, model} @updateContent(view)
Thursday, September 13, 12
![Page 71: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/71.jpg)
Backbone Routerclass AIR.Routers.Wishlists extends Backbone.Router routes: 'wishlists/:id' : 'show' 'wishlists/:id/edit' : 'edit'
...
show: (id) -> @app.fetchWishlist id, (model) => view = new AIR.Views.Wishlists.ShowView {@app, model} @updateContent(view)
Thursday, September 13, 12
![Page 72: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/72.jpg)
Backbone Routerclass AIR.Routers.Wishlists extends Backbone.Router routes: 'wishlists/:id' : 'show' 'wishlists/:id/edit' : 'edit'
...
show: (id) -> @app.fetchWishlist id, (model) => view = new AIR.Views.Wishlists.ShowView {@app, model} @updateContent(view)
Thursday, September 13, 12
![Page 73: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/73.jpg)
Backbone Routerclass AIR.Routers.Wishlists extends Backbone.Router routes: 'wishlists/:id' : 'show' 'wishlists/:id/edit' : 'edit'
...
show: (id) -> @app.fetchWishlist id, (model) => view = new AIR.Views.Wishlists.ShowView {@app, model} @updateContent(view)
Thursday, September 13, 12
![Page 74: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/74.jpg)
Data-on-demand
Thursday, September 13, 12
![Page 75: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/75.jpg)
Data-on-demand # AIR.Apps.Wishlists
fetchWishlist: (id, callback) -> model = @wishlists.get(id) if model? callback(model) else @appView.setLoading(true) @wishlists.fetchById id, (model) => @appView.setLoading(false) callback(model)
Thursday, September 13, 12
![Page 76: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/76.jpg)
Data-on-demand # AIR.Apps.Wishlists
fetchWishlist: (id, callback) -> model = @wishlists.get(id) if model? callback(model) else @appView.setLoading(true) @wishlists.fetchById id, (model) => @appView.setLoading(false) callback(model)
Thursday, September 13, 12
![Page 77: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/77.jpg)
Data-on-demand # AIR.Apps.Wishlists
fetchWishlist: (id, callback) -> model = @wishlists.get(id) if model? callback(model) else @appView.setLoading(true) @wishlists.fetchById id, (model) => @appView.setLoading(false) callback(model)
Thursday, September 13, 12
![Page 78: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/78.jpg)
Data-on-demand # AIR.Apps.Wishlists
fetchWishlist: (id, callback) -> model = @wishlists.get(id) if model? callback(model) else @appView.setLoading(true) @wishlists.fetchById id, (model) => @appView.setLoading(false) callback(model)
Thursday, September 13, 12
![Page 79: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/79.jpg)
Data-on-demand # AIR.Apps.Wishlists
fetchWishlist: (id, callback) -> model = @wishlists.get(id) if model? callback(model) else @appView.setLoading(true) @wishlists.fetchById id, (model) => @appView.setLoading(false) callback(model)
Thursday, September 13, 12
![Page 80: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/80.jpg)
Data-on-demand # AIR.Apps.Wishlists
fetchWishlist: (id, callback) -> model = @wishlists.get(id) if model? callback(model) else @appView.setLoading(true) @wishlists.fetchById id, (model) => @appView.setLoading(false) callback(model)
Thursday, September 13, 12
![Page 81: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/81.jpg)
api.airbnb.com
Thursday, September 13, 12
![Page 82: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/82.jpg)
api.airbnb.com• Used by iOS, Android, Mobile Web clients
Thursday, September 13, 12
![Page 83: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/83.jpg)
api.airbnb.com• Used by iOS, Android, Mobile Web clients
• No Cross-Domain XHR
Thursday, September 13, 12
![Page 84: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/84.jpg)
api.airbnb.com• Used by iOS, Android, Mobile Web clients
• No Cross-Domain XHR
• JSONP for GET; but no POST, PUT, DELETE
Thursday, September 13, 12
![Page 85: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/85.jpg)
api.airbnb.com• Used by iOS, Android, Mobile Web clients
• No Cross-Domain XHR
• JSONP for GET; but no POST, PUT, DELETE
• Added CORS support in API to allow requests coming from valid Airbnb domain (*.airbnb.com, *.airbnb.co.uk, *.airbnb.de...)
Thursday, September 13, 12
![Page 86: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/86.jpg)
Accessing API from Backbone
Airbnb.Api.getUrl(‘/v1/users/1234’)
Thursday, September 13, 12
![Page 87: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/87.jpg)
Accessing API from Backbone
Airbnb.Api.getUrl(‘/v1/users/1234’)
=> "https://api.airbnb.com/v1/users/1234?currency=USD&locale=en& key=...&oauth_token=..."
Thursday, September 13, 12
![Page 88: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/88.jpg)
Accessing API from Backbone
class AIR.Models.WishlistUser extends Backbone.Model jsonKey: 'user' apiPath: -> "/v1/users/#{@id}" ...
_.extend AIR.Models.WishlistUser.prototype, AIR.Mixins.ApiResource
Thursday, September 13, 12
![Page 89: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/89.jpg)
Accessing API from Backbone
AIR.Mixins.ApiResource = url: (options = {}) -> apiPath = options.apiPath || @apiPath if _.isFunction(apiPath)
apiPath = apiPath.call(@) Airbnb.Api.getUrl(apiPath)
sync: (method, model, options) -> options = _.defaults options, url: @url(options) Backbone.sync method, model, options
Thursday, September 13, 12
![Page 90: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/90.jpg)
Accessing API from Backbone
AIR.Mixins.ApiResource = url: (options = {}) -> apiPath = options.apiPath || @apiPath if _.isFunction(apiPath)
apiPath = apiPath.call(@) Airbnb.Api.getUrl(apiPath)
sync: (method, model, options) -> options = _.defaults options, url: @url(options) Backbone.sync method, model, options
Thursday, September 13, 12
![Page 91: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/91.jpg)
Accessing API from Backbone
AIR.Mixins.ApiResource = url: (options = {}) -> apiPath = options.apiPath || @apiPath if _.isFunction(apiPath)
apiPath = apiPath.call(@) Airbnb.Api.getUrl(apiPath)
sync: (method, model, options) -> options = _.defaults options, url: @url(options) Backbone.sync method, model, options
Thursday, September 13, 12
![Page 92: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/92.jpg)
Accessing API from Backbone
AIR.Mixins.ApiResource = url: (options = {}) -> apiPath = options.apiPath || @apiPath if _.isFunction(apiPath)
apiPath = apiPath.call(@) Airbnb.Api.getUrl(apiPath)
sync: (method, model, options) -> options = _.defaults options, url: @url(options) Backbone.sync method, model, options
Thursday, September 13, 12
![Page 93: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/93.jpg)
AIR.Views.BaseViewclass AIR.Views.BaseView extends Backbone.View
postInitialize: ->
postRender: ->
getRenderData: ->
cleanup: ->
...
Thursday, September 13, 12
![Page 94: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/94.jpg)
Beforeclass WishlistIndexView extends Backbone.View
template: 'wishlists/wishlist_index_view'
render: ->
@$el.html JST[@template](@model.toJSON())
@renderSomeThing()
@
renderSomeThing: -> ...
Thursday, September 13, 12
![Page 95: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/95.jpg)
Beforeclass WishlistIndexView extends Backbone.View
template: 'wishlists/wishlist_index_view'
render: ->
@$el.html JST[@template](@model.toJSON())
@renderSomeThing()
@
renderSomeThing: -> ...
Thursday, September 13, 12
![Page 96: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/96.jpg)
Beforeclass WishlistIndexView extends Backbone.View
template: 'wishlists/wishlist_index_view'
render: ->
@$el.html JST[@template](@model.toJSON())
@renderSomeThing()
@
renderSomeThing: -> ...
Thursday, September 13, 12
![Page 97: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/97.jpg)
Beforeclass WishlistIndexView extends Backbone.View
template: 'wishlists/wishlist_index_view'
render: ->
@$el.html JST[@template](@model.toJSON())
@renderSomeThing()
@
renderSomeThing: -> ...
Thursday, September 13, 12
![Page 98: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/98.jpg)
Beforeclass WishlistIndexView extends Backbone.View
template: 'wishlists/wishlist_index_view'
render: ->
@$el.html JST[@template](@model.toJSON())
@renderSomeThing()
@
renderSomeThing: -> ...
Thursday, September 13, 12
![Page 99: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/99.jpg)
Beforeclass WishlistIndexView extends Backbone.View
template: 'wishlists/wishlist_index_view'
render: ->
@$el.html JST[@template](@model.toJSON())
@renderSomeThing()
@
renderSomeThing: -> ...
Thursday, September 13, 12
![Page 100: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/100.jpg)
Afterclass WishlistIndexView extends AIR.Views.BaseView
template: 'wishlists/wishlist_index_view'
postRender: ->
@renderSomeThing()
renderSomeThing: -> ...
Thursday, September 13, 12
![Page 101: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/101.jpg)
Afterclass WishlistIndexView extends AIR.Views.BaseView
template: 'wishlists/wishlist_index_view'
postRender: ->
@renderSomeThing()
renderSomeThing: -> ...
Thursday, September 13, 12
![Page 102: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/102.jpg)
Afterclass WishlistIndexView extends AIR.Views.BaseView
template: 'wishlists/wishlist_index_view'
postRender: ->
@renderSomeThing()
renderSomeThing: -> ...
Thursday, September 13, 12
![Page 103: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/103.jpg)
Before, Part IIclass WishlistIndexView extends Backbone.View
...
render: ->
@$el.html JST[@template](@model.toJSON())
@
Thursday, September 13, 12
![Page 104: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/104.jpg)
Before, Part IIclass WishlistIndexView extends Backbone.View
...
render: ->
data = _.extend @model.toJSON(),
show_share_button: @options.show_share_button
@$el.html JST[@template](data)
@
Thursday, September 13, 12
![Page 105: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/105.jpg)
Before, Part IIclass WishlistIndexView extends Backbone.View
...
render: ->
@$el.html JST[@template](@getRenderData())
@
getRenderData: ->
_.extend @model.toJSON(),
show_share_button: @options.show_share_button
Thursday, September 13, 12
![Page 106: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/106.jpg)
After, Part IIclass WishlistIndexView extends AIR.Views.BaseView
...
getRenderData: ->
_.extend super,
show_share_button: @options.show_share_button
Thursday, September 13, 12
![Page 107: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/107.jpg)
After, Part IIclass WishlistIndexView extends AIR.Views.BaseView
...
getRenderData: ->
_.extend super,
show_share_button: @options.show_share_button
Thursday, September 13, 12
![Page 108: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/108.jpg)
cleanup()class AIR.Views.BaseView extends Backbone.View
...
cleanup: ->
@undelegateEvents()
@model?.off(null, null, @)
@remove()
Thursday, September 13, 12
![Page 109: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/109.jpg)
cleanup()class WishlistIndexView extends AIR.Views.BaseView
...
cleanup: ->
super
@someChildView.cleanup()
clearInterval(@interval)
Thursday, September 13, 12
![Page 110: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/110.jpg)
cleanup()
Backbone 0.9.2 adds new method: Backbone.View.prototype.dispose()
Thursday, September 13, 12
![Page 111: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/111.jpg)
Modular, DRY views
Thursday, September 13, 12
![Page 112: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/112.jpg)
Modular, DRY views
• Re-usable bits of markup and behavior
Thursday, September 13, 12
![Page 113: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/113.jpg)
Modular, DRY views
• (screenshot)
Thursday, September 13, 12
![Page 114: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/114.jpg)
Modular, DRY views
• (screenshot)
Thursday, September 13, 12
![Page 115: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/115.jpg)
Subview initializationclass EditView extends AIR.Views.BaseView
...
postRender: ->
@renderPrivacyDropdown()
renderPrivacyDropdown: ->
view = new AIR.Views.Shared.PrivacyDropdownView
'private': @model.get('private')
@$('data-privacy-dropdown').replaceWith view.render().el
Thursday, September 13, 12
![Page 116: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/116.jpg)
Subview initializationclass EditView extends AIR.Views.BaseView
...
postRender: ->
@renderPrivacyDropdown()
renderPrivacyDropdown: ->
view = new AIR.Views.Shared.PrivacyDropdownView
'private': @model.get('private')
@$('data-privacy-dropdown').replaceWith view.render().el
Thursday, September 13, 12
![Page 117: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/117.jpg)
Subview initializationclass EditView extends AIR.Views.BaseView
...
postRender: ->
@renderPrivacyDropdown()
renderPrivacyDropdown: ->
view = new AIR.Views.Shared.PrivacyDropdownView
'private': @model.get('private')
@$('data-privacy-dropdown').replaceWith view.render().el
Thursday, September 13, 12
![Page 118: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/118.jpg)
Subview initializationclass EditView extends AIR.Views.BaseView
...
postRender: ->
@renderPrivacyDropdown()
renderPrivacyDropdown: ->
view = new AIR.Views.Shared.PrivacyDropdownView
'private': @model.get('private')
@$('data-privacy-dropdown').replaceWith view.render().el
Thursday, September 13, 12
![Page 119: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/119.jpg)
Subview initializationclass EditView extends AIR.Views.BaseView
...
postRender: ->
@renderPrivacyDropdown()
renderPrivacyDropdown: ->
view = new AIR.Views.Shared.PrivacyDropdownView
'private': @model.get('private')
view.on ‘private-changed’, (isPrivate) =>
# do something
console.log(isPrivate)
@$('data-privacy-dropdown').replaceWith view.render().el
Thursday, September 13, 12
![Page 120: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/120.jpg)
What goes into a view?
Thursday, September 13, 12
![Page 121: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/121.jpg)
What goes into a view?
• app/assets/coffeescripts/views/shared/privacy_dropdown_view.coffee
Thursday, September 13, 12
![Page 122: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/122.jpg)
What goes into a view?
• app/assets/coffeescripts/views/shared/privacy_dropdown_view.coffee
• app/assets/templates/views/shared/privacy_dropdown_view.hbs
Thursday, September 13, 12
![Page 123: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/123.jpg)
What goes into a view?
• app/assets/coffeescripts/views/shared/privacy_dropdown_view.coffee
• app/assets/templates/views/shared/privacy_dropdown_view.hbs
• app/assets/stylesheets/partials/_ privacy_dropdown_view.scss
Thursday, September 13, 12
![Page 124: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/124.jpg)
What goes into a view?
• app/assets/coffeescripts/views/shared/privacy_dropdown_view.coffee
• app/assets/templates/views/shared/privacy_dropdown_view.hbs
• app/assets/stylesheets/partials/_ privacy_dropdown_view.scss
• lib/phrase_bundles/privacy_dropdown_view.rb
Thursday, September 13, 12
![Page 125: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/125.jpg)
Rdio’s Backbone-based View Component FrameworkJustin Tulloss, @justin_tullosshttp://www.youtube.com/watch?v=TB-l2nF67iU
Thursday, September 13, 12
![Page 126: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/126.jpg)
Modular, DRY views
• (screenshot)
Thursday, September 13, 12
![Page 127: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/127.jpg)
Infinity.js
• (screenshot)
http://airbnb.github.com/infinity
Thursday, September 13, 12
![Page 128: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/128.jpg)
I18n.js
Thursday, September 13, 12
![Page 129: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/129.jpg)
I18n.js
• 192 countries
Thursday, September 13, 12
![Page 130: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/130.jpg)
I18n.js
• 192 countries
• 31 locales
Thursday, September 13, 12
![Page 131: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/131.jpg)
I18n.js
• 192 countries
• 31 locales
• Client-slide translation library
Thursday, September 13, 12
![Page 132: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/132.jpg)
I18n.t()I18n.t('edit_wish_list');
Thursday, September 13, 12
![Page 133: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/133.jpg)
I18n.t()I18n.t('edit_wish_list');
"Edit Wish List"
Thursday, September 13, 12
![Page 134: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/134.jpg)
I18n.t()I18n.t('edit_wish_list');
<h1>{{t "edit_wish_list"}}</h1>
"Edit Wish List"
Thursday, September 13, 12
![Page 135: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/135.jpg)
I18n.t()I18n.t('edit_wish_list');
<h1>Edit Wish List</h1>
<h1>{{t "edit_wish_list"}}</h1>
"Edit Wish List"
Thursday, September 13, 12
![Page 136: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/136.jpg)
InterpolationI18n.t('owners_wish_list', {name: name});
Thursday, September 13, 12
![Page 137: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/137.jpg)
InterpolationI18n.t('owners_wish_list', {name: name});
"Spike’s Wish List"
Thursday, September 13, 12
![Page 138: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/138.jpg)
Interpolation
<h1>{{t "owners_wish_list" name=name}}</h1>
I18n.t('owners_wish_list', {name: name});
"Spike’s Wish List"
Thursday, September 13, 12
![Page 139: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/139.jpg)
Interpolation
<h1>{{t "owners_wish_list" name=name}}</h1>
<h1>Spike’s Wish List</h1>
I18n.t('owners_wish_list', {name: name});
"Spike’s Wish List"
Thursday, September 13, 12
![Page 140: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/140.jpg)
I18n.extend()
I18n.extend({ "edit_wish_list": "Edit Wish List", "owners_wish_list": "%{name}’s Wish List", ...});
Thursday, September 13, 12
![Page 141: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/141.jpg)
I18n.pluralize()I18n.pluralize("Listing", listings);
Thursday, September 13, 12
![Page 142: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/142.jpg)
I18n.pluralize()I18n.pluralize("Listing", listings);
3 Listings
Thursday, September 13, 12
![Page 143: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/143.jpg)
I18n.pluralize()
<span>{{t_pluralize "Listing" count=listings}}</span>
I18n.pluralize("Listing", listings);
3 Listings
Thursday, September 13, 12
![Page 144: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/144.jpg)
I18n.pluralize()
<span>{{t_pluralize "Listing" count=listings}}</span>
<span>3 Listings</span>
I18n.pluralize("Listing", listings);
3 Listings
Thursday, September 13, 12
![Page 145: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/145.jpg)
pluralize() just calls t(){
"pluralize.Listing.zero": "%{count} Listings",
"pluralize.Listing.one": "%{count} Listing",
"pluralize.Listing.many": "%{count} Listings"
}
Thursday, September 13, 12
![Page 146: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/146.jpg)
PhraseBundle
Thursday, September 13, 12
![Page 147: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/147.jpg)
PhraseBundle• Composable bundles of I18n phrases
Thursday, September 13, 12
![Page 148: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/148.jpg)
PhraseBundle• Composable bundles of I18n phrases
• Keep phrases DRY
Thursday, September 13, 12
![Page 149: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/149.jpg)
PhraseBundle• Composable bundles of I18n phrases
• Keep phrases DRY
• Separation of concerns: treat phrases as data source
Thursday, September 13, 12
![Page 150: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/150.jpg)
PhraseBundleI18n.extend(<%= { 'map_view' => t('wishlists.Map View', :default => 'Map View'), 'list_view' => t('wishlists.List View', :default => 'List View'), ...}.to_json.html_safe %>);
Thursday, September 13, 12
![Page 151: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/151.jpg)
PhraseBundleI18n.extend(<%= { 'map_view' => t('wishlists.Map View', :default => 'Map View'), 'list_view' => t('wishlists.List View', :default => 'List View'), ...}.to_json.html_safe %>);
I18n.extend(<%= PhraseBundles::Wishlists.new.to_json.html_safe %>);
Thursday, September 13, 12
![Page 152: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/152.jpg)
module PhraseBundles class Wishlists < PhraseBundle includes :privacy_dropdown, :share_dropdown, :wishlists_modal def phrases { 'map_view' => t('wishlists.Map View', :default => 'Map View'), 'list_view' => t('wishlists.List View', :default => 'List View'), ... } end endend
PhraseBundle
Thursday, September 13, 12
![Page 153: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/153.jpg)
module PhraseBundles class Wishlists < PhraseBundle includes :privacy_dropdown, :share_dropdown, :wishlists_modal def phrases { 'map_view' => t('wishlists.Map View', :default => 'Map View'), 'list_view' => t('wishlists.List View', :default => 'List View'), ... } end endend
PhraseBundle
Thursday, September 13, 12
![Page 154: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/154.jpg)
module PhraseBundles class Wishlists < PhraseBundle includes :privacy_dropdown, :share_dropdown, :wishlists_modal def phrases { 'map_view' => t('wishlists.Map View', :default => 'Map View'), 'list_view' => t('wishlists.List View', :default => 'List View'), ... } end endend
PhraseBundle
Thursday, September 13, 12
![Page 155: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/155.jpg)
CDN Asset URLs• Image paths need to go through Sprockets
Thursday, September 13, 12
![Page 156: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/156.jpg)
CDN Asset URLs
https://localhost.airbnb.com:3001/static/icons/facebook.png
• Image paths need to go through Sprockets
Development:
Thursday, September 13, 12
![Page 157: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/157.jpg)
CDN Asset URLs
https://localhost.airbnb.com:3001/static/icons/facebook.png
https://a0.muscache.com/airbnb/static/icons/facebook-e04e8c0c43e40ff7a277a3a7a734ed52.png
• Image paths need to go through Sprockets
Development:
Production:
Thursday, September 13, 12
![Page 158: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/158.jpg)
CDN Asset URLs
Thursday, September 13, 12
![Page 159: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/159.jpg)
CDN Asset URLswindow.ImagePaths = <%= map_image_paths([ 'icons/facebook.png', ...]).to_json.html_safe %>;
Thursday, September 13, 12
![Page 160: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/160.jpg)
CDN Asset URLswindow.ImagePaths = <%= map_image_paths([ 'icons/facebook.png', ...]).to_json.html_safe %>;
ImagePaths['icons/facebook.png'];=> “https://a0.muscache.com/airbnb
/static/icons/facebook-e04e8c0c43e40ff7a277a3a7a734ed52.png”
Thursday, September 13, 12
![Page 161: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/161.jpg)
CDN Asset URLswindow.ImagePaths = <%= map_image_paths([ 'icons/facebook.png', ...]).to_json.html_safe %>;
<img src=”{{image_path “icons/facebook.png”}}” ...>
ImagePaths['icons/facebook.png'];=> “https://a0.muscache.com/airbnb
/static/icons/facebook-e04e8c0c43e40ff7a277a3a7a734ed52.png”
Thursday, September 13, 12
![Page 162: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/162.jpg)
FutureIn pursuit of the Holy Grail
Thursday, September 13, 12
![Page 163: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/163.jpg)
Backbone.js is just a stopgap
Thursday, September 13, 12
![Page 164: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/164.jpg)
Backbone.js is just a stopgap
• Backbone.View is DOM-centric
Thursday, September 13, 12
![Page 165: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/165.jpg)
Backbone.js is just a stopgap
• Backbone.View is DOM-centric
• Backbone.History is window-centric
Thursday, September 13, 12
![Page 166: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/166.jpg)
Backbone.js is just a stopgap
• Backbone.View is DOM-centric
• Backbone.History is window-centric
• Backbone.Model and Backbone.Collection are more portable (with override of Backbone.sync)
Thursday, September 13, 12
![Page 167: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/167.jpg)
It’s a great time to be a JavaScript hacker.
Thursday, September 13, 12
![Page 168: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/168.jpg)
It’s a great time to be a JavaScript hacker.
But not a great time to build modern, plug-and-play web apps.
Thursday, September 13, 12
![Page 169: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/169.jpg)
Testing the Node.js Waters
Thursday, September 13, 12
![Page 170: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/170.jpg)
Testing the Node.js WatersWe are refactoring m.airbnb.com with a Node backend instead of Rails.
Thursday, September 13, 12
![Page 171: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/171.jpg)
Testing the Node.js WatersWe are refactoring m.airbnb.com with a Node backend instead of Rails.
Primary goal is to learn how to productionize a Node app.
Thursday, September 13, 12
![Page 172: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/172.jpg)
Testing the Node.js WatersWe are refactoring m.airbnb.com with a Node backend instead of Rails.
Primary goal is to learn how to productionize a Node app.
Secondary goal is to prototype a new way of building web apps.
Thursday, September 13, 12
![Page 173: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/173.jpg)
Testing the Node.js Waters
Thursday, September 13, 12
![Page 174: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/174.jpg)
Node Frameworks
Thursday, September 13, 12
![Page 175: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/175.jpg)
Node FrameworksGeddy, TowerRails-inspired. Not utilizing Node’s strengths.
Thursday, September 13, 12
![Page 176: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/176.jpg)
Node FrameworksGeddy, TowerRails-inspired. Not utilizing Node’s strengths.
SocketStreamModular, real-time, but optimized for The Easy Way.
Thursday, September 13, 12
![Page 177: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/177.jpg)
Node FrameworksGeddy, TowerRails-inspired. Not utilizing Node’s strengths.
SocketStreamModular, real-time, but optimized for The Easy Way.
MeteorSolves for The Hard Way, but all-or-nothing. Alpha.
Thursday, September 13, 12
![Page 178: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/178.jpg)
Node FrameworksGeddy, TowerRails-inspired. Not utilizing Node’s strengths.
SocketStreamModular, real-time, but optimized for The Easy Way.
MeteorSolves for The Hard Way, but all-or-nothing. Alpha.
DerbySolves for The Hard Way, but not very modular. Alpha.
Thursday, September 13, 12
![Page 179: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/179.jpg)
Node Frameworks
Solves for The Hard Way, but not very modular. Alpha.Derby
Active authors.Active mailing list.Small, if messy, codebase.
Thursday, September 13, 12
![Page 180: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/180.jpg)
Node Frameworks
Solves for The Hard Way, but not very modular. Alpha.
DerbyActive authors.Active mailing list.Small, if messy, codebase.
Thursday, September 13, 12
![Page 181: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/181.jpg)
Node Frameworks
Solves for The Hard Way, but not very modular. Alpha.
DerbyActive authors.Active mailing list.Small, if messy, codebase.
Thursday, September 13, 12
![Page 182: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/182.jpg)
Other ResourcesSingle Page App Book, by Mikito Takadahttp://singlepageappbook.com/
view.json, by Mikito Takadahttp://mixu.net/view.json/
Building The Next SoundCloudhttp://backstage.soundcloud.com/2012/06/building-the-next-soundcloud/
Sean McBride, Bridging the Client-Server Dividehttp://seanmcb.com/client-server-divide/
NodeUp Podcasthttp://nodeup.com/
Thursday, September 13, 12
![Page 183: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/183.jpg)
res.end()
Thursday, September 13, 12
![Page 184: Building a Single-Page App: Backbone, Node.js, and Beyond](https://reader034.vdocuments.mx/reader034/viewer/2022042623/54b777254a7959df648b469d/html5/thumbnails/184.jpg)
Let’s chat@spikebrehm
Thursday, September 13, 12