- 7 minutes read
Adding a Seamless Offline Mode to Your Web Application. Image by S. Terfloth User:Sese_Ingolstadt [CC BY-SA 2.5 (https://creativecommons.org/licenses/by-sa/2.5 )], from Wikimedia Commons
(Image source: Wikimedia)
Today I learned that it's surprisingly easy to reach the holy grail of progressive web applications. Or at least one critical aspect of any PWA. A well-designed PWA should survive a short period of being offline. Just think of doing work with your laptop on the train. You know the drill: Exactly the second you hit the "save" button, the train enters a tunnel. Bye bye, network connection. Bye bye, carefully drafted document.

It doesn't have to be this way. In 2018, browsers can deal with temporary network losses. You just have to use the API. A particularly powerful and unobtrusive option is to use a small JavaScript library called - guess what! - Offline.js.

This article discusses this option, plus two alternatives.

Let Offline.js do the hard work for you

Adding Offline.js to your web application is a matter of a few minutes. Basically, you need to add one JavaScript file and two CSS style sheet files.

You can download these files from the project page or its GitHub repository. There's also an npm package, but it's incomplete: The CSS files are missing. So I guess the best approach is to download each file individually.

That's it! Now each time you're going offline, an unobtrusive indicator appears at the top of your page.

By the way, you can see the plugin in action on this page by activating flight mode or pulling the network plug. The library is small enough to add it to BeyondJava.net.

Delaying AJAX until you're online again

There are many features of Offline.js I like, but there's one feature I'd like to point out particularly. It intercepts AJAX requests, postponing them until the network is available again. At the time of writing, I'm not entirely sure if it manages to do the same trick with requests that had already been started when the connection was lost. I think so, but the source code is fairly advanced stuff, so I'm not sure. Be that as it may, that's useful stuff, solving most challenges we're encountering when we're trying to implement a simple offline mode.

But can you recommend it?

There's just one catch: the library was abandoned some 18 months ago, and the authors failed to pass the library to someone ready to pick it up. There are volunteers, but it's hard to find out who's serious about the project. So my best guess is to use the original library. It does the trick, and there's no reason to update as long as it works.

On the other hand, the library has been actively maintained for at least four years and collected 338 commits. That's a lot of programmer wisdom and experience. So using the library is a potential time bomb in the light of the creativity of malicious hackers, but it seems to be a reasonable risk to take.

Do it yourself

Alternatively, you could implement a similar feature yourself. It's straightforward. Every modern browser has the attribute navigator.online and the window events online and offline.

So all you have to do is to implement an event handler reacting on the online and offline event.

An alternative approach is to implement a global error handler observing HTTP requests. Firefox offers an API called webRequest allowing you to intercept arbitrary HTTP requests. However, this article focuses on progressive web applications, so intercepting AJAX requests is probably all you need. You can do this using the traditional XMLHttpRequest API. If you're not familiar with that approach, have a look at the source code of Offline.js.

I suppose that's a good option, but you'll be surprised by the amount of work to implement the offline mode. That's why I continued to look for an offline library that's still actively maintained.

I have to admit I failed. Even so, I found an attractive alternative that's been abandoned half a year after Offline.js.

What about UpUp?

Mind you, telling our users that the application is temporarily offline isn't exactly state of the art in 2018. We can do a lot better. Modern web APIs allow us to react much more cleverly.

UpUp is a library employing web workers to serve a response to the web application even if your device is offline. The idea is to fetch the response from the server by default. If that's not possible, we serve a default response. This might be a generic error message or sending cached data to the application. Actually, the latter is precisely the use case that caused me to investigate the topic.

Setting up UpUp is just as easy as setting up Offline.js. You only have to download the JavaScript file, define an HTML file that's shown in flight mode, and add a few lines to your HTML page:

UpUp loads the default HTML page in advance and stores it in a cache. If you're navigating to another page when offline, the UpUp loads the file from the cache instead.

BTW, the default HTML page doesn't have to be a static page. You can use a page dynamically rendered on the server. This way you can predict the next action of the user, and display data matching the user's activity.

Can you recommend UpUp?

Like Offline.js, UpUp seems to be abandoned. The last commit and the last release were published on December 30, 2017. Since then, there was almost no activity on the GitHub project. But then, that's only half a year, so it doesn't raise a red flag.

More disturbing is that UpUp has a fairly limited scope. There's precisely one page you can store in the page (plus an array of CSS files). What you can't do is to react differently depending on the user's action. For example, if I were to add UpUp to this blog, every link showed the same cached page, instead of displaying the article you wanted to read.

Do-it-yourself revisited

That's not quite what I expect from an "offline first" approach. So we're back to doing it all ourselves. Basically, using service workers allows you to do a lot of clever things. Caching is only the beginning. However, even caching is a huge topic. A couple of years ago, Jake Archibald wrote a nice introduction to caching with service workers.

Another topic you should cover is saving data to the server. If the server is offline, you need to store it locally in the browser until the application is online again. Brace yourself for a lot of work if you follow this road.

Wrapping it up

As a user, I don't want to lose my data just because I'm sitting on a train entering a tunnel just the moment I hit the "save" button. However, as a developer, I know that supporting the offline mode is opening Pandora's box. You can do it, but I reckon it's hardly ever cost-efficient. That's why I like the approach of Offline.js. It's simple, it clearly indicates the lost connection so users won't try to save data in the tunnel, and by intercepting AJAX requests, it even has a limited approach to protecting you from losing data you're sending to the server. It's not perfect, but it sounds like a good compromise.


Comments