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.
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.
An application must register a service worker in order to use it.
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.
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.
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.
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).
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.
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.
At startup and during navigation, the application caches imagery data from the provider. When the user stops navigating, the application saves its current location.
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.
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.
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.