CSS & JS Compression for Web Applications

The Problem

If you’re writing a web application from scratch, there are a lot of things you need to account for.  Security, performance, usability, accessibility, cross-browser support, the list goes on and on.  In the decade and a half that I’ve been doing web work, the focus has shifted from writing web sites from scratch using a HTML editor to using a CMS (Content Management System) such as Drupal or WordPress.  CMS’s do the heavy lifting for you… they have security built in, are tested for performance and usability, have accessibility plugins, and most have well behaved cross browser support.

Honestly that’s why my own website here is using WordPress.  Why re-invent the wheel?  Well, sometimes you need a big gnarley wheel that doesn’t exist yet.  That was the case with Maestro, a huge compliance documentation system I wrote for NMSU Research.  Since I wrote it from scratch, it needed all those things I wrote earlier, and I had to write them myself.

More Specifically

I may talk more about other aspects in other posts, but today I’m going to talk about performance.  Performance isn’t as much of an issue as it used to be.  15 years ago, filling a web page with huge images, gifs, or even, heaven forbid, music, could slow things to a crawl pretty quickly.  The intervening years have seen a steady increase in internet bandwidth, so downloading huge images isn’t much of a concern anymore.  Still, there’s no reason to be blase about performance.  Might as well shave off bits and bytes where you can as a general good practice.

In the world of huge scale enterprise applications, however, simply avoiding a devil may care attitude isn’t enough.  When you’re talking about hundreds of thousands of lines of code, to include recursive functions and many database calls, performance can become a real issue.  Many tools exist to help diagnose bloated code, and any programmer worth their salt knows how to use a benchmarking kit.  There are a few places, though, that small gains, which add up over time, can be had simply by knowing the right tricks.

The Point?

Imagine you have a web page, or a web app.  The app has thousands of lines of code split up into main files, included files, bootstrapping files, class files, and certainly JavaScript and CSS files.  While most of the actual code files themselves usually get interpreted on the server, which is done blazingly fast, JavaScript and CSS files must be sent to the client’s browser for parsing and interpretation.  Each of those files requires a HTTP request to be made and answered, then the file must be downloaded and processed.  It may not seem like much, but in a large web app there could be tens or hundreds of these files.  Especially if, like me, you like using open source packages and plug-ins to make your life easier.

Some of this is mitigated by caching… the act of saving the file locally on a client’s machine so that it doesn’t need to be re-downloaded every time.  Caching is great, but it requires the programmer to properly set the timing of the file, or set a blanket timeout on the server.

Another issue which seems insignificant on it’s face, is that there’s usually a lot of wasted space in these files.  Every space, carriage return, or other extraneous character represents a bit that must be transmitted.  Even if the file is cached, the transmission of these superfluous characters must happen at least once.

My Answer

My answer for this was to write a class that combined all these files together and then to use a tool called YUI Compressor, which is a command line tool for Linux.  When you run it against a file, YUI Compressor strips out all the extra characters and mashes the file down in a compressed state.  It will even shorten the variable names in JavaScript files so the files become extra small, and extra hard to read… as a bonus.  Harder to read JavaScript files give just a little extra bit of security from script kiddies trying to weasel their way into your web app.

My compressor class takes all the CSS files you feed it, combines them all together, finds all the images from those files and places them in a single location (so the path references will match up correctly) and runs YUI Compressor on the resulting file.  At the end, I run a quick hash of the file names along with the last modified time of each file.  I use the resulting hash as the file name of the combined file.  That way, when my user comes back to the app, I can use the file name to quickly determine if any of the css files included have changed, or if any need to be added or removed.  If everything is the same, I just stick the file name in a CSS tag.  If not, I re-run the compression and then stick the new file name in a CSS tag.

JavaScript is handled the same way, without the image moving.

In the end, no matter how many files I start with, I always end up with two, or maybe three (I split the JavaScript into pre and post page load sets).  Three files is far easier for a browser to download and handle than 300, and it saves time and bandwidth.  Once the script is in place, the process is automatic and takes almost no time at all.

See the Code

To see what I’m talking about or to get a copy of the code, check it out on GitHub.