JavaScript - Blocking scripts, defer and async
http://stackoverflow.com/questions/5250412/how-exactly-does-script-defer-defer-work
// 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
present).
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
complete
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.
page revision: 2, last edited: 14 Nov 2016 22:39