Update Oct 2013: for a more bulletproof version, tested in the wild, IE and all, check Philip's snippet at http://www.lognormal.com/blog/2012/12/12/the-script-loader-pattern/
Asynchronous JS is cool but it still blocks window.onload
event (except in IE before 10). That's rarely a problem, because window.onload
is increasingly less important, but still...
At my Velocity conference talk today Philip "Log Normal" Tellis asked if there was a way to load async JS without blocking onload
. I said I don't know, which in retrospect was duh! because I spoke about Meebo's non-onload-blocking frames (without providing details) earlier in the talk.
Stage fright I guess.
Minutes later in a moment of clarity I figured Meebo's way should help. Unfortunately all Meebo docs are gone from their site, but we still have their Velocity talk from earlier years (PPT). There are missing pieces there but I was able to reconstruct a snippet that should load a JavaScript asynchronously without blocking onload.
Here it goes:
(function(url){ var iframe = document.createElement('iframe'); (iframe.frameElement || iframe).style.cssText = "width: 0; height: 0; border: 0"; var where = document.getElementsByTagName('script'); where = where[where.length - 1]; where.parentNode.insertBefore(iframe, where); var doc = iframe.contentWindow.document; doc.open().write('<body onload="'+ 'var js = document.createElement(\'script\');'+ 'js.src = \''+ url +'\';'+ 'document.body.appendChild(js);">'); doc.close(); })('http://www.jspatterns.com/files/meebo/asyncjs1.php');
The demo page is right here. It loads a script (asyncjs1.php
) that is intentionally delayed for 5 seconds.
window.onload
nor DOMContentLoaded
* The script works fine in Opera too, but blocks onload
. Opera is weird here. Even regular async scripts block DOMContentLoaded
which is a shame.
The script (asyncjs1.php) runs is in an iframe, so all document
and window
references point to the iframe, not the host page.
There's an easy solution for that without changing the whole script. Just wrap it in an immediate function and pass the document
object the script expects:
(function(document){ document.getElementById('r')... })(parent.document);
src
to a new URL. This fires onload
of the iframe immediately and the whole thing is completely out of the wayscript
tag so far, which is the snippet itself. This is in order to glue the iframe to the snippet that includes it.document
object of the iframeTell your friends about this post: Facebook, Twitter, Google+