Introduction to Offline Web Apps

Swati Sucharita
7 min readFeb 5, 2019

--

The best thing about web applications is the ease of access. We have a web browser and internet access, we are good to go. But what if we don’t have internet access or we have slow internet access, we still want to read our favorite content. That is where offline by default web applications come into play. We can enjoy all beautiful features of web applications without internet too!

The question is how. The answer is simple, we cache the application in the browser. There are two ways to cache content in browser.

  • Application cache
  • Cache storage

Application cache is less controlled. It’s getting deprecated.

App cache compatibility from MDN

We can use use cache storage by using Service Workers. It gives us ability to control what to cache, what not to cache or to cache up-to which level. Service workers are not yet supported in all browsers but it has a very promising future.

Service Worker compatibility from MDN

We can see Chrome supports it, Edge and Firefox also has good amount of support. We can provide the offline experience to large amount of users as the user base for these browsers combined is quite large. Other users will have the traditional web app for them. So nothing lost.

Let’s dive into what is Service Worker and how it can help us.

Service Worker is an event driven JavaScript code that runs in the background thread. It can control how the application behaves in certain situations (Like the network is not available). Apart from this offline behavior, it can also do many more things for us like

  • Background Sync
  • Push notifications

But in this article we will focus mainly on the offline functionality.

So, what do we mean by event driven JavaScript code:

Service worker has some life cycle events. It responds only when the events are triggered. The life cycle events are:

  • Register
  • Install
  • Activate

First we install a service worker in our website using navigator.serviceWorker.register() method. Install is fired when the service worker is getting ready to be used. When one version of service worker is already active, the website gets another version of the service worker, it does not activate it. It only installs it.

Activate is called when the service worker come into use.

Let’s build a small application where we can see things working

We can use this basic one page application to get started.

Visit http://localhost:8080

This page is about my latest travel to Hampi, a village in south of India. So far so good.

If you look at the network tab in the browser (I recommend using google chrome for this tutorial). You can see various calls being fired to fetch data.

As we can see, there is an offline option in the network tab. Let’s turn it on and see what happens when the network is not available.

We reload the page, and it’s gone.

We can improve this scenario using service worker. Even if there is no network available, still we should be able to see the info we already have.

Let’s go to the app and add that support. In the /src/js/app.js file, we have to register the service worker. Add the following lines of code.

We are registering the service worker if the browser supports. As you can see we define the service worker in a file called sw.js.

Let’s add a very simple service worker in location public/sw.js

If we go back to our browser and reload it, we can see the service worker in the dev tools. It’s available in Application > Service Worker section.

And if we see our console, we can see logs for the service worker being registered, installed and active.

Let’s go and try our offline mode now, let’s see if it works. No it does not because, we still have to make use of the cache storage. Let’s add the code to store data in cache storage. Let’s modify our sw.js file to store info in the cache.

We go back to our browser. Close all the windows for the application and open the app in a new window(Required to update the service worker). Reload the page to get the app to store data. Let’s see now if we have data. We can see our cache storage from chrome dev-tool.

Cache storage in dev-tool

We can see all the files mentioned in the install handler is added to the cache.

We wrote the data into cache. Now it’s time to read the data from cache when user requests those data instead of going to the network.

More info about the caching API

For that we have to add another event handler on “fetch”. Whenever “fetch” is called from the app, this handler will intercept the call. So let’s add it to the sw.js file.

This code is trying to fetch the data from cache and return it if found. So the request won’t go to the internet anymore. If data not found in cache, it’s trying to fetch data from internet.

Let’s see how it affects our application. We go back to application, go to Dev Tools > Application Tab > Service Workers. If we see another version of service worker in waiting state, we click on skip waiting. we can also follow the earlier way to close windows and open new one (more reliable).

Let’s reload the page and click on offline option in the Service Workers tab / Network tab.

It’s a good improvement from the “No Internet” state. We will miss the game though :) .

We can see few things missing though, like the image on the card and the icons. We can add another cache, which stores all the new contents, that’s not present in the initial cache. It will keep adding data as we fetch them for first time.

Let’s update the sw.js file.

If we reload the page and use the updated service worker, we can see the new Dynamic cache in the cache store too.

Let’s try to go offline now.

Now we can see the full page in offline mode!!

Congrats!! We got our offline application up and running. You can see the complete code in the following repository.

Caching how much data is always tricky though. Ideally we should cache only the layout then let the user decide what they want to store as offline. There are multiple caching strategies and fallback mechanisms to manage the cache.

We can also cache the JSON responses from an API. That’s story for another time :)

If you like this story, give it a clap or give it five :)

Thanks for reading.

--

--