01.27.09

Using javascript to change img src attribute, far-future Expires headers and cacheing

Posted in Web authoring, javascript at 11:36 pm by karl

The Leitrim Design House web site went down the other day because it had exceeded its bandwidth allocation. This caught me by surprise - it’s a relatively small site for a niche audience and I was quite sure I had put it on a hosting plan with enough available resources. The server statistics revealed that the same 6 images were requested over 80,000 times each on a single day. Huh?

The pictures in question appear in a slideshow on the site’s home page. There is a javascript component that fades the images into each other every 10 seconds or so. Using Live HTTP Headers I could see that every time the image changed a new HTTP request was being sent. On my machine I was getting a status code 304 and the image wasn’t being requested every time but it seems this wasn’t the case everywhere (local cache disabled? Badly-behaved browser? It’s hard to tell.). So, what to do?

I decided to take a belt-and-braces approach on this to prevent a recurrence (and to avoid incurring the wrath of the nice people at blacknight). The first thing was to have a look at the javascript and stop it requesting images unnecessarily. The original slideshow code worked like this:

  1. clone the DOM node containing the first image in the slideshow
  2. put the new image under the old one (using z-index and absolute positioning)
  3. change the src attribute of the lower image to contain the URL of the next image in the slideshow
  4. wait a few seconds
  5. fade the upper image to 0 opacity
  6. swap the Z position of the 2 images
  7. set the lower image to full opacity
  8. go to step 3

I could see that a new HTTP request was going out at step 3 above, even when it was reloading an image that had previously been displayed. So I changed the code to this:

  1. clone the original image node N-1 times (for a slideshow with N images)
  2. hide all but 2 images
  3. put the visible images 1 on top of the other (using z-index and absolute position)
  4. wait a few seconds
  5. fade the upper image to 0 opacity
  6. hide the upper image and increase the z-index of the lower image
  7. unhide the next image
  8. go to step 3

The new code loads all the images at once and makes no more requests once they are loaded. There are some obvious problems with this code

  • what happens if there are hundreds of images?
    • there will be a stampede of HTTP requests which will inevitably lead to timeouts and missing images
    • potentially unlimited amounts of memory will be used to store all the images
  • what if the wait period between displaying images is shorter than the time it takes to load them all?
    • once again there will be partially loaded/missing images

However, I’m a firm believer in the agile mantra “You’re not gonna need it“. For this application there are no more than 6 images in any slideshow, the images are all under 50kB and the wait time is about 10 seconds so the above problems shouldn’t arise. If I need to refactor in future, so be it.

Finally, I realised that I hadn’t configured apache to set the Expires header on images to a date far in the future. I added a couple of lines in the top-level .htaccess fileto make the images expire in 5 years. This means that on repeat visits to the site, if there is a copy of an image in your browser cache, the browser won’t even check to see if the image has been modified.

Leave a Comment

You must be logged in to post a comment.