Tonight I have been finishing up a plugin heavily based upon Scott Becker’s AssetPackager based upon my own interpretations of Serving JavaScript Fast. Mostly, I changed the way packages were handled, inserting each revision into a versioned directory instead of altering the filename. Further, jsPacker.pl is now preferred over jsmin if it is present in RAILS_ROOT/tools.
AssetPackager used the Subversion revision for each asset package. The revision is supposed to allow the browser to cache the file forever should you configure your Web server appropriately. Unfortunately, Subversion, unlike say, CVS, applies a revision repository wide. As a result, each production deployment under Asset Packager will build you a new asset package, defeating caching entirely. Since November the latest revision for each file is investigated to determine the correct revision to use.
Instead, Asset Bundle allows you to specify the revision in the yaml definition itself. Though not automatic, it is simplistic in its implementation. Simply bump the version number anytime you need browsers to request the latest version of your JavaScript code.
Further, bundles, much like asset packages, allow you to balance download filesize against number of requests. As discussed previously, the quantity of asset requests greatly effects the perceived speed at which a Web site loads. Fewer requests tend to be preferable, though with a single bundle any JavaScript change at all will necessitate that users download all JavaScript code again.
Finally, jsPacker.pl, based up Dean Edwards’ JavaScript Packer, is used to tightly compact each script. I also investigated Dojo, though I don’t especially want to deploy a Java stack to each system nor change Asset Bundle to generate bundles on the deployment host, which would have Java, and deploy those to Web hosts via Capistrano. (Though that would be moderately trivial to do, I had already decided against Dojo as I am biased towards minimizing file sizes, even at the expensive of being able to debug the compacted result.)
A typical bundle is defined thusly in yaml:
- prototype:
- revision: 1
- bundle:
- application
- prototype
- effects
- controls
Javascript bundles can then be loaded within your layout. Optionally the bundle name can be the key of a hash with the value a list of controllers and controller/action pairs to load the bundle on. The list acts as an only condition to further reduce the download burden and request quantity to load a page.
javascript_bundle_include( :stack, :calendar => ['listing/index', 'vrl'] )
Actually, I’d like to integrate Scott’s new revision code and revert back entirely to Asset Packager yaml. I wrote half the code during the closing hours of a ten hour car ride with the screen bouncing in nauseating directions.
Update, December 27th. The ordering isn’t respected and the arguments aren’t quite happy. I believe this will take some time.