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.