4

I want to load a non-blocking javascript on my page. Before async is supported, the best practice seems to dynamically load it via a simple script.

Here is an example that works fine in which it is inserted before the first <script>:

var myscript = document.createElement('script');
myscript.async = true; // cannot hurt, right?
myscript.type = 'text/javascript';
myscript.src = 'myscript.js';
var node = document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(myscript, node);

I found several versions inserting the script in different places like the end of <head> or the <body>:

document.getElementsByTagName("head")[0].appendChild(myscript);  
document.getElementsByTagName("body")[0].appendChild(myscript);

The order seems to matter in some browsers though it is asynchronous. Are there any difference in terms of browser support? performance? blocking risk?

I don't have any constraint in terms of order (they don't impact each other) but I want to make sure that if my script takes too long to load the page content will still load just fine. I would think the last solution works best but I am not sure of the differences.

Community
  • 1
  • 1
Mad Echet
  • 3,723
  • 7
  • 28
  • 44

4 Answers4

2

You'll want to use something like $script.js: http://www.dustindiaz.com/scriptjs

eikes
  • 4,811
  • 2
  • 31
  • 31
  • This looks great, however I don't need the dependency feature so I will check if it does not overshoot my problem. However, it is good inspiration for sure! – Mad Echet Jan 08 '13 at 22:00
1

Appending the scripts at the end of the body is the best solution here. It still allows for loading the DOM without blocking for the script tags. Also if you put your scripts at the end of the document you no longer need to wrap your functions in a DOM ready event because at the moment your scripts start executing the DOM will already be loaded by the browser and you could directly start manipulating it or subscribing to some events.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thanks, it makes sense. However, I wonder what is the risk of being impacted by any script taking seconds to load before me. Ideally I would like my inline script to fire an independent thread that does not wait for anyone and cannot make anyone wait (besides parsing and execution for single core computers). Is it possible? Does putting it at the end of the body means that it won't be executed if anything fails to load anywhere above? – Mad Echet Jan 08 '13 at 22:02
1

Your question focuses on the load part, but actually performance can be impacted by different phases:

  • load
  • parsing
  • execution

For this reason adding the script at the end of the body is usually considered the less obtrusive.

To push it even further, you could wait for DOM ready to run your load script. In this case, it won't matter whether you attach the script to the head or the body.

[Edit] Side comment: the head and body tags are not mandatory in html pages. document.getElementsByTagName('script')[0] is a good approach in such edge cases as it guarantees that you'll get an element (there's at least your load script in the page).

Christophe
  • 27,383
  • 28
  • 97
  • 140
  • Thanks, it makes sense. However, I wonder what is the risk of being impacted by any ad script taking seconds to load. Ideally I would like that my inline script fires an independent thread that does not wait for anyone and cannot make anyone wait (besides parsing and execution for single core computers). Does putting it at the end of the body means that it won't be executed if anything fails to load anywhere above? – Mad Echet Jan 08 '13 at 21:58
  • 1
    @MadEchet not sure, but I think the risk is the same no matter where you load the script - an error will prevent the execution of the remaining scripts. Independent threads are hard to get (I heard browsers are starting implementing this in iframes) and you would need to consider Web workers. Also, see my edit. – Christophe Jan 08 '13 at 22:03
1

You could try having a script that waits for the page to be complete and then loads the script that you want to add. Have done this recently and the page loads fine and then a new block appears.

var Widget = {}
    Widget.myDocReadyInterval = setInterval(function(){
        if (document.readyState === "complete")
    {
        clearInterval(Widget.myDocReadyInterval);
        Widget.startLoading();
    }
}, 20);
Widget.startLoading(){
// do what you need here...
}
Dave Gill
  • 234
  • 1
  • 14