Serving JavaScript and CSS
by Naneau
Now that JavaScript based sites are on the rise again, I have noticed that a lot of people serve their JavaScript and CSS uncompressed. With the discussion about all those nifty JavaScript libraries out there reaching an all time high, the fact that you can easily reduce file size by over two thirds should not be overlooked. There are two techniques you can use to reduce the file size of your .js and .css files.
First, you can make sure that they are being served compressed. Modern browsers all support gzip compression. It’s easy to set that up under apache using mod_deflate. You can also do that from php. I like the last way because it gives me greater control over the caching. I’m sure it’s more memory and cpu intensive though.
Second, you can reduce the contents of your JavaScript and CSS directly. Comments, for instance, are usually little importance to the end user. In CSS you can also reduce all white space to single spaces (it has no meaning). There are more sophisticated techniques of reducing size of course. Think about the following:
1 2 3 4 5 6 | #someid { padding-top:10px; padding-right: 5px; padding-bottom: 20px; padding-left:0px; } |
It could easily be rewritten as:
1 | #someid {padding:10px 5px 20px 0;} |
There are libraries out there that can do things like this automatically. For JavaScript similar things can be done of course.
I decided to bundle all of that into a simple module, for use with the Zend Framework. I was tired of setting it up time and time again. Because I think it can be useful for many of you, I’m going to release it. Because I’m not very imaginative, I called it ‘jscsscompressor’. Which, though boring, is quite descriptive. It’s pretty easy to install, just check it’s install.txt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | how to install in a few easy steps. Assuming you use Apache for a web server: - Remove all .htaccess files from your javascript and css folders under your webroot - make sure that your "root" .htaccess routes .js and .css files to your bootstrap. If you've followed a tutorial for setting up the framework, you'll probably want to change: RewriteRule !\.(js|css|ico|gif|jpg|png)$ index.php into RewriteRule !\.(ico|gif|jpg|png)$ index.php - unpack the contents of this archive. The contents of the controllers directory go into where you keep your controllers. The contents of the library directory go into your library. (I told you they were easy steps ;)) - Make sure the front controller knows where the jscsscompressor module lives. You can do this by adding the controller directory to it like so: $frontcontroller->addControllerDirectory('path/to/your/controllers/jscsscompressor', 'jscsscompressor') - Edit the IndexController.php file. Set both the root directory of your site, and a cache directory. - Set up a route for the module, so it will start serving .js and .css files. If you don't know what a rewrite router is, see (http://framework.zend.com/manual/en/zend.controller.router.html). If $router is your rewrite router: $router->addRoute( 'jscsscompressor', //name of the route new Zend_Controller_Router_Route_Regex('(.+)\.(css|js)', array( 'module' => 'jscsscompressor', 'controller' => 'index', 'action' => 'compress' ), array( 1 => 'file', 2 => 'type', ) ) //jscsscompressor/index/compress ); - Enjoy your new gzipped and compressed files |
The most interesting part is probably the custom route to the module:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $router->addRoute( 'jscsscompressor', //name of the route new Zend_Controller_Router_Route_Regex('(.+)\.(css|js)', //everything ending with .css or .js array( 'module' => 'jscsscompressor', 'controller' => 'index', 'action' => 'compress' ), array( 1 => 'file', 2 => 'type', ) ) //jscsscompressor/index/compress ); |
With it I was able to reduce file sizes quite dramatically. Ext JS‘ ext-all.js weighs 458 KB, with gzip compression, that will be reduced to 123 KB. If you also pack it it can be reduced to 114KB. That’s about a 4 to 1 reduction
. Packing JavaScript may cause some problems though, mainly with prototype.js which leaves out semicolons at places where it shouldn’t.
At any rate, hope I can help you with JsCssCompressor
update May 29, 2007
With the newer releases of the framework (newer than the current stable one, 0.9.3), there’s an action helper enabled by default called viewRenderer. It will mess up my implementation quite nicely. I suggest you disable it, by calling the following on your frontcontroller (in your bootstrap):
1 | $frontController->setParam('noViewRenderer', true); |
That should get rid of those irritating exceptions about somecontroller/someaction.phtml not being found.
Comments
Great post. I also fret about optimizing my JS and CSS files though I haven’t delved into the many compression possibilities. Not sure about you, but I find it very surprising that Prototype leaves out some semicolons. Don’t they know that people will try to compress and/or pack it?
Cool!
Just one notice:
ZF Requires E_STRICT compatibility so optimizing css with CSSTidy throws a bunch of Strict Standards lines:
Non-static method csstidy::is_important() …
Add litlle hacking in class.csstidy_optimise.php file!
Adding static to these two functions solves the problem!
static function is_important($value)
static function gvw_important($value)
Regards,
AlesL
AlesL is of course absolutely right. I included the packing as a bit of an afterthought, and didn’t feel like editing the respective files (csstidy, while functional, could do with some phpdoc as well).
If you really require E_STRICT compatibility, I would suggest you follow AlesL’s suggestions, or leave the packing out all together.
Ultram….
Ultram. Generic ultram….