Robert has posted 1 posts at DZone. View Full User Profile

YSlow Rules and Tomcat 5.5 SSL

10.21.2008
| 9930 views |
  • submit to reddit

A few weeks ago I attended The Rich Web Experience where I went to talks by Scott Davis and Nathaniel Schutta and heard about using YSlow to measure how well your web application performs. Of course I rushed right back to the office to check my current project's grade and implement as many of the performance enhancing techniques as I could. My application is running in Tomcat 5.5 over SSL. As it turned out this posed an unexpected challenge and in the end the solution was trickier than I anticipated. In case anyone else is in the same boat I'll reference the helpful article I found and summarize what I did to improve my grade.

Adding a far-future expires header to static content (rule 3) should have been no problem. I started out creating a simple filter that I applied to CSS, JavaScript and image files. Here's the crux of the code.

response.setHeader("Expires", "Wed, 21 Oct 2009 11:49:28 GMT");
response.setHeader("Cache-Control", "public");

To be safe, I actually set the expires header to be one day after the current time because I read that if you set it too far in the future some browsers may reject it. Well, the filter did change the expires header but according to Firebug, Tomcat kept going back to the server to download the files anyway. The problem was a pragma no-cache header put in by Tomcat for some reason. This appears to trump the expires header. After some failed attempts to get rid of that pesky header I found this article which prompted me to add the following to my context.XML file.

<Valve className="org.apache.catalina.authenticator.SSLAuthenticator" disableProxyCaching="false" />

This solved my caching problem.

Next on the laundry list was CSS and JavaScript minification (rule 10). Like most projects we are using several different JavaScript libraries and divide our custom written JavaScript into several files. Our CSS is similarly divided. I wanted to use YUI compressor to minify these into a single JS and a single CSS file. (Single files to satisfy rule 1.) Of course we don't want to have to read or edit the code in this minified state so I wrote an ant target to concatenate the files in the correct order and then invoke the compressor. This works well unless you're trying to debug JavaScript in Firebug so I put in a switch to disable the minification during development.

The next task was to make sure the CSS comes at the top of our pages and the JavaScript at the bottom (rules 5 and 6). We use SiteMesh so putting our single CSS file in the head was no problem. It just goes in the master decorator page. So far we have been able to avoid page-specific CSS so we need just the one link tag on every page. Putting the JavaScript right before the end of the body tag was a little trickier. Almost all of our pages have page-specific JS code that uses functions and variables from the different libraries that have been rolled into the single JS file. So the link to this script must appear before the page-specific script. I achieved this by setting a request attribute called pagejs in pages that need specific script. Then this text gets rendered after the script link but before the end body tag in the master decorator page, like so.

...
</div>
<script type="text/javascript" src="<c:url value="/scripts/script.js" />">
${pagejs}
</body>

I played around with externalizing the page-specific JS but much of it is generated dynamically. Even when it was completely static there wasn't much of a performance boost by extracting it so we keep it inline. (I think this is because the JavaScript gets loaded serially.) One thing I like about this approach is that I can still put the JavaScript at the top of my JSP's where I'm used to seeing it and let the decorator take care of rendering it at the bottom.

After performing these fairly simple modifications I've noticed a big improvement in performance. The user hits the home page and the browser downloads two extra minified files and a few images. Then for the rest of the day users are just loading dynamic HTML and taking the rest from cache. My only remaining task is to make use of a content delivery network or something like it for the static content. That ought to raise my B grade to an A! Thanks Firebug and YSlow!!!

References
Published at DZone with permission of its author, Robert Donaway. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Ivan Lazarte replied on Tue, 2008/10/21 - 3:59pm

thanks for the tips.  stuff like that valve setting are always the kind of things that take people hours to track down for some reason.

matt raj replied on Fri, 2008/10/24 - 7:53am

The easiest way I've found to combine and minify your js and css is to use http://sourceforge.net/projects/packtag

It's LGPL and does it on-the-fly with a debug mode. 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.