Skip to Main Content

Mar 16, 2010 | 6 minute read

JavaScript and Page Loading Performance

written by Armando

No one likes to wait for a Web site to load.

Least of all someone doing some last minute birthday shopping for an expectant niece or nephew or the pressured husband that just realized tomorrow is his anniversary.

Shoppers have very little tolerance for slow loading retail Web sites, therefore, developers should do more to speed up site performance when possible.

YSlow Survey Demonstrates the Problem

I recently took a survey of 25 leading retail Web sites using Yahoo's YSlow Firefox add-on. The tool measures site performance against 35 performance best practices.  And of these best practices, I was most interested in HTTP Requests.

As the good folks at Yahoo say, something like 80% of a page's load time is spent making HTTP requests for images, style sheets, JavaScript, and Adobe Flash or similar. Speed up this processes and a site will load faster, sometimes even if the browser is loading a greater number of kilobytes.

In my little survey, many leading online retail sites performed poorly. For example, when I ran the test, Borders received an overall YSlow grade of D and an overall performance grade of 66. But the site actually got an F for HTTP Requests. Improving this one area could have helped to pull up the site's overall performance score, not to mention make it load faster when would-be shoppers surfed by to get a copy of Seth Grahame-Smith's new tomb, Abraham Lincoln : Vampire Hunter or a DVD of Disney's Up.

Online florist, 1-800 Flowers had an even worse YSlow grade and performance score, and again, an F for HTTP requests. In fact, the site sought to load 27 separate, external JavaScript files and six separate style sheets.

Some site's scores actually varied. When I first tested Amazon, the site scored a D in YSlow, with an overall performance grade of 65. But later, I retested Amazon, and it earned a B, having less than half as many HTTP requests as it had when I first test it. While I cannot be certain why Amazon decided to load fewer JavaScripts and style sheets, I can say  that making fewer HTTP requests had a significant, positive impact on how the site performed.

In my less-than-scientific survey, sites that made fewer HTTP requests generally had better YSlow scores and faster load times. Conversely, sites that made a lot of HTTP requests had poor scores and poor load times.

JavaScript Files can be Road Blocks

JavaScript, which is actually one of my favorite languages, is a leading cause of performance-sapping HTTP requests and a page block. Since while the HTTP request for a JavaScript file is underway the browser is blocked from downloading other resources until after the script has been completely loaded and, in some cases, executed.

New browsers can, in fact, load two or more external JavaScript files simultaneously, but other page elements like images or even text that appear lower in the mark up will still have to wait.

There is an excellent demonstration of how blocking—the concept that a browser stops rendering a page while it loads a JavaScript—effects a page's load time on Steve Souders' High Performance Web Sites Blog. Souders' demonstration cuts a page into two sections—literally above and below a line. The top portion of the page is quickly loaded, but then the browser encounters two external JavaScripts and miscellaneous additional elements. The HTTP requests to get the JavaScript files block any other page elements from loading.

In fact, it takes almost an additional 8 seconds for the balance of the demonstration page to load.

Of course, I should point out that blocking is actually very important. Often one JavaScript file will be dependent on another. We want a JavaScript Library like jQuery or MooTools to load before any files that call functions from the library. Blocking ensures this is the case, since most browsers will not load and execute the files in order.

Addressing HTTP Requests for JavaScript

There are several things that a site developer or designer can do, to minimize HTTP Requests and blocking, thus improving site performance.

The most basic fix is to organize JavaScript files. Older web browsers, like Microsoft's Internet Explorer (IE) 7, can only download a single JavaScript file at a time, so many web developers began organizing all of their JavaScript into a single, often massive, file. By the way, massive is no understatement. When I conducted my aforementioned survey of leading retail sites, I found several extreme examples like Barnes & Noble's site, which called 39 separate, external JavaScript files.

But creating a single, all inclusive JavaScript file is not always best either.

Some browsers, for example Google's Chrome or even IE8, can load files in parallel so that two smaller JavaScript files might load more quickly than one massive file.

And as Kyle Simpson wrote in his article Tame Those Performance Monsters in the March 2010 issue of jsmag, a single combined would not make sense when you were calling libraries like jQuery, which are better downloaded from optimized content delivery networks and which can be cached.

Without a doubt you'll want to organize files—39 is too many, one may not be enough—but some combining should probably take place.

Other potential solutions (improvements) include techniques like XMLHttpRequests (XHR), wrapping scripts in iFrames, and using the defer attribute in script tags. But each of these techniques has limitations.

For security reasons, XHR requires that all of the scripts being loaded and the host page have the same domain, so it won't work if a site needs to load jQuery.

Wrapping scripts in an iFrame will allow the even older browsers to asynchronously load JavaScripts, but you will need to function to access the JavaScripts that were loaded with the iFrame, and you must add more mark up.

The defer attribute, which is part of the World Wide Web Consortium's HTML 4.0 Specification, essentially tells the browser to wait until the page is loaded before executing the enclosed script.

<script language="javascript" defer>

But defer is not supported in every or even most web browsers.

I don't mean to dissuade you from using these solutions, but I want to introduce you to what I believe is a better one.

The LABjs Solution

Kyle Simpson, who I mentioned above, started the LABjs project and has since gotten help from performance guru, Steve Souders, who I also mentioned above. LABjs is a tool for dynamically loading JavaScripts in parallel while preserving the order of execution and dependency.

LABjs also enables the browser to load both JavaScripts and other page elements at the same time, so your images and text, don't have to wait for your JavaScripts.

Implementing LABjs is also pretty easy. You end up replacing mark up like:

<script src="http://jquery-ui.googlecode.com/svn/tags/latest/jquery-1.4.2.js"></script>

<script src="some.js"></script>

<script src="someother.js"></script>

With mark up like:

<script>

$LAB

.script("http://jquery-ui.googlecode.com/svn/tags/latest/jquery-1.4.2.js ")

.script("plugin.framework.js")

.script("myplugin.framework.js").wait()

</script>

According to Simpson's jsmag article, using a page calling three external JavaScript files went from loading in 16.84 sections to loading in just about 6.24 seconds when LABjs was used, demonstrating a significant improvement.

This post was contributed by our guest columnist Armando Roggio. Armando is a journalist, web designer, technologist and the site director for Ecommerce Developer.