3.3 Providing an Offline Status
PWAs provide an offline experience, and it's useful to tell users when they are offline. We'll look at how you can do that in this lesson.
1.Introduction1 lesson, 02:03
2.Getting Started4 lessons, 34:07
3.Caching Resources5 lessons, 40:57
4.Background Sync3 lessons, 23:35
5.Notifications2 lessons, 21:35
6.Making the Application Installable1 lesson, 08:14
7.Conclusion1 lesson, 01:07
3.3 Providing an Offline Status
The offline experience is probably the most important part of a progressive web application because when you think about it, our application works just fine when it's connected. It's when it's not connected to that we start running into issues. And so it makes sense to really start with the offline experience first and think about what you want to achieve and what you want to provide. And it really doesn't matter as long as it kind of makes sense. Guess it really doesn't need to make sense because there are some applications that actually just give you a game to do something while you're offline. But in our case, I want us to display the last cached status report. Because, to me, that makes the most sense, if I am offline and I look at my application on my phone, I want to see whatever it is that I previously had. So what I want to do then is of course, display our status report, which we will go ahead and cash, that's gonna cause us problems, but we will eventually fix that. But I want to show the status report but I also want to show a message that says that we are offline. So on the surface, this is going to be very simple. Really all we have to do is whenever we initialize our application, we just need to listen for a couple of events. These are on the window object and the first is on offline. So whenever we are offline, this event will fire and all we will do is set a property called is offline to true. And then there's a similar event called online, so we will just listen for that event and then we will change the value of r is offline to false. And we do need to define this here so that Alpine can track it for us. So we will initialize it as false and then of course it will be changed to true based upon if we are offline or not. So with that done, we can go to our index and we need a template element here, because we're going to use the x if statement. And we can only use this if statement on a template. But basically, we're just gonna check if we are offline and if so then we will have a div element that uses bootstraps alert. And we will also use the alert warning color and we will just say that you are offline. Now this is going to get us most of the way there, let's go to the browser, let's clear out the storage. And let's do a hard refresh so that it loads everything fresh. And we're going to click offline and we see that hey, we are offline. And if we go back online, that message goes away. So that works, however, if we are offline, and if we refresh the page, well, we're going to see that that message goes away. Of course, we've lost our report, but we haven't cashed the report yet, but why did our message go away since we are offline? Well, here's the thing, our application made a request in a got a response. So therefore it thinks that it is not offline, even though that response came from the service worker. So the service worker is going to provide responses that are indistinguishable from a real time response. And that's really awesome but in our particular case, that's not really what we want. We want at least to some way to determine if a response is coming from our cache, so that means that we need to modify the response that we are sending back in our fetch event listener. And the cleanest way to do that is to just add a custom header. So we are gonna write a function to do that. And I'm going to use the a sync await keywords because when you start dealing with multiple promises and you have multiple nestings and well, my eyes tend to glaze over yours might not. And more power to you but mine do, so I'm just going to take the easy way out a sync and await makes things so much clearer for me. And since we are working with a service worker, we have the He's available to us. So we're going to have this ad cache header function, and it's going to accept the response that we passed to it right here in our fetch event listener. But here's the thing, right here, this response object might not be an object at all. If we don't actually find a match, then the response is undefined. So the first thing that we're going to do then is check to see if we don't have a response and if not, we are just simply gonna return. Otherwise, we are gonna build a new response and provide the headers provide the body for that response and then return that response. Sounds complicated, but it's really not. So let's have a variable called header, copy or let's call it headers, and we are going to new up the headers constructor. And we're going to pass in the headers from the response. So this is essentially going to give us a copy of the headers, so that we can then set our own custom header. I'm just going to call it SW cache for ServiceWorker cache, and I'm going to set the value to true. Now the value really doesn't matter here because in our app js file, we're just going to check to see if we have this header. And then from there we will assume that it came from our service worker. But that's not it, we also have to get the actual body of the request. So we are gonna use the responses, arraybuffer method to give us that body so that we can then return a new response with the body of that response. And we're going to set three properties, we'll set the status equal to whatever the responses status was. We'll do the same thing with the status text but then for the headers, well we have new headers. So we're going to use the headers that we created and that is going to be it. We have essentially copied the response from the cache but we are now including our own custom header. So let's go down to our fetch event listener and we are simply going to make this async so that we can await it. And we'll call add cache header, we'll pass in that response and that should work. Now let's go ahead and let's cache our data so that we can see that also In the browser, and actually so that we can make a request for that, and we will have a cached response. So that was data dot Jason because it all hinges upon retrieving this from cache, so that we can get the header. So now inside of our app js whenever we fetch our data, we need to check to see if we have that custom header before we convert it to Jason. So, all we will do is check to see if our rez headers get and we will test for that SW cache header. And if so, then we are going to set the is offline property to true. And then we will just return the responses Jason, so there we go, that should make everything work. Let's go back, let's go online, let's clear out the storage, let's do a hard refresh and everything should be there now. So if we hit offline, you are offline, that's perfect. If we refresh the page, we see our data, we still have our message. If we go back online, the message goes away, we refresh, we still see everything. Although now we have this message, you're offline, we are not offline. Well, the reason is because we cached our data and so right now, everything about our application is stored in cache and our ServiceWorker is responding with that cache. So that's going to give us the perfect reason to revisit our caching strategy. And we will start doing that in the next lesson.