Monday, July 30, 2007

How to GZIP compress ColdFusion 8 Javascript in pure CF!

This was going to be a comment on rob gonda's blog about compressing the ajax javascript includes that ColdFusion 8 uses, but it became to long so im posting it here:

There is CF only solution to this that works on IIS and probably apache.
Heres the setup:

1. make a folder under your webroot /CFIDE/Scripts/
2. put 1 file in this folder index.cfm
3. set the default document on this folder to be index.cfm
4. set the 404 for this folder to redirect to /cfide/scripts/index.cfm

5. The code of index.cfm uses the CGI.query_string, since web server passes the attempted URL to the 404 page as a parameter, to work out the URL or the JS file under CFIDE thats required. eg.

[cfset fileName = mid(cgi.QUERY_STRING,find("/CFIDE",cgi.QUERY_STRING), len(cgi.QUERY_STRING) - find("/CFIDE",cgi.QUERY_STRING)+1 )]

6. then include the content


[cfsavecontent variable="rawJS"]
[cfoutput][cfinclude template="#fileName#"][/cfoutput]
[/cfsavecontent]

This relies on the fact that CFINCLUDE uses CF Mappings. So even tho IIS has /CFIDE/scripts/ mapped somewhere else, the CFMapping takes over on the include to get you the JS file you need.

7. GZIP the result and output if the browser supports it.

[cfif cgi.HTTP_ACCEPT_ENCODING contains "gzip" AND not showRaw]

[cfheader name="Content-Encoding" value="gzip" ]

[cfset bos = createObject("java","java.io.ByteArrayOutputStream") ]
[cfset bos.init()]
[cfset gzipStream = createObject("java","java.util.zip.GZIPOutputStream")]
[cfset gzipStream.init(bos) ]
[cfset gzipStream.write(rawJS.getBytes("utf-8")) ]
[cfset gzipStream.close()]
[cfset bos.flush()]
[cfset bos.close()]

[cfset encoder = createObject("java","sun.misc.BASE64Encoder")]
[cfset outStr= encoder.encode(bos.toByteArray())]
[cfoutput]#toString(bos.toByteArray())#[/cfoutput]
[cfelse]
[cfoutput]#rawJS#[/cfoutput]
[/cfif]

using Rob's CFWindow example i got the request down to 116K with CF debugging turned on.

3 comments:

Michael Long said...

Ummm... couldn't you just gzip the set of files once and then use cfdocument to add a "zipped" header?

Pat said...

the problem is that cfwindow will add the URL's into the response every time.

using the redirection enables you to control the content of those SCRIPT and LINK tags.

Dawesi said...

Interesting reading for more reasons than one, most not even related to cf8. I am inspired to write another method or two from a quite lateral thought. Nice one. Cheers. Maybe I should get my blog syndicated too...