Speed Up Your Javascript Load Time
Javascript is becoming increasingly popular on websites, from loading dynamic data via AJAX to adding special effects to your page.
Unfortunately, these features come at a price: you must often rely on heavy Javascript libraries that can add dozens or even hundreds of kilobytes to your page.
Users hate waiting, so here are a few techniques you can use to trim down your sites.
(Check out part 2 for downloadable examples.)
Find The Flab
Like any optimization technique, it helps to measure and figure out what parts are taking the longest. You might find that your images and HTML outweigh your scripts. Here’s a few ways to investigate:
1. The Firefox web-developer toolbar lets you see a breakdown of file sizes for a page (Right Click > Web Developer > Information > View Document Size). Look at the breakdown and see what is eating the majority if your bandwidth, and which files:
2. The Firebug Plugin also shows a breakdown of files - just go to the “Net” tab. You can also filter by file type:

3. OctaGate SiteTimer gives a clean, online chart of how long each file takes to download:

Disgusted by the bloat? Decided your javascript needs to go? Let’s do it.
Compress Your Javascript
First, you can try to make the javascript file smaller itself. There are lots of utilities to “crunch” your files by removing whitespace and comments.
You can do this, but these tools can be finnicky and may make unwanted changes if your code isn’t formatted properly. Here’s what you can do:
1. Run JSLint (online or downloadable version) to analyze your code and make sure it is well-formatted.
2. Use Rhino to compress your javascript. There are some online packers, but Rhino actually analyzes your source code so it has a low chance of changing it as it compresses, and it is scriptable.
Install Rhino (it requires Java), then run it from the command-line:
java -jar custom_rhino.jar -c myfile.js > myfile.js.packed 2>&1
This compresses myfile.js and spits it out into myfile.js.packed. Rhino will remove spaces, comments and shorten variable names where appropriate. The “2>&1″ part means “redirect standard error to the same location as the output”, so you’ll see any error messages inside the packed file itself (cool, eh? Learn more here.).
Using Rhino, I pack the original javascript and deploy the packed version to my website.
Debugging Compressed Javascript
Debugging compressed Javascript can be really difficult because the variables are renamed. I suggest creating a “debug” version of your page that references the original files. Once you test it and get the page working, pack it, test the packed version, and then deploy.
If you have a unit testing framework like jsunit, it shouldn’t be hard to test the packed version.
Eliminating Tedium
Because typing these commands over and over can be tedious, you’ll probably want to create a script to run the packing commands. This .bat file will compress every .js file and create .js.packed:
compress_js.bat:
for /F %%F in ('dir /b *.js') do java -jar custom_rhino.jar -c %%F > %%F.packed 2>&1
Of course, you can use a better language like perl or bash to make this suit your needs.
Optimize Javascript Placement
Place your javascript at the end of your HTML file if possible. Notice how Google analytics and other stat tracking software wants to be right before the closing </body> tag.
This allows the majority of page content (like images, tables, text) to be loaded and rendered first. The user sees content loading, so the page looks responsive. At this point, the heavy javascripts can begin loading near the end.
I used to have all my javascript crammed into the <head> section, but this was unnecessary. Only core files that are absolutely needed in the beginning of the page load should be there. The rest, like cool menu effects, transitions, etc. can be loaded later. You want the page to appear responsive (i.e., something is loading) up front.
Load Javascript On-Demand
An AJAX pattern is to load javascript dynamically, or when the user runs a feature that requires your script. You can load an arbitrary javascript file from any domain using the following import function:
function $import(src){
var scriptElem = document.createElement('script');
scriptElem.setAttribute('src',src);
scriptElem.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild(scriptElem);
}
// import with a random query parameter to avoid caching
function $importNoCache(src){
var ms = new Date().getTime().toString();
var seed = "?" + ms;
$import(src + seed);
}
The function $import('http://example.com/myfile.js') will add an element to the head of your document, just like including the file directly. The $importNoCache version adds a timestamp to the request to force your browser to get a new copy.
To test whether a file has fully loaded, you can do something like
if (myfunction){
// loaded
}
else{ // not loaded yet
$import('http://www.example.com/myfile.js');
}
There is an AJAX version as well but I prefer this one because it is simpler and works for files in any domain.
Delay Your Javascript
Rather than loading your javascript on-demand (which can cause a noticeable gap), load your script in the background, after a delay. Use something like
var delay = 5;
setTimeout("loadExtraFiles();", delay * 1000);
This will call loadExtraFiles() after 5 seconds, which should load the files you need (using $import). You can even have a function at the end of these imported files that does whatever initialization is needed (or calls an existing function to do the initialization).
The benefit of this is that you still get a fast initial page load, and users don’t have a pause when they want to use advanced features.
In the case of InstaCalc, there are heavy charting libraries that aren’t used that often. I’m currently testing a method to delay chart loading by a few seconds while the core functionality remains available from the beginning.
You may need to refactor your code to deal with delayed loading of components. Some ideas:
- Use SetTimeout to poll the loading status periodically (check for the existence of functions/variables defined in the included script)
- Call a function at the end of your included script to tell the main program it has been loaded
Cache Your Files
Another approach is to explicitly set the browser’s cache expiration. In order to do this, you’ll need access to PHP or Apache’s .htaccess so you can send back certain cache headers (read more on caching).
Rename myfile.js to myfile.js.php and add the following lines to the top:
<?php
header("Content-type: text/javascript; charset: UTF-8");
header("Cache-Control: must-revalidate");
$offset = 60 * 60 * 24 * 3;
$ExpStr = "Expires: " .
gmdate("D, d M Y H:i:s",
time() + $offset) . " GMT";
header($ExpStr);
?>
In this case, the cache will expire in (60 * 60 * 24 * 3) seconds or 3 days. Be careful with using this for your own files, especially if they are under development. I’d suggest caching library files that you won’t change often.
If you accidentally cache something for too long, you can use the $importNoCache trick to add a datestamp like “myfile.js?123456″ to your request (which is ignored). Because the filename is different, the browser will request a new version.
Setting the browser cache doesn’t speed up the initial download, but can help if your site references the same files on multiple pages, or for repeat visitors.
Combine Your Files
A great method I initially forgot is merging several javascript files into one. Your browser can only have so many connections to a website open at a time — given the overhead to set up each connection, it makes sense to combine several small scripts into a larger one.
But you don’t have to combine files manually! Use a script to merge the files — check out part 2 for an example script to do this. Giant files are difficult to edit - it’s nice to break your library into smaller components that can be combined later, just like you break up a C program into smaller modules.
Should I Gzip It?
You probably should. I originally said no, because some older browsers have problems with compressed content.
But the web is moving forward. Major sites like Google and Yahoo use it, and the problems in the older browsers aren’t widespread.
The benefits of compression, often a 75% or more reduction in file size, are too good to ignore: optimize your site with HTTP compression.
All done? Keep learning.
Once you’ve performed the techniques above, recheck your page size using the tools above to see the before-and-after difference.
I’m not an expert on these methods — I’m learning as I go. Here are some additional references to dive in deeper:
- Ajax patterns: Performance Optimization
- Think vitamin: Serving Javascript Fast
- Detailed post on page load time
- Detailed Caching Tutorial and online tool to check your cacheability
Keep your scripts lean, and read part 2 for some working examples.
43 Comments »
Trackbacks & Pingbacks
-
Pingback by Webmaster Libre | links for 2007-02-22 — February 22, 2007 @ 7:05 pm
-
Trackback by Sentido Web — February 23, 2007 @ 8:15 am
-
Pingback by Speed Up Your Javascript, Part 2: Downloadable Examples! | BetterExplained — February 25, 2007 @ 11:46 pm
-
Pingback by Vinny Carpenter’s blog » Daily del.icio.us for Feb 25, 2007 through Feb 26, 2007 — February 26, 2007 @ 5:30 pm
-
Pingback by links for 2007-02-27 » mhinze.com — February 27, 2007 @ 4:19 am
-
Pingback by Ruby Brasil - » Diminua o load do código AJAX — February 27, 2007 @ 4:56 am
-
Pingback by Fatih Hayrio?lu’nun not defteri » 27 ?ubat 2007 Web’den seçme haberler — February 27, 2007 @ 2:09 pm
-
Pingback by All in a days work… — February 27, 2007 @ 5:28 pm
-
Pingback by How To Debug Web Applications With Firefox | BetterExplained — March 19, 2007 @ 11:56 pm
-
Pingback by How to Optimize Your Site with GZIP Compression | BetterExplained — April 4, 2007 @ 11:09 pm
-
Pingback by How To Optimize Your Site With HTTP Caching (Part 1) | BetterExplained — April 7, 2007 @ 2:26 am
-
Pingback by links for 2007-05-08 « Skywalker — May 7, 2007 @ 5:27 pm
-
Pingback by links for 2007-05-08 « J.Uma Shankar Ladha — May 7, 2007 @ 7:17 pm
-
Pingback by Speed Up Your Javascript Load Time « [REF] — June 15, 2007 @ 2:56 pm
-
Pingback by Starting Ruby on Rails: What I Wish I Knew | BetterExplained — June 19, 2007 @ 11:06 pm
-
Pingback by Rainbow in the AJAX Toilet — July 26, 2007 @ 5:00 am
-
Pingback by User First Web » Speed Matters: Presentation Files and Resources — September 19, 2007 @ 10:13 pm
-
Pingback by links for 2007-10-16 at atariboy.com — October 16, 2007 @ 4:21 am
-
Pingback by Loading time improvements with Javascript < Terminal Hacker — December 31, 2007 @ 9:05 am
-
Pingback by Design Shrine | AJAX SCRIPT RESOURCES — March 13, 2008 @ 9:43 am
-
Pingback by How To Make a Bookmarklet For Your Web Application | BetterExplained — April 16, 2008 @ 10:38 pm
-
Pingback by Scott » Blog Archive » Speed up javascript techniques — July 22, 2008 @ 12:42 am
Comments
RSS feed for comments on this post. TrackBack URI
Leave a comment
Have a question? Know an explanation that caused your own a-ha moment? Write about it here.




RSS

geez man…
instead of plugins [web-developer toolbar]&[OctaGate SiteTimer] you can use an another great fx-plugin. this is firebug!
magic.ant — February 22, 2007 @ 7:43 am
Can you be more specific about the problematic part? Because the great advantage of gzipping javascript is that the code is still readable.
I haven’t had any problems with it so far, but maybe I’m overlooking something.
Blaise Kal — February 22, 2007 @ 4:01 pm
@magic.ant: Thanks, I forgot about mentioning firebug. It’s great for debugging, but does it break down page sizes as well? (Update: Firebug does show page sizes on the Net tab, not sure how I missed that one! I’ve updated the article.)
@Blaise: The ThinkVitamin article goes into more detail — apparently some versions of Netscape and Internet Explorer (4-6) have issues correctly decompressing gzipped content:
“When loading gzipped JavaScript, Internet Explorer will sometimes incorrectly decompress the resource, or halt compression halfway through, presenting half a file to the client. If you rely on your JavaScript working, you need to avoid sending gzipped content to Internet Explorer.”
There may be workarounds by detecting the browser and returning different code, but I don’t think it’s worth the risk.
However, if you do get it working in all browsers, I’d love to hear about it!
Kalid — February 22, 2007 @ 4:26 pm
Nice article. You can also mention about merging all javascript files into one - this would reduce the no. of HTTP calls (even if the individual files are cached). And if you are pulling JS files from another host, it also makes sense to move those files to your domain, as this would reduce the server lookup time.
Anand — February 25, 2007 @ 11:19 pm
Thanks Anand, I had forgotten to mention that. I just put up Part 2 which has a script to combine your files into a javascript library.
Kalid — February 25, 2007 @ 11:59 pm
HTTP already allows to gzip the payload, so there is really no need to think about gzipping.
jpl — February 26, 2007 @ 6:04 am
i wrote n uploaded a javascript in my website
that script loads as the page loads
but i want to enter some 30 seconds delay in javascript to load
can i do it
plz help me
raheel — March 4, 2007 @ 12:54 am
Hi Raheel, check out the example in part 2:
http://betterexplained.com/articles/optimized-javascript-example/
There’s a script that loads after 5 seconds — you can change the delay to 30 instead (30 * 1000).
Kalid — March 4, 2007 @ 1:35 pm
There’s a script that loads after (24 * 1024).
tank’s
http://unidadlocal.com/?buscar=javascript
Omar — March 13, 2007 @ 4:37 pm
Kalid, I don’t agree with your comment on not using gzip. Gzip is required to be supported by HTTP 1.1 protocol, which includes most modern browsers. The bug in IE 6 that is referenced by the ThinkVitamin article affects not just gzip content, but other content as well. People are far better off using gzip than not.
Also, regarding your comments on caching you need to be careful about what HTTP 1.1 caching commands you use because users could be going through proxies that are HTTP 1.0 resulting in odd/unexpected behavior.
Trevin — March 17, 2007 @ 4:27 pm
Hi Trevin, thanks for the comments.
1) Regarding gzip compression, I agree that it is extremely useful (in fact, I’m researching the best way to turn it on for InstaCalc).
One problem with IE6 is that it says it accepts gzip’d content but may have problems decoding it:
http://www.google.com/search?q=ie6%20gzip%20problem
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312496
As a result, webmasters serving gzip’d content have to resort to hacks like detecting the browser user-agent and returning regular content to IE6, even if it says it can accept compressed content:
http://httpd.apache.org/docs/2.0/mod/mod_deflate.html
These tricks can be done, but may be tough for a newbie. Of course, we can just take a scorched earth approach and let IE6 choke if it can’t render the page, but this is tough stance to take given that IE6 still has a large fraction of browser share.
However, I agree with you that output compression is extremely valuable. In my tests it shaves over 2/3 of the bandwidth, so I really, really want to enable it (and find a suitable workaround for IE6).
2) Yes, caching can be tricky as well. As I followed these topics down the rabbit-hole I’m seeing more of the intricacies here.
In general though, it appears to me that an old HTTP 1.0 proxy won’t cache something a new HTTP 1.1 header is set. You might not get the performance benefit when using an old proxy, but I’m not sure what other impact there would be.
Both of these are probably topics for a follow-up article
Kalid — March 17, 2007 @ 4:42 pm
Excellent , thanks
Abdullah Arslan — September 25, 2007 @ 12:07 am
Hi Abdullah, glad you liked it.
Kalid — September 25, 2007 @ 7:26 am
I just installed Java..What will it do? I need it to speed up my browser. Will it do that? If not, what?
Peace
Dirk
DIRK PATRICK — October 30, 2007 @ 11:10 pm
Hi Dirk, Java and Javascript have similar names but actually aren’t related (it’s often a big source of confusion).
I’ve been using Opera (http://www.opera.com) as my browser — it’s really fast and you may find it fits your needs.
Kalid — October 30, 2007 @ 11:30 pm
Microsoft to Force Upgrade IE6 to IE7 on Feb 12. So you may turn compression on
collector — January 22, 2008 @ 9:11 am
Good point… although I think there may be some other ancient browsers in the “gzip not welcome” list too
Kalid — January 22, 2008 @ 10:51 pm
response to “Should I Gzip It?” paragraph:
You CANNOT ignore old browsers. It shouldn’t even be an option unless you re making an intranet app for a specific browser. As a (web) developper, it’s YOUR JOB to make it work for everyone. Any other mindset and you might as well just go sell peanuts…
nnm — February 1, 2008 @ 5:27 am
@nnm
while I agree that efforts should be taken to support older browsers, who elected you to decide what his job is? Do you still support NCSA Mosaic 1.0?
Mosaic 1.0 is only 15 years old, IE 5 is 9 years old, IE 5.5 is 8 years old. When is something so outdated that you don’t support it anymore? Or is the web developer supposed to shoulder all the burden when the browser vendor doesn’t provide proper patches for their browser or the consumer runs a buggy browser?
huxley — February 17, 2008 @ 6:08 pm
Combine Your Files … why on heart no one talk about packed.it? It could combine in ONE file both CSS and JavaScript, merging them in a way that Rhino could not do!
At the same time, packed.it parses conditional comments as well, there’s JavaScript inside, but of course a JavaScript that Rhino could not understand.
Did I forget something? Yes, packed.it uses deflate before gzip, about 3% bigger but probably much more safer with old IE too?
Anyway, good stuff, and Kind Regards
Andrea Giammarchi — March 13, 2008 @ 2:06 am