Reducing Javascript and CSS Load Times

I was making a complex ajax web application and ran into problems with load times. In some cases, it was taking up to 7 or 8 seconds to load a page. I found out the culprit was multiple large javascript and css files. Here's how I was able to get my load times under a second with a few changes. All of the examples below are for javascript files, but they apply equally to css files.

Combine javascript and CSS files

There is overhead each time the browser has to load an external file, so reducing the number of server calls can speed up page loads. Originally, I put all of my javascript scripts in one large file. This helped page load times, but made it difficult to edit individual scripts. I then switched to a PHP solution.

I created the following PHP page, which combines multiple javascript files on the fly.

<?php
//set content type
header('Content-type: text/javascript');

//pull list of comma-separated files from $_GET
$js_files = explode(',',urldecode($_REQUEST['files']));

//read each file
foreach($js_files as $js_file) {
 echo "\n\n\n/*******************$js_file********************/\n";
 $file = '/path/to/js/directory/'.$js_file.".js";
 if(file_exists($file)) readfile($file);
}
?>

Here is how you would load javascript files in the head section of page.

<!-- Using PHP's urlencode function -->
<?php
$files = array("jsfile1","jsfile2","jsfile3");
?>
<script type='text/javascript' src='/path/to/js/directory/javascript.php?files=<?php
 echo urlencode(implode(',',$files));
?>'></script>

<!-- No PHP, hard code commas as "%2C" -->
<script type='text/javascript' src='/path/to/js/directory/javascript.php?files=jsfile1%2Cjsfile2%2Cjsfile3'></script>

This reduced my load times to about 5 or 6 seconds.

Take Advantage of Parallel Downloading

This partially contradicts the previous tip when I said less files were always better. Most browsers are capable of downloading a limited number of javascript and css files at the same time. For example, Firefox will usually download up to 3 files simultaneously from a single host.

If you have 1 or 2 large javascript files, you should put them in their own script tags and combine the rest of the scripts as before. This way, the browser doesn't have to wait for the large script to download before fetching the other ones. Here's an example.

<!-- Large js file -->
<script type='text/javascript' src='/path/to/js/directory/javascript.php?files=largefile'></script>

<!-- Multiple smaller files -->
<script type='text/javascript' src='/path/to/js/directory/javascript.php?files=jsfile1%2Cjsfile2%2Cjsfile3'></script>

Even though you are only loading one file in the first case, you should still use the php script to take advantage of the later tips.

This reduced my load times further to about 2 or 3 seconds.

Compress Javascript and CSS files

The basic idea behind this is to reduce the size of javascript and css files by removing comments and extra white spaces among other things. There are two ways to do this, each with their advantages and disadvantages.

The first is to compress the files directly. The advantages here are speed and reduced server load. The server doesn't have to waste time compressing each file at runtime. The big disadvantage is that compressed files are almost impossible to edit. This method works best for 3rd party scripts, such as javascript frameworks, that you aren't going to be editing yourself. Most frameworks offer compressed versions directly, but you can also compress any file yourself with http://jscompress.com/ for javascript files and http://www.cssdrive.com/index.php/main/csscompressor/ for css files.

The other method is realtime compression. The advantage is files remain editable and the development process is much easier. The disadvantage is that the server must re-compress each script at runtime, which takes time and processing power. This method is best for scripts which you edit often. There is a great php script for doing this called minify that works for js and css files. They have plenty of documentation on the site and it's pretty easy to implement into the php script we created above.

Compressing files can reduce the size by anywhere from 10% to 50% or more. As an example, the uncompressed jquery framework is 160kb and the compressed version is 70kb. This can potentially cut loading times in half, but the actual gain is probably less than that.

Take Advantage of Caching

A lot of times, javascript and css files don't change very often and it doesn't make sense to load them on each page view. With a few simple changes to our php script, we can make the browser cache these pages. This provides the biggest improvement in load times.

<?php
//set content type
header('Content-type: text/javascript');

//if the nocache parameter is not explicitly set
if(!$_REQUEST['nocache']) {
 //store in cache for 1 day (86400 seconds)
 header('Expires: '.gmdate('D, d M Y H:i:s', time()+86400).'GMT');  
 header('Cache-Control: max-age=86400'); 
 header('Pragma: max-age=86400'); 
}

...

If you have some file which changes frequently or is generated at the server side, you can pass "nocache=true" in the script tag source.

One problem you may notice is that if you make a change to a javascript file, a user may not get the latest version for a full day, which could break the site in the meantime. Luckily, there is an easy solution.

If the script src changes, a browser will always reload the script, even if it was cached. Since we're already passing parameters in the script url, we can add "version=#" and increment this number whenever we make a change. That way, the script will be reloaded the next time the page is.

The first time the webpage is loaded, there is no added benefit, but the load times of subsequent pages was reduced to less than a second.

If you can think of any other tips to reduce page load times, let me know.

blog comments powered by Disqus