Awesome
MapWorkBox
Little PoC to test dynamic precaching for map tiles
WTF is this
This is a little Frankenstein monster made to check whether the use of Workbox as precaching manager and some dark magic could smooth even more the Mapbox GL JS experience by precaching the most possible upcoming tiles requests.
THIS IS NOT PRODUCTION READY, AS OF TODAY IT'S JUST A PROOF OF CONCEPT. Feel free to fork it and PR to improve it if you're in the mood.
The demo
https://abelvm.github.io/mapworkbox/
And, how does it work?
It relies on Workbox libraries to ease the cache management through service workers, so the main thread is kept isolated from this task.
Every time the map ends a movement (zoom, pan, whatever), the service worker starts precaching the potentially upcoming tiles in the background. The criterium in this PoC is that any tile with at least one point in the current viewport and zoom levels z+1 or z-1 will be precached
. This could flood the cache, so the number of tiles will be limited to 250 and 2min as oldest.
BTW, I'm using tilebelt for all the viewport-tiles logic.
Results
Quite impressive indeed. Using Mapillary coverage layers with a heatmap in the lower zoom levels (as it's a CPU consuming styling), I have found that this technique lowers the source loading time to a 35% of the original time and improves the cache hits in up to 50%, so up to 85% of the tiles requests are served from cache vs 55% without precaching.
How to use it
You need to add both mapworkbox.mjs
and mwb.js
to a folder in your project and load only the first file, but as module. Any other requirements are dynamically loaded.
<script src="mapworkbox.mjs" type="module"></script>
You might want to edit the cache limits, located at mwb.js
file
expconfig ={
maxEntries: 250,
maxAgeSeconds: 120
}
Then, just initialize the service worker in the onload
event of your Mapbox map
map.on('load', e => {
mapboxgl.mwb.init(e.target, layers);
});
Being layers
the list of layers to be precached, as an array of objects, each of them like
{
name: 'mylayername',
minzoom: 5,
maxzoom: 10
}
minzoom
and maxzoom
are optional and it would take the layer source zoom limits for the sake of precaching.
Caveats
Take into account that this technique will make use of extra bandwidth and extra disk space as the criterium to choose the next-to-be-requested tiles is quite simplistic. In the example, the cache size is kept under 200MB and usually has 45MB-75MB size.
Do NOT trust the Chrome Dev. Console in terms of service workers and cache storage (Application
tab). Same applies to the Workbox methods that are supossed to return cache related info (like this).
If you benchmark this with a map with a not precached layer, the results might be misleading as the timer would be affected by the loading time of the tiles of that layer.