Using vector tiles instead of large geoJSON to render features
@Homeday, we often work with maps and geodata visualization. For example, you can look at our flagship product — Preisatlas.
Recently we had a chance to implement an app which contains a map, with lots of interactive features (the feature is usually just a geometric shape) drawn on top. The basic use case of the app is map consumption, clicking on features and editing associated data.
Challenge
Usually, our go-to set of tools for this kind of tasks is Google Maps API + geoJSON, containing the features. However in this specific case, our geoJSON had a lot of features, to be specific, it had ~60MB of features. Of course, that is way to big to be served as initial payload and being an integral part of the app, we had to consider alternatives.
geoJSON simplification
The first thing that we tried is removing all unnecessary data from geoJSON and simplifying the points that represent features. With that, we managed to reduce the size of our geoJSON to “only” 10 MBs. Obviously that is progress, however, the size was still way too big, and the imprint on our initial payload size was still significant.
That was also not the only problem, feature simplification broke the features topology, so when a user would zoom in, features would start to overlap and that was far from the desired user experience. There has to be a better way.
Vector tiles to the rescue
Then our GEO team suggested that we take a look at Mapbox — shout out for suggestion and article review Vitor Sapucaia Fortunato! ;)
They have recently released this awesome thing called vector tiles which could solve our massive geoJSON challenge. And so we did. After initial struggles with their documentation (sorry Mapbox, you’re great, but sometimes documentation is hard to consume. However they provide lots of demos which help with understanding core concepts), they have pointed us into the right direction (very quick response on Twitter — kudos!).
Vector tiles — what’s that?
If we look at vector tiles section intro on Mapbox website, they say:
Vector tiles make huge maps fast while offering full design flexibility. They are the vector data equivalent of image tiles for web mapping, applying the strengths of tiling — developed for caching, scaling and serving map imagery rapidly — to vector data.
Usually, maps are built with a bunch of PNG tiles, which are loaded when needed. This works great when you need to display features — as they can be drawn on your PNG tile. But it also comes with some major drawbacks: They can’t be styled, you can’t associate data with them and you can’t attach events on the specific tile.
And this is where vector tiles come to play. Instead of PNG tiles, we use small vector tiles. They deal with all above drawbacks of regular PNG tiles and additionally, they are very small, offer high resolution and efficient caching.
How does it work?
In essence, you take your geoJSON data and upload it to Mapbox, there, data is converted to vector tiles which you can use as a layer in Mapbox Studio (it’s a visual editor of your map styles).
A few notes here, you can only upload geoJSONs that are under 5MB directly in Mapbox web interface. If your dataset is larger, then you have to use their API. We found this a bit clunky, as it’s a multi-step process, first you have to get S3 credentials from Mapbox, then use them to upload the data there. From there, Mapbox picks it up and converts your geoJSON to vector tiles. You are notified once the process is done. This can take some time though, so we found a better option is to use Tippecanoe. With Tippecanoe, you can convert your geoJSON to tiles yourself and then just upload those to Mapbox through the web interface (so you skip the s3 upload).
That’s pretty much it, from that point on, you can load your styles in the browser and take it from there.
Demo
Here you can find a demo of vector tiles in action. For this demo, we’ve used open data, which represents world countries as features. We needed to modify the original data a bit, as each feature needs to have a unique id, so we can target it with our JS.
The demo shows how you can leverage features associated data and make features interactive.
Conclusion
Switching from large geoJSON to vector tiles, really proved as the right choice for us. With the above approach, we managed to eliminate any performance bottlenecks, that we’ve described above.
Of course, is not all roses, to switch from Google Maps API to Mapbox, you’ll need a few days to adjust your mind to new API. Mapbox API is very jQuery like, which is not a big deal (if you’re more old school 😎), however, styling is more declarative then imperative(you push tiles in predefined states), which you might be used from Google Maps API. One thing you will have to master(or at least learn to use :) ), to take full advantage of this technology, is their expression system. At the beginning it might seem hard to understand, but once you get a hand of it, you kind of start appreciating it and the powers it has. Due to that, it’s sometimes possible to hit a mental block, when working with Mapbox. But their website is full of useful examples and demos, that can help you find your way around.
Hope that sheds some light on vector tiles. We are really excited about this approach and encourage you to give it a try.
Happy coding!