Cesium and PWA

Progressive Web Apps, or PWA, are web applications that are built with the latest web technologies and provide enhanced user experience with the following characteristics:

  • Speed: load instantly and respond quickly to user interactions.
  • Reliability: operate properly even in offline scenarios.
  • Engagement: feel like a native application on the device and can be installed on the user’s home screen. It can even re-engage users with push notifications.

You can visit the Progressive Web Apps page in Google Developers website to learn more about it.

Cesium is an open source Javascript library that allows you to integrate world-class 3D globes and maps in your application. It is cross-platform and uses WebGL for hardware-accelerated graphics. It is constantly evolving the past years with a GitHub repo of over 2,000 stars. They even have created their own arcade game using the library!

In this article, we will cover speed and reliability and will investigate how Cesium applications can benefit from progressive web app techniques. For the needs of this experiment, we have created an application that saves the current view of a map along with the last known location so that they can be loaded instantly next time and the user can continue from where it left off. You can find the complete source code here along with a demo of the application.

The application is mainly based on service workers to deliver a fast and reliable user experience.

Service Worker

A service worker is a Javascript file that acts as a client proxy between your application and the outside world. It can intercept network requests and pre-cache content allowing the application to work efficiently in environments with poor network performance or even during offline.

Registration

An application must register a service worker in order to use it.

Service worker registration

We need to check if the service worker is available in the current browser because it is currently fully supported in Firefox, Chrome, and Opera only. Please check http://caniuse.com/#feat=serviceworkers for more information.

Installation

After the successful registration of the service worker, an install event is triggered. In this event handler we cache all needed assets by the application (Javascript, CSS, fonts, images) which are referred to as the App Shell. The event is fired only the first time the user visits the application.

Service worker installation

Intercept network requests

Each time the application originates a network request, a fetch event is triggered. In this event handler we cache the response from the request so that we can easily access it later. There are two types of requests, each one handled with a different caching strategy.

Imagery data

When the application requests imagery data, the service worker goes to the network and caches the response. The next time the same request is initiated, the service worker will respond instantly with the cached version and simultaneously will go to the network and try to fetch fresh data (cache-then-network). So the user will always see some data, either from the cache or the network. In this scenario we use Open Street Maps provider to get imagery data, but others could be used as well.

Fetch and cache imagery data

App shell files

When the application requests app shell files, the service worker will immediately use whatever is in the cache, which was added during the installation of the service worker. If the files are not in the cache already, it will fetch them from the network (cache-falling-back-to-network).

Get app shell files

Below you can see the complete source code of the fetch event. You can find more about alternate caching strategies in the offline cookbook.

Since imagery data do not update so often, we could have implemented the same strategy as for the app shell files. We decided to implement a different one just for demonstration purposes.

Service worker fetch event

The service worker events that we use, are some of the basic ones. There are others that deal with activation of the service worker and update of cached data.

Results

At startup and during navigation, the application caches imagery data from the provider. When the user stops navigating, the application saves its current location.

Application launch first time

Next time the user opens the application, it loads the last known location along with imagery data instantly. If we try to navigate to another location we will notice that the map is not fully loaded, as we zoom in. This is due to the fact that the user is currently offline.

Offline navigation

As soon as the user goes online, the application starts to load the rest of the map and it concurrently caches the new imagery data.

Online navigation

Conclusion

Progressive web app techniques, although not yet fully mature, can give many benefits to a Cesium application especially in a mobile one where speed and reliability are a great concern. Caching data eliminates the need for frequent network requests and improves the load time of the application.

Throughout the experiment, we identified some issues that should be taken into account:

  • An alternate caching mechanism should be implemented because the size of the Cache Storage is limited. We could maintain a queue and keep the last (n) items each time.
  • We should use a local copy of Cesium and not referencing it directly from index.html because cache.addAll() is atomic, if any of the files fail the entire cache addition fails. The ideal would be to add Cesium library to the App Shell cached files.
  • The techniques demonstrated should not be used for production environments because of the many unhandled edge cases. For example, it is very easy to find yourself in a situation where the app shell will never update. You can find more about such cases here. Thus, it is preferred to use an advanced library such as sw-toolbox and sw-precache which eliminate most of the boilerplate code and provide better control on the updates.