Very nice article indeed.<p>One commonly used variant I missed in the article and I'd be interested what it's positive/negative aspects are (if there are differences at all):<p><pre><code> <script>
var script = document.createElement('script');
script.src = "http://example.com/awesome-widget.js";
script.async = true;
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</code></pre>
(Note the additional async param)
Thank for yet another gem of an article. As a mostly backend developer, I depend a lot on these types of posts to help me keep up with the current front-end best practices. Anything that is on igvita.com I pretty much absorb without questioning due to the consistently high quality (and correctness!) of the posts.
What if you stick this as the first thing in your body:<p><pre><code> <iframe src="/file.js" style="display:none">
</code></pre>
And then at the very end of the body tag:<p><pre><code> <script src="/file.js"></script>
</code></pre>
Wont that allow us to start a non-blocking fetch of the script early, but then execute it later? I assume it wont be fetched twice. Especially if you send future Expires headers.
What keeps browsers from running the scripts immediately and only blocking if/when the script actually does access the CSSOM? It seems like an easy latency win.
I like Dojo/AMD because when you specify dependencies, you implicitly give an execution order.<p>Now, that doesn't necessarily help for this kind of "top level" code, but wouldn't it be cool if you could say: "Load this <script> tag asynchronously, but only run it once the following other <script> tags finish"? (You can give <script> tags HTML IDs just like anything else, right?)
I don't understand why the browser treats the script injection case differently than the blocking script tag case, insofar as blocking on CSSOM is concerned. Why doesn't the browser download the script right away and then just hold up executing it while the CSSOM finishes? I can't think of why it waits to <i>download</i> it.
Very cool, thanks for revisiting the best practices of yesteryear!<p>Quick test in FF: seems it blocks either way, but at least schedules the fetch in the async=true case <a href="http://i.imgur.com/AmNjhgz.png" rel="nofollow">http://i.imgur.com/AmNjhgz.png</a>
I'm using LAB.js, which lets me declare dependencies between scripts, and then handles sequential or parallel retrieval and execution. Not sure how I could easily replace this as suggested in the article, unless I merge all js into one big file?
Do these page performance optimizations check out across the modern browsers? Chrome and Firefox tend to implement such things differently. Not sure about Safari, IE11, etc.
Great stuff from Ilya as usual. But this tip is only important when you'd like Javascript execution to happen as fast as possible. The problem with async is that JS executes as soon as it is downloaded, and that may be before the page has fully loaded or the DOM has been built. For cases where your core content is in HTML and JS is only used for progressive enhancement, won't it be better to use defer?<p>Why isn't defer more popular?
The underlying problem is the loading of the CSS is blocking (blocks DOM as well).<p>However, that problem is complex to workaround.<p>Using the async flag doesn't fix that problem, and the async flag also means that you need to make sure your scripts can run in any order (which will cause problems unless you are very careful e.g. use a loader that manages dependencies asynchronously).
Another option is to inject the script:<p>A. At onDOMContentLoaded
and
B. Inside a setTimeout(func, 0) block<p>Then the browser's loading indicator will stop before the script has been loaded, executed and all its assets loaded.<p>Useful for social media widgets, etc.
I'd say this post is mildly hypocritical. You're using two script-injected async scripts, one from Google Tag Manager and another from Disqus!<p>Which is to say: if it were <i>that</i> harmful, then maybe you could try fixing them yourself and tell us how it goes? It would be great to provide some advice on how to convert a few popular script-injected async scripts from third parties (especially Google Analytics) into non-"harmful" ones.
Meta, but if you're going to write an article named "X considered harmful", then X really has to be as least as harmful as GOTO's prevalence was in 1968. This article is about a little thing that's current between now and now+3y, and that doesn't really hurt anybody when done wrong. Coding a script tag the wrong way is not going to stop the software engineering industry from making fundamental improvements.