tags:

views:

818

answers:

5

What tricks can be used to stop javascript callouts to various online services from slowing down page loading?

The obvious solution is to do all the javascript calls at the bottom of the page, but some calls need to happen at the top and in the middle. Another idea that comes to mind is using iframes.

Have you ever had to untangle a site full of externally loading javascript that is so slow that it does not release apache and causes outages on high load? Any tips and tricks?

+1  A: 

Not easy solution. In some cases it is possible to merge the external files into a single unit and compress it in order to minimize HTTP requests and data transfer. But with this approach you need to serve the new javascript file from your host, and that's not always possible.

I can't see iframes solving the problem... Could you please elaborate ?

Guido
+1  A: 

If you're using a third-party JavaScript framework/toolkit/library, it probably provides a function/method that allows you to execute code once the DOM has fully loaded. The Dojo Toolkit, for example, provides dojo.addOnLoad. Similarly, jQuery provides Events/ready (or its shorthand form, accessible by passing a function directly to the jQuery object).

If you're sticking with plain JavaScript, then the trick is to use the window.onload event handler. While this will ultimately accomplish the same thing, window.onload executes after the page--and everything on it, including images--is completely loaded, whereas the aforementioned libraries detect the first moment the DOM is ready, before images are loaded.

If you need access to the DOM from a script in the head, this would be the preferred alternative to adding scripts to the end of the document, as well.

For example (using window.onload):

<html>
    <head>
     <title>Test Page</title>
     <script type="text/javascript">
      window.onload = function () {
       alert(document.getElementsByTagName("body")[0].className);
      };
     </script>
 <style type="text/css">
  .testClass { color: green; background-color: red; }
 </style>
    </head>
    <body class="testClass">
     <p>Test Content</p>
    </body>
</html>

This would enable you to schedule a certain action to take place once the page has finished loading. To see this effect in action, compare the above script with the following, which blocks the page from loading until you dismiss the modal alert box:

<html>
    <head>
     <title>Test Page</title>
     <script type="text/javascript">
      alert("Are you seeing a blank page underneath this alert?");
     </script>
     <style type="text/css">
      .testClass { color: green; background-color: red; }
     </style>
    </head>
    <body class="testClass">
     <p>Test Content</p>
    </body>
</html>

If you've already defined window.onload, or if you're worried you might redefine it and break third party scripts, use this method to append to--rather than redefine--window.onload. (This is a slightly modified version of Simon Willison's addLoadEvent function.)

if (!window.addOnLoad)
{
    window.addOnLoad = function (f) {
     var o = window.onload;

     window.onload = function () {
      if (typeof o == "function") o();
      f();
     }
    };
}

The script from the first example, modified to make use of this method:

window.addOnLoad(function () {
    alert(document.getElementsByTagName("body")[0].className);
});

Modified to make use of Dojo:

dojo.addOnLoad(function () {
    alert(document.getElementsByTagName("body")[0].className);
});

Modified to make use of jQuery:

$(function () {
    alert(document.getElementsByTagName("body")[0].className);
});

So, now that you can execute code on page load, you're probably going to want to dynamically load external scripts. Just like the above section, most major frameworks/toolkits/libraries provide a method of doing this.

Or, you can roll your own:

if (!window.addScript)
{
    window.addScript = function (src, callback) {
     var head = document.getElementsByTagName("head")[0];
     var script = document.createElement("script");
     script.src = src;
     script.type = "text/javascript";
     head.appendChild(script);
     if (typeof callback == "function") callback();
    };
}

window.addOnLoad(function () {
    window.addScript("example.js");
});

With Dojo (dojo.io.script.attach):

dojo.addOnLoad(function () {
    dojo.require("dojo.io.script");
    dojo.io.script.attach("exampleJsId", "example.js");
});

With jQuery (jQuery.getScript):

$(function () {
    $.getScript("example.js");
});
Christopher Parker
I think the original poster was interested in loading of external JavaScript files. Usually, this is done in the <head> and the page can't continue to load until those links are resolved. Your answer is about how to invoke JS after the page loads, not how to pull in the JS to being with.
Ben Combee
After re-reading the original question, I see your point. In that case, my answer could be combined with something such as this: http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
Christopher Parker
I've updated my answer with your comment in consideration. Thanks!
Christopher Parker
+1  A: 

See articles Serving JavaScript Fast and Faster AJAX Web Services through multiple subdomain calls for a few suggestions.

Jay
+2  A: 

window onload is a good concept, but the better option is to use jQuery and put your code in a 'document ready' block. This has the same effect, but you don't have to worry about the onload function already having a subscriber.

http://docs.jquery.com/Core/jQuery#callback

$(function(){
  // Document is ready
});

OR:

jQuery(function($) {
  // Your code using failsafe $ alias here...
});

edit: Use this pattern to call all your external services. Refactor your external script files to put their ajax calls to external services inside one of these document ready blocks instead of executing inline. Then the only load time will be the time it takes to actually download the script files.

edit2: You can load scripts after the page has loaded or at any other dom event on the page using built in capability for jQuery.

http://docs.jquery.com/Ajax/jQuery.getScript

jQuery(function($) {
   $.getScript("http://www.yourdomain.com/scripts/somescript1.js"); 
   $.getScript("http://www.yourdomain.com/scripts/somescript2.js"); 
});
Michael
A: 

If you don't need a particular script ad load time, you can load it later by adding another script element to your page at run time.

Diodeus