Building Reactive, Realtime AppsWithout Writing JavaScript
Bryan Powell @bryanp
All Things Open 2015
The web should not be single-page.
We need a better way to build the web.
Collaboration
Content
Progressive enhancement is necessary when content has priority.
Sorry, web standards will win.
But isomorphic JavaScript!
Server Rendered w/ Real-Time Layer
Keep Business Logic on Server
(real-time as progressive enhancement)
(write no JavaScript)
WAT.
Example Time!!!Disclaimer: everything you’re about to see
works and is available now on GitHub.
<div data-scope="stats"> <span data-prop="active"> 1 </span>
<span data-prop="total"> 2 </span> </div>
<div data-scope="stats"> <span data-prop="active"> 1 </span>
<span data-prop="total"> 2 </span> </div>
<div data-scope="stats"> <span data-prop="active"> 1 </span>
<span data-prop="total"> 2 </span> </div>
<div data-scope="stats"> <span data-prop="active"> 1 </span>
<span data-prop="total"> 2 </span> </div>
<div data-scope="stats"> <span data-prop="active"> 1 </span>
<span data-prop="total"> 2 </span> </div>
<div data-scope="stats"> <span data-prop="active"> 1 </span>
<span data-prop="total"> 2 </span> </div>
{ active: 3,
total: 42
}
<
<div data-scope="stats"> <span data-prop="active"> 1 </span>
<span data-prop="total"> 2 </span> </div>
{ active: 3,
total: 42
}
view.scope(:stats).apply(data)
<
<div data-scope="stats"> <span data-prop="active"> 1 </span>
<span data-prop="total"> 2 </span> </div>
{ active: 3,
total: 42
}
view.scope(:stats).apply(data)
<
<div data-scope="stats"> <span data-prop="active"> 1 </span>
<span data-prop="total"> 2 </span> </div>
{ active: 3,
total: 42
}
view.scope(:stats).apply(data)
<
<div data-scope="stats"> <span data-prop="active"> 3 </span>
<span data-prop="total"> 42 </span> </div>
{ active: 3,
total: 42
}
view.scope(:stats).apply(data)
<
<div data-scope="stats"> <span data-prop="active"> 3 </span>
<span data-prop="total"> 42 </span> </div>
{ active: 3,
total: 42
}
view.scope(:stats).apply(data)
<
Non-Destructive Rendering
get '/' do view.scope(:stats).render(:display, with: data(:stats).all ).subscribe end
get '/' do view.scope(:stats).render(:display, with: data(:stats).all ).subscribe end
get '/' do view.scope(:stats).render(:display, with: data(:stats).all ).subscribe end
get '/' do view.scope(:stats).render(:display, with: data(:stats).all ).subscribe end
get '/' do view.scope(:stats).render(:display, with: data(:stats).all ).subscribe end
get '/' do view.scope(:stats).render(:display, with: data(:stats).all ).subscribe end
server
>
<
websocket
JavaScript Library
state change server> transformations>
JavaScript Library
>
<<
[ "apply", [ { "total": "4", "active": "2" } ] ] websocket
View Transformation Protocol
View Transformation ProtocolBusiness logic is written once, stays on the server.
View Transformation ProtocolFaster since we render only the changes.
View Transformation ProtocolThe real-time web as progressive enhancement.
mutable
server> transformations> >
<<
state change
websocket
Simple State Propagation
Simple State PropagationAll changes in view state come from the server.
Simple State PropagationServer contains the ultimate truth, client follows.
Simple State PropagationPrioritizes user trust over performance.
pakyow.org
pakyow.org
metabahn.com
@bryanp
bryanp/realtime-talk