Solving Cache First Bug Recovery in Service Workers

Tony Guglielmi
Imgur Engineering
Published in
4 min readFeb 26, 2018

The team at Imgur is always excited for new web technologies that will improve our site’s experience. The most notable newcomer in the past year has been the addition of Service Workers. Naturally, after we migrated all traffic to HTTPS everywhere, we dove head first into experimenting on our mobile web site with offline support and caching strategies.

Long story short, we landed on a “Cache First” strategy that vastly improved load times:

No Service Worker (Slow 3G)
Service Worker with Cache First Strategy (Slow 3G)

Woah! The “DOMContentLoaded” event was reduced from 2.77 seconds to 395 milliseconds (85.7% improvement). The “Load” event was reduced from 7 seconds to 4.91 seconds (30.4% improvement). Beyond the numbers, the visual load difference is apparent as you can see below.

No Service Worker, Browser Cache Disabled (Slow 3G)
Service Worker Cache First Strategy, Browser Cache Disabled (Slow 3G)

Awesome, so what now? Just ride off into the distance on the back of a unicorn like the heroes we are? Not quite.

We found out quickly this strategy has draw backs. Due to how service workers replace each other (read here about “worker in waiting”), it doesn’t allow for fast recovery when we push a bug to our production code. While one can argue: “Hey, you shouldn’t push bugs to production,” that just isn’t realistic since, excluding our office dogs, our whole team is human.

So that was our next hurdle we had to solve: fast recovery when a bug fix is deployed. After some research, we landed on a strategy that allowed us to keep cache first, but to prompt a user when there is a major update worth having.

Prompt for updated version of site.

Why not just auto refresh the page? I felt it was better to let the user decide, they may be in the middle of an action that is not relevant to the bug and we could let them finish.

In our final implementation, we decided since this was only to be used when a huge site breaking bug occurs; it made more sense to auto refresh the page when a user first comes to the page with an update.

Technical Implementation

For those of you interested in how this is done, I want to dive a bit deeper into our code. As with any project, it is good to start with a diagram of what you are building in order to get feedback. The flow diagram of what we built looks like this:

Below are a few snippets outlining the changes needed for the implementation, but for brevity I excluded nonessential parts relating to our mobile site. The goal of this code is to be as decoupled as possible from the app code itself.

It is important to note, we implement the service worker with the Offline plugin for Webpack.

We updated our webpack.config.js with the necessary plugin changes. events: true in Service Worker properties ended up being the only change (aside from initial installation) to implement the strategy.

Update the entry.js to have the install logic and event functions for the service worker.

In our sw-entry.js, we add the listener for the post message that the client sends to the service worker.

Post message listener in the service worker to broadcast back to clients the version.

With all these changes in place and deployed, to start a bug recovery process we need to deploy the fix with an updated timestamp to swversion inside of the service worker entry file.

This project really outlines a core value of the company: Always Learning. It would have been easy to shy away from this technology when this issue came up. By taking the time to do the research and learning from our mistakes, we have given our users a better experience, which is always worth it in the end.

--

--

Tony Guglielmi
Imgur Engineering

Senior Software Engineer at Imgur, who loves creating joyful and useful products.