Slide 1

Slide 1 text

Offline rules Taking the FT offline on the eb ndre Betts (@triblondon) FT Labs (@ftlabs)

Slide 2

Slide 2 text

1880 1900 1920 1940 1960 1980 2000 2020 e’ve been doing this for a hile.

Slide 3

Slide 3 text

orks offline Portable Long battery life Can be read in bright sunlight Cheap Ubiquity Bookmarking Sharing Nesprint is a great client Fast start up Clipping/saving Can be read in the dark Updates in real time Electronic delivery Search Personalisation Deep linking

Slide 4

Slide 4 text

orks offline Portable Long battery life Can be read in bright sunlight Cheap Ubiquity Bookmarking Sharing ‘Traditional’ eb Fast start up Clipping/saving Can be read in the dark Updates in real time Electronic delivery Search Personalisation Deep linking

Slide 5

Slide 5 text

orks offline Portable Long battery life Can be read in bright sunlight Cheap Ubiquity Bookmarking Sharing pps Fast start up Clipping/saving Can be read in the dark Updates in real time Electronic delivery Search Personalisation Deep linking

Slide 6

Slide 6 text

e need to care about supporting existing features as much as getting ne ones.

Slide 7

Slide 7 text

HTML5 is not a ‘mobile thing’. It’s not an alternative to native apps. It’s a ay of making better ebsites.

Slide 8

Slide 8 text

Lose the constraints •  Tablet •  Phone •  Desktop •  Laptop •  TV •  Games console •  In car screen •  In flight screen •  Billboard •  Kiosk •  e-ink reader

Slide 9

Slide 9 text

Screenshot  of  the  app  

Slide 10

Slide 10 text

Offline vs dependency management Offline vs responsive images Offline vs media queries Offline vs analytics Offline vs login state

Slide 11

Slide 11 text

Offline makes everything harder.

Slide 12

Slide 12 text

Client side storage options Meet the family from hell.

Slide 13

Slide 13 text

ppCache Teen localStorage Dad IndexedDB Mum Cookies Grandad Files PI Imaginary friend

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

appCache indexedDB

Slide 16

Slide 16 text

Speed: read/rite cycles 242   296   175   259   6873   29897   1 10 100 1000 10000 100000 IDB Large IDB Small ebSQL Large ebSQL Small localStor Large localStor Small Operations per second (more is better) h7p://jsperf.com/indexeddb-­‐vs-­‐localstorage/13  

Slide 17

Slide 17 text

Bootstrapping Start small and enhance

Slide 18

Slide 18 text

CONTENT   adver   Jsing   adverJsing   adverJsing   twaddle   crap   nonsense   tomfoolery   tripe   baloney   garbage   poppycock   trash   rubbish   filler   irrelevance   faff   hidden   unseen   ferreted   concealed   invisible   buried   latent   sequestered   shrouded   unrevealed   withheld  

Slide 19

Slide 19 text

hy Bootstrap? •  Keep content clean •  Start ‘enhanced experience’ on any URL – Need front-end router / front controller •  Handle errors •  Run only hat e need •  Mollify attention seeking app cache

Slide 20

Slide 20 text

Main content Basic CSS / fonts Boot and error handling code JS modules CSS modules HTML fragments dditional content Initial pageload appCache/Netork Modules and dependencies Local storage / appCache / netork uthentication tokens Cookies Extra content and prefetching ebSQL / IndexedDB / netork uthentication token

Slide 21

Slide 21 text

Taming the appCache Grump grump grump grump grump...

Slide 22

Slide 22 text

CACHE MANIFEST # 14120120420 / /favicon.ico /lib/fonts/ofsnmd__.ttf /lib/imgs/sprite.png FALLBACK: /issues /fb/issues /api /fb/api NETWORK: * Manifest version Explicit caching llo stuff not in appcache Offline controllers

Slide 23

Slide 23 text

ny page ith manifest attribute ill get cached, like it or not. ny cached page ill be used in preference to fetching a fresh copy, even hen online.

Slide 24

Slide 24 text

   

Slide 25

Slide 25 text

Only cache one ‘master’ URL: ...

Slide 26

Slide 26 text

Internet Explorer ill not populate an appCache unless the manifest is cacheable. Firefox on’t store any resource if it’s served ith no-store, even if explicitly listed in the manifest.

Slide 27

Slide 27 text

Cache-control: max-age=1, private; Prevent proxy caching

Slide 28

Slide 28 text

hen the manifest is updated, every entry in it is redonloaded

Slide 29

Slide 29 text

CACHE MANIFEST # 14120120420 /js/mymodule1.js?v=1.15 /js/mymodule2.js?v=1.18 /js/mymodule3.js?v=1.1 /js/mymodule4.js?v=1.18 /js/mymodule5.js?v=1.19 FALLBACK: /issues /fb/issues?v=2.34 /api /fb/api?v=2.34 NETWORK: * Manifest version Far future cached resources

Slide 30

Slide 30 text

ppCache HTTP Cache Server Updated manifest Donload just one

Slide 31

Slide 31 text

On slo netorks a request must time out before the fallback is used.

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

Ideas for fixing it: •  Separate the cache and offline router •  More granular atomicity •  Read/rite/load/purge PI in JavaScript •  Spec the quota behaviour

Slide 34

Slide 34 text

•  Redefine appcache syntax •  Still mostly declarative •  Sub-manifests: multiple atomic groups •  JS PI to bring transparency •  eb orker option for advanced usage •  Pattern matching fallbacks •  Remove the ‘magic’, like auto- adding masters •  Ditch appcache, define ne PI •  lmost entirely imperative •  Individual atomic cache groups accessed via PIs •  Install a controller to intercept and route requests •  “Bring your on unicorn” EVOLUTION REVOLUTION

Slide 35

Slide 35 text

Mozilla proposed manifest { "expiration": 300, "cache": ["index.html", "index.js", "index.css", "show_bug_handler.html", "forum.html"], "urlmap": [ { url: "show_bug?id=*", page: "show_bug_handler.html" }, ], "network-controller": "httpworker.js” }

Slide 36

Slide 36 text

Google proposed controller navigator.controller.register("/*", "/navctrl.js") URL space to control Path to controller script

Slide 37

Slide 37 text

this.caches.set(”app", new Cache([ "/resources/js/bundle.js?v=2.3", "/resources/css/bundle.css?v=4", "/resources/html/templatepack.js?v=1.1", "/fallbacks/main.html" ])); this.caches.set("edition-20130301", new Cache([ "/issues/20130301/uk/article1.html", "/issues/20130301/world/article3.html", "/issues/20130301/media/images/chavez.jpg", "http://cdn.example.com/audio/readaloud.mp3" ])); pplication (high priority) Content (loer priority) navcntl.js – setting up caches

Slide 38

Slide 38 text

this.onrequest = function(e) { var resource = this.caches.get("edition-20130301").match(e.url); if (resource) { e.preventDefault(); e.respondWith(resource); return; } } lays serve from cache (if available) navcntl.js – handling requests

Slide 39

Slide 39 text

this.onrequest = function(e) { if (this.onLine) return; var resource = this.caches.get("edition-20130301").match(e.url); if (resource) { e.preventDefault(); e.respondWith(resource); return; } } Or, only if offline (if you prefer) navcntl.js – handling requests

Slide 40

Slide 40 text

this.onrequest = function(e) { if (this.onLine) return; var resource = this.caches.get("edition-20130301").match(e.url); if (resource) { e.preventDefault(); e.respondWith(resource) } else { e.preventDefault(); var fallback = this.caches.get("app") .match('/fallbacks/main.html'); e.respondWith(fallback); } } navcntl.js – handling requests Choose to return a different resource

Slide 41

Slide 41 text

hich should in? •  Both? •  NavigationController offers rich and highly granular control to advanced developers •  Moz advanced appCache provides the declarative option for simpler use cases •  NC could be the ‘netork-controller’ of the Moz manifest.

Slide 42

Slide 42 text

•  NetorkController •  ResourceController •  ProxyController •  FetchController •  NavigationController •  CacheController

Slide 43

Slide 43 text

Meanhile...

Slide 44

Slide 44 text

Meanhile... appCache is good for: YES: •  Fonts •  Splash image •  pp icon •  Entry page •  Fallback bootstrap NO: •  CSS •  HTML •  JavaScript Local Storage

Slide 45

Slide 45 text

Storage optimisation ll storage technologies are limited by tiny quotas. e need to learn to live ith less.

Slide 46

Slide 46 text

ebSQL () / IndexedDB (i) ppcache localStorage Cookies iOS Safari (6.1) : 5MB / 50MB 25MB 5MB 4KB total Up to 50 per domain MacOS Safari (5.2) : 5MB / Unlimited Unlimited 5MB ndroid broser (2.3) ? Unlimited 5MB Chrome (26) Unlimited 260MB (ish) 5MB IE (10) i: 500MB 50MB 10MB Opera (12) : 5MB / Unlimited 50MB / Unlimited 5MB / Unlimited Firefox (20) i: 50MB / Unlimited Unlimited 10MB Storage limits Two  figures  separated  by  /  indicate  limit  with  and  without  user  consent  prompt,  which  appears  automaJcally  when  you  try  to   store  more  than  the  lower  limit.    The  user  may  not  consent  to  more  than  the  upper  limit.  

Slide 47

Slide 47 text

UTF-16 in JavaScript •  Provides great compatibility but halves precious quota! •  Can make compromises on compatibility to get more storage efficiency 00   48   00   45   00   4C   00   4C   00   4F   00   20   00   57   00   4F   00   52   00   4C   00   44   H   E   L   L   O   W   O   R   L   D  

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

Squeezing your bits Text   S   i   m   p   l   e   Decimal   83   105   109   112   108   101   As  binary   01010011   01101001   01101101   01110000   01101100   01100101   Shi[ed   01010011  01101001   01101101  01110000   01101100  01100101   As  hex   53  69   6D  70   6C  65   UTF-­‐16   卩   浰   汥  

Slide 50

Slide 50 text

SCII packed into UTF-16! Simple = 卩浰汥 6 chars 3 chars

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

SCII to UTF-16 function  compress(s)  {    var  i,  l,  out='';    if  (s.length  %  2  !==  0)  s  +=  '  ';    for  (i  =  0,  l  =  s.length;  i  <  l;  i+=2)  {      out  +=  String.fromCharCode((s.charCodeAt(i)<<8)  +                s.charCodeAt(i+1));    }    return  out;   }  

Slide 53

Slide 53 text

Too simple?

Slide 54

Slide 54 text

Bit-shifting base-64 data? •  Could go further if e kno e’re only using base 64. •  64 characters requires only six bits •  Potential 63% compression ratio •  6 divides into 48 •  8 base-64 chars per 3 UTF-16 chars

Slide 55

Slide 55 text

Base64 hiding in UTF-16 Original   A   B   C   D   o   p   q   9   b64  index   0   1   2   3   40   41   42   61   As  binary   000000   000001   000010   000011   101000   101001   101010   111101   Shi[ed   00000000  00010000   10000011  10100010   10011010  10111101   As  hex   00  10   83  A2   9A  BD   UTF-­‐16   ☐   莢   丢  

Slide 56

Slide 56 text

UTF-8 hiding inside UTF-16 UTF-­‐8   R   o   y   ’   s   Decimal   82   111   121   8217   115   As  binary   01010010   01101111   01111001   11100010  10000000  10011001   01110011   Shi[ed   01010010  01101111   01111001  11100010   10000000  10011001   01110011   As  hex   52  6F   79  E2   80  99   73  00   UTF-­‐16   副   秢   肙   猀  

Slide 57

Slide 57 text

Connection state Taking online and offline events at face value

Slide 58

Slide 58 text

Q: If the value of indo.navigator.onLine is true, hat does that mean? : The device might be online.

Slide 59

Slide 59 text

Donloading! Not sure. Still trying... Bah. e give up.

Slide 60

Slide 60 text

Open source releases e did it already. Use our code.

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

FT Columnflo orld's most advanced column layout tool Forked by The Telegraph and Baidu bit.ly/Mmhd1z

Slide 63

Slide 63 text

FT Scroller Momentum scrolling support ith ultra ide compatibility including Internet Explorer 10 bit.ly/SJcJR4

Slide 64

Slide 64 text

FT Fastclick Virtually instant responsiveness for touch UIs bit.ly/Ndvbmo

Slide 65

Slide 65 text

A new kind of one-day conference on advanced web technologies for developers and browser vendors. September 2013, New York City edgeconf.com

Slide 66

Slide 66 text

Thanks andre@labs.ft.com @triblondon, @FTLabs