How to optimize the web speed of a Leaflet map - leaflet

I'm trying to optimize the speed of a web page, where a Leaflet map is included. According to GTMetrix and Google PageSpeed Insight, I should:
Optimize the following images to reduce their size [several images served from 'https://services.arcgisonline.com/ArcGIS/rest/services/...'], serving them in next-gen formats
Defer parsing of the JavaScript https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.4.0/leaflet.js
Serve 'leaflet.js' and 'leaflet.css' inline
I would appreciate any similar experiences optimizing Leaflet maps. Is it worth serving JS and CSS of Leaflet inline? Can I modify the code to call 'arcgisonline.com' images in other lighter formats?
The code of my simple webpage
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.4.0/leaflet.css'>
<script src='https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.4.0/leaflet.js'></script>
<div id='myMap' style='height:700px;width:700px;'></div>
<script>
var map = L.map('myMap').setView([51.505, -0.09], 13);
L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {maxZoom: 19, attribution: 'Tiles © Esri — Source: Sources: Esri, DigitalGlobe'}).addTo(map);L.tileLayer('https://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer/tile/{z}/{y}/{x}', {maxZoom: 19}).addTo(map);
L.tileLayer('https://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Transportation/MapServer/tile/{z}/{y}/{x}', {maxZoom: 19}).addTo(map); L.marker([51.505, -0.09]).addTo(map);
</script>
Thank you very much.

this is quite old and may come a bit general to your question, but regarding geodata:
you should decrease the amount of data that is loaded (i.e. do you really need all observations?)
you should simplify the geometries if you work with polygons. The incredible mapshaper does a lot there for your speed. You can use it e.g. in R with the rmapshaper package to preprocess your data before.
you could think of using vector tiles and implement a tileserver between backend and frontend that preloads your data for different zoom levels (use.e.g. geoserver) or alternatively tile the data dynamically inside your database (postgis is able to do that with st_AsMV()) and serve tiles to your leaflet interace which then needs a plugin to create dynamic requests for the server based on the current bounding box of the map or alternatively use a webmapframework that supports tiling in the frontend (e.g. openlayers).

Most of the speed "optimizations" you refer to are general to webpages, there is little specific to Leaflet in particular.
Deferring is usually approached by simply placing your JS (including the Leaflet script tag) just before the end of your page body, so that it does not delay rendering of the rest of your HTML.
You can implement true deferring but then it becomes more complex ensuring your script executes after Leaflet is done loading; the easiest would be in that case to indeed inline Leaflet JS together with your script. But then you lose the potential cache of Leaflet asset, in case your visitor had browsed to other websites which have used these exact same assets.
In the case of Leaflet, you can also use a "skeleton" as a placeholder for your map, so that your visitor sees a static image while Leaflet and your script are loading. Make sure you have the right to host the static image.

Related

Poor GeoTIFF display performance using JS plugins contrary to Leaflet for R package

I have question regarding displaying GeotTIFF using leaflet or react-leaflet.
There are some packages allowing displaying tiffs, for example I had used:
https://github.com/stuartmatthews/leaflet-geotiff
https://github.com/IHCantabria/Leaflet.CanvasLayer.Field
Both of them are great but regarding performance they are much slower than using leaflet for R package.
https://rstudio.github.io/leaflet/raster.html Scroll down to example on this site.
Why is that displaying Tiff in Leaflet for R is much faster than in Java Script? Are there any solution to achieve something similar in JS?
Saying that I tried displaying same bunch of geotiffs in every cases and R is much faster than both of plugins. I need solution to be in JS.

What happened to this Mapbox Tile image?

So I'm attempting to get Mapbox working with my Leaflet implementation (using React Leaflet), and my spidey sense is telling me something is off.
The URL:
https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/11/568/825#2x.jpg?access_token=pk.eyJ1IjoiamFtaWxsZXI2MTkiLCJhIjoiY2t3Y3JnbG5uMzZ2MzJ1bmhyaHhpczJpcCJ9.3X8OkNioN_C8CN15YPmDDQ
Note: I created the access_token used above for this SO question, and will be deleted soon. So the link may not work when you see this, which is why I used SO's handy dandy image upload!
I assume this has something to do with how the tile coordinates and/or zoom is being calculated, but really, I don't have a damn clue in the world.
Using mapbox.mapbox-streets-v4 as the tileset_id produces results that are better, but still bad. I haven't yet been able to load a stylesheet either...
What gives?
As it turns out I was correct in my hunch that it had something to do with how the tiles were being generated by Leaflet. And while I'll probably never know the specific reasons behind it, I was able to solve it. The secret sauce ended up being mapbox-gl-leaflet.
I threw together a super simple example on Code Sandbox showing the successful implementation of Mapbox tiles as a React component within React Leaflet. It's pretty snazzy, IMO, even if you have to import a few hundred different packages (doubly if using TS) to make it all work 😕
https://codesandbox.io/s/sharp-payne-m3hll
NOTE: To see the codesandbox link working, you'll need to supply your own Mapbox API key. The API key from above won't work (even if it was still valid, which it may or may not be depending on how much I care to do anything about it...)
The mapbox.mapbox-streets-v11 tileset from Mapbox is originally intended to be used as vector data, e.g. with Mapbox Vector Tiles API : https://docs.mapbox.com/help/glossary/vector-tiles-api/
The only difference with your URL is the requested format mvt (instead of jpg). And no #2x resolution modifier.
What may be confusing is that the vector tilesets can also be requested as raster, by specifying a raster format like jpg or png through Mapbox Raster Tiles API https://docs.mapbox.com/help/glossary/raster-tiles-api/.
Mapbox server then generates an image from the vector data. But in the case of the streets tileset, it has a lot of data in hand, and it renders all of it, making it appear messed up.
Mapbox provides 5 default tilesets (https://docs.mapbox.com/studio-manual/reference/tilesets/), some of them are raster only (typically Satellite mapbox.satellite) while others are originally vector, but can also be generated as raster (Streets, Terrain, Terrain-RGB/elevation, Traffic).
Unfortunately Leaflet does not handle vector data built-in. If you really need to use vector data, you have to use plugins like Leaflet.VectorGrid or Mapbox GL Leaflet, or another switch to another mapping library.

Supporting older browsers (lte IE 10)?

As far as I can see, Mapbox GL JS is not supported by IE 10 and below. Correct?
I want to implement GL-JS for my site, but need to support these incompatible browsers, and am hoping to find an elegant solution, probably just showing them the mapbox tile layer I'm currently using.
I thought IE conditional comments would do it, but they only work up to IE9, leaving a gap where a lot of my users are.
I know I can use if (!mapboxgl.supported()) within the javascript function block, but I also need to conditionally load the javascript and css files. No point loading them both - would probably cause conflicts, and it's just plain dodgy.
So… suggestions?
Mapbox GL JS renders maps using WebGL which is only supported in IE11+
If compatibility is important, you have two options:
use Mapbox.js (raster tiles) in all cases
use Mapbox GL JS in supported browsers, use Mapbox.js in unsupported browsers
You can check for support without loading unnecessary Javascript or CSS files by using the mapbox-gl-supported module and loading additional JS and CSS files dynamically
var scriptElement = document.createElement('script');
scriptElement.setAttribute('src', 'https://api.mapbox.com/mapbox-gl-js/v0.20.1/mapbox-gl.js');
document.body.appendChild(scriptElement);

Mapbox : Bulk markers breaks down browser

Could anyone please help me on this,
I am using map box to plot different markers around 10,000+ in a window using GeoJSON format. While loading so, the browser window will get stuck and the user is not able to perform any actions. Is there any other alternative way to get rid of this or optimizing it.
Thanks in advance
You can have a look at Mapbox-GL-JS. The guys at mapbox have implemented a smart strategy to parse and visualize large GeoJSON files using web workers.
Additionally, MapboxGL uses WebGL to visualize the data, so it should perform better with large datasets.
Other options include using an Html5 Canvas to render the data. Here is an example with Leaflet and Canvas overlay: http://bl.ocks.org/sumbera/11114288
Please check this out to optimize the loading & performance :
Optimizing data in mapbox

OpenStreetMap Grayscale tiles?

I'm building up experience with web development and my next projects are some web maps. I've looked into Google Maps and Open Street Maps and would like to use OSM for a project as it contains more detailed information of building footprints.
I've tried styling Google Maps which seemed fairly straightforward, but I'm a little lost with OSM. I've got to the point of trying to create my own renders (with TileMill) but this is crashing my system due to the amount of data.
What I essentially need is this (but for the UK);
http://maps.stamen.com/#terrain/12/37.7706/-122.3782
Are there any resources which you can recommend or how easy/ difficult is this to create myself? I think I would need to create the map (with TileMill or similar and then find my own servers to host), or is there an easy way to convert the standard map to Grayscale?
I want to keep it as simple as possible so please any recommendations?
Turning the standard map to grayscale: I might be very late to this but for anyone else running into this question: I found a very easy solution if you're working with HTML and Javascript using OpenLayers and the standard OpenStreetMap-Tile-Layer in color. I took the solution from here: https://openlayers.org/en/latest/examples/semi-transparent-layer.html
I don't know much about web development but this solution worked for me. Upon creating the map, as done in main.js in the example from the link, a class name is defined ('bw')
className: 'bw',
that can be used in index.html to manipulate the style o f it in the part:
<style>
.bw {
filter: grayscale(100%);
}
</style>
My application was altering a pre-built web-map from the qgis2web extension for QGIS. I was able to turn the tile layers from the background map to grayscale so the results would stand out more.
You could use https://github.com/Zverik/leaflet-grayscale to display any tile layer in grayscale. It's a plugin built upon the leaflet map displaying library.