The emotional toils of building a simple progressive web app

At the beginning of the year I set about building a simple offline progressive web app. The TL;DR of this is results in a usable application that you can try out here, or take a look at the code on GitHub. The rest of this post goes into the story behind it, and how it came to fruition.

All stories start with a villain

...and this villain is none other than the office building security team. To increase security and prevent strangers from using the toilet, the aptly named "speedlanes" were installed recently, along with a QR code for each of us and a suggested app to use with it. Wonderful. Except now we have lines of people sat there tapping and swiping through this app to try and navigate to the one QR code they have stored in it, just so they they can get into the building. Why can't I just have an app that takes one tap to show me my access pass, instead of three? Surely there must be something we can do?

A glimmer of hope

A light shines over OpenUI5, one of our saviours at work. We can build our own! Let's make a web app that can show a QR code for us! We can even turn it into a progressive web app (PWA) and make it optimal for mobile devices! One of my recent goals was to get familiar with PWAs in general, and a simple app like this seems like a great way to start. We can:

  • have an app icon
  • make it act as a standalone app so that it doesn't look like it's in a browser window
  • store resources on the device so it works offline using a service worker

And it all falls down

So I got a UI5 web app up and running, and hosted on Firebase. It seemed to work ok, but there were a few issues that I couldn't quite get around.

App size

Damn, this is a big library. Downloading the mobile optimised version of OpenUI5 comes to over 40MB! Ok, a few unused chunks can be hacked off, and the debug files won't really be needed, so we can get this down to just under half the size. Still, 17MB before there's any custom code added for such a basic web app is just too much.

Speed

With all that UI5 library to load, it's slower than any other app on my phone to open from a cold boot. There are some preload files that we can generate using Grunt, but they still don't make it fast over a cellular connection. one of the main requirements for this application was that it needed to be faster than the current app. Sure, there are less taps, but when it takes upwards of 30 seconds to load on a slow connection, it still makes for a poor user experience.

Offline support

Once the app loads, you can press the home button and it's pretty damn snappy after that. However, if the garbage collector comes along and closes the app, then it starts again. It shouldn't take that long for the app to load though, because the service worker is caching the preload files for use later right? Well yes, it does cache them, but then I find out that service workers use asynchronous XMLHTTP requests, something that OpenUI5 does not support, but coming sometime 2018 hopefully (requires authentication to access).

The twist in the tale

I threw my toys out of the pram on this one and sulked for a few days, because at this point it felt like everything I've tried to do has failed and the world was against me. What's taken me weeks of playing around with in my spare time hasn't met the goals of what I set out to do.

I then remember something that I saw a while ago from Google around Material Design, and their introduction of Material Design Lite, or MDL. It's a small JavaScript and CSS library that allows you to build responsively designed web apps, or incorporate it into other larger frameworks. At this point I figure it's worth giving it a shot, and work on a fresh implementation of Speedlanes, borrowing some chunks of code from my UI5 project. Two evenings later, and there before me is a small, simple, speedy offline-capable progressive web application that does just as much as the UI5 implementation and more.

But the story doesn't stop here!

After using UI5 for so long as my main web development framework, interacting with the DOM layer again felt oddly strange but comforting. It proved to be the simplest way for me to get something up and running so quickly with offline support. For more complex applications this wouldn't be the way this would be handled, and so more investigation will be required to figure out how to use the service worker's offline support in combination with other frameworks and workflows.

As with all software, this is more than likely a beta with a bunch of bugs in. I've already added and removed a couple of features that didn't seem to work so well, and I'll continue refining things as my knowledge of PWAs increases.