SuRvIvInG RoBoTs aNd OlD BrOwSeRs bY
       SeRvEr-sIdE BaCkBoNe"
                                                    LaUrI SvAn @lAuRiSvAn
                                                    Sc5 OnLiNe @sC5




             HtMl5 eXpErTiSe aT yOuR sErViCe 	
  
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	
  




 Server	
  API	
     Full	
  
                     app	
  
                                          Plain	
  HTML	
  




                                     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
GrAiLs: WhAt yOuR ApP MiGhT LoOk LiKe
                                           •  Some partial layering model
Application Logic & Templates
                                           •  App touches the browser APIs
  Backbone
                                              through all the layers
       jQuery

        Browser API
                                           •  Everything needs server-side
     JavaScript Runtime
                                              shims!



                      Runs on both as-is
                        Compatibility
                            Layer
                      Platform Specific
GrAiLs: PrOxY BrOwSeR (PhAnToM.Js)
             Browser                   •  Full WebKit implementation on
                                          server-side
                                       •  Runs on its own process/server
          Reverse Proxy

smart
clients
                            dumb
                            clients    •  Context sharing with Phantom.js
App Server             Proxy Browser
                                          process is tricky
                                       •  Chromium Embedded Framework
                                          & Node.js would even better?
GrAiLs: TeMpLaTe ShArInG (tHe nOrMaL wAy)
                Templates                        •  Share the templates on client
            Data Representation                     and server
Application Logic        Server Logic            •  Separate codebases for
Backbone                                            compositing the page fragments
   jQuery

  Browser API                                    •  Simple to understand
   JavaScript
    Runtime
                         Any Runtime             •  Double code paths: Double
                                                    testing, maintenance etc.
                            Runs on both as-is
                              Compatibility
                                  Layer
                            Platform Specific
GrAiLs: ShArEd ClIeNt-sErVeR Fw (DeRbY, MeTeOr)

                                          •  Full app frameworks that hide
Application Logic & Templates
                                             the DOM
     Custom Framework
                                          •  Hide client/server messaging
                                             (socket.io etc.)
                                          •  Meteor still uses PhantomJS to
     JavaScript Runtime
                                             render for robots?
                                          •  Lock-in to a certain
                                             development model
                     Runs on both as-is
                                          •  Lock-in to a certain backend
                        Compatibility
                            Layer
                      Platform Specific
GrAiLs: SeRvEr-sIdE DoM (JsDoM)
                                          •  JSDOM - Full JavaScript DOM
Application Logic & Templates
                                             implementation
  Backbone
                                          •  How about the other APIs?
       jQuery
                                          •  Browser/HTML5 APIs is huge!
    Browser API Subset
                                          •  Slow to emulate
     JavaScript Runtime




                     Runs on both as-is
                        Compatibility
                            Layer
                      Platform Specific
GrAiLs: SeRvEr-sIdE jQuErY (ChEeRiO)
                                            •  Use jQuery for compatibility
Application Logic & Templates

  Backbone
                                            •  Hide the DOM below
      jQuery / Cheerio

                                            •  Limited adaptation problem
     JavaScript Runtime                     •  Potentially faster
                                            •  Changes to Backbone needed


                     Runs on both as-is
                           Compatibility
                               Layer
                         Platform Specific
GrAiLs: AbStRaCt oUt DoM (AiRbNb / ReNdR)
                                            •  Backbone, but abstract out all
  Application Logic & Templates
                                               DOM manipulation from view
    Backbone
                                               manipulation
        Adaptation Layer
                                            •  AirBNB - Concatenate
                                               templates on server
       JavaScript Runtime                   •  No jQuery, no DOM access
                                            •  Is it the same anymore?

                       Runs on both as-is
                          Compatibility
                              Layer
                        Platform Specific
GrAiLs: CoMpArIsOn                                                 Template	
  Sharing	
  
                                                                                        Templates
   Your	
  Typical	
  App	
       Shared	
  Client-­‐Server	
  FW	
                 Data Representation

  Application Logic & Templates        Application Logic & Templates    Application Logic        Server Logic

    Backbone                                Custom Framework            Backbone

         jQuery                                                            jQuery

          Browser API                                                     Browser API

       JavaScript Runtime                   JavaScript Runtime             JavaScript            Any Runtime
                                                                            Runtime



DOM	
  Abstracted	
  out	
                    JSDOM	
                                Cheerio	
  
  Application Logic & Templates        Application Logic & Templates          Application Logic & Templates

    Backbone                             Backbone                               Backbone

        Adaptation Layer                      jQuery                                 jQuery / Cheerio

                                           Browser API Subset
                                                                                                                Runs on both as-is
                                                                                                                  Compatibility
       JavaScript Runtime                   JavaScript Runtime                      JavaScript Runtime                Layer
                                                                                                                Platform Specific
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
       Application              client and server with minimal extra
                                conventions
Backbone
                             •  Removes Backbone DOM depencies
 jQuery / Cheerio            •  Cheerio jQuery subset for DOM
Browser / Adaptation Layer
                                manipulation
                             •  Polyfills for Cheerio (events, ajax)
   JavaScript Runtime

                             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
SeRvEr-sIdE BaCkBoNe RePlAcEmEnTs
                                              •  The classes you typically use will run
                                                 as-is
           Collection




                                    Router
Model




                                              •  The classes that touch the DOM
                           View




                                                 underneath need changes
    sync
                                              We stub out/replace a few things
                                    History
                           jQuery




    Ajax
                                              •  jQuery: Cheerio and its fake DOM
                                              •  Ajax: Replace jQuery.ajax with a 3rd
                                                 party node.js module
                        Runs on both as-is
                          Compatibility       •  History: Trim away DOM specifics
                              Layer
                        Platform Specific         (window.navigator.location etc.)
WhEn ArE We ReAdY tO SeNd tHe PaGe BaCk?
Browser / Server
                                                                            One way on how to handle
     parse path /
      pushState
                                            Inject to DOM                   the problem
Backbone App
                                                                            •  Use Backbone events for
   Router                                                                      messaging
       handle
        route
                        verify all
                         states
                                              pass the
                                               results                      •  Single point of control
   Model                             View                                      (App Singleton/Router)
        fetch
       models
                    notify            render       notify
                                                                            •  All relevant objects have an
                                                            Legend:            observable state
Server API
                                                              direct call
        serve
        JSON
                                                                event
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?
LeT’s SoLvE tHe CrAwLaBiLiTy PrObLeM!


                                LaUrI SvAn
                                Software Architect, SC5 Online Ltd
                                https://github.com/laurisvan
                                @laurisvan




            HtMl5 eXpErTiSe aT yOuR sErViCe 	
  

2013 04-02-server-side-backbone

  • 1.
    SuRvIvInG RoBoTs aNdOlD BrOwSeRs bY SeRvEr-sIdE BaCkBoNe" LaUrI SvAn @lAuRiSvAn Sc5 OnLiNe @sC5 HtMl5 eXpErTiSe aT yOuR sErViCe  
  • 2.
    HeLp! My SiNgLePaGe ApP FaIlS fOr RoBoTs!
  • 3.
    WhY dEsIgN yOuRApP fOr 1% oR 0.1% oF YoUr tRaFfIc?
  • 4.
    UsE a PrOxYfOr LeGaCy BrOwSeRs Browser   Browser  interfaces   Server  API   Full   app   Plain  HTML   App  Proxy  
  • 5.
    WhAt Do IGaIn? •  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
  • 6.
    WhAt DoEs iTTaKe 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
  • 7.
    QuEsTs FoR tHeHoLy GrAiL ReViSiTeD
  • 8.
    GrAiLs: WhAt yOuRApP MiGhT LoOk LiKe •  Some partial layering model Application Logic & Templates •  App touches the browser APIs Backbone through all the layers jQuery Browser API •  Everything needs server-side JavaScript Runtime shims! Runs on both as-is Compatibility Layer Platform Specific
  • 9.
    GrAiLs: PrOxY BrOwSeR(PhAnToM.Js) Browser •  Full WebKit implementation on server-side •  Runs on its own process/server Reverse Proxy smart clients dumb clients •  Context sharing with Phantom.js App Server Proxy Browser process is tricky •  Chromium Embedded Framework & Node.js would even better?
  • 10.
    GrAiLs: TeMpLaTe ShArInG(tHe nOrMaL wAy) Templates •  Share the templates on client Data Representation and server Application Logic Server Logic •  Separate codebases for Backbone compositing the page fragments jQuery Browser API •  Simple to understand JavaScript Runtime Any Runtime •  Double code paths: Double testing, maintenance etc. Runs on both as-is Compatibility Layer Platform Specific
  • 11.
    GrAiLs: ShArEd ClIeNt-sErVeRFw (DeRbY, MeTeOr) •  Full app frameworks that hide Application Logic & Templates the DOM Custom Framework •  Hide client/server messaging (socket.io etc.) •  Meteor still uses PhantomJS to JavaScript Runtime render for robots? •  Lock-in to a certain development model Runs on both as-is •  Lock-in to a certain backend Compatibility Layer Platform Specific
  • 12.
    GrAiLs: SeRvEr-sIdE DoM(JsDoM) •  JSDOM - Full JavaScript DOM Application Logic & Templates implementation Backbone •  How about the other APIs? jQuery •  Browser/HTML5 APIs is huge! Browser API Subset •  Slow to emulate JavaScript Runtime Runs on both as-is Compatibility Layer Platform Specific
  • 13.
    GrAiLs: SeRvEr-sIdE jQuErY(ChEeRiO) •  Use jQuery for compatibility Application Logic & Templates Backbone •  Hide the DOM below jQuery / Cheerio •  Limited adaptation problem JavaScript Runtime •  Potentially faster •  Changes to Backbone needed Runs on both as-is Compatibility Layer Platform Specific
  • 14.
    GrAiLs: AbStRaCt oUtDoM (AiRbNb / ReNdR) •  Backbone, but abstract out all Application Logic & Templates DOM manipulation from view Backbone manipulation Adaptation Layer •  AirBNB - Concatenate templates on server JavaScript Runtime •  No jQuery, no DOM access •  Is it the same anymore? Runs on both as-is Compatibility Layer Platform Specific
  • 15.
    GrAiLs: CoMpArIsOn Template  Sharing   Templates Your  Typical  App   Shared  Client-­‐Server  FW   Data Representation Application Logic & Templates Application Logic & Templates Application Logic Server Logic Backbone Custom Framework Backbone jQuery jQuery Browser API Browser API JavaScript Runtime JavaScript Runtime JavaScript Any Runtime Runtime DOM  Abstracted  out   JSDOM   Cheerio   Application Logic & Templates Application Logic & Templates Application Logic & Templates Backbone Backbone Backbone Adaptation Layer jQuery jQuery / Cheerio Browser API Subset Runs on both as-is Compatibility JavaScript Runtime JavaScript Runtime JavaScript Runtime Layer Platform Specific
  • 16.
    AlMoSt aLl oFoUr aPpS aRe BaCkBoNe & JqUeRy YoU cAn’t tEaCh oLd dOg nEw tRiCkS
  • 17.
    BaCkBoNe-SeRvErSiDe – oUrDeSiGn 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
  • 18.
    InTrOdUcInG BaCkBoNe-SeRvErSiDe •  Run the same Backbone SPA on both Application client and server with minimal extra conventions Backbone •  Removes Backbone DOM depencies jQuery / Cheerio •  Cheerio jQuery subset for DOM Browser / Adaptation Layer manipulation •  Polyfills for Cheerio (events, ajax) JavaScript Runtime 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
  • 19.
    SeRvEr-sIdE BaCkBoNe RePlAcEmEnTs •  The classes you typically use will run as-is Collection Router Model •  The classes that touch the DOM View underneath need changes sync We stub out/replace a few things History jQuery Ajax •  jQuery: Cheerio and its fake DOM •  Ajax: Replace jQuery.ajax with a 3rd party node.js module Runs on both as-is Compatibility •  History: Trim away DOM specifics Layer Platform Specific (window.navigator.location etc.)
  • 20.
    WhEn ArE WeReAdY tO SeNd tHe PaGe BaCk? Browser / Server One way on how to handle parse path / pushState Inject to DOM the problem Backbone App •  Use Backbone events for Router messaging handle route verify all states pass the results •  Single point of control Model View (App Singleton/Router) fetch models notify render notify •  All relevant objects have an Legend: observable state Server API direct call serve JSON event
  • 21.
    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
  • 22.
  • 23.
    BaCkBoNe-SeRvErSiDe – WoRkiN 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)
  • 24.
  • 25.
    LeT’s SoLvE tHeCrAwLaBiLiTy PrObLeM! LaUrI SvAn Software Architect, SC5 Online Ltd https://github.com/laurisvan @laurisvan HtMl5 eXpErTiSe aT yOuR sErViCe