Not everyone is blessed with a high-speed Internet connection. Even if everyone were, there can be hundreds of reasons why your Web application seems slow and sluggish. In this age of ever-increasing broadband speed, don't think that you shouldn't pay attention to page load times. Shave off valuable seconds of your page load times and even more valuable milliseconds of your request and response times. You'll create a better experience for your visitors.
After reading this article, you will have a better understanding of the basics of Web page load time optimization. You'll also have the tools and knowledge to better identify and judge slow-loading page segments and bottlenecks.
Ideally, you should have Mozilla Firefox installed. You should also have an understanding of Web development in general. The topics involved in this article are not difficult, but they'll "click" faster if you know about topics such as Hypertext Markup Language (HTML), Cascading Style Sheet (CSS), and the JavaScript™ programming language. You do not need an integrated development environment (IDE): You can just follow along with your favorite editor.
You must have JavaScript enabled in your browser. Also, to follow along with the segments on Firebug and YSlow, you need the Firefox Web browser installed.
Many people access the Internet through some kind of broadband connection—be it DSL, cable, fiber-optic, or some other method. However, those users who don't have access to such technologies are forced to use dial-up connections. You've undoubtedly forgotten the dial-up experience, but try to remember back when you actually could see a Web page load line . . . by . . . line . . . .
Fortunately, help is on the way for these poor folks. You can improve their experience by decreasing the time required for pages to load. But, users on dial-up are not the only reason to cut back on load and response times. Many Web designers have erroneously assumed that the advent of high-speed Internet connections would make Web site performance optimization irrelevant. This can't be further from the truth. For instance, many tasks that used to be performed using desktop software can now be done online. Getting the same responsive feel in a Web application as you have in desktop software can be quite difficult, and performance optimization is incredibly important. Luckily, several tools and best practices are available to decrease response and load times for a much snappier experience.
With all optimization-oriented tasks, you must have tools to diagnose bottlenecks and identify problems. Two of the most widely used tools in Web development today are Firebug and YSlow—both Firefox plug-ins that are open source and available at no cost.
Firebug (see Resources) is one of the most popular of the Firefox extensions and an application that makes Web developers' lives much easier. It includes a lot of very useful features, such as:
- JavaScript debugging
- The JavaScript command line
- Monitoring JavaScript performance and tracking
XmlHttpRequests - Logging to the Firebug console
- Tracing
- Inspect HTML elements and live editing of HTML code
- Live editing of CSS documents
YSlow (see Resources) analyzes Web pages and tells you why they're slow based on the rules for high-performance Web sites drafted by Yahoo! (see Resources). YSlow is a Firefox add-on integrated with Firebug, so you need to have Firebug installed before you can install and start using YSlow.
Both Firefox extensions are easy to install. To install Firebug, perform the following steps:
- Open Firefox, and go to the Firebug home page.
- Install the current version of Firebug.
- If Firefox is configured to block pop-ups, click Allow to allow the installation window to open. Otherwise, click Install Now.
- Restart Firefox.
You can now access Firebug from the Tools menu. You can open Firebug in a new window or in the existing window (see Figure 1).
Figure 1. Firebug's HTML and Style views of the Firefox start page
After you have installed Firebug, the next step is to install YSlow. To do so, perform the following steps:
- Open Firefox, then go to the YSlow home page.
- Install the add-on, then restart Firefox.
Note: Unlike many other Firefox extensions, YSlow does not start automatically. It must be activated first.
- To activate YSlow, right-click its icon in the status bar, then click Autorun.
Figure 2 shows the results of the YSlow performance analysis.
Figure 2. YSlow performance analysis of the Firefox start page
Common sense: Remembering design rules
It is surprising how often simple design rules are neglected, resulting in non-optimized, slow-to-download pages. Bear the following rules in mind, and your pages will load more quickly.
Extensible HTML (XHTML) has many advantages, but
its disadvantages are equally notable. XHTML might make your pages
more standards-compliant, but its verbose use of tags (the mandatory
<start> and <end> tags) means more code for the browser to
download. So, all things being equal, try to use less XHTML coding in
your pages to decrease page size.
If you really can't go
without XHTML, try to optimize it as much as possible. For instance,
remove white space and adopt strict XHTML coding practices for faster
downloads and parsing. To enforce XHTML Strict, add the following
doctype statement to your document:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
XHTML 1.0 Strict is the equivalent of Strict HTML 4.01 and includes elements and attributes that have not been marked as deprecated in the HTML 4.01 specification. Remember that a couple of tags that were allowed in XHTML Transitional are not allowed in XHTML Strict, for instance:
<center><font><iframe><strike><u>
Before blogs (and news sites in general) became popular, it was considered bad practice to have pages that scroll horizontally or even vertically. The page size was small, and it was more difficult (although certainly not impossible) to fill up the screen nicely. Now, with blogs and content-driven Web sites, it is not uncommon to see long pages many hundreds of kilobytes in size. Yes, you have more space to fill, but this doesn't mean that you must fill it with large background images, tons of tables, or simply lots of content. Be minimalistic: Less is more. Cluttering your pages with all kinds of images, videos, ads, and so on is a usability nightmare, as well, so think twice before you visually oversaturate the page.
Don't use images to represent text
Unlike fonts, where you have little control over the way they appear in different browsers, images always appear exactly how you designed them. But this isn't an excuse to use images in place of text.
One of the most frequent examples of using images to represent text is in navigation. Fancy buttons may look appealing, but they load slowly. Additionally, images are still not indexed directly by search engines, so using images for navigation is a search engine optimization (SEO) sin. There's no reason to use images of text to represent text when there are many CSS tricks for creating good-looking buttons without images.
One particular type of navigation well suited to CSS styling is tab-style navigation, shown in Figure 3.
Figure 3. Tab-style navigation
Besides being "low cal," this way of implementing navigation is also more Web-standards based.
The code in Listing 1 and Listing 2 implements tab-based navigation as pure CSS/XHTML.
Listing 1. CSS document for tab-based navigation
#nav {
float:left;
width:100%;
background:#E7E5E2;
font-size:95%;
line-height:normal;
border-bottom:1px solid #54545C;
}
#nav ul {
margin:0;
padding:10px 10px 0 50px;
list-style:none;
}
#nav li {
display:inline;
margin:0;
padding:0;
}
#nav a {
float:left;
background:url("tableftK.gif") no-repeat left top;
margin:0;
padding:0 0 0 4px;
text-decoration:none;
}
#nav a span {
float:left;
display:block;
background:url("tabrightK.gif") no-repeat right top;
padding:5px 15px 4px 6px;
color:#FFF;
}
/* Commented Backslash Hack hides rule from IE5-Mac \*/
#nav a span {float:none;}
/* End IE5-Mac hack */
#nav a:hover span {
color:#FFF;
background-position:100% -42px;
}
#nav a:hover {
background-position:0% -42px;
}
#nav a:hover span {
background-position:100% -42px;
}
|
Listing 2. HTML code for tab-based navigation
<div id="nav">
<ul>
<li><a href="#" title="Link 1"><span>Link 1</span></a></li>
<li><a href="#" title="Link 2"><span>Link 2</span></a></li>
<li><a href="#" title="Link 3"><span>Link 3</span></a></li>
<li><a href="#" title="Longer Link Text"><span>Longer Link Text</span></a></li>
<li><a href="#" title="Link 5"><span>Link 5</span></a></li>
</ul>
</div>
|
Cookies might be small files, but browsers still need to download them. Large cookies take longer to download, which in turn increases the time the browser takes to load the page. That's why it's important to keep cookies as small as possible to minimize the impact on browser response times.
Additionally, setting an earlier
expire date, or not setting an expire date at all decreases the response
time. To set the expire date for a cookie
in the PHP language, use this code:
<?php $expire = 2592000 + time(); // Add 30 day’s to the current time setcookie(userid, “123rrw3”, $expire); ?> |
This
snippet sets the cookie called userid as
well as the expire date to be 30 days from
the current date.
Don't include JavaScript code you don't need, and externalize whenever possible
Similar to cookies, JavaScript files take time to download, which inevitably slows down the whole page. So, use JavaScript files wisely—only when it's really necessary—and optimize your scripts for size and speed.
Another way to speed up JavaScript download times is to use external files instead of including the script inline. This approach is applicable to CSS, as well, because externalized files get cached by the browser, whereas CSS or JavaScript that is coded inline (in the HTML page itself) gets loaded every time along with the HTML. To externalize your CSS and JavaScript code loading by referencing them in your HTML, use code like this:
<link href="/stylesheets/myStyle.css" media="all" rel="Stylesheet" type="text/css" /> <script src="/javascripts/myJavascript.js" type="text/javascript"></script> |
Tables used to be the main building block of Web pages, but now they're considered bad practice as page layout elements. Sometimes, you must use tables (and they're considered good practice for the display of tabular data). If you do, explicitly specify the widths and heights of the table cells, rows, and columns; otherwise, browsers have to perform many operations to calculate how to display them, which slows down page loading:
<td width="50px" height="10px">...</td> |
Remove anything you don't need
Maybe this is the most obvious tip of all, but it is also one of the most frequently forgotten. I mentioned that "less is more": It's not only visually appealing to a broader spectrum of users, but it also means less stuff to download and process. If you really need to put a lot of stuff on your Web page, consider splitting the page into two, three, or more separate pages.
Tips for optimizing your Web pages
You can use several methods to optimize your Web pages, including compressing your JavaScript files, using Hypertext Transfer Protocol (HTTP) compression, and setting your image sizes.
Compress and minify your JavaScript files
JavaScript files can be quite impressive in size, which means that their download times can exceed that of all other components combined, in some cases. One approach to this problem is to compress JavaScript files. You can use GNU zip (gzip) to do so, because many browsers support this compression algorithm.
Another alternative is to minify. Minification removes from the code all the unnecessary characters, such as tabs, newlines, and spaces. It also removes comments left in the code and white spaces, further reducing the file size. You can use minification for both external and internal style sheets. The two most popular minification tools are JSMin and YUI Compressor (see Resources).
Use HTTP compression, and always use lowercase divs and class names
You can reduce the traffic between the server and the browser by using
HTTP compression. You can configure HTTP compression in Apache (the
.htaccess file), or you can include it in your pages (in the case of
PHP, by using an HTTP_ACCEPT_ENCODING
header). But beware: Not all browsers support compression. Even for
those that do, compression and decompression loads the processor. To
enable blanket—that is, all text and
HTML—compression in Apache, use the following
command:
AddOutputFilterByType DEFLATE text/html text/plain text/xml |
Also, think about what you're trying to compress. Images, music, and videos are already compressed at the time of their creation, so you can limit your compression efforts to HTML, CSS, and JavaScript files.
One more trick to lessen the effort with compression is to use
lowercase <div> elements and class
names. Because case sensitivity and the fact that the compression
scheme used is lossless, <header> is
different from <Header> and is
compressed as two different tags. In the following example, the Important class is different to the
compressor than the important class, which
means that to the compressor, they represent two different things and
therefore are compressed individually as two different pieces of text.
<div class="Important">read this!</div> <div class="important">This will cost you some valuable load time</div> |
This attention to detail might not sound like a big deal. But when you're optimizing your files, every little bit counts— literally.
As with table cells, rows, and columns, when you don't explicitly set the image size, the browser needs to perform calculations to display the image, which slows down processing. Additionally, in certain cases, images sizes can be calculated incorrectly, and, as a result, the image might appear distorted.
Use CSS image maps for heavily used decorations
Using image maps instead of multiple images is another way to decrease load times, because downloading the separate parts of the image simultaneously speeds the download process for the whole page. Or, you can use something known as CSS sprites (see Resources.) CSS sprites help decrease the number of HTTP requests. A single image can hold all the image elements needed to decorate or lay out a page. You use CSS to choose (by calling certain positions and dimensions) which map is used for a particular element.
Delay your script loading, if possible
I mentioned earlier that not including JavaScript code you don't absolutely need speeds up loading and processing. But what if you have already cut to the bone and can't skip including JavaScript code on your page?
In this case, one of the possible ways to speed page download times is to put the script at the bottom of the page, so that the page loads more quickly. Often, browsers download no more than two parallel objects (from the same domain); if one of those objects is a piece of JavaScript code, the download of the other page components will halt until the script is downloaded. When you put the JavaScript code at the bottom, it will (in most cases) download last, after the other components.
Use the Firebug extension to trace which files load slowly, and I bet that your JavaScript files are among the slowest. Compressing JavaScript files helps, but it might be not all you need. You can defer JavaScript loading by using the following snippet:
var delay = 5;
setTimeout("heavy();", delay * 1000);
|
This code delays the call to the heavy()
method for five seconds. You can use this code in combination with the
next trick to delay the loading of the JavaScript file entirely.
Load JavaScript files on demand
To load JavaScript on demand, use the import() function, shown in Listing 3.
Listing 3. The import() function
function $import(src){
var scriptElem = document.createElement('script');
scriptElem.setAttribute('src',src);
scriptElem.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild(scriptElem);
}
// import with a random query parameter to avoid caching
function $importNoCache(src){
var ms = new Date().getTime().toString();
var seed = "?" + ms;
$import(src + seed);
}
|
You can also verify that a function has been loaded and, if it hasn't, load the JavaScript file. To do so, use the code in Listing 4.
Listing 4. Verify that a function has loaded
if (myfunction){
// The function has been loaded
}
else{ // Function has not been loaded yet, so load the javascript.
$import('http://www.yourfastsite.com/myfile.js');
}
|
Note: You could use the defer
attribute, but not all browsers— including
Firefox— support it.
CSS files don't have to be large if you optimize and maintain them properly. CSS files with many orphaned classes, for example, affect download times. As with JavaScript files, you need to optimize your CSS files to include everything you need, yet be reasonable in size. Also, use external files rather than inline definitions to accommodate the browser's caching mechanism.
Use a content-distribution network
Content-distribution networks (CDNs) are another great way to improve download times. When you put your static images on many servers around the Internet, users can download them from whichever server is closer to them. Besides, most CDNs run on fast servers, so no matter how loaded the server is, it will still respond more quickly than a small, overloaded server.
Use multiple domains for your assets to increase connections
An additional advantage of CDNs is that they are a separate domain. Because your browser limits the number of concurrent connections to a single domain, whenever a page loads, it's easy to occupy all the threads. So, the connection to other assets is delayed. However, your browser can open new threads or connections to other domains; therefore, any asset loaded from another domain is loaded concurrently with all the other assets.
Use Google Gears when available
Using Google Gears (see Resources) is
another great way to spare your users from downloading the same
content over and over again. Gears allows users to access Web
applications offline, but also allows for the persisting of page
elements onto the user's computer. So, frequently loaded but not
updated content could be stored in the Gears database, which is an
SQLite3 relational database-management system. All next requests to the same content could be loaded directly
from the database instead of from the server.
After you've installed Gears, get the gears_init.js file for easy access to the Gears factory and application programming interface (API), save it as gears_init.js, and reference it in your code as follows:
<script type="text/javascript" src="gears_init.js"></script> |
To determine whether you have Gears installed, use the code in Listing 5.
Listing 5. Determine whether Gears is installed
<script>
if (!window.google || !google.gears) {
location.href = "http://gears.google.com/?action=install&message=<welcome message>"
+ "&return=<return url>";
}
</script>
|
If you don't have Gears installed, the code presents you with the URL at which you can download it.
When everything is validated and Gears is installed, you can test the incredibly useful database feature of Gears by using the JavaScript code in Listing 6.
Listing 6. Test database features
<script type="text/javascript">
var db = google.gears.factory.create('beta.db');
db.open('database-test');
db.execute('create table if not exists Test' +
' (Phrase text, Timestamp int)');
db.execute('insert into Test values (?, ?)', ['Monkey!', new Date().getTime()]);
var rs = db.execute('select * from Test order by Timestamp desc');
while (rs.isValidRow()) {
alert(rs.field(0) + '@' + rs.field(1));
rs.next();
}
rs.close();
</script>
|
This code creates a local database on your computer or server named db. Create a table named Test if it doesn't exist already, and insert some test data (Monkey! and the time). The code retrieves the data from the database and presents it as alerts in the browser.
Imagine the possibilities!
The Graphic Interchange Format (GIF) and Joint Photographic Experts Group (JPEG) image formats are past: Portable Network Graphic (PNG) is the format of the future. Of course, you can't say that GIF and JPEG are dead or that PNG doesn't have its disadvantages, but all things being equal, PNG provides good quality with an optimal file size. So, if you have the choice, use PNG images whenever possible.
Keep your Ajax calls short and to the point
When techniques collectively known as Asynchronous JavaScript + XML (Ajax) came along a couple of years ago, they provided a revolutionary method for handling page requests and responses. However, users on dial-up might never be able to experience its real advantages, because in many cases, Ajax requires a lot of communication between browsers and servers. So, if you can keep your Ajax calls short and to the point, you can prevent the user spending endless time waiting in vain for elements to refresh or respond.
Make one big Ajax call and handle the client data locally
If short Ajax calls aren't possible or if they don't provide the desired result, consider the alternative: one big Ajax call to get everything you need, then leave the client to process the data locally. In this way, the client waits once (to get the data in), but after that—when no communication between the browser and the server is necessary—things will process much more quickly. Of course, there's more to Ajax optimization than I can include in this tutorial. If you want to learn more about Ajax, see Resources.
Here's another common-sense tip that's frequently forgotten. Although there is hardly a sane Web developer who doesn't test his or her applications before launching them, sometimes maintenance tasks get sidelined from testing or new features are added too quickly and without enough thought or testing. The result is that the rest of the script gets slowed down.
If you're adding a new function, try it out first in a sandbox—preferably completely outside the rest of the application—to see it behave as a single function. That way, you can check, recheck, and analyze performance and response times without having to cope with the rest of the Web application. Then, when the new function behaves as it should, you can introduce it into the rest of the application and run it against other tests, knowing that the feature itself behaves as expected.
Self-reflection is good advice on many fronts. Luckily, in the case of development, we have tools to help with this and make the practice as objective as possible. A tool like JSLint (see Resources) that, as the site proclaims, "may hurt your feelings", is invaluable because it presents you with all your potential code shortcomings—shortcomings that not only make for more challenging-to-debug problems but also for potentially longer response times.
Check your JavaScript code for errors or bad coding practices using JSLint
You don't have to be a perfectionist to try to make your JavaScript code look great. However, many developers don't take code analysis in earnest and often skip this step of the development process. Unfortunately, errors and bad coding practices are not only unprofessional but can also slow down your application. When the browser is fighting errors and bad coding practices, loading not only takes more time but can also lead to difficult-to-debug errors.
So, if you want your code to look good, consider using code-analysis tools. Different tools are available, but one of the best for the JavaScript language is JavaScript Lint, or JSLint (see Resources). You can also use Firebug, but JSLint is more pedantic, and it's included in YSlow.
Check for orphaned files and missing images
Checking for orphaned files and missing images is a wise thing to do. Most Web developers check bad file references, but it's worth mentioning. Missing files are problematic because they result in error messages such as "The image/page cannot be displayed." But in terms of Web page speed optimization, they have a larger disadvantage: When the browser is looking for a missing or orphaned file, it's consuming resources, which leads inevitably to slowing down page processing. So, run a check for orphaned or missing files, including misspelled file names.
The YSlow Firebug extension will make subjective Web page analysis a thing of the past. Using the definitive rules for high-performance Web sites as drafted by Yahoo!, YSlow analyzes Web pages and tells you why they're slow.
Analyze your pages using YSlow
YSlow is a relatively small but extremely useful Firefox extension. When you launch YSlow, the extension opens in the lower part of the browser, as shown in Figure 4.
Figure 4. The YSlow extension in Firefox
Figure 4 shows the Performance view, in which you see how YSlow rates the performance of your page along with whatever issues the extension has detected. Clicking a link in the list opens a page with explanations of the error. If there is a page component that you can improve, YSlow suggests improvements.
In the Inspect view, shown in Figure 5, you can dissect the page element by element. One of the most helpful features of the Inspect view is that it refreshes automatically when you move the mouse pointer over the page, so you don't have to scroll through long lines of code to find the line you need to inspect.
Figure 5. The YSlow Inspect view in Firefox
As you can guess from its name, the Stats view—shown in Figure 6—shows statistical data about the current page. This data includes empty and primed caches and cookies.
Figure 6. The YSlow Stats view in Firefox
The Components view, which is shown in Figure 7, lists the components on the current page. The data displayed about each component includes the file type and path, when the page expires, and the HTTP response headers. Clicking a component opens that component for viewing. Click a column heading to sort the table in ascending or descending order.
Figure 7. The YSlow Components view
YSlow is a small, useful extension that can help you a lot in your efforts to make your pages load more quickly. If you haven't tried yet, you have no more excuses not to do so now.
Optimizing your Web pages for speed is hardly rocket science. In fact, you can often achieve speed optimization with minimal effort. If you follow the tips in this article along with Web development best practices, you won't have to go extra miles to make your pages load more quickly.
It never hurts to gather many page-optimization tips in one place, and I hope this article provides a valuable resource. However, if you think that the list of speed optimization starts and ends with the tips presented here, you're in for a surprise. But even if you follow just these 20+ tips, your pages will load more quickly and your users will be happier—no matter whether they run on dial-up or on a dedicated broadband line.
Learn
- Check out Wikipedia for general
information about broadband Internet access and metrics.
- Read the rules
of high-performance Web sites as drafted by the Yahoo! Exceptional
Performance team.
- Read Martin Brown's article, "Using
HTTP Compression" (ServerWatch, June 2005), for details about the
aspects surrounding HTTP compression.
- Learn about CSS
sprites—what they are and how you can use them to
speed up image load times.
- Learn how to speed up JavaScript load times.
- Read Jesse Skinner's developerWorks
article, "Where
and when to use Ajax in your applications" (February 2008).
- Learn more about the gzip compression library.
- The developerWorks Web
development zone is packed with tools and information for Web 2.0
development.
-
developerWorks technical events and Webcasts: Stay current with
the latest technology.
-
Technology bookstore: Browse for books on these and other
technical topics.
Get products and technologies
- Minify your
JavaScript files to the absolute minimum with JSMin.
-
YUI Compressor is
Yahoo!’s JavaScript compressor and part of the Yahoo! UI Library. This
site also provides excellent reading into the different aspects that go
into compressing code in general and how the ideal code obfuscates side
effects.
-
JSLint helps you identify bad coding
practices.
-
Firebug is a Firefox add-on that puts
a wealth of development tools at your fingertips.
- Discover and
download Google Gears.
-
YSlow is a Firebug add-on
developed by Yahoo! that analyzes your pages and tells you why they are
slow.
Discuss
-
developerWorks
blogs: Check out developerWorks blogs and get involved in the developerWorks
community.

Marco Kotrotsos is a developer with 10 years of experience building software systems ranging from enterprise-class applications for top insurance companies to administrative tools for SMBs and Web applications for startups. Marco is the founder of Incredicorp, which focuses on helping startups and small businesses get their product to market. He collaborates with technical experts on leading-edge topics such as semantic Web, AI, CSS3, and semantic search.





