farmOS-map icon indicating copy to clipboard operation
farmOS-map copied to clipboard

Offline map tile caching

Open mstenta opened this issue 5 years ago • 6 comments

We are going to be incorporating farmOS-map into the farmOS-client, which is an offline-first progressive web app. One of the limitations that maps currently have is that tiles are loaded over the network, so creating an OpenLayers map without internet connection doesn't work.

Ideally, the farmOS-map library would include functionality to cache tiles locally so that it could work offline. Or, maybe this is best left to applications like farmOS-client? Let's discuss!

mstenta avatar Jul 18 '19 18:07 mstenta

Some potential resources:

Here is an old example of caching tiles locally with OpenLayers 2.x: http://dev.openlayers.org/examples/offline-storage.html

It sounds like OL3+ allows you to create your own TileSource and customize the tileLoadFunction() (as a wrapper around other sources we use, perhaps): https://stackoverflow.com/questions/26860046/can-openlayers-3-use-websql-or-indexeddb-to-cache-map-tiles

mstenta avatar Jul 18 '19 18:07 mstenta

Another option that was floated is to use a service worker (in farmOS, farmOS-client, or both).

mstenta avatar Dec 05 '19 01:12 mstenta

Another option for some use-cases might be MapProxy which can be used to create cached mirrors of existing GIS services - WMS/WFS/tile server/etc.

symbioquine avatar Mar 03 '20 03:03 symbioquine

Oh good to know @symbioquine ! I could see that being really useful if you are hosting farmOS on a local network and want to keep the maps working on multiple devices connecting to that.

I started experimenting with the service worker idea, which would basically cache tile URLs on your local device after you've accessed them. Seems like a simple and flexible option, albeit not all-encompassing.

mstenta avatar Mar 03 '20 03:03 mstenta

Cool @mstenta! That's a good option for arbitrary raster/tile sources.

Alternatively, just get the system vending the tiles to set the right caching headers and no cache-busting parameters and the browser will do all the work :)

symbioquine avatar Mar 03 '20 03:03 symbioquine

On SoilStack we're currently using mapboxgl-js, which has some tile caching built in, their source might be interesting.

We're using Workbox for the PWA service worker, which lets you specify matching functions for requests to cache, here's a simple example. All requests that match the pattern will be cached, and future requests will grab the response from the cache if they can't get it from the network. This approach requires that the user views the map before going offline, which may be undesirable.

Brian came up with a simple solution to create a prefetch button that creates a component which renders a copy of your map with display: none set and listen for a ready event before unmounting. The downside with that approach is that the user can't pan or zoom on the map, and you have to actually initialize the mapping library. I also found a feasible approach for manually generating all the necessary tile requests (which can be cached with Workbox/service worker) for a given bounding box with some optional padding and zoom levels. See our SoilStack offline maps issue on Gitlab for more details. Both solutions should let you prefetch map tiles with a user's button click, rather than telling them they need to first open up the map.

We've talked about caching a smaller region and single zoom level of satellite tiles, but downloading the vector tiles too. This would make satellite imagery visible in the overview, and provide a scalable fallback with smaller file size.

wgardiner avatar Feb 09 '21 19:02 wgardiner