May 3, 2014

Google Maps Asynchronous Loading

While working on a project that uses Google Maps API, I noticed the following problems:

  1. The content below Google maps appeared after a slight delay
  2. Google PageSpeed Insights kept telling me to "eliminate render-blocking JavaScript and CSS in above-the-fold content"
  3. The maps did not load when the page was loaded via AJAX
  4. The maps did not work in jQuery Mobile

All of these problems were caused because I was loading the Google Maps API synchronously. Let me explain. Almost all Google Maps API examples tell you to do this:

Google Maps Asynchronous Waterfall
<script src="//maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&sensor=SET_TO_TRUE_OR_FALSE"></script>
<script>
    function initialize() { /* Map Initialization JavaScript */ }
    google.maps.event.addDomListener(window, "load", initialize);
</script>

This works but it blocks the page to load/render slowly and does not work with AJAX for the following reasons:

  • The browser stops rendering the page when it encounters the script tag, download the script, execute it, then resume rendering; this explains problem 1 and 2
  • The downloaded script calls document.write() which makes both asynchronous and AJAX loading impossible; this explains problem 3 and 4

See the synchronous loading example below:

The workaround is simple. Wrap the map initialization code inside a named function and pass its name as the callback query string parameter inside the Google Maps API script URL. The script loaded this way does not use document.write() allowing you to use the HTML5 async and defer attributes or script element injection; resulting in non-blocking behavior. See the asynchronous loading example below:

Asynchronous loading also allows you to load pages that contain Google Maps via AJAX. I have had success with jQuery.load() since it executes JavaScript code blocks and resources that are present inside fetched content. Sorry, no demo for this!