Packaging JavaScript

13. April 2010 10:59

I've been working on a number of web based applications recently, and have taken to using a few techniques that I thought I would share. I won't be sharing the code so much, which is ASP.Net centric, but will discuss what I am trying to accomplish.

First, I am using two .ashx handlers, one is AllStyles.ashx, the other is AllScripts.ashx.  They both work similarly, one for stylesheets, the other for scripts.  I have a static list of files that are to be included for the application, as well as a handful of static methods to be used within the master pages.  The master page calls a static method on the AllScripts.ashx (for example) which will then perform one of two actions depending on the environment.  If it's in debug mode, it will include an individual script tag for each script listed.  If it's in release mode, it will include a script tag pointing to the ashx itself.  When the ashx is called, it will return a minified compilation of all of the files in the list.  I have additional logic which maintains the DateTime of the last modified file in the list, and will match that against the If-Modified-Since header, and return a 304 (unchanged) response if there's a match.  The minified version of the response is also kept in a static variable.  This could use a caching system, but since this file is relatively small, and called fairly often, I feel it isn't harmful to use a static var vs. a cached version.

What this does is reduce the number of HTTP requests, as well as return a minified version in production, while using the original, un-minified versions in development.  I have the ashx static methods check for a couple of querystring parameters.  If the querystring parameter allscripts=min, it will use the minified/single version, regardless of environment.  If allscripts=full, it will use the full/direct script tags, regardless of environment.  There are also querystring parameters for AllScripts.ashx when called directly as well.  ?action=list will return a list of the included files, for example.  By adding these couple of extra features, you can still inspect the values that are being called/returned for scripts and stylesheets.

There are a couple of gotchas, however.  I'm injecting a couple of semi-colons (;) after each script file, as well as a line with a comment for the name of the file that's being included.  The css compression was a bit hairy, mainly because of the changes to relative paths regarding images.  I needed to use the base application path, and base file path against the relative path to the original css, to adjust any url() values within the stylesheets.  That was probably the most complicated piece.  There are a number of JavaScript and CSS minifiers out there, I used fairly simple ones that didn't do code optimization, mainly whitespace and comment cleaning.  With a general minification, and HTTP compression, I find the results very acceptable, there are places to optimize further, but I find the tradeoffs to be much harder in terms of the development process.

Because I am building web applications, I am less concerned about the load time of the first page, and more concerned about performance as one navigates through the application(s).  With this in mind, I am following a fairly simple pattern, similar to the Module Pattern, in order to include the functionality for all pages and controls into the general include script.  What this means is after the first page is hit, each subsequent page will already have it's relevent static scripts included.

From here, the master page includes the allscripts, as well as a script entry with site-wide configuration values.  (Localization strings, url templates, site mapping, etc).  The page will include it's own activation script, to activate the module/method(s) used for the page itself, as well as the page's configuration values.  I know this post is lighter on code, and heavier on words.  I'd be happy to followup with a post including the code I am using to accomplish this, if I get enough feedback.

Comments are closed

Tracker1

Michael J. Ryan aka Tracker1

My name is Michael J. Ryan and I've been developing web based applications since the mid 90's.

I am an advanced Web UX developer with a near expert knowledge of JavaScript.