It’s annoying when a web page is loading and gets stuck downloading a Javascript file from a remote domain. Until the file has downloaded, rendering on the page stalls which could potentially lose you traffic as people give up waiting. Instead it’s a good idea to load the remote Javascript asynchronously so the page can continue to render and the code is downloaded in the background.
How to download the remote Javascript asynchronously
Pop this bit of code in the <head> section of your web page template. Alternatively it should also work nicely in your own external Javascript file but by putting it in the head it will load earlier. Obviously change the ‘http://www.example.com/somefile.js’ filename to the file you want to load.
(function(){ var a = document.createElement('script'); a.type = 'text/javascript'; a.async = true; a.src = 'http://www.example.com/somefile.js'; var b = document.getElementsByTagName('script')[0]; b.parentNode.insertBefore(a, b); })();
If you’ve ever inserted Google’s asynchronous analytics tracking code into a page template you’ll note the method used is the same, although they put several lines of code into single lines.
Deferring the functions in the file from running until the page has rendered
Now that the Javascript file has started downloading while the rest of the page loads and renders, it’s more or less random when the code in that page will start to execute. If it’s in the cache it will run sooner; if it has to download the file it could be any amount of time (or not all if it times out).
If the code in the remote Javascript file needs to modify something in the DOM then it needs to wait until the page has rendered before doing anything. If all it’s doing is sending off some tracking information (or similar) then this step may not be necessary.
To defer running the script functions until the page has rendered, put the code into a function and then attach an event to the page which runs that function when the page is ready as shown in the example below.
function my_initialization_function() { // do something } if(document.readyState === "complete" ) { my_initialization_function(); } else if(document.addEventListener) { window.addEventListener("load", my_initialization_function(), false ); } else if(window.attachEvent) { window.attachEvent("onload", my_initialization_function()); }
The test on line 5 will run the initialization function is the page has already finished loading. This is important because if the page has loaded already and an load event is subsequently attached it will not be fired.
The section on lines 8 to 10 adds an event listener for the browsers that support it (all non IE browsers) and lines 11 to 13 for browsers that instead support attachEvent (IE browsers).
Now when the page has finished loading, or if it had already finished loading when the script has fully downloaded, the initialization function will be called.
One final note
I have seen some examples show the last two lines as one line like so:
(document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(a);
However, when I tested asynchronous loading, I found using this method would prevent the whole page loading in Internet Explorer 6, although it was fine for all other browsers. IE6 would display a modal dialog saying the page could not be loaded. For this reason, it’s best to use the way I have presented in the first example in this post.