Defer JavaScript

Configuration

The 'Defer JavaScript' filter is enabled by specifying:

Apache:
ModPagespeedEnableFilters defer_javascript
Nginx:
pagespeed EnableFilters defer_javascript;

in the configuration file.

Description

Warning: Defering JavaScript can often dramatically improve the rendering speed of a site, but careful evaluation is required to ensure the site continues to operate properly. The limitations are described below.

defer_javascript tries to defer JavaScript execution until page load. It defers this by changing the type and src attributes of <script> elements on the HTML page to data-pagespeed-orig-type and data-pagespeed-orig-src respectively. It also adds a new type attribute whose value is set to text/psajs. A window.onload handler is added to the HTML, which executes all the deferred scripts.

defer_javascript doesn't defer a script tag if it has the data-pagespeed-no-defer attribute (preferred) or pagespeed_no_defer attribute (deprecated). This is useful when a script tag needs to be executed while loading the page. For example, a script tag may be updating the main content dynamically as a slideshow of images in the visible content of the page. Usage:

<script data-pagespeed-no-defer>...</script>

Example

The effect of this filter can be observed on modpagespeed.com before and after rewriting.

Limitations

Parent variables accessed from an iframe may be undefined when defer_javascript is used.

All JavaScript code is downloaded and executed serially, whereas without defer_javascript the browser tries to download JavaScripts in parallel as much as possible.

Calls to document.write fail in cases where they span multiple script tags. An example is:

<script>document.write('<div>')</script>
<span></span>
<script>document.write('</div>')</script>
Without defer_javascript the span would have been created inside the div. With defer_javascript the span would have been created outside and after the div.

Any document.body.appendChild calls will always get appended to the bottom of the page.

Requirements

defer_javascript is supported for browser versions of chrome 15+, safari5+, Firefox3.6+ and IE9+. For other user agents the filter is turned off automatically.

Risks

This filter is considered high risk. JavaScript whose logic depends on the state of the DOM may behave differently when defer_javascript is turned on.

If JavaScript is written to expect user actions before the page is loaded completely, such scripts will behave differently with defer_javascript. For example, if an alert is placed at the start of the page, then with defer_javascript the alert would appear only after the page is loaded completely.

User actions that trigger events such as onclick onkeypress will not be handled until the page is rendered completely.

Content in the page will reflow if visible elements are inserted in the page by JavaScript.

The data-pagespeed-no-defer attribute can change the order of script execution because those scripts using it are executed inline while those not using it are deferred. This can cause errors if these scripts depend on each other in any way.