Home » Speed » Tweak » Defer

JavaScript: Defer Execution

Summary: Defer execution of your JavaScripts with the defer attribute to speed initial content display.

First introduced by Internet Explorer 4, the defer attribute of the script element is now part of the HTML 4 and XHTML specifications. The defer attribute gives a hint to the browser that the script does not create any content so the browser can optionally defer interpreting the script. This can improve performance by delaying execution of scripts until after the body content is parsed and rendered.

Here’s the brief paragraph describing the defer attribute from the HTML 4.01 specification:

When set, this boolean attribute provides a hint to the user agent that the script is not going to generate any document content (e.g., no “document.write” in javascript) and thus, the user agent can continue parsing and rendering.

<script src="script.js" type="text/javascript" defer="defer"></script>

Defer Loading or Execution?

A frequent question online is if the defer attribute delays the loading of an external script until after the body content is parsed. In our tests IE4+ deferred the execution of deferred scripts, not their loading. IE4+ loaded external files sequentially, regardless of the defer attribute value. However, the execution order of scripts can be changed by the defer attribute. The HTML 4.01 DTD gives us a hint here saying that the “UA may defer execution of script.”

<!ELEMENT SCRIPT - - %Script;          -- script statements -->
<!ATTLIST SCRIPT
  charset     %Charset;      #IMPLIED  -- char encoding of linked resource --
  type        %ContentType;  #REQUIRED -- content type of script language --
  src         %URI;          #IMPLIED  -- URI for an external script --
  defer       (defer)        #IMPLIED  -- UA may defer execution of script --
  >

The Bugzilla bug report cited below gives us another hint on how IE works when processing scripts. It appears that IE executes scripts in the following order:

  1. All non-deferred scripts in order of occurrence
  2. Deferred inline scripts in order of occurrence
  3. Deferred external scripts in order of occurrence

So it appears that deferring an external script, regardless of where it’s included, causes it to be executed after all inline scripts, deferred or not. This, it turns out, is the behavior that we observed. The scripts in our test page have the following order:


  Inline Head Deferred
  Inline Head
  External Head Deferred
  External Head
  Inline Body Deferred
  Inline Body

In the case of IE 6/Win98 and IE 6/Win2K, the defer attribute did have an effect on the execution order of the scripts. The first time we ran our test pageon Internet Explorer 6 for Windows 2000 the scripts executed in the following order (see Figure 1):

  Inline Head
  Inline Head Deferred
  External Head
  Inline Body
  Inline Body Deferred
  External Head Deferred
Internet Explorer 6 Windows 2000 defer test output screen shows deferred execution

Figure 1: Internet Explorer 6 Windows 2000 shows deferred execution with the defer attribute

Or does it? When I had Porter Glendenning test our same test page from a remote location, the “Inline Head Deferred” executed later in the execution sequence (see Figure 2).

Internet Explorer 6 Windows 2000 defer test output screen shows deferred execution, but inline head deferred scripts vary

Figure 2: Internet Explorer 6 Windows 2000 can also execute deferred inline head scripts later in the execution sequence

In IE6, deferred inline scripts in the head of XHTML documents exhibited inconsistent execution order. They either executed at the end of the head sequence, or just after the body script executed. The non-deferred scripts are executed in their order of occurrence, but deferred inline scripts execute after any non-deferred scripts within the head or body sections of the page. Deferred external scripts execute after the head and body scripts, deferred or otherwise.

So to defer scripts to the very end of the execution order you can defer external scripts. In this case the defer attribute delays script execution until all other scripts have been executed, in all versions of IE/Windows that we tested.

Firebird, Opera, and IE Mac and the defer attribute

Firebird 0.7 and Opera 7.11 (Win2K) and IE 5.1.7 Mac all executed the scripts in the order of occurrence (see Figures 3 and 4):

  Inline Head Deferred
  Inline Head
  External Head Deferred
  External Head
  Inline Body Deferred
  Inline Body

Firebird 0.7 for Windows 2000 does not support the defer attribute (see Figure 3).

Firebird 0.7 Windows 2000 defer test output screen shows no deferred execution

Figure 3: Firebird 0.7 for Windows 2000 executes scripts in sequential order

Internet Explorer for the Mac does not support the defer attribute and displays the alerts in sequential order (see Figure 4).

Internet Explorer 5.1.7 Mac defer test output screen shows sequential execution

Figure 4: Internet Explorer 5.1.7 Mac shows sequential execution despite the defer attribute

Note that in Firefox, deferred scripts block rendering and parallel downloads, so use the defer attribute with caution. Our you could defer scripts only for IE using browser sniffing, or place them at the end of the body element to enable progressive rendering.

What about HTTP Compression and Deferred JavaScripts?

You can delay the execution of external scripts by placing them just before the end of the closing body tag. However, for older browsers compressed external JavaScripts are not reliably decompressed when they are placed within the body section, only when they are placed within the head are they reliably decompressed. So the defer attribute allows you to defer the execution of compressed JavaScripts, when they are placed within the head of your XHTML documents.

This requirement to place compressed JavaScripts within the head section is a legacy behavior from Netscape’s original specification for JavaScript 1.1. This specification implied that external scripts should appear within the head section of HTML documents. Scripts placed within the body section are not pre-processed, and cannot be compressed. So the defer attribute gives another performance option for webmasters who elect to compress their external scripts (see Speed Up Your SiteChapter 18: “Compressing the Web,” for more details).

Conclusion

The defer attribute gives authors another performance option to speed up the display of their web pages. Deferred scripts are interpreted later in the page execution cycle, allowing non-deferred scripts and body content to be parsed and displayed first. Deferring inline body and external head scripts gave consistent results in our tests. Deferring inline head scripts gave us inconsistent results and should be avoided unless the execution sequence is taken into account. While the defer attribute is only currently supported by Internet Explorer 4+ for Windows, this standards-based technique can help speed up your site for the majority of users today.

Further Reading

Bugzilla RFE: scripts with defer attribute not deferred
The Mozilla request for enhancement bug #28293 includes a discussion of the defer attribute by Mozilla developers. Note that as of January 2004 the bug has not yet been fixed.
Building High Performance Pages: Defer Your Scripts
Briefly describes the benefits and use of the defer attribute first introduced in Internet Explorer 4. Note that in XHTML defer="defer" is the syntax to use. From Microsoft.
Compressing the Web
Chapter 18 of Speed Up Your Site shows how to compress the textual content of web sites. Includes sections on JavaScript compression and associated gotchas.
Defer Attribute | Defer Property
Microsoft describes the syntax of the defer attribute. Note that defer="defer" should be used instead of defer="true" or false for XHTML documents.
JavaScript defer attribute test page
This test page builds a compound alert box using deferred and non-deferred inline and external scripts throughout the page to show how different browsers change the execution order based on the defer attribute.
Scripts in HTML Documents
The HTML 4 recommendation includes the defer attribute to the script element. From the W3C’s HTML 4.01 Specification of December 24, 1999.
Use HTTP Compression
Describes the HTTP compression, or content encoding, standard built into HTTP 1.1 and most modern browsers.
XHTML 1.0
The XHTML specification includes the defer attribute to the script element in both the transitional and strict DTDs.

By website optimization on 16 Jan 2004 AM