HTML5’s async Script Attribute

By  on  

HTML5 Async Script

One of the big reasons I'me excited about HMTL5 is that features are being implemented that have been long overdue.  We've been using placeholders forever but we've needed to use JavaScript to do it.  We've been making entire blocks clickable like links but we've needed to use JavaScript to do it.  WebKit recently implemented HTML5's async attribute for SCRIPT tags.  We've been accomplishing this task with a variety of JavaScript hacks but this new attribute will allow us to prevent blocking in an easy way.

async - The HTML

As I mentioned above, it's as easy as adding an attribute:

<script async src="siteScript.js" onload="myInit()"></script>

The truth is that if you write your JavaScript effectively, you'll use the async attribute to 90% of your SCRIPT elements.

defer - The HTML

Safari has also added a defer attribute:

<script defer src="siteScript.js" onload="myInit()"></script>

Very similar to the async assignment.

async & defer - What's the Difference

This WebKit blog post explains the difference between defer and async best:

Both async and defer scripts begin to download immediately without pausing the parser and both support an optional onload handler to address the common need to perform initialization which depends on the script. The difference between async and defer centers around when the script is executed. Each async script executes at the first opportunity after it is finished downloading and before the window's load event. This means it's possible (and likely) that async scripts are not executed in the order in which they occur in the page. The defer scripts, on the other hand, are guaranteed to be executed in the order they occur in the page. That execution starts after parsing is completely finished, but before the document's DOMContentLoaded event.

Who Supports async and defer?

Also from the Safari blog:

In addition to upcoming versions of WebKit-based browsers, Firefox has long supported the defer and onload attributes and support for async was added in version 3.6. Internet Explorer has also long supported the defer attribute. While async is not yet supported, support for the onload attribute was added in version 9.

async FTW!

Seeing that WebKit had implemented async put a huge smile on my face.  Blocking is a huge bottleneck for every website and the ability to easily direct a script to load asynchronously should speed up the web!

Recent Features

Incredible Demos

  • By
    Facebook Open Graph META Tags

    It's no secret that Facebook has become a major traffic driver for all types of websites.  Nowadays even large corporations steer consumers toward their Facebook pages instead of the corporate websites directly.  And of course there are Facebook "Like" and "Recommend" widgets on every website.  One...

  • By
    MooTools Zoomer Plugin

    I love to look around the MooTools Forge. As someone that creates lots of plugins, I get a lot of joy out of seeing what other developers are creating and possibly even how I could improve them. One great plugin I've found is...

Discussion

  1. Okay… so what is the benefit of the async tag vs defer. It seems that in all use cases defer is just as efficient and more useful as it will prevent nasty dependency problems?

    Please explain why async is ftw better than defer…

    • defer loads the script when everything else is finished. async can load whilst other elements are loading. This is mainly going to be more useful in complex cases (multiple scripts all with the potential to block)

  2. Nice! Way better than putting the scripts at the bottom of the <body>

  3. @benjamin : you could use async for scripts that does not depend on other scripts to run. I’m thinking about scripts such as Google Analytics, for instance.

    @David Walsh: is it possible to mix async and defer? I’m explaining my thoughts: If I’ve two scripts A and B that depends both on a library (like mootools), but haven’t any dependencies together, could I do:

    1. defer mootools
    2. async A
    3. async B

    so mootools will be loaded first, and then A and B in any order?

    So, I’m clarifying my question: what’s the priority between defer and async:
    1. defer over async, like above
    2. async over defer / none, means A and B could be loaded before mootools

    Thanks for your blog David, it’s delightful

    • @Alexander Mercier you said that it’s possible to mix ‘async’ and ‘defer’. So you’re saying that I can use ‘defer’ for a library (like jQuery) and ‘async’ for any other like Google Analytics. What about top header modernizr.js? Can I use ‘async’ for it?

  4. Champ

    Walshe… I have been checking your stuff out, and it looks good! The JS looks big and bulky and I am wondering if its going to hurt the first time I implement it. Any advice?

  5. Thank you for the great article Walsh!

    @Alexandre: I was also wondering something similar and I read a bit of interesting text in this article:

    “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.”

    To better explain my situation: I’m not only interested in making sure my scripts load in the correct order (as you are) but I’m also very interested in each being non-blocking across as many browsers possible (including legacy browsers).

    While this may not directly answer your question I believe it may be helpful to your case (and mine). It sounds like async will override defer if it (async) is supported, so it would be safest to give your first script (mootools) a defer attribute, and then give your other scripts (A and B) both async and defer attributes. I could be totally misunderstanding the use of these here, so someone please correct me if I’m wrong.

    @Walsh: Do you have any insight you can add this particular topic?

  6. how long does it take for updates to webkit like this to make it out into the wild of production chrome/safari?

    it seems like this should have been a standard across all modern browsers long ago (i know, i know, if you had a nickel…), if only for the single use case of allowing publishers to load ads after content. think of all the billions of seconds wasted…

  7. rajkamal

    @Alexandre Mercier :
    async scripts execute at the first opportunity after download and before window onload event. So there is a possibility of script A or script B getting getting executed even before executing MooTools. Because as MooTools is given Defer attribute , it will get the first opportunity of executing only just before the DomContentLoaded event.So there may be some dependency errors.correct?

    @ David Walsh,

    Post comment button is not working ;-(
    i used this to post my comment

    var form = document.forms[1];
    var request = new Request({
    url: form.get('action'),
    method: form.get('method'),
    link: 'ignore',
     onRequest: function() {
    dotter.start();
     indicator.fade(1);
     }
    }).send(form.toQueryString());
    
  8. Hey, David; My recent tests show that the only browsers to support script async are FireFox 3.6+ and Chrome. I’m running tests for defer, but Safari definitely doesn’t support it; so perhaps it doesn’t have the latest version of Webkit support.

    I wrote a simple test which I ran through BrowserCam. The link is here:

    http://test.marketruler.com/js/async.php

    The embedded async_js.php script does a 2 second delay, then returns its results which set a global value to true.

    • That test is insanely useful! (and will remain so over time as unsupported browsers release new versions)

      Thanks!!!

    • Awesome Kent! Thanks for doing some legwork!

    • Well, it’s my business, but no problem. I’ll report back after the defer tests. I wrote an article on our wiki here:

      http://wiki.marketruler.com/How_does_JavaScript_run_on_a_web_page%3F

      which kind of covers the issue as I understand it.

    • Final point: Script “defer” attribute is supported by Chrome, FireFox 3.6+, and Internet Explorer 5+ on Windows. Worthwhile if you want to speed up your pages.

  9. David

    Actually, the webkit’s blog isn’t relevant anymore about the async attribute. If a script has async attribute it can be executed after the DOMContentLoaded event was fired:

    http://dev.w3.org/html5/spec/the-end.html

    But since the post was written in 2010 the spec was probably different then.

  10. Chung Xa

    As you said, the only difference between async and defer is when the script is executed. For me, the browser can run the script very fast, so it doesn’t matter to consider the different speed although the async is a bit faster but not significant..

    After all, I still prefer the defer attribute because it guarantees everything will work fine without worries :P

  11. Is it possible for ASYNC scripts to be executed before DEFER scripts? If so, how does one make sure a script like jquery.js is ready for other scripts that will depend on it? Must jQuery be a blocking script (i.e., not using ASYNC or DEFER)?

  12. I think 1 big problem using async and defer is maintaining script dependency (or execution order). For example if we need 2 scripts: jQuery and our custom file which requires jQuery to run, then we should add async or defer to our custom code file.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!