Best practices for speeding up your web site

making web/javascript 2008.11.09 01:36
/ Yahoo! The Exceptional Performance team

Minimize HTTP Requests

80% of the end-user response time is spent on the front-end.
  • Combined files are a way to reduce the number of HTTP requests by combining all scripts into a single script, and similarly combining all CSS into a single stylesheet. Combining files is more challenging when the scripts and stylesheets vary from page to page, but making this part of your release process improves response times.
  • CSS Sprites
  • Image maps
    only work if the images are contiguous in the page such as a navigation bar. But, it is not accessible too, so it's not recommended.
  • Inline images not yet supported across all major browsers.
As described in Tennu Theurer's blog post Browser Cache Usage - Exposed!, 40~60% of daily visitors to your site com in with an empty cache.

Use a Content Delivery Network

Add an Expires or a Cache-Control Header
for static components: implement "Never expire" policy by setting far future Expires header
for dynamic components: use an appropriate Cache-Control header to help the browser with conditional requests.
At Yahoo! we often make this steo part of the build process: a version number is embedded in the component's filename, for example, yahoo_2.0.6.js

Gzip Components
Gzipping generally reduces the posponse size by about 70%.

Put Stylesheets at the Top
Putting stylesheets in the HEAD allows the page to render progressively.(Some browsers(including IE) block rendering to avoid having to redraw elements of the page if their styles change. The user is stuck viewing a blank white page.)

Put Scripts at the Bottom
The problem caused by scripts is that they block parallel downloads. The HTTP/1.1 specification suggests that browsers download no more than two components in parallel per hostname. While a script is downloading(not images), however, ths browser won't start any other downloads, even on different hostnames.
In some situations it's not ezsy to move scripts to the bottom. An alternative suggestion that often comes up is to use deferred scripts. The DEFER attribute indicates that the script does not contain document.write, and is a clue to browsers that they can continue rendering. (Unfortunately, Firefox doesn't support the DEFER attribute.)

Avoid CSS Expressions
CSS expressions are a powerful (and dangerous) way to set CSS properties dynamically. The problem width expressions is that they are avaluated more frequently than most people expect. Not only are they evaluated when the page is rendered anc resized, but also when the page is scrolled and even when the user moves the mouse over the page.
if the style property must be set dynamically throughout the life of the page, using event handlers instead of CSS expressions is an alternative approach.

Make Javascript and CSS External
question: Should Javascript and CSS be contained in external files, or inlined in the page itself?
The key factor is the frequency with which external JavaScript and CSS components are cached relative to the number of HTML. If users on your site have multiple page views per session and many of your pages re-use the same scripts and stylesheets, there is a greter potential bebefit from cached external files.
The only exception where inlining is preferable is with home pages, such as Yahoo!'s front page and My Yahoo!. Home pages that have few (perhaps only one) page view per session may find that inlining JavaScript and CSS results in faster end-user response times.
One such technique is to inline JavaScript and CSS in the front page, but dynamically download the external files after the page has finished loading. Subsequent pages would reference the external files that should alredy be in the browser's cache.

Reduce DNS Lookups
The DNS maps hostnames to IP addresses. It typically takes 20~120 milliseconds for DNS to lookup the IP address for a given hostname. The browser can't download anything from this hostname until the DND lookup is completed.
DNS looups are cached for better performance. Most browsers have their own caches, separate from the OS's cache. As long as the browser keeps a DNS record in its own cache, it doesn't bother the OS with a request for the record.
IE cache DNS loopups for 30 minutes by default, FF caches DNS loopups for 1 minutes.
Reducing the number of unique hostnames has the potential to reduce the amount of parallel downloading that takes place in the page. My guideline is to split these components acress at least two but no more than four hostnames. This results in a good compromise between reducing DNS lookups and allowing a high degree of parallel downloads.

Minify Javascript and CSS
Two popular tools for minifying Javascript code are JSMin and YUI compressor(also minify CSS).
Even if you gzip your scripts and styles, minifying then will still reduce the size by 5% or more.

Avoid Redirects
Use of redirects include using Alias and mod_rewrite if the two code path are hosted on the same server. If a domain name change is the cause of using redirects, an alternative is to create a CNAME(a DNS record that creates an alias pointing from one domain name to another) in combination with
Alias and mod_rewrite.

Remove Duplicate Scripts
Unnecessary HTTP requests happen in IE, but not in Firefox. In IE, if an external script is included twice and is not cacheable, it generates two HTTP requests during page loading. Even if the script is cacheable, extra HTTP requests occur when the user reloads the page.

Configure ETags
Entity tags(ETags) are an mechanism that web servers and browsers use to determine whether the component in the browser's cache matchs the one on the origin setver. (An "entity" is another word a "component": images, scripts, stylesheets, etc.) ETags were added to provide a mechanism for validating entities that is more flexible than the last-modified date. An ETag is a string that uniquely identifies a specific version of a component.
... problems ...
If you're not taking advantage of the flexible validation model that ETags provide, it's better to just remove the ETag altogether. Removing the ETag reduces the size of the HTTP headers in both the response and subsequent requests. In Apache, this is done by simply adding the following line to your Apache Configuration file: FileETag none

Make Ajax Cacheable
The most important way to improve the performance of Ajax is to make the responses cacheable, as discussed in Add a Expires or a Cache-Control Header. Some of the other rules also apply to Ajax: Gzip Components, Reduce DNS Lookups, Minify Javascript, Avoid Redirects, Configure ETags.
Even though your Ajax responses are created dynamically, and might only be applicable to a single user, they can still be cached. Doing so will make your Web 2.0 apps faster.

Flush the Buffer Early
In PHP you have the function flush(). It allows you to send your partially ready HTML response to the browser so that the browser can start fetching components while your backend is busy with the rest of the HTML page. The benefit is mainly seen on busy backends or light frontends.
A good place to consider flushing is right after the HEAD because the HTML for the head is usually easier to produce and it allows you to include any CSS and JavaScript files for the browser to start fetching in parallel while the backend is still processing.
Yahoo! search pioneered research and real user testing to prove the bebefits of using this technique.

Use GET for AJAX Requests
The Yahoo! Mail tean found that when using XMLHttpRequest, POST is implemented in the browsers as a two-step process: sending the headers first, then sending data. So it's best to use GET, which only takes on TCP packet to send (unless you have a lop of cookies). The maximum URL length in IE is 2K, so if you send more than 2L data you might not be able to use GET.

Post-load Components
"What's absolutely required in order to render to page initially?"
JavaScript is an ideal candidate for splitting before and after the onload event.
Tools to help you out in your effort: YUI Image Loader, YUI Get utility

Preload Components
There are actually several types of preloading:
Unconditional preload: as soon as onload fires, you go ahead and fetch some extra components. Check for an esample of how a sprite image is requested onload.
Conditional preload: based on a user action you make an educated guess where the user is headed next and preload accordingly. On you can see how some extra components are requested after you start typing in the input box.
Anticipated preload: preload in advance before launching a redesign. Your old site can use the time the browser is idle and request images and scripts that will be used by the new site.

Reduce the Number of DOM Elements
YUI CSS utilities
How many DOM elements are too many? For example the Yahoo! Home Page is a pretty busy page and still under 700 elements (HTML tags).

Split Components Across Domains
Make sure you're using not more than 2~4 domains because of the DNS lookup penalty.
For more informatin check "Maximizing Parallel Downloads in the Carpool Lane" by Tenni Theurer and Patty Chi.

Minimize the Number of iframes
<iframe> pros:
- Helps with slow third-party content like badges and ads
- Security sandbox
- Download scripts parallel
<iframe> cons:
- Costly even if blank
- Blocks page onload
- Non-semantic

No 404s

Reduce Cookie Size
"When the Cookie Crumbles"
by Tenni Theurer and Patty Chi

Use Cookie-free Domain for Components
When the browser makes a request for a static image and sends cookies together with the request, the server doesn't have any use for those cookies. So they only create network traffic for no good reason. You should make sure static components are requested width cookie-free requests. Create a subdomain and host all your static components there.

Minimize DOM Access
- Cache references to accessed elements
- Update nodes "offline" and then add them to the tree
- Avoid fixing layout with Javascript
For more information check "High Performance Ajax Applications" by Julien Lecomte.

Develop Smart Event Handlers
Using event delegation is a good approach.
DOMContentLoaded is the event you might consider using instead of onload, but until it's available in all browsers, you can use the YUI Event utility, which has an onAvailable method.

Choose <link> over @import
In IE @import behaves the same as using <link> at the bottom of the page, so it's best no to use it.

Avoid Filters
The problem with AlphaImageLoader filter is that is blocks rendering and freezes the browser while the image is being downloaded. It also increases memory consumption and is applied per element, not per image, so the problem is nultiplied.
The best approach is use gracefully degrading PNG8 instead, which are fine in IE. If you absolutely need
AlphaImageLoader, use the underscore hack _filter as to not penalize your IE7+ users.

Optimize Images

Optimize CSS Sprites
Arrainging the images in the sprite horizontally as opposed to vertically usually results in a smaller file size. Combining similar color in a sprite helps you keep the color count low, ideally under 256 colors so to fit in a PNG8.
"Be mobile-friendly" and don't leave big gaps between the images in a sprite.

Don't Scale Images in HTML
Don't use a bigger image than you need just because you can set the width and height in HTML.

Make favicon.ico Small and Cacheable

Keep Components under 25K
iPhone won't cache components bigger than 25K. (uncompressed size)
"Performance Research, Part 5: iPhone Cacheability - Making it Stick" by Wayne Shea and Tenni Theurer.

Pack Components into a Multipart Document
Packing components into a multipart document is like an email with attachments, it helps you fetch several components with one HTTP request (remember: HTTP request are expensive).

티스토리 툴바