Monday, December 29th, 2008

Eeking out performance in script loading

Category: Performance

<p>Steve Souders has detailed the coupling of script loading with various asynchronous techniques with examples that show the timings that you can get. First he sets the scene:

One issue with async script loading is dealing with inline scripts that use symbols defined in the external script. If the external script is loading asynchronously without thought to the inlined code, race conditions may result in undefined symbol errors. It’s necessary to ensure that the async external script and the inline script are coupled in such a way that the inlined code isn’t executed until after the async script finishes loading.

There are a few ways to couple async scripts with inline scripts.

  • window’s onload – The inlined code can be tied to the window’s onload event. This is pretty simple to implement, but the inlined code won’t execute as early as it could.
  • script’s onreadystatechange – The inlined code can be tied to the script’s onreadystatechange and onload events.  (You need to implement both to cover all popular browsers.) This code is lengthier and more complex, but ensures that the inlined code is called as soon as the script finishes loading.
  • hardcoded callback – The external script can be modified to explicitly kickoff the inlined script through a callback function. This is fine if the external script and inline script are being developed by the same team, but doesn’t provide the flexibility needed to couple 3rd party scripts with inlined code.

Then he goes into an example showing a simple asynchronous loading technique, and then coupling John Resig’s degrading script tags pattern, added to the end of the target script, and lazy loadingit:

javascript
< view plain text >
  1. // -- lazily load the script
  2. window.onload = function() {
  3.     var script = document.createElement('script');
  4.     script.src = "sorttable-async.js";
  5.     script.text = "sorttable.init()";
  6.     document.getElementsByTagName('head')[0].appendChild(script);
  7. }
  8.  
  9. // -- at the end of the script
  10. var scripts = document.getElementsByTagName("script");
  11. var cntr = scripts.length;
  12. while ( cntr ) {
  13.     var curScript = scripts[cntr-1];
  14.     if ( -1 != curScript.src.indexOf('sorttable-async.js') ) {
  15.         eval( curScript.innerHTML );
  16.         break;
  17.     }
  18.     cntr--;
  19. }

Finally, the conclusion:

Loading scripts asynchronously and lazyloading scripts improve page load times by avoiding the blocking behavior that scripts typically cause. This is shown in the different versions of adding sorttable to UA Profiler:

The times above indicate when the onload event occurred. For other web apps, improving when the asynchronously loaded functionality is attached might be a higher priority. In that case, the Asynchronous Script Loading version is slightly better (~400 ms versus 417 ms). In both cases, being able to couple inline scripts with the external script is a necessity. The technique shown here is a way to do that while also improving page load times.

Related Content:

  • Data loading
    Describes a few of the capabilities you will likely need during the loading process from a database to a data...
  • Load average issues
    ++++-
    4.4 rating from 10 votes

9 Comments »

Comments feed TrackBack URI

Why not use XHR to load an array of urls (excluding cross domain issues)? You can asynchronously import 6 or so simultaneously, build a document fragment containing the script tags and finally append the fragment to the page when they all arrive.

Comment by TNO — December 29, 2008

The onreadystatechange method would be the best one just a bummer that it doesn’t work correctly on IE 6. I tried making a cross domain loading method for scripts using this method but the problem is that IE 6 fires the load event when the script file is loaded and not after it’s parsed and executed. So if you load scripts in a specific order things tends to break. The method works perfectly fine on other browsers and IE 7.

Comment by Spocke — December 29, 2008

In many cases, you want the script to be present and ready on the initial pageload. Clients typically want their GUI applications to be nearly instantanious, especially with enterprise websites.
.
You gain faster pageloads, but if for example you use unobtrusive javascript to physically change the visual layout, you will have to be very confident in the next meeting with the client when you explain why the page jumps around like mad on each pageload.
.
Use these techniques where they CAN be used, not everywhere. Fall back on gzip and minimizing as much as you can otherwise.
.
This is more of a warning then an opinion, I’ve already had some issues with it 1 year ago and had to replace all the fancy smart techniques with dumb old ones.

Comment by BenGerrissen — December 29, 2008

This behavior is part of the reason that James Burke’s excellent work on the x-domain package loader for Dojo has proven to be such a performance win. It gives this this async technique to Dojo package authors for free so long as they x-domain enable their builds or use Dojo packages off of Google or AOL’s CDN.

Regards

Comment by slightlyoff — December 29, 2008

@Spocke:
Are you sure? I remember onreadystatechange working for script tags in IE6.
.
Can anybody verify this on the top of their head>

Comment by matanlurey — December 29, 2008

@matanlurey
Yes it does work in IE6.

Comment by V1 — December 30, 2008

@matanlurey/V1: I can’t manage to get it working correctly. I guess it depends on the script size and how fast it’s being parsed. I tested this by loading pretty large scripts 100k or more. If I remember correctly it only returned some other ready state than IE 7 and that state is before the file is parsed and executed and any other state never happened. So the only way to know when it’s loaded is to timeout wait for it or load it through a XHR and a eval call.

Comment by Spocke — December 30, 2008

I must say that these are VERY VERY VERY good techniques, not only for speed, but also SEO and website management. I use the same technique throughout my flat-file driven site and it keeps it very maintainable!

Comment by oopstudios — December 30, 2008

Someone had to be a pedant. Today it’s me. Shouldn’t your title be “eking out performance…”? http://dictionary.reference.com/browse/eke
btw I liked the article.

Comment by adohall — January 4, 2009

Leave a comment

You must be logged in to post a comment.