Scott Gray wrote:
> On 20/12/2010, at 10:04 PM, Adam Heath wrote:
> 
>> Be very careful about combining lots of javascript files into one.
>> You *must* do proper If-Modified-Since handling, or you will greatly
>> increase the bandwidth usage of client browsers.
>>
>> Without a proper ETag, and If-Modified-Since handling, the browser
>> will download the combined javascript file repeatedly, on each page
>> load.  The solution, is a bit convoluted.
>> ==
>> allETags = []
>> greatestLastModified = 0
>> for(file in files) {
>>  perFileETag = perFileLastModifiedTime + '-' + perFileSize
>>  allETags.add(perFileETag)
>>  if (perFileLastModifiedTime > greatestLastModified) {
>>    greatestLastModified = perFileLastModified
>>  }
>> }
>> etag = allEtags.join(':')
>>
>> response.setHeader('ETag', etag)
>> response.setLastModifiedTime(greatestLastModified)
>> ==
>> and...
>>
>> in IMS mode, the previous ETag will be given.  Split that on ':',
>> iterate each part, comparing the lastModifiedTime and size to the
>> current list of files.
>>
>> IMS mode is also different in HEAD and GET mode.
>>
>> I suppose I should pull out the Binary handler in webslinger, as it
>> has support for all of this.
>>
> 
> The combined files are written to runtime/tempfiles (tempfiles being a webapp 
> mount point) and only regenerated when the cache entry is removed, in 
> production you wouldn't set an expireTime so they'd essentially only be 
> regenerated if the instance is restarted.  No special handling should be 
> necessary, the app or http server would set the headers in the same way it 
> does for the static javascript files.

Why rewrite the combined files into tempfiles at all?  Just iterate
over them each time during serve.  No need to use extra disk space.

Would the cache have to cleared anytime one of the member files is
modified on disk?  If so, then ew.  That's very sucky.

Then, if the multi-binary code were extracted and reused, and a member
file was very large, the copying to a on-disk cache entry is another
hit to be concerned about.  Being able to have read-only access for
various subsystems is a nice goal to have.

Webslinger already supports multi-binary javascript and css(but not
@import; multi-css is only used in the base code we have, which don't
use @import).  We developed this code in response to the firefox yslow
plugin.  You will find that in multi-binary mode, @import should not
really be used, as the multi mode is more efficient.

Our etag output is also more efficient than both apache and catalina.
 They use $lastModified-$size, but use a base-10 encoding.  We use a
base-64 encoding, to reduce the size of the response headers(and
subsequent request header in IMS mode).

The reason for encoding the lastModified time for each file into the
etag, btw, is so that you can detect when a file was reverted to
something previous.  This could happen by checking out an old version,
with a rcs that restores timestamps, or by just copying a previously
saved version from another location.

I've thought about doing something similiar to gwt, in that it uses a
hashsum(can't recall if it is sha1 or md5, or something else) for each
static file.  If a multi-binary renderer can place the combined url
into the page(the webslinger version doesn't support this), then
adding some hash->list-of-files wouldn't be hard to do.

Reply via email to