Rendr: SF Node.js Meetup presentation April 30, 2013

Preview:

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!