Google PageSpeed Double Loading: A Third Party Blind Spot

As humans we often trust a product or tool, and innocently believe it works as expected. However, in today’s complex web world with multiple factors at play and products changing on daily basis, this trust could turn into a big blind spot.

Two of the most popular dynamic page optimization solutions are Google’s PageSpeed products, one a module for Apache, the other an online service.

The main advantage of both products is that they apply optimizations automatically without requiring changes to site content, configuration, or coding. The products apply several types of optimizations, all configurable by the site. One particular optimization feature is the “Defer JavaScript,” which defers execution of JavaScript until page load is complete – a great way to improve the page load time and the user’s perceived load time.

While recently troubleshooting a client issue, we identified a problem with the Defer JavaScript module. During testing we noticed that jQuery library was being loaded by the browser twice, though the HTML only referenced it once. After careful troubleshooting, it turned out to be the PageSpeed feature in certain browsers and OS.

Consider the following HTML:

In the code above we are using PageSpeed’s “Defer Javascript” to defer the loading of jQuery.

This results in the following in the network panel in Chrome devtools:

We can see in the Initiator column that the parser initiated the request to jQuery. This was then followed by a request to the Defer JavaScript library. Immediately after is a request to jQuery again, but this time initiated by the Defer JavaScript library – and luckily served out of cache.

Now, since this is a simple page built to illustrate the problem, it is easy to identify the double request, and the impact was negligent since it came out of cache. However, the client’s page that this was identified on was much more complex and comprised of many more requests. In the live example, the repeat requests were separated by so many requests that when the Defer JavaScript library was added to the page, the problem wasn’t noticed.

The lesson here is that when making changes to a page, always measure before and after. Are the expected amount of requests being triggered, or are there more than there should be? Are more bytes being served than expected? Is there an impact on performance?

The other problem we noticed in the client’s page was that the second request did not always come from cache; sometimes Chrome on Mac loaded the same jQuery library twice.

We noticed this same issue occurring on various pages including PageSpeed’s own example page. In their case, the duplicate request also didn’t come from cache and the downloaded file size was the same (according to devtools).

One of the hard lessons we have learned at Catchpoint is to never trust a single tool, and one should always cross reference and check in a different tool to be safe. Therefore, we made sure Wireshark was running and repeated the test. Here is the packet capture that it provided:

The Wireshark capture confirmed that there were two requests made. In this example, the file size was small so the consequence of this problem is minimal, but had these duplicate requests been larger, and if this was on a mobile device, the impact would be even worse.

Sadly, for our client who reported this problem, the above scenario occurred with jQuery.

Downloading 33KB is a pretty significant impact both on the user and the site’s bandwidth bill. It is unclear what the impact is across the web, or what devices and browsers are exactly impacted. According to Datanyze, mod_page_speed is used by 100,895 sites.

It is unclear how many of these sites use the “Defer JavaScript” feature, but for those using it, we encourage you to take a close look at this blind spot to make sure that your pages aren’t being affected as well. Test your pages on various browsers and operating systems, and ensure your libraries are not double loading.

Note: Ensure you test multiple times in the same browser and device, as the problem can happen intermittently. When testing ensure you do not enable “Disable cache” in the browser’s developer tools, as this feature will cause the second request to always load again from server – it is not what happens to actual end users. To defeat caching in between tests, simply delete the cache manually.