Post on 15-Jan-2015
description
HtMl5 eXpErTiSe aT yOuR sErViCe
LaUrI SvAn @lAuRiSvAn Sc5 OnLiNe @sC5
SuRvIvInG RoBoTs aNd OlD BrOwSeRs bY SeRvEr-sIdE BaCkBoNe"
HeLp! My SiNgLe PaGe ApP FaIlS fOr RoBoTs!
WhY dEsIgN yOuR ApP fOr 1% oR 0.1% oF YoUr tRaFfIc?
UsE a PrOxY fOr LeGaCy BrOwSeRs Browser
Browser interfaces
Plain HTML
Full app
Server API
App Proxy
WhAt Do I GaIn? • Solve the Robot problem – remove double code paths • Speed up time to first render – bootstrap your DOM • Potentially solve the “legacy browser” problem • Ease your test automation – mocking your API/App
WhAt DoEs iT TaKe tO AcHiEvE?
• JavaScript support (node.js) • Shared module loader (Require.js / Browserify) • Some way to emulate/abstract out DOM • Some shims for Browser APIs (XHR, localStorage etc…) • Some way to tell your app has completed rendering
QuEsTs FoR tHe HoLy GrAiL ReViSiTeD
• Some partial layering model • App touches the browser APIs
through all the layers • Everything needs server-side
shims!
GrAiLs: WhAt yOuR ApP MiGhT LoOk LiKe
Runs on both as-isCompatibility
LayerPlatform Specific
Application Logic & Templates
Backbone
jQuery
Browser API
JavaScript Runtime
GrAiLs: PrOxY BrOwSeR (PhAnToM.Js)
• Full WebKit implementation on server-side
• Runs on its own process/server
• Context sharing with Phantom.js process is tricky
• Chromium Embedded Framework & Node.js would even better?
Browser
Reverse Proxy
App Server Proxy Browser
smartclients
dumbclients
• Share the templates on client and server
• Separate codebases for compositing the page fragments
• Simple to understand • Double code paths: Double
testing, maintenance etc.
GrAiLs: TeMpLaTe ShArInG (tHe nOrMaL wAy)
Runs on both as-isCompatibility
LayerPlatform Specific
Application Logic
Backbone
jQuery
Browser API
JavaScript Runtime
Server Logic
Templates
Any Runtime
Data Representation
• Full app frameworks that hide the DOM
• Hide client/server messaging (socket.io etc.)
• Meteor still uses PhantomJS to render for robots?
• Lock-in to a certain development model
• Lock-in to a certain backend
GrAiLs: ShArEd ClIeNt-sErVeR Fw (DeRbY, MeTeOr)
Application Logic & Templates
Custom Framework
JavaScript Runtime
Runs on both as-isCompatibility
LayerPlatform Specific
• JSDOM - Full JavaScript DOM implementation
• How about the other APIs? • Browser/HTML5 APIs is huge! • Slow to emulate
GrAiLs: SeRvEr-sIdE DoM (JsDoM)
Runs on both as-isCompatibility
LayerPlatform Specific
Application Logic & Templates
Backbone
jQuery
Browser API Subset
JavaScript Runtime
• Use jQuery for compatibility • Hide the DOM below
• Limited adaptation problem • Potentially faster • Changes to Backbone needed
GrAiLs: SeRvEr-sIdE jQuErY (ChEeRiO)
Runs on both as-isCompatibility
LayerPlatform Specific
Application Logic & Templates
Backbone
jQuery / Cheerio
JavaScript Runtime
• Backbone, but abstract out all DOM manipulation from view manipulation
• AirBNB - Concatenate templates on server
• No jQuery, no DOM access • Is it the same anymore?
GrAiLs: AbStRaCt oUt DoM (AiRbNb / ReNdR)
Runs on both as-isCompatibility
LayerPlatform Specific
Application Logic & Templates
Backbone
Adaptation Layer
JavaScript Runtime
GrAiLs: CoMpArIsOn Shared Client-‐Server FW
Template Sharing
JSDOM Cheerio
Your Typical App
DOM Abstracted out
Runs on both as-isCompatibility
LayerPlatform Specific
Application Logic & Templates
Backbone
jQuery
Browser API
JavaScript Runtime
Application Logic & Templates
Custom Framework
JavaScript Runtime
Application Logic
Backbone
jQuery
Browser API
JavaScript Runtime
Server Logic
Templates
Any Runtime
Data Representation
Application Logic & Templates
Backbone
jQuery
Browser API Subset
JavaScript Runtime
Application Logic & Templates
Backbone
Adaptation Layer
JavaScript Runtime
Application Logic & Templates
Backbone
jQuery / Cheerio
JavaScript Runtime
AlMoSt aLl oF oUr aPpS aRe BaCkBoNe & JqUeRy YoU cAn’t tEaCh oLd dOg nEw tRiCkS
BaCkBoNe-SeRvErSiDe – oUr DeSiGn PrInCiPlEs
• We do not need to be a full browser • We cannot expect the world to change our way • API compatibility is our friend
• Make it a polyfill, not a library or framework • Do not assume anything else than Backbone • Retain API compatibility, hide the dirty tricks if possible • Retain the possibility to use 3rd party JavaScript libs • Keep app specific changes to minimum
InTrOdUcInG BaCkBoNe-SeRvErSiDe • Run the same Backbone SPA on both
client and server with minimal extra conventions
• Removes Backbone DOM depencies • Cheerio jQuery subset for DOM
manipulation • Polyfills for Cheerio (events, ajax)
Things you may need to change in your app: • Stick to a subset of jQuery (Cheerio) • Use a dependency manager that you can
run on both ends (AMD/RequireJS, CommonJS/Browserify)
• Implement a messaging mechanism between your node.js server and your app
Application
Backbone
jQuery / Cheerio
Browser / Adaptation Layer
JavaScript Runtime
SeRvEr-sIdE BaCkBoNe RePlAcEmEnTs
• The classes you typically use will run as-is
• The classes that touch the DOM underneath need changes
We stub out/replace a few things • jQuery: Cheerio and its fake DOM • Ajax: Replace jQuery.ajax with a 3rd
party node.js module • History: Trim away DOM specifics
(window.navigator.location etc.)
Runs on both as-isCompatibility
LayerPlatform Specific
Model
Collection
View
sync
Router
Ajax History
jQuery
One way on how to handle the problem • Use Backbone events for
messaging • Single point of control
(App Singleton/Router) • All relevant objects have an
observable state
WhEn ArE We ReAdY tO SeNd tHe PaGe BaCk?
Backbone App
Router
Model View
Server API
fetch models
handle route
serve JSON
notify
pass the results
Browser / Server
parse path / pushState
Inject to DOM
notify
direct call
event
Legend:
render
verify all states
FeAtUrE dEtEcTiOn – A MuSt HaVe?
• Require.js is hard to get right on the both ends • Conditional switches between jQuery and Cheerio needed • Some client-slide libraries just won’t load
• Typical applications use DOM and Browser APIs directly • Typical 3rd party libraries use DOM & Browser APIs
extensively
à You will benefit from a feature detection library
DeMo TiMe
BaCkBoNe-SeRvErSiDe – WoRk iN PrOgReSs
• It is still experimental, but already demonstrable • Contributions wanted at our GitHub at
SC5/backbone-serverside • An article in Mozilla Hacks just got out • Some of the near-term work involves
• Handling feature detection (analytics, DOM events) • Cross-request user state management (localStorage adapters?) • Concurrency handling (currently we have single, shared DOM) • Samples on robot & browser detection (express-device)
QuEsTiOnS?
HtMl5 eXpErTiSe aT yOuR sErViCe
LaUrI SvAn
LeT’s SoLvE tHe CrAwLaBiLiTy PrObLeM!
Software Architect, SC5 Online Ltd https://github.com/laurisvan @laurisvan