Avoid Javascript blocking content download on your website during page load

Posted by php-manual on Mar 18, 2009 in Web |

Around 80% of the end-user response time is spent on the front-end. A fair share of this time is spent on downloading components of the page like scripts, Flash, stylesheets, images etc.  Javascript takes majority of the loading time of a webpage because scripts block parallel downloading and rendering in the page. Even if you do not have a lot of Javascript files to load on your webpage they can still block loading other content on your page while they load.  Lets have a look at how the standard javascript file include method and the script DOM element method in detail below.

Standard Javascript file include method


<SCRIPT src="A.JS" language="JavaScript/text"></SCRIPT>
<SCRIPT src="B.JS" language="JavaScript/text"></SCRIPT> 

<IMG src="1.GIF" />
<IMG src="2.GIF" />
<IMG src="3.GIF" />
Javascript blocks the other elements from loading

Javascript blocks the other elements from loading (Example)

Script DOM element method


var p = g.getElementsByTagName("HEAD")[0];
var c = g.createElement("script");
c.type= "text/javascript";
c.onreadystatechange = n;
c.onerror = c.onload = k;
c.src = e;
p.appendChild(C);
Javascript executed without blocking any element from loading

Javascript executed without blocking any element from loading

This method creates a DOM element for each Script and then adds the element to the HTML. 

NOTE

1) Only when the appendChild function is called the Javascript will be executed.
2) For inlined code that depends on the Javascript and also for a similar method of Asynchronous Script Loading – See Steve Souders blog
3) If you go to MSN.com (Alexa top 10 site based on traffic) and hit view source you can see the javacript elements are included by using the script dom element to load the web pages faster. This is a good example of where you can use the script dom element method for certain js files that do not have inlined code dependency. Let us run a Pagetest waterfall report and you can see the following for MSN.COM

Javascript loading in MSN does not block

Pagetest Waterfall report of MSN.COM shows no blocking during page load

Tags: , ,

20 Comments

theContesto
Mar 18, 2009 at 3:17 pm

Interesting. Run a Pagetest waterfall report of AOL.com (Notice that 1 second is spent downloading and executing JavaScript, one at a time.)


 
Christian Sonne
Mar 18, 2009 at 4:40 pm

I know most people can probably figure out how to correct this themselves. But how should I include the JS files such that g, n, k, e and C will be replaced?


 
JamesTheDude
Mar 18, 2009 at 5:20 pm

So the code will look like
var p = g.getElementsByTagName(“HEAD”)[0];

//FOR A.JS
var c = g.createElement(“script”);
c.type= “text/javascript”;
c.src = A.JS;

//For second JS
var c1 = g.createElement(“script”);
c1.type= “text/javascript”;
c1.src = B.JS;

p.appendChild(C);
p.appendChild(C1);

Above is enough and works fine. You dont have to use the following if your app doesnt need it.
c.onreadystatechange = n;
c.onerror = c.onload = k;


 
Justin
Mar 18, 2009 at 8:37 pm

Also have a look at: google-code-updates.blogspot.com/2009/03/steve-souders-lifes-too-short-write.html

If memory serves me correctly, the method presented isn’t 100% full-proof, but typically gets the job done.


 
Michael Wales
Mar 19, 2009 at 11:28 am

We were attempting something similar to this, using jQuery’s document.ready() – what we found was that, depending on the performance of the server, some times scripts would reference functions from other scripts (higher up in the source code) that had yet to finish loading.


 
Gábor Farkas
Mar 19, 2009 at 12:51 pm

This is nice for javascript that does not have other code dependency (most of the javascript belong to this category).


 
bobindashadows
Mar 19, 2009 at 1:03 pm

Another way to improve the “blocking effect” is to move your javascript to the bottom of your layout. Though, again keep in mind – if you are using an MVC framework (like RoR), you won’t be able to put javascript in your views. They’ll need to also be at the end of the file.
If you do this, your page will load, and javascript will be executed after that.


 
Cynos
Mar 19, 2009 at 1:09 pm

Yeah, if you use third party advertising networks, whose code relies heavily on document.writes. then there can be some issues
We wrote our first code to specifically not block (in case our servers were down), so our code always run after the document had loaded – but as we served third party adserving code, we had to mimic document.write (by assigning our own function to document.write, go go JS, everything’s fair game) for stuff like Google’s text ads, otherwise their calls to document.write would blow away the loaded document. And this approach worked… for a year or so, but it was becoming so brittle it wasn’t funny, and the issues with handling multiple document.write calls from multiple scripts in the same document were getting insane. We also were doing some things that made Firefox 2 (but not 3) barf up security warnings for certain Flash files, etc. etc. So we gave up on it and we went the same route as everyone else – corral third party code in iframes so it doesn’t matter if it blocks, and make sure our script serving servers always respond, now that we’ve got the capacity.


 
FlySwat
Mar 19, 2009 at 1:17 pm

I just wrote a tiny (2.3k) script that manages dynamic DOM insertion of Javascript for you.
http://www.gfilter.net/?Post=JSManager.js—Easily-manage-JS-dependancies
Web developers can speed up page load by simply avoiding Javascript blocking. So this does what this blog says for you :)


 
Sergey Shepelev
Mar 19, 2009 at 1:58 pm

Nice post, thanks!

The defer script attribute also does something like this. BUT note – it only works on certain browsers.


 
Justin George
Mar 25, 2009 at 12:20 pm

Thanks. We can also try to use an asset packager to strip whitespace, comments, and minify the JS, and concat it all into one file. You can also zip/gzip it if your server will serve the asset compressed.


 
doktor wurst
Mar 25, 2009 at 3:39 pm

As the post mentions beware modifying the DOM before the load event is fired. IE6 has the nasty habit of crashing randomly when you do that. Good use of caching best-practices rather seems to be the solution here as the download time is virtually 0 after the initial loading. Safari 4’s “speculative loading” also is a nice approach


 
Martin
Mar 28, 2009 at 1:40 pm

As mentioned in the post. It is good to stick your script tags as the very last thing before the closing bodytag and not in the head section.


 
Embabs Spew
Dec 21, 2009 at 6:47 pm

Thanks, I managed to speed up my web app by 32% by removing javascript blocking!


 
Janmek
Jan 7, 2010 at 12:43 pm

The second javascript gotcha happens to me all the time!


 
Natasha
Feb 24, 2010 at 8:00 am

Many thanks for the information and the code.


 
Carol
May 26, 2010 at 7:39 am

I am the first time on this site and am really enthusiastic about and so many good articles. I think it’s just very good job and less ads.


 
Rosario
May 26, 2010 at 9:26 am

This technique increased my web page loading speed by 19%. Tracked by yslow on firebug.


 
David
Jun 1, 2010 at 9:39 pm

A very useful tip indeed. Thanks for sharing the link to the web speed test site.


 
Jogu
Jun 2, 2010 at 4:35 pm

This solved my big problem with loading time on my web app.


 

Reply

Copyright © 2010 PHP, Web and IT stuff All rights reserved. PHP Web development in London.