One of the rules of thumb that you always hear regarding script elements is to put them very close to the </body> closing tag of the Web page. The main reason for that is that script elements are fetched and executed immediately when the browser encounter them. This default behavior includes blocking the browser’s rendering, loading a JavaScript file into memory, and executing its code immediately. In many circumstances, and in particular when large JavaScript files are involved, this might create a performance bottleneck.
One of the solutions for this problem is to use script tag injections or other Ajax techniques to prevent the browser from blocking. That might help to increase performance but it requires more coding and testing and in some occasions might create bugs because it is very hard to synchronize the file loading and executioning.
HTML5 introduces the async script attribute which helps to load scripts asynchronous. In the specifications you can also find another attribute, the defer attribute, that is very similar to the async attribute but it has another purpose. Both of the attributes will be presented in this post.
The async Attribute
The async attribute was introduced in HTML5. Its purpose is to signal the browser that a script should be executed asynchronously, and as soon as it is available. This means that when a browser encounter a script tag with the async attribute, it will download the script asynchronous and not block the rendering process. At the first opportunity after the script finished downloading and before the window’s load event the browser will execute the script. Here is how you will use the async attribute:
<script src="jsFile.js" async></script>
The async attribute can be used only on script element that point to external JavaScript file. That means that the src attribute must exists when you use the attribute. Also, you can’t know the execution order of scripts that use the async attribute.
In most of the major browsers, such as Chrome, Firefox, and Opera, the attribute is available for use. IE9 and previous versions of IE don’t support the attribute yet.
The defer Attribute
The defer attribute is not new in HTML5. It can be found in most of the browser (even in very early versions of IE). Its purpose is to signal the browser that a script should be executed in parallel and without stopping the page’s rendering. Deferred scripts guaranteed to run in sequence in the order that they are written in the code. They are executed before the DOMContentLoaded event. Here is an example of using the defer attribute:
<script src="jsFile.js" defer></script>
As in the async attribute, defer attribute can be used only on script element that point to external JavaScript file.
Pay attention not to use the defer attribute on external script files that use the document.write or generate document content.
What happens if you add both of the attributes to a script element?
Here is the answer in the specifications:
“The defer
attribute may be specified even if the async
attribute is specified, to cause legacy Web browsers that only support defer
(and not async
) to fall back to the defer
behavior instead of the synchronous blocking behavior that is the default.”
Summary
The post introduced the async and defer script attributes. Both of them can be used to improve the performance of Web pages because they help to load scripts asynchronous without blocking the page rendering. In most of the times you will use the attributes instead of writing your script elements in the bottom of the Web page.
Add comment
Originally published at blogs.microsoft.co.il on December 29, 2011.