Defer inline javascript execution?

It would be much better if you could place your javascript at the end of the document. Sprinkling your source with small inline javascript snippets is a killer on page performance.

That said, you could create an array and push functions on this array. Then, at the end of your page, right after you load jquery, loop over the array and execute each function.

E.g.:

<html>
  ...
  <script>window.loadEvents = [];</script>
  ...
  <script>loadEvents.push(function() { alert("inline code here"); });</script>
  ...
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script>$.each(loadEvents, function(_,f) { f(); });</script>
</html>

However - as I said - it would be better to just push all the script elements into the bottom of the page, instead of switching back and forth between html and javascript. The rendering performance will be severely degraded, if you do this.


You could simulate a defer by setting the type of the inline scripts to one that would not be processed by the browser like text/example, and the cloning those scripts at the end of the document replacing the type with text/javascript.

The code that processes all the text/examples is really simple:

window.addEventListener("load", function() {

    var arr = document.querySelectorAll("script[type='text/example']");
    for (var x = 0; x < arr.length; x++) {
        var cln = arr[x].cloneNode(true);
        cln.type = "text/javascript";
        document.querySelectorAll("body")[0].appendChild(cln);
    }

});

Or if you prefer to use jQuery (you'll have to add this script after including the jQuery file):

$(function() {
    $("script[type='text/example']").each(function() {
        $(this).clone().attr("type","text/javascript").appendTo("body"); 
    });
});

This code waits until the page has loaded, then selects all the scripts with type text/example, and copies them at the end of the body with a type of text/javascript so they are executed normally.

For example:

...
<script type="text/example">
    console.log("I am before the h1");
</script>

<h1>Page Title</h1>

<script type="text/javascript">
    console.log("I am after the h1");
</script>
...

Will result in these messages in the console:

I am after the h1

I am before the h1

You can see a running demo on this JSFiddle: http://jsfiddle.net/rqckwc79/


Pros of this solution:

  • It is a cross-browser solution.
  • The code is valid HTML/JavaScript.
  • It works in strict mode.

Cons of this solution:

  • You need to have control over the inline scripts to change the type.
  • As troelskn said, performance would be worse than moving all the code to the bottom (but I understand there are situations in which that is not possible).
  • It doesn't work on older IE versions (although the code could be modified to support them).