Last fall, my company developed an election game for the primaries and caucuses called Kingmaker, which we launched in the middle of December. We built portions of the site in Adobe Flex. Although this provided some cool functionality, it increased our page sizes significantly. So, I began my search for ways to shrink down everything else on the site to compensate for the tremendous increase caused by Flex apps.
- I like Prototype. I wanted to keep it. But it's huge (124K uncompressed).
- I like Script.aculo.us. I wanted to keep that too. Again, it's huge (I only use effects, controls, slider, and dragdrop... 111K uncompressed)
What Didn't Work
JSMin is also regex based, so it has the same issues.
Fixing Prototype's Syntax
A Changing Solution
Shortly, I discovered the pack:tag JSP Tag Library, which seemed to be what I was looking for. The pack:tag had many benefits:
- Simultaneous minification and obfuscation
- gzip compression
- Combination of static resources to minimize round-trips from client to server
- Caching of compressed static resources via a memory (Servlet) or file cache, and thus minification, obfuscation, and compression at resource request time (as opposed to compile time)
- Pluggable compression algorithms (and an implementable interface for creating your own packing strategy)
- Configuration via a .properties file
My favorite additional benefits are as follows:
Second, the pack:tag checks to ensure that a resource is not included more than once in the same page, automatically ignoring subsequent requests, which can accidentally happen quite easily when using multiple JSP includes (used in multiple places) to dynamically build a page.
<pack:script src="/my/file.js" />
Or, to combine multiple resources:
An added benefit of using the YUICompressor is a significant amount of logging output that complains to you're doing something stupid. Unfortunately, I haven't found a way to turn off that output, so it does fill up the log a bit when compressing files wherein I reference functions that are declared in other files (which it has no context of, unless the files are combined before processing).
For testing, all downloaded file size measurements were taken using the Firefox plugin Firebug, version 1.05.
Or for the other scenarios using pack:tag to include each with:
<pack:script src="/js/prototype.js" />
Grouped - The JavaScrpt files were included together in one file. For the case with minification and gzip via:
For the minified test without gzip, I created a new file (total.js) with the output of the above grouping and included it via:
Versions used in testing
Script.aculo.us 1.7.1 Beta 3
As a testament to this conclusion, more compression options have become available lately. John-David Dalton has released a collection of compressed Prototype and Script.aculo.us versions on Google Code. He explained his process in an Axajian post last December:
I format the code manually, fixing semi-colons and fixing references to $super. I run them through a compressor with quotes around the $super vars so they aren’t changed then fix their method arguments. I use Dean Edward’s Packer because it creates the smallest files. From there you can use a server side solution to gzip/version/and deploy the file. I use Prado (www.pradosoft.com) and their asset publishing capabilities.
I have a Blog but it’s currently in the early stages, I never have time to work on it.