Optimistic Offline Experiences
(upbeat music) - [Simon] We're doing a terrible job.
Given my talk title, I'm sorry to open on such a downer but I did a lot of research and I had already named the talk and here we are.
So I just got back from being overseas on holiday for few weeks and I saw a lot of this. This is the most common offline experience we offer people. This is not great: Error internet disconnected. Can't really do much with that.
There's the dinosaur game that's kind of a pro but you see this, you play the dinosaur game, you lose, and then you forget what you were doing. Within the app we've got something more like this, which is just still sad face, so we've got a bit of a negative thing about being offline. Not enough of this.
And maybe you wonder why does offline matter anyway. I don't have any offline users for my site. But everyone's offline some of the time.
Maybe if you're on a plane, if you're on a train in that spot just outside the station where they wait for five minutes while the other train's on the thing. That's usually an offline dead zone.
There's that spot where you leave your house just before you've left your home wifi but your phone still thinks it's connected so it doesn't connect to the wireless network yet. Offline is everywhere, even if you're on a wifi network in a building much like this one and you get hundreds of people on computers and phones all connected to it at the same time then you get internet that looks like this. And this internet is slow enough that before the upload test finishes then Chrome thinks you're offline.
So, offline is not just for offline.
Offline is for slow internet, it's for legitimately offline, just all sorts of cases we don't consider.
So currently, how we handle offline with network requests, usually looks like this.
Try to fetch something, then we handle success, and then we'll try to handle fail.
So, we'll just look at this last line here. Usually, the way that we handle failure is something like this: we show an error, which is the red message at the top, that's probably adequate, right? We just say "try again later." More commonly, we might do something like this. (laughter from audience) I've never done this myself.
But again, we just consider offline as being an edge case. We don't worry about it, it doesn't matter. These users are not important to us.
But, offline is not an error, it happens to almost everyone. The one person it doesn't happen to is the guy who has a cable plugged into his dial-up modem and hasn't left his basement since 1992.
Everyone else is offline at some point when they travel or the internet goes down, their home router is misconfigured, I have got a bunch of these examples, I'll just keep dropping them in as we go.
But it's real life; offline is what we're all gonna have happen at some point, but we're not developing for it yet.
And, as such, we should probably do something about it. We should think about it, we should write something in that cache block.
You're allowed to write code inside cache blocks. And, now we can.
This is how we do something about offline.
Since a few months ago, there's been a "Yes." on this page, it's really exciting.
All major browsers support it, including everyone's favourite, (giggles) the Samsung built-in browser.
(laughter from audience) Which they track the latest version of Chrome and then they use something like fifteen or twenty versions behind that but Samsung browser supports it now so we're at something like 85% of commonly used browsers now support Service Worker, which gives you offline support. So, Service Worker is basically just code you can run in the browser when the tab's not there or when they're not connected, all your requests will check with the Service Worker first before they go through the network.
So that means we will replace the default stage. This is the first thing you're gonna do when you've added a Service Worker.
You say I can add offline pages now so we're gonna replace this guy.
You're gonna make a file called offline.html and you're gonna put some content in there. And there's some good examples of this, this is a semi-common thing that gets done because it's everyone's first Service Worker activity. So, Trivago has a maze if you're offline.
I didn't solve this one, and they just have a timer. So it's a pretty simple, static page.
You don't need anything super smart on there. You just have a reconnect button, countdown timer, and give them an activity to do.
I didn't want to have to make a maze, so my attempt attempt was just a message and an animated version of my SVG face.
It can be simple as anything, you're just giving them an experience that says "Here's where you are" and something a bit more comforting than just the dinosaur game. It's probably preferable to this but it's a start. But people don't really want that.
As enjoyable as the maze was, I don't really like mazes. I didn't try to access that page looking for a maze. I wanted content, and we can give people content. If someone's been to a page before and they then come back to that page, then they should be able to see it again.
But they can't; we're obsessed with freshness. The internet's obsession is with the newest content being visible at all times. Imagine you walk into this bakery and you see some bread rolls there you say to one of those two people in the background "I'd like this bread roll" and they say "sure, we're gonna go bake you a fresh loaf of bread." (laughter from audience) And they wait, this doesn't go anywhere, it's an infinite spinner, this is what happens if you wait for your fresh bread while you're offline on a slow network.
Instead, I say "give me the bread from the picture before, I've seen bread already, you've got bread right here." And, why can I not keep that available? This seems ridiculous, why would we have pictures of bread? Content is not bread.
I don't wanna pick on Reddit because they're great but part of the reason this is so noticeable is their initial load is so fast and then this loading thing takes so long.
This is just me mashing refresh on the page. The content doesn't change at all between refreshes here And I've still got to wait the full load time because I'm not saving these things because they assume we want the freshest content. But unlike bread, your content can actually be a little bit stale and it's fine.
I'd rather stale content than have to keep looking at this little guy.
You can just give them the stale posts and then say, we've got some up to date ones now and push the new ones up, which I think Twitter does as an example, there's a lot of examples of of this sort of thing, of serve the stale content that you have available because loading spinners are getting pretty annoying.
Any time you've visited a page, then you should be able to save the content.
So you can do that with latest posts, you just save the entire response.
A good example, a way to check what's possible with offline is just check the blogs and articles and other pages written by clever people.
If you look at the blog of Jeremy Keith, he's the author of a great book on offline that you should all read, if I don't mention it at the end, then please remind me 'cause I should tell you to look it up.
This page is saved, this is me being offline and loading this page and I've been there before so it works fine.
And this is really good, this means that anytime I want to go back and read this page again then I have the content there and it's not a big ask that we save that instead of me just getting an offline message. But the problem with this is this is a pretty good experience, I can read this content.
But then I get to the bottom of the page and I have these guys and I click on newer or older, and then I'm gonna get an error, because I haven't seen the newer or older page before. So we can do better than just saving the current page you're on.
If you are a blog or some kind of content page for a bigger site, you might have your about and contact pages, these don't change very often unless you're changing your company's phone number every week, there's probably a good reason to cache those kinds of pages where the content doesn't change. So, in this case, what we could do is when you load a page, we can say "save the content of this blog post and grab the newer and older articles and save the content of those as well." And then if someone reads the article they'll say "oh that was great, I'm gonna read something newer" and they click that and that'll work.
You could then also save those links.
You can save a lot of text content.
You can save save lower-res versions of images. You can use up quite a bit of storage with text. For reference, consider Moby Dick is something like 1.2 meg of text.
It's a substantial book, your posts probably aren't that long, you can save a lot of them. But even so, 1.2 meg is not huge in the amount of storage we get available for caches. You could fit a lot of Moby Dicks in your cache and even more posts, so keep your storage cleaned up. Don't go overboard and fetch the entire site, but you could grab most of links and this sort of thing. If you want to be even smarter about it, you can do something like get an export from analytics and just see if someone's on this page, there's a 90 percent chance they then read this article next so you can use analytics data from what people have been doing to determine what should be cached. Alternatively, if it is something small, like you've only got three posts, or if you're a documentation site, then you can just save all the content.
The Lodash docs are a good example of this. I read these on the flight back.
I didn't even need to use Lodash but I was just amazed that I could.
It's not just the current version, they have the docs of different versions.
So here's me reading the docs for a version I didn't have and didn't need, (laughter from audience) but nothing else would work on the plane.
Aeroplane wifi is a nice dream, but it's awful to use. If you have small enough content, I think the pages are maybe 50K each, so about 200K of total content and I have all the Lodash docs I'll ever need.
But if you don't do that and don't make all your content available, so realistically for blogs, or for articles, or for news sites, say for a news site you just want to load the five latest articles, so there's going to be a lot of cases where people are hit content that they don't have, and we don't want to just throw them back to the maze, so we'll give them something.
This is Ethan Marcotte's, this is a great example of offline.
It'll save the page you're on, it'll save a few other suggested pages and if you then try to load a page you haven't been to before, then it'll say you're offline at the moment, here's some stuff that we have saved for you. One of them is called "Chimpin'." If you're not gonna read "Chimpin'..." But just giving people options is useful.
It's a step up from the maze game rather than giving them something they didn't come to do, you're giving them something at least loosely related. Again, you could go smarter with this, you could say we couldn't find that article about this particular topic, here's ones related to that we have saved.
You can do all sorts of elaborate sorting and other grouping and just giving people content that they have asked for. But also, with all this forward loading, so text, mostly fine unless you're storing a library of entire books, you can just preload articles, that's alright.
Images, pre thread some, but be a bit thoughtful about it. Don't be downloading full-res hero images of every single post you've ever written, you could download a lower-res version of the images, you could just download the alt tags of images, it's a good reason to mark things up properly, assuming people won't have the images when they read your article.
If you've got truly big things, so video files, audio, other giant stuff, or you want to have a switch to download all my articles offline, then you go for this guy.
So this is on videos for some sites, you can just toggle it and save it offline. It's good for being opt-in, you want to tell them the size of the file, ideally, as well.
But this also means that if they notice they're running out of room on their device, then they can switch this off and get rid of it. Just being a bit more considerate of how we use people's data.
But, unfortunately, the web isn't just all static content. It's kind of an exciting, interactive, 3D, dynamic place now, so we have forms.
Forms are pretty exciting if you're into forms. Love filling out forms.
Sometimes you'll get an email, you click the link, you start filling out the form on your phone, and then you realise it was a little bit longer than you anticipated, "oh, I'll finish this later." So you do, and you finish filling out the form when you're in transit and then you hit submit without checking your network status and then you hit this and you're like "Shit, I'll go back" (groans).
This is below stage zero.
I don't need to explain how wrong this is.
Worst-best case here, we could at least keep the form data so I don't have to go through 485 questions again.
Better than that is preventing them from submitting the form.
Don't let them make the mistake when they're offline. Our travel friends at Trivago again.
When you're offline, they show you a little prompt there and they disable all the form fields.
This is kind of good because then I don't accidentally submit my giant form, kind of bad, because they don't tell me why these fields are disabled. So if I didn't notice the notification, I don't know why I can't click on stuff.
But if you want easy way in, just do this.
Make sure people can't submit forms and lose all their stuff.
This is a good, easy starting point.
Or we can do better than that.
We can retry stuff, this is an obvious one. If you want to allow the form to be submitted, then submit it and if it fails, write some code in the cache block that says try again. If we submit this incident report then it'll just retry. This says retrying in five seconds and kind of increases over time.
This is a good improvement and I know I'm probably not going to lose my data unless I close this tab.
That's still a thing that can happen.
The retrying thing is good, but while I'm waiting to be connected I'm going to go do another activity and then maybe turn off my phone later and then this is gone.
So, in recent years, we can do better than this with background sync.
So background sync is the next level of retry. We still want to do retry because that's just a good idea, maybe they'll be offline soon.
But if that fails again and we have repeated fails, then we want to be able to tell them "we'll do this when we can." So often you're writing a form and you think if I don't write this now I'm gonna forget what I'm saying so you just hit submit and it can't send but background sync will then grab this form, and then send it in the background regardless of the tab being open. So background sync is still very new.
It's less widely supported than Service Worker and other things.
But I think it's only Chrome and Opera.
But it's coming to the others pretty rapidly. This is kind of an ideal experience that you give to people who support it.
This means that they can close the tab and the Service Worker, when it's available, will just send this form data.
This is great; this means that you could safely fill in your application and send stuff.
This is how chat can work, this is how any kind of dynamic online experience can work is just do things when you can online.
I would rather I'm talking to my computer at some time, I tell it to do some stuff and it says I'll do it later.
That's good, I can trust it to actually do it. But this does introduce some complications. This is another great example of the offline. This is in Chrome now the download when online button. This is if you hit any content when you're offline then you get this button that says I will tell you when you reconnect.
And this is a very good experience.
This means I can't access the content right now but when it's available, you will get it for me automatically and you will tell me when that's done. So when I reconnect, then it'll notify you. You can get a push notification, or some kind of other telling that it's ready. This is kind of peak offline experience.
Rather than giving someone internet, this is about as well as we can do.
But it does introduce some complications.
So we've kind of made our interface fully async. We've gone from now someone might come to the site, they try to do stuff and they leave and we need a way to communicate this status with them later and we can't do this like with a form where you just show them an error message.
We're trusting that when they submit stuff then it will probably work later and if it doesn't then we need a way to tell them. And we can do that with push notifications if we have permissions, they're pretty widely supported and you can then have a push notification saying this works or this failed. Usually you shouldn't even need to notify on success. Consider I checkout of a store.
You're shopping online and then you suddenly get disconnected but but you still want to enter your payment details and hit pay.
You should ideally be able to just leave that page then and then when you next connect it'll send the request and say confirmed, and you get an order confirmation email, and everything's fine. I want to just be able to hit pay, checkout and I know that it'll work later.
The only time I'll need to be notified is if it fails and then I can get a notification that says error or something. That is quite tricky, because it's dependent on getting push notification permissions as sort of a whole thing there.
But the other tricky aspect of adding offline push notifications is you send a notification to someone and then they might be offline.
If you're offline and you get a push notification and then you click because you want to sign up, then the push notification disappears and you're offline. So now I don't really have a record of that page. Probably gonna run that again.
So we lose the push notification and we have no content on this page.
It's not great, this is giving someone an opportunity and then taking it away.
Again, hard to do, if you're gonna be sending push notifications when you ask for permission then you can kind of say here's pages we're likely to send you through and we'll pre-cache some content for those. At least don't send them to the dinosaur.
Offline isn't an error.
It happens to me all the time, I don't know if it's just 'cause I'm constantly toggling network on my phone so I can find these offline pages but it happens to people all the time.
The experience right now: not great.
We can do a much better job than we are.
So lets try to make better offline experiences. (audience applause) (upbeat techno music)