views:

214

answers:

2

Looked around, couldn't find this specific question discussed. Pretty sure the difference is negligible, just curious as to your thoughts.

Scenario: All Javascript that doesn't need to be loaded before page render has been placed just before the closing </body> tag. Are there any benefits or detriments to lazy loading these instead through some Javascript code in the head that executes when the DOM load/ready event is fired? Let's say that this only concerns downloading one entire .js file full of functions and not lazy loading several individual files as needed upon usage.

Hope that's clear, thanks.

A: 

In terms of Usability, you definitely shouldn't do this with anything that the user expects a quick response from like having a button do double duty as the load trigger in addition to it's other function.

OTOH replacing pagination with continuously loading the page as the user scrolls is a very good idea. I do find it a distraction when the load trigger is towards the end of the page, better to put it 1/2 to 3/4 the way down.

Indolering
+4  A: 

There is a big difference, in my opinion.

When you inline the JS at the bottom of the <body> tag, you're forcing the page to load those <script>s synchronously (must happen now) and sequentially (in a row), so you're slowing down the page a bit, as you must wait for those HTTP calls to finish and the JS engine to interpret your scripts. If you're putting lots of JS stacked up together at the bottom of the page, you could be wasting the user's time with network queueing (in older browsers only 2 connections per host at a time), as the scripts may depend on each other, so they must be downloaded in order.

If you want your DOM to be ready faster (usually what most wait on to do any event handling and animation), you must reduce the size of the scripts you need to as little as possible as well as parallelize them.

For instance, YUI3 has a small dependency resolution and downloading script that you must load sequentially in the page (see YUI3's seed.js). After that, you go through the page and gather the dependencies and make 1 asynchronous and pipelined call to their CDN (or your own servers) to get a big ball of JS. After the JS ball is returned, your scripts execute the callbacks you've supplied. Here's the general pattern:

<script src="seed.js"></script>
<script>

    YUI().use('module', function(Y) {
        // done when the ball returns and is interpretted
    });

</script>

I'm not a particularly big fan of putting your scripts into 1 big ball (because if 1 dependency changes, you must download and interpret the whole thing over again!), but I am a fan of pipe-lining (combining scripts) and the event-based model.


When you do allow for asynchronous, event-based loading, you get better performance, but perhaps not perceived performance (though this can be counteracted).

For instance, parts of the page may not load for a second or two, and hence look different (if you're using JS to affect the page style, which I don't advise) or not be ready for user interaction until you (or those hosting your site) return your scripts.

Additionally, you must do some work to ensure your <script>s have the right dependencies to be able to execute properly. For instance, if you don't have jQuery or Prototype, you can't successfully call:

<script>

    $(function () {
        /* do something */
    });

</script>

or

<script>

    document.observe('dom:loaded', function {
        /* do something */
    });

</script>

as the interpretter will say something like "Variable $ undefined". This can happen even if you've added both <script>s to the DOM at the same time, as I'd bet jQuery or Prototype are bigger than you're application's JS (so the request for the data takes longer). Either way, without some type of limiting, you're leaving this up to chance.


So, the choice is really up to you. If you can properly segment your dependencies - i.e. put the stuff you need up front and lazily load the other stuff later, it'll result in faster overall time until you hit the DOM being ready.

However, if you use a monolithic library like jQuery or the user expects to be able to see something involving JS animation or style right away, inlining might be better for you.

Dan Beam
This is a great assessment, thanks. I appreciate the detail. The one thing I didn't ask in my original question and am wonder is for the YUI instance whether the big ball'o'js is cached for subsequent visits if unchanged when served in that manner. Do you know?
mVChr
Actually, the info is appreciated, but turns out we can't do this because our static files are served through our CDN, so we can't pull them through Javascript (cross-domain). I'm sure I (and others) will be able to use this info though, so thank you.
mVChr
The ball'o'js **isn't** cached if **any** dependencies are different. I was recently at a Yahoo! event where they were highlighting YUI3, and this was my fundamental difference with this system, :(. Google Closure Library (used on many Google properties) does the same thing. It seems like 2 connections - 1 for your core JS and 1 for that page's deps, seems like the way to go (though I think you can do this with Closure, not sure about YUI3).
Dan Beam