A good user experience requires responsiveness. Speed. Web pages that don’t make you wait more than a couple of seconds while they load, or even worse, load in bits and pieces and reorganize themselves in front of the user; “that’s the way these things work” isn’t good enough an excuse. Your users don’t want to know how your site works (even if your site is about how the internet works – they want to read about the problems, not experience them), they just want to get things done and move on. As Eve says in Gaiman’s The Sandman Vol. 6: Fables and Reflections, “Some people have real problems with the stuff that goes on inside them … sometimes it can just kill the romance”.
Two of the culprits these days seem to be huge JavaScript and CSS files. They’re by no means the only causes, but they can cause trouble at times. Delays when loading a CSS file result in the dreaded flash of unstyled content on some browsers. Problems loading a JavaScript file… well, let’s just say it ain’t pretty. The delivery of these files can be slowed down by a number of factors. File size is one of them; a 168kb file will download considerably more slowly than a 6kb one.
This is made worse by the use of multiple JavaScript and/or CSS files. Separating functionality or styles in a sensible way is heaven-sent when it comes to maintenance, but the way the web works means that it’s a lot easier to download one largish file than several small ones. Multiple files mean that the browser must make multiple requests to the server, and each request carries a small overhead since the server has to include a certain amount of information with each response it makes. To top it off, most browsers are configured to open a limited number of connections to a server at any one time – IE8 allows up to 6 concurrent downloads on broadband, while Firefox allows 8; these connections must be shared between the JavaScript, style, images, and other embedded files. This can cause the downloads to be queued up on pages with a lot of stuff on them.
What we need, then, is a small number of reasonably sized files: how do we get to that?
Bring ‘em together
Your users don’t need to have 3 style sheets. They need to see your page. While you’re working, you should definitely split things up to keep them manageable, but in production? Nope. You might decide to split because you don’t want your users to have to download content they don’t need, but that can be false economy in most cases – it robs you of your ability to use caches to your advantage. If you use a lot of different files, users will have to download something every time they hit a new page. By contrast, if you use less files, most subsequent requests to your page will be served from the cache – much faster.
Unless you have an incredibly massive codebase, or scripts/styles that change regularly, or a massive chunk of code that’s only used in a single, rarely visited page, I’d suggest pulling them all on a single file when you publish. Hell, if you have stuff that changes regularly, you might want to isolate that and still consolidate everything else. The ideal state of affairs would be 1 css and 1 JavaScript file, but that’s not a law.
An easy way of consolidating files before releasing them is to use a simple MS-DOS batch file like:
1: del script.js
2: copy /B *.js script.js
Which will collect all javascript files in a given folder into a single file called script.js. The same can be done for CSS files just by changing the extension. If you only want to collect some files, and leave others out, you can also use the following:
1: copy /B file1.js + file2.js script.js
So now we have a couple of files, which are sort of huge. Ouch. What next?
Cut the flab
Removing unnecessary material from the files we publish sounds right for the next step. Both JavaScript and CSS files tend to be written in a way that makes it easy for humans to read them. This is true even for the sloppiest coder; a hand written script will contain at least some line breaks, spacing, and possibly some variables and comments that are necessary for us to make sense of them. But guess what – they’re totally useless to a machine, and every excess line break, every excess space, is one byte you shouldn’t have to send.
No, I’m not advocating unreadable code. You need neat, readable code if you want to maintain it. However, that neat, readable code is not what your users need – it slows them down unnecessarily. What you can do is, grab a code compressor like Julien Lecomte’s YUI Compressor and use it to crunch your scripts and styles. YUI Compressor requires a Java runtime, and can be run from the command line. I use the following batch files for it:
compress-js.bat
1: "c:\Program Files\Java\jre1.6.0_07\bin\java.exe" -jar yuicompressor-2.4.1.jar --type js --charset UTF-8 -o %1-min.js %1.js
compress-css.bat
1: "c:\Program Files\Java\jre1.6.0_07\bin\java.exe" -jar yuicompressor-2.4.1.jar --type css --charset UTF-8 -o %1-min.css %1.css
Both these batch files take a file name (without extension) as a parameter, and will create a file tagged –min. For example, if we call compress-js myscriptfile, the batch file would look for myscriptfile.js, and compress it into myscriptfile-min.js
To give a trivial example
This 221 byte file …
1: // Pops a message box saying foo.
2: function foo()
3: {
4: alert('foo');
5: }
6:
7: // Pops a message box saying bar.
8: function bar()
9: {
10: alert('bar');
11: }
12: // Pops a message box saying baz.
13: function baz()
14: {
15: alert('baz');
16: }
… gets compressed into an 85 byte file:
1: function foo(){alert("foo")}function bar(){alert("bar")}function baz(){alert("baz")};
The reduction is even higher if you have local variables, since their names get munged, saving more space.
Zip it
Want more crunch? You can use gzip to compress your JavaScript files even further, but be warned: you need to mess a tiny bit with your server settings (real tiny, promise) and it doesn’t play well with all browsers. IE, Firefox and Chrome seem to handle it fine, but Safari might have some problems getting it down; you should still be able to configure the server to serve an uncompressed copy if the browser doesn’t accept gzip encoding.
To let a page use compressed script files, map a file extension – we’ll use .jsz – to the text/javascript mime type, and add the gzip encoding to that. This tells the server to tell the browser that .jsz files are javascript files with the gzip encoding.
In Apache, we can do this through an .htaccess file:
1: AddType “text/javascript" .jsz
2: AddEncoding gzip .jsz
I’ll get back on how to do this in IIS at a later stage, since I don’t have an installation I can mess with right now 😛
To gzip the file, we just have to use a blindingly simple command:
1: gzip -c script.js > script.jsz
We can now call the .jsz file as we would call a normal javascript file. Remember that you can also use modules like mod_gzip to compress other outgoing content.
… And that should hopefully keep everything running smoothly.
Further reading: Smashing magazine has a great post on cleaning up and reducing CSS file sizes at http://www.makeuseof.com/tag/useful-tools-to-check-clean-and-optimize-your-css-file/