It was just a couple of years ago that Steve Souders introduced the concept of blocking vs. non-blocking into the common lexicon of web developers around the world. His big focus was pointing out how
<script> tags block the rendering of the page as well as the downloading of other resources. Obviously, this is really bad for your initial page load, where a single high-latency
<script> tag causes your page to appear blank for a large amount of time. Even with all of this discussion, it seems that there’s still some confusion over non-blocking scripts and how they relate to parallel downloads. This is my attempt to clear up the confusion.
With this knowledge, think of what happens as a page downloads to the browser. The page has started to render as it was downloaded, and then a
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 (for more information, read Steve’s post on this).
A blocking script means that the page cannot continue rendering until the script has been:
- Completely downloaded
So loading scripts in a non-blocking way basically frees up the browser to continue rendering while the script file is being downloaded. The *loading *of these files is done asynchronously, but *execution *will still cause the UI thread to block for a small amount of time.
The HTML5 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. Basic usage is as follows:
When supporting browsers see the
async on the first script informs the browser that it need not wait to execute this script before executing others that may come after it. When Opera implements this feature, it will likely work the same way. This is the apparent motivation behind the Google Analytics source code that creates a dynamic script node and then sets
async on it. Internet Explorer, Safari, and Chrome do not preserve the order of execution, as scripts are executed as soon as they are retrieved regardless of the order in which they were inserted. In these browsers, setting
async on script nodes has no effect (but also doesn’t hurt anything).
async attribute is still a bit misunderstood, as evidenced by the Google Analytics source code that creates a dynamic script node and then sets
async on it. Doing so is redundant since dynamic script nodes are loaded asynchronously already. The
async attribute is only really useful when
<script> is included directly in HTML.
async attribute of a
Update (10 August 2010): Fixed small typos and updated description of
async attribute to reflect Steve’s and James’ comments.