Tuesday, March 10, 2009

Steve Souders: Life's Too Short, Write Fast Code (part 2)

By Steve Souders, Member of Technical Staff

I've been working on a follow-up book to High Performance Web Sites called Even Faster Web Sites. As I finish chapters, I talk about the findings at conferences and tech talks. The first three chapters are Split the Initial Payload, Load Scripts Without Blocking, and Don't Scatter Inline Scripts. You can hear about those best practices in my video from Google I/O.

This talk presents the next three chapters: Couple Asynchronous Scripts, Use Iframes Sparingly, and Flush the Document Early.

The adoption of JavaScript is growing, but the blocking behavior of external scripts is well known. That's why it's important to use one of the techniques to load scripts without blocking (see the Google I/O talk). But loading scripts asynchronously means that inlined code that uses symbols from the script must be coupled in some way. Without this coupling, undefined symbol errors occur when the inlined code is executed before the external script arrives.

There are five techniques for coupling asynchronous scripts: hardcoded callback, window onload, timer, script onload, and degrading script tags. All of the techniques work. Degrading scripts tags is the most elegant, but isn't well known. Script onload is the most versatile technique and is the one I recommend people use. In the talk, I then go into detail, including many code examples, on how to load scripts asynchronously and use these coupling techniques to speed up your web page.

Iframes have a negative impact on web pages. They are the most expensive DOM element to create. They block the parent's onload event (although there's a workaround to this problem in Safari and Chrome). Also, the main page can block resources in the iframe. It's important to understand these interactions if you use iframes in your page.

Flushing the document early allows the browser to start rendering the page and downloading resources in the page, even before the entire HTML document has arrived. But getting flushing to work can feel like trying to get the stars to align. You need to understand PHP's output_buffering, HTTP/1.1's chunked encoding, Apache's DeflateBufferSize, the impact of proxies, minimum HTML size requirements in Safari and Chrome, and the need for domain sharding to avoid having the HTML document block other downloads.

If your company wants a better user experience, increased revenues, and reduced operating costs, the key is to create even faster web sites. For more information on these best practices, watch the video below and read the slides.

Check out other talks in this tech speaker series:


  1. This comment has been removed by the author.

  2. What happened to part one?

    It's supposed to be at http://www.youtube.com/watch?v=-QKebcaoUxg but there's a message saying it's been removed...

  3. In case anybody's interested, I adapted Steve's example from the talk to make "good" Google Analytics tracker insert code, using DOM script insertion and script onload to activate the tracker. So, asynchronous lazy-loading goodness keeps GA out of the way of your pages loading fast! More info and code here.

    I do wonder if Steve's using GA as his "bad" example will filter its way to the Urchin/GA team. It would be lovely for GA and maybe even Adsense (haha) to work sanely and efficiently out-of-the-box.

  4. I implemented the onload technique for calling a function once a script has loaded and noticed my code only executed sometimes in IE.

    I found that you need to check for *both* the "loaded" and the "complete" readyState's, otherwise your code block will not run when the external file you're loading has been cached.

  5. Technique 5 has a major drawback: It tights the script to its name! If the user renames menu-degrading.js to menu-degrading-1.0.js the loading is broken