November 12th, 2010
The most recent redesign of Google Sightseeing added many embedded “live” Google Maps blocks to the main homepage, and a column of the latest Street View sights. This certainly makes the content easier to explore, but is detrimental to the page load speed, as each of those maps can take a few seconds to load into the browser.
“Lazy loading” is when you don’t load code or media until it’s required. On webpages, that means not loading content (such as images) that are further down the page until the user scrolls down there (if they do at all). It’s used on some large websites to reduce their server cost, as all those images near the bottom that the user never sees can add up to a lot of bandwidth.
However, we don’t want to lazy load Google Maps for bandwidth concerns (it’s all served by Google remember) but instead to speed up the page load. Each embedded map adds a few seconds to the initial page load, so those maps quickly add up.
There’s also an additional issue which forced me to look into the lazy loading: The iPad (with software v3.2) can’t handle more than a couple of Google Maps on one page. If you try to load 5 or 6 Google Maps API instances (Street Views are worse) then Safari just quits without any explanation. The soon-to-be released v4.2 of the iOS software does fix this, but the experience of having your browser consistently crash is so annoying we had to fix it for everyone.
The first step to lazy loading the maps is to provide a hook for loading and unloading each map individually, rather than launching them all in the <head> of the HTML.
I achieved this using jQuery’s custom events, which we attach to each map and called “loadmap” and “unloadmap”:
Here the “loadmap” function switches the map DIV’s classes, and then does the normal Google Maps API map loading for the DIV in the current context (this). The unload function just clears the contents of the DIV to remove the map, and switches back the class.
So now we can load maps into a particular DIV with the command:
or load all the available maps on the page with:
But we don’t want to be doing any of this until the Google Maps API itself is loaded, so we set a callback on the maps API to kick off the process:
As an additional speedup the Maps API is being loaded asynchronously, so the rest of the page loading doesn’t get held up waiting for the Maps API.
At this point in the process it’s fair to say I’ve not achieved much – all the map instances on the page still load for every user. However, we have added a tidy method for loading individual maps, and can now conditionally load them.
Inview keeps a cache of a pre-defined set of elements, and then reports to your callback whenever these elements enter or leave the viewport. This means that we can load up the Google Maps as the user scrolls to them, greatly speeding up the initial page load.
We also unload any “maploaded” DIVs that are no longer in the viewport, preventing the iPad from crashing due to too many map instances. This has a downside of losing any zoom or panning the user has done to the unloaded map, so we may yet limit this functionality to the older iOS software.
At present I’ve only activated the lazy loading for Google Sightseeing visitors who use Webkit or Mozilla-based browsers (IE needs more testing), but please give it a try and let me know what you think.