Friday 17 August 2007

Firefox 2.0.0.6 vs Opera 9.20

This post is not just to let you know what browsers I'm using at the moment.
It's rather about this speed problem a colleague of mine and I are having for a web application.

Just to make it simple, there are two divs, each contain a huge table, each with around 100 rows of 20 columns each, in each cell there is either some text, a checkbox or a select tag with around 5 options. Just to sum things up, there are like 800 checkboxes and 800 selects. They are loaded by pulling data from the server through a HttpRequest object.

We were expecting loading to take a long time and it really does :-)
What is really surprising is what happens when they're both loaded and their classNames are changed, one gets a class name that has among others "display: none" to hide it and the other gets "currentDiv" class name which sets a few properties.

I'm really surprised about how ling time it takes Firefox 2 to do this operation. I checked with FireBug exactly what part of the code takes the most to run and this is it:

  myDiv.className = "currentDiv";

This is where it spends around 10 seconds.

I thought instead of changing the class name, to try and change the style.display property, but there was no visible difference. Here's a nice test on this subject.

Just for tha hell of it, I also took down any other CSS properties from the "currentDiv" class and especially these kind of lines:

  div.currentDiv table td.commentTd{ ... }

I thought maybe the rendering engine has to go through all cells of the table in this specific div and change the visual attributes. Well, again, no improvement.

I was curious what had Opera to say about this matter and I tested the same code on Opera 9.20. Result: under 2 seconds including loading the div. Absolutely surprising.

I'm not giving up on Firefox, yet, I still love it :-) But I'm looking forward to Firefox 3 with its new and improved JavaScript engine ;-)

Wednesday 15 August 2007

Prevent browser caching of web pages

I'm having problems with cached web pages in some of my web applications.
There is this particular application that is in continuous development, while employees are using it and whenever I make some modifications the old version conflicts with the new one throwing errors or displaying some mixed information: some from the old html code and some new information the web page retrieves by AJAX.

I got a fix for the html code, now it isn't cached any more. I use this code in PHP:

  header("Cache-Control: no-cache, must-revalidate");
  header("Expires: Tue, 29 Mar 1983 07:20:55 GMT");

This really works, everything I modified in the PHP code is updated every time someone browses the web page, but not the JS and CSS files that are linked from the html code :-(

I found some more tips for preventing caching here. They consist in adding some meta tags in the head section of the web page:

  <meta http-equiv="expires" value="Tue, 29 Mar 1983 07:20:55 GMT"/>
  <meta http-equiv="pragma" content="no-cache"/>

The value of the first one is a date in the past, obviously. I'll let you guess the miracle that happened on that particular date I chose to put in there :-)

I tried this as well and it doesn't work for js and css files, unfortunately :-(

This wouldn't have been a problem if my js code was inline, but I never insert inline JavaScript code if there are more than 20 lines. I always like to split the code in many files each representing a module that can be taken and put on another website and works without changing anything except maybe a few variables.

Another idea was to send a header for each js or css file, but that would mean changing the js and css files to .php and send the headers I wrote at the begining of this post. I really don't want to do that, I want to keep them as js and css, because it's makes the application neat and organised. Many editors highlight code according to the file extension, I don't want to switch to choosing manually the highlighting style.

Some other ideas I got from Matt Raible and this forum. The idea is simple, very simple, just add a random number as a variable sent by GET method. This will foul the browser to think that it's always a new file without affecting the file itself.

Some other idea is to use subfolders for each version and just change the version folder in the path provided in the html code. This won't be a big problem because I use this piece of code to load dependencies, if versions change, I'll need to change only the main file that loads the dependencies, but others might find this annoying.

These last methods work fine, problem solved. But thinking about optimisation, the js and css files will never be cached so I lose one of the most important advantages I got by using external files, exactly what I want to get rid of: caching. Caching is meant to store information that is used often instead of loading it again and again.

As I don't update these files so often I decided to use a combination of all these methods. I use the headers to make sure the html code is always updated (usually there isn't too much html code in my html files, so not too much overhead ;-) ). I added a variable called version to the end of the file and I update it when I want the code in js and css files updated as well.

Here are the sample lines:

  <link rel='stylesheet' type='text/css' href='stylesheet.css?version=3' />
  <script type="text/javascript" src="js/toolbox.js?version=3"></script>

Don't forget to update the version number to the files you load dynamically from other js files!