The future of online is offline
Building modern web applications
by Matt Andrews, FT Labs (mattandre.ws / @andrewsmatt)
Good hacks and great performance, smart multivariate responsiveness, and web apps that deserve far more than the lowly title of ‘page’.Summary
- No review / approval process & automatic updates
- Instant install
- One app, many platforms
- Direct relationship with readers
- Apple don't take 30% cut
- Native-ish: homescreen icon, swiping, offline, fast (enough)
The catch?
They're really difficult to make well :(
Offline challenges
- Caching
- Backwards compatibility
As a web developer it's really easy to forget how powerful the browser actually is - and how much work it does for you. Unlike traditional software development when you make a webpage you normally don't need to worry about memory management or garbage collection or backwards compatability - even if you do break something, most mistakes can be fixed by the user simply clicking refresh.
Naive approach
-
if device is online, load from the web
-
else load from cache
- Browser even has handy method for checking connection: navigator.onLine
What does online mean anyway?
At best, that the device is connected to a wired or wireless router
navigator.onLine doesn't work
Fun fact:
On Desktop Firefox navigator.onLineis only false when File » Work Offline is ticked
Who even uses that anyway?
So how do we know if we're online?
You don't need to know
Live with uncertainty
-
Always assume the device is offline, load from cache
- Then try the network for new data in the background
(Also stops slow connections ruining your site)
For a page to load offline,you need to use the HTML5 Application Cache
Manifest looks like this:
CACHE MANIFEST
# 2014-05 v1
/lib/fonts/BentonSansBold.ttf
/lib/img/startupscreen/splash-logo.png
NETWORK
*
And to use it you need to add an attribute to <html>
<DOCTYPE html>
<html manifest="mywebapp.manifest">
Sadly, it's not quite that easy
-
Leaks storage (workarounds exist)
-
Inflexible and unintuitive API
- Makes browser susceptible to scary man in the middle attacks… whether you use it or not
- Will soon be replaced by Service Worker
Technically already available in Canary, behind a flag - but you can only install, uninstall and send messages to it right now - all the cool offline stuff not ready yet
Even Chrome dev relations people will tell you the Application Cache is a douchebag.
But…
- It does work
-
across 80%+* of browsers (iOS, Android, Chrome, Opera, IE10+)
- Only Chrome and Firefox have committed to building Service Worker implementations
* http://caniuse.com/offline-apps
AppCache OK
- Yes it's ugly for developers
- But it enables amazing experiences for users
- There are use cases where it works well
- Unfortunately, building a newspaper app isn't one of them
The spec says:
Service Workers are a new browser feature that provide event-driven scripts that run independently of web pages […] They have access to domain-wide events such as network fetches. ServiceWorkers also have scriptable caches. Along with the ability to respond to network requests from certain web pages via script, this provides a way for applications to "go offline".
https://github.com/slightlyoff/ServiceWorker/
A Service Worker:
- is a javascript file that you write and can be 'installed' onto your website
- lets you to do things with requests between browser and server
- has special caches that you can reliably store content in
More code than AppCache - but you can read what it does!
// Install process
this.oninstalled = function(event) {
var myCache = new Cache(
'/lib/fonts/BentonSansBold.ttf',
'/lib/img/startupscreen/splash-logo.png'
);
// The coast is only clear when all the resources are ready.
event.waitUntil(myCache.ready());
// Add Cache to the global so it can be used later during onfetch
caches.set("my-cache", myCache);
};
// (scroll for more)
// Request handling
this.addEventListener("fetch", function(e) {
e.respondWith(caches.match(e.request));
});
Unlike native apps,offline websites only download updates
when they're open
and only apply those updates on refresh
And some users get stuck on old versions - we're still detecting API callsfrom Javascript that hasn't been served for a year
App start events split by version of client side code
Guidance
-
Expect some users to get stuck, add tools to help users recover their apps
- Test different versions of client side code against different backend versions
- Add monitoring
- Add buttons to recovery tools that appear after a CSS animation if JS fails
-
Version everything - API endpoints, data formats
- Client side database migrations are painful. Store data in its simplest form (JSON better than HTML)
Summary
-
Offline websites are possible today, with enough persistence
- … but expect some users to get stuck
-
Service Worker will make things better (but only on Chrome & Firefox)
-
Test, measure and monitor everything