Runic Software
Published in

Runic Software

Publishing Your MapApp

Using Service Workers and PWA with Angular Leaflet or OpenLayers

Photo by Enrique Alarcon on Unsplash

This is the second part of a series about Including Leaflet javascript interactive maps into Angular.io applications. The other parts of the series are :

The objective of this series is to that you will be able to create a Leaflet map in an Angular-CLI based project without hassle, fuss and dead-ends.

Part Five

In this part, we will :

  • Add a Service Worker to the Angular leaflet.
  • Make the application into a PWA.

Background

Part one of this series explained the basics of how to add a Leaflet based map to Angular.io applications using @asymmetriks/ngx-leaflet.

There is also another article on Simple OpenLayers Apps in Angular. The solution documented here will work with all types of apps.

An HTML application has many benefits in terms of ease of access and scalability but it is also very dependent on the data connection. We will now look at making a Progressive Web Application and thus, to make an application that has all of the benefits of both an HTML application and a native application.

Progressive Web Applications

Progressive Web Apps are web apps that use emerging web browser APIs and features along with traditional progressive enhancement strategy to bring a native app-like user experience to cross-platform web applications.

What does this mean in practice? Broadly,

  • PWAs should be capable of working on any platform, securely and comfortably
  • PWAs should be designed to work with no connection,
  • PWAs should be installable, and thus self-contained.

This can be achieved by the combination of technologies, usually described as:

  • HTML and Javascript/ Typescript to create a cross-platform app,
  • HTTPS to ensure security,
  • manifest.json to encapsulate the metadata needed for an installable application, and
  • Service Workers to provide the caching required for the App to work offline.

HTML / JS App

If you have your Leaflet or OpenLayers Angular app, you already have the basis for a PWA. The Angular compiler will have created bundles for working across multiple browser types as well, which increases the portability of the code.

HTTPS

All sites should anyway be served across https these days, so I am going to assume that this is a done deal. If not, there is plenty of literature about how to do it.

Manifest.json

Your manifest.json file provides information about the look and feel of the application over and above that provided by the HTML — especially how it will look as a standalone app.

Creating it is not hard, it is mostly a matter of wrangling the correct formats and sizes of images. A good guide to creating the file is on web.dev.

Icon wrangling is whole other set of articles and one I will never write. All I can say is that I use GIMP, swear at it more often than I swear by it but generally get there in the end!

In addition, you should complete all of the metadata in the HTML <head>, including the link to the manifest.json file. It will probably look something like this :

<meta charset="UTF-8"><base href="/"><meta name="description" content="Online for Sandwich Flats Project"><meta name="keywords" content="NAS, Nautical, Archeology, Sandwich"><meta name="author" content="Paul Harwood"><meta name="theme-color" content="#3367D6"/><title>Sandwich Flats Project"</title><link rel="icon" type="image/png" href="/swb_small.png"><link rel="apple-touch-icon" href="/swb_small.png"><link rel="manifest" href="manifest.json">

Note the Apple Touch Icon, at least one will be required and should be a PNG of either 180x180 pixels or 192x192 pixels (see web.dev).

Note that for a PWA the manifest.json must include :

  • short_name or name
  • icons - must include a 192px and a 512px icon
  • start_url
  • display - must be one of fullscreen, standalone, or minimal-ui
  • Note: prefer_related_applications must not be present, or be false

Service Worker

Finally, you must have a Service Worker to manage and cache the off-line content.

This is a more complicated subject, both to create the Service Worker and to insert it into your build workflow so that the Service Worker is always up to date.

I create another, dedicated, article on my approach to simple Service Worker creation for Angular Apps, see …

Note that for a PWA, it is important to have routes configured (whether pre-cache or on-demand cache routes) for all content so that the application can run offline. This needs to include the root of the site (i.e. / ). The Service Worker MUST give a return code of 200 for the start_url as defined in the manifest.json when off-line for it to be a PWA (i.e. you can launch the app when offline).

Note also the discussion about the scope of the Service Worker, and link this to the discussion about the scope of the manifest.json. It is important that both the Service Worker and manifest.json have scopes that fully cover the whole site.

Testing the Configuration

Once this is all configured, you will ideally need a web served test environment with https. It is difficult to get a true idea of what you have without this test environment.

When you load this test environment into Chrome (and similarly for Safari and new IE), you can go to the Application tab in the Developer Tools and you should be able to see:

  • The manifest.json correctly loaded and your icons showing correctly,
  • The Service Worker loaded correctly and running,
  • The cached files as per the routes configured in the Service Worker.

Once you have this, you can move onto the next stage. This is to run Lighthouse, a Google tool that tests the PWA against the requirements and produces a report on the app. Basically, if your PWA passes the Lighthouse tests it will be accepted by browsers as a PWA.

Lighthouse is accessed as a tab on Dev Tools in Chrome. You use it to generate a report on your Application, including performance, security and sustainability. Broadly, if your App passes the installability tests in Lighthouse, it is going to be accepted as a PWA by browsers.

You can see some more information on the tests and the response messages from Lighthouse here.

But — Maps are Maps …

It is of course, not quite that simple.

Maps are not apps that play well offline! Map libraries do their own caching that mostly but not always works offline if the map is already loaded but generally have high timeouts and generally use a network-first type of strategy which means long delays and slow screen builds.

Lighthouse primarily measures performance by First Meaningful Paint and Time to Interaction — for very good reasons. But, with Leaflet and OpenLayers, both of those measures require the map to be fully rendered (i.e. the tool does not know about the library to know that the map is useable before then). So, you are going to get scarily poor performance figures for these types of app.

My response to that is usually: as long as the app passes the non-performance tests and gets accepted by the browser as a PWA, ignore it. Yes, you should do everything to be as fast as possible but if it feels usable to you and the users, then you have to look at the Lighthouse metrics as being too blunt a tool for mapping apps.

More generally, I would love to get around at some point to integrating the mapping libraries with the Service Worker libraries to create a much more intelligent and predictive caching mechanism that would, therefore, get around both the problems of offline maps without the user nightmare of “download your offline map”, and the performance hit shown in Lighthouse. But who has the time? If you know of a good solution, please let me know.

What do you get?

If you have done all of this and the browsers start to recognise the app as a PWA (and that is the way that it works), what you get is:

  • The WebApp should now work smoothly offline, both in the browser and as an app, and
  • The WebApp can be installed, i.e. you will able to create an icon or link to the WebApp.

The second point is deliberately vague since the actual details will depend on both the platform you are on and the browser you are using. If, for instance, you are using Chrome on Android then the browser will prompt you to install the app which then appears to work pretty much like Android app to the user. If you are using Chrome on a Desktop, you get the same prompts but it is loaded on to the Chrome App Page. Other combinations work with PWAs in different ways — see the documentation.

If you want to see an example — try www.trackbash.co.uk

This also comes to another couple of refinements. The First is that you need to have an installation strategy (even if that strategy is “accept the defaults” like I mostly do!). The installation strategy is explained here.

The second is that you need to have an Upgrade Strategy. The upgrade is going to be managed by the Service Worker since the upgrade strategy for the PWA is actually the upgrade strategy for the Service Worker. My article, linked above, on using Workbox covers this to some extent and provides links to much deeper discussions. The bottom line is really that you are going to have to update the Service Worker script whenever either the strategy changes or any of the key resources changes (thus the integration of the Service Worker build into the App build workflow). Then, you are going to have to get the new Service Worker installed and running on the User Agent — while it is itself running.

You can actually all of this just be accepting the defaults, both of Workbox and in my article. However, the user will have to close and open the App (sometimes more than once) to see the latest version. This is often acceptable as long as you do not have close coupling between a front-end and a back-end. Better processes are also available and are documented. I am just not going to delve into them here.

It is still better than the messiness that comes with updating native apps (especially if you have tried living on a low-end phone with full memory — the experience of actually most of the people in the world).

What is missing?

So you have a WebApp that looks to the user like it is a native app.

But, it is not a native app. So what are the differences?

The main things that you do not get are related to the device APIs that are not available in the sandbox. It is really difficult to describe the size of a hole but a rough idea of the things that people are saying cause problems because they CANNOT do them can be seen from the Google Capabilities project and the link on there to the Fugu List of new API requests.

As well giving pointers to where other developers have hit brick walls, this list also shows where alpha and beta fixes are available, with admittedly a strong focus on Chrome.

A typical example of this of particular relevance to mapping apps is the ability to keep the device screen awake, for instance when the user is navigating using the map.

I have published another article discussing my experiences with the draft version of the WakeLock API available in origin-trial on Chrome and IE and I believe target for release in one of the next versions of Chrome.

You can also now provide App Shortcut links into your app that appear exactly like Android Shortcut links.

What to Read Next

Coming up … how to turn your App into a TWA and publish it in Play Store.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Paul Harwood

Paul Harwood

Paul is a long time veteran of the tech industries — with 30 years in the trenches including stints with Nokia and Google as well as startups QR8 and trackbash.