JavaScript - Blocking scripts, defer and async


// JavaScript - Blocking script, defer, and async:

Before the browser can render a page it has to build the DOM tree by parsing 
the HTML markup. During this process, whenever the parser encounters a script 
it has to stop and execute it before it can continue parsing the HTML. In the 
case of an external script the parser is also forced to wait for the resource 
to download, which may incur one or more network roundtrips and delay the time 
to first render of the page.

We should avoid and minimize the use of blocking JavaScript, especially 
external scripts that must be fetched before they can be executed. Scripts 
that are necessary to render page content can be inlined to avoid extra network
requests, however the inlined content needs to be small and must execute 
quickly to deliver good performance. Scripts that are not critical to initial 
render should be made asynchronous or deferred until after the first render. 

External blocking scripts force the browser to wait for the JavaScript to be 
fetched, which may add one or more network roundtrips before the page can be 
rendered. If the external scripts are small, you can inline their contents 
directly into the HTML document and avoid the network request latency. 

Inlining the script contents eliminates the external request for small.js and 
allows the browser to deliver a faster time to first render. However, note that 
inlining also increases the size of the HTML document and that the same script 
contents may need to be inlined across multiple pages. As a result, you should 
only inline small scripts to deliver best performance. 

By default JavaScript blocks DOM construction and thus delays the time to first 
render. To prevent JavaScript from blocking the parser we recommend using the 
HTML async attribute on external scripts. For example: 
<script async src="my.js">

Asynchronous scripts are not guaranteed to execute in specified order and 
should not use document.write. Scripts that depend on execution order or need 
to access or modify the DOM or CSSOM of the page may need to be rewritten to 
account for these constraints. 

// Defer loading of JavaScript:
The loading and execution of scripts that are not necessary for the initial 
page render may be deferred until after the initial render or other critical 
parts of the page have finished loading. Doing so can help reduce resource 
contention and improve performance.

<script src="demo_defer.js" defer></script> 

The defer attribute is a boolean attribute.  When present, it specifies that 
the script is executed when the page has finished parsing.  The defer attribute 
is only for external scripts (should only be used if the src attribute is 

There are several ways an external script can be executed:

1. If async is present: The script is executed asynchronously with the rest of 
   the page (the script will be executed while the page continues the parsing)
2. If async is not present and defer is present: The script is executed when 
   the page has finished parsing
3. If neither async or defer is present: The script is fetched and executed 
   immediately, before the browser continues parsing the page

Older browsers would actually stop doing everything, including downloading 
additional resources in the page, while a script was downloading. That meant 
two <script> tags in a row would result in the browser waiting to begin 
download of the second script until after the first was downloaded and executed.

Newer browsers will download the script files in parallel and then execute them 
in order, so the second script is ready to be executed as soon as the first 

Parallel downloading should not be confused for asynchronous execution. Remember, 
JavaScript is single threaded, so you literally cannot be executing two scripts 
at the same time. Parallel downloading of scripts only means that two scripts 
are downloaded at the same time, not that they’re executed at the same time. 
There’s a big difference.

// To load script in a non-blocking manner:
1. Create a script node dynamically after the initial page is rendered.
2. Use the async attribute.  HTML5 introduces a new attribute on the <script> 
   tag called async. This is a Boolean attribute (doesn’t require a value) and, 
   when specified, causes the script file to be loaded as if you had created a 
   dynamic script node. 

When the async attribute is set on two script tags, modern browsers will 
download the script files in parallel and then execute them in order, so the 
second script is ready to be executed as soon as the first complete.

When set on a dynamic script node, the behavior of the async attribute has a 
subtle distinction.   Test this yourself and see if removing the async attribute 
from the dynamic script tags make any difference.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License