Upload
spike-brehm
View
2.246
Download
3
Tags:
Embed Size (px)
DESCRIPTION
The presentation @spikebrehm gave for the SF Node.js meetup group April 30 2013. http://www.meetup.com/Node-js-Serverside-Javascripters-Club-SF/events/114998792/
Citation preview
Rendr: Bacbone.js on the client and serer
Spike Brehm@spikebrehm
SF Node.js MeetupApril 30, 2013
2008
2013
Exciting times in the world of web apps.
<your framework here>
Client-side MVC
Client
Serer
Your app API
+
Poor SEO; not crawlable
Performance hit to download and parse JS
Duplicated application logic
Context switching
Client-side MVCDownloadskeleton
HTML
Fetch data from API
User sees content
Download JavaScript
Evaluate JavaScript
Exacerbated on mobile: high latency, low bandwidth
It’s still a PITA to build fast, maintainable rich-client apps.
Wat if our app could run on the client and the serer?
Client + serer MVC
Client
Serer
Your app API
Provides SEO
Initial pageload is drastically faster
Consolidated application logic
Evaluate JavaScript
Client + serer MVCDownload
fullHTML
User sees content
Download JavaScript
Has anyone already done this?
Meteor: client/serer, but no serer-side rendering; owns data layer
Derby: client+serer rendering, but owns data layer
Mojito: client+serer rendering, but full stack, and... I.
Okay... how hard can it be?
+
+
+
Rendr.
JavaScript MVC on client & server
Backbone & Handlebars
BaseView, BaseModel, BaseCollection, BaseApp, ClientRouter, ServerRouter...
Express middleware
Minimal glue between client & server
Wat it is.
Batteries-included web framework
Finished
Wat it ain’t.
Write application logic agnostic to environment.
Library, not a framework.
Minimize if (server) {...} else {...}.
Hide complexity in library.
Talk to RESTful API.
No server-side DOM.
Simple Express middleware.
Design goals.
Classes:
- BaseApp < Backbone.Model- BaseModel < Backbone.Model- BaseCollection < Backbone.Collection- BaseView < Backbone.View- AppView < BaseView
- ClientRouter < BaseRouter- ServerRouter < BaseRouter
- ModelStore < MemoryStore- CollectionStore < MemoryStore
- Fetcher
|- client/|- shared/|- server/
Rendr directory structure
Sent to client}
|- app/|- public/|- server/
App directory structure
|- app/|--- collections/|--- controllers/|--- models/|--- templates/|--- views/|--- app.js|--- router.js|--- routes.js|- public/|- server/
App directory structure
Entire app dir gets sent to client}
var User = require(‘app/models/user’);var BaseView = require(‘rendr/shared/base/view’);
CommonJS using Stitch
On the server:
On the client:var User = require(‘app/models/user’);var BaseView = require(‘rendr/shared/base/view’);
Demo
github.com/airbnb/rendr-app-template
Render lifecycle, serer.
• On server startup, parse routes file and mount as Express routes
• GET /users/1337• Router matches "/users/:id" to "users#show" with
params = {"id": 1337}• Router finds controller:
require("app/controllers/users_controller")• Router executes show action with params = {"id": 1337}• The show action says to fetch User#1337 and use
UsersShowView view class• Router instantiates new UsersShowView with data• Router calls view.getHtml()• Hands HTML to Express, which decorates with layout
and serves response
Render lifecycle, client.
• On page load, Router parses routes file and mounts Backbone routes
• pushState /users/1337• Router matches "/users/:id" to "users#show" with
params = {"id": 1337}• Router finds controller:
require("app/controllers/users_controller")• Router executes show action with params = {"id": 1337}• The show action says to fetch User#1337 and use
UsersShowView view class• Router instantiates new UsersShowView with data• Router calls view.render()• Insert into DOM
• On page load, Router parses routes file and mounts Backbone routes
• pushState /users/1337• Router matches "/users/:id" to "users#show" with
params = {"id": 1337}• Router finds controller:
require("app/controllers/users_controller")• Router executes show action with params = {"id": 1337}• The show action says to fetch User#1337 and use
UsersShowView view class• Router instantiates new UsersShowView with data• Router calls view.render()• Insert into DOM
• On page load, Router parses routes file and mounts Backbone routes
• pushState /users/1337• Router matches "/users/:id" to "users#show" with
params = {"id": 1337}• Router finds controller:
require("app/controllers/users_controller")• Router executes show action with params = {"id": 1337}• The show action says to fetch User#1337 and use
UsersShowView view class• Router instantiates new UsersShowView with data• Router calls view.render()• Insert into DOM
v0.4.0: CoffeeScript -> JavaScript
Almost done abstracting out Handlebars, supporting other templating languages
Example app with session handling
Recent developments.
Share routing logic between client & server.
Lazy load views, templates, etc as needed.
Break down into smaller modules.
Much more...
TODO.
Find the right set of primitives and abstractions for isomorphic JavaScript apps
Catalyze an isomorphic JavaScript movement within the community
Catalog the various approaches
Project goals.
Hack with us.
github.com/airbnb/rendr
@rendrjs@AirbnbNerds@spikebrehm
Thanks!