So, I’ve already said I agree that HTTP request reduction is very important. But it isn’t the final answer, mostly because there is no final answer, only a helpful set of principles to guide you on your way — it is only part of what you need on this journey.
What else is there to consider?
If you have less than 5k of JavaScript loading on your site, you’re not likely to see much appreciable difference. But if you’re like a lot of sites on the web these days, you have frameworks, ui widgets, plugins, analytics, social bookmark sharing scripts, and so on… you blink and you’re loading 50k, 75k, even 100k of JavaScript. And some of you use heavy JavaScript frameworks where the file size, even gzip’d, is well over 250k. Throw in some custom font-face files (all the rage these days), and it’s not surprising to see even 1MB of scripts loading!
Whether you have 50k of JavaScript, or 500k, if it’s all in one file, the browser is going to load that file byte-by-byte, serially. Someday maybe we’ll get multi-cast BitTorrent’ing of our page resources, but that’s not a reality now.
So, concat’ing all your JavaScript into one file completely eliminates any possibility that the script code itself can be loaded in any way in parallel (though with LABjs, as mentioned before, you can still load that code in parallel with other page resources like images/CSS/etc).
If you have 100k of code to load, in one file, the user will wait for that entire file to load all at once. But, if you were to take that 100k and break it up into even 2 files of approximately 50k each, and you used a dynamic loader like LABjs, both files would load in parallel, meaning in approximately half the time of the original single 100k file.
True, you’ll pay some slight overhead for the second HTTP request, but if you’re talking about larger (>50k) files, it’s still likely to be modestly quicker than one request for the larger and serially-loaded file.
You have to balance this technique out, because loading 10 files of 10k each is probably not the best answer either. There’s some complicated formula which will determine the sweet spot between one 100k file and one-hundred 1k files — and what that balance is will probably vary from site to site. I can say in my case, I usually try to get it down to 2, maybe 3 files, and that’s usually pretty good performance. The point is, loading only 1 file is going to hinder an important optimization method, dynamic parallel loading in favor of saving the small (but non-trivial) HTTP request overhead. And there’s a point at which that type of tradeoff is actually detrimental to your site. So maybe you should re-think how you construct and load your files, or at least experiment with some variations?
Don’t forget the cache!
I’m not sure about you, but I can’t remember the last time I wrote and deployed a JavaScript file and then left that entire file alone for more than a few weeks or months at maximum. In reality, I tinker with my files constantly, because I’m always improving and tweaking them, both for run-time performance and for improved user-experience.
If all of your site’s code is in one file, and you change even one character of that file, the next time every single visitor comes to your site, they’re gonna re-download the other 99.999k unnecessarily.
Sure, the user’s browser cache is not fully reliable and a significant portion of views happen with empty caches, even with return visitors. But that doesn’t mean we should throw the baby out with the bath water and completely ignore the browser cache as being irrelevant. We should intelligently try and figure out what code is less likely to change, and what code is more likely to change, and separate the two code segments into two files.
That way, our tried-and-tested framework code that changes rarely doesn’t have to be re-downloaded every time we tweak other frequently changing code that animates our banner ads, etc.
Again, you can’t just create a dozen separate files and expect to have optimum experience, but I’ve found that splitting the lines between two (maybe three) levels of tendency-to-frequently-change gives pretty good overall performance. For instance, my frameworks and third-party plugins that I use, which I almost never change, I include them in one file. But for code that initializes the page and plugins and controls site-specific behavior, I include that in a second file.
Just because the browser cache is finicky, don’t completely ignore it as an important tool in optimizing overall user experience, not only across subsequent page views but also subsequent visits.
And what about those remote files?
This is a part of the conversation that seems to almost universally get ignored when I hear arguments for JavaScript concatenation. It’s like people take completely for granted that code loaded from a remote source (hopefully a CDN) is not only a reality for almost all sites, but also that it loads basically for free. This is not true. There’s still HTTP request overhead involved, just not on your server! And yes, it’s probably much less against a highly optimized CDN than against your little server farm, but that doesn’t make it ignorable.
A lot of people learned a valuable lesson a few months back when Google Analytics went down (a rare occurrence), and millions of sites all had that awful “document.write()” garbage in the bottom of their page that GA suggests for including their JS file. What happened? Most pages failed to finish loading and initialize, and the users were all held hostage helplessly as a result.
But that wouldn’t have been true if you loaded that remote GA file with LABjs. My sites didn’t suffer that fate! If done correctly, the loading of the “ga.js” file simply would have failed silently, but the rest of the JavaScript loading and initialization would have continued as normal, and users would probably never even have known that the outage occurred.
The reality is, most sites on the web load one or a couple of files from remote locations. And it doesn’t make sense to self-host these files so you can concat them in with your other local scripts. You need to load them from their remote locations, and you need to do so in a way that is optimized and robust. The <script> tag is not the right way!
But a loader like LABjs will let you easily and seamlessly load one (or a couple) of files from your own server, along with a couple of files from other locations. And, you can even easily queue up initialization logic for the various different script resources separately, so that your code will load and initialize, even if the GA code fails to load because of another outage.
More to the story
This is really just the tip of the iceberg. There’s a lot more complexity to this issue, far more than I could ever cover in even a couple of blog posts. But I hope you can see there’s enough questions to be answered that something like LABjs as a script loader is worth looking into. We can’t just sit by and blindly expect that one answer (reducing HTTP requests by JS concat’ing) will ever get us the most optimum page load behavior. We’ve got to be a little more creative than that!
Pages: 1 2


Hello. I’m not convinced with that “huge is ok” approach.
I’m fond of the download-the-code-when-needed approach. Meaning, you click a button and the needed code is downloaded and executed. If the button isn’t clicked the code is not downloaded. The REST architecture itself praises “Code-On-Demand”.
What’s your opinion on this?
I’m definitely a big fan of load-on-demand and load-when-needed approaches. For instance, Facebook now has a “bootstrapper” script (called “Primer”) that they load at the beginning of the page, which can handle default actions, and then they layer in additional functionality with futher downloads as the page loads and gets more complicated.
You do have to balance on-demand with potential slow-downs that can occur if it takes a second to download code when someone clicks a button to do some action. If the user can see these delays when they are interacting with elements, it can detract from the UX. So, I’m in favor of an approach that progressively downloads more behavioral JS in the background so there’s less chance that a user will have to wait on the JS.
You make a good point, but I’m not sure that’s a problem because we’re talking about a one second delay (give or take, on a bad day) only on the first click. But that’s something for me think about. Thanks for responding.
Filipe Martins
“One second” was kind of an exaggeration. It’s been shown that users can perceive a delay if it’s over 200ms, which is quite possible if there’s a decent sized JavaScript file (or several) that need to be loaded when a user clicks a button. Of course, even a really small file could take 200ms if there’s high network latency involved. Because you can’t really guarantee someone’s connection speeds, I’d tend to assume loading files when a button is clicked could have a noticeable delay and would avoid it.
But certainly if you are going to do this, give some sort of visual indication (like a loader/spinner) even for the short loads (so that it’s present if the load is really long) so users aren’t multiple-clicking things because they click and don’t see a response quickly enough.
I’m not claiming that a 200ms or 1s delay isn’t noticeable. I’m saying that it probably won’t be important because it’s a one time only thing (don’t we love the cache?).
I do agree with you about the visual feedback, though.
For developers with web sites that DO get over 160,000,000 page views a month, this post appears to concede that using LAB.js versus concatenating and minifying JavaScript into a single file adds little value. Considering that the majority of our visitors spend 10-15 minutes surfing our site, it’s it enough to rely on the browsers caching mechanisms? Am I missing something?
@Klevak
If you scroll to the beginning of the article, you’ll see this paragraph:
That way you reduce HTTP requests, and you prevent the single, large JS file from blocking the rendering of the page as it loads.
Surely the other benchmark you need to run here for the full picture is when caching is used. I notice that you’ve deliberately disabled caching in your requests to show the actual download time between a concatenated file and your load on demand. Interestingly, my results are sometimes longer for the labJS solution.
A more realistic scenario IMHO would be to compare any typical homepage which may have around 10 different JS files (eg. jquery, jquery UI, Knockout, modernizr, etc.etc) and illustrate that as one file vs many files when caching is optimised. I think you’ll see that for all but the first request, a single concat file will be quicker the more individual files are included. There are only so many that will load in parallel.
Where I think this way of loading really wins is only loading what you actually need. Personally, I’m less worried about how long a script takes to download (given I can optimise that) than I am about whether I actually need the script at all. There’s obviously no point spending time processing a script I’m not using. I quite like the fact that you can can customize many libraries, for instance jQuery UI lets you build a JS file containing only those parts of the UI you’re actually using on your site.