Thursday, November 12, 2009

new and improved super GZIP js/css with coldfusion

so a long time ago a blogged about using GZIP libraries in java to compress output on the fly. Since then i have made some tweaks to this technique.

1. I only have 2 SCRIPT tags in my pages.
<script src="/js/index.cfm?filenames=prototype.js,otherglobaljs.js....."
<script src="/js/index.cfm?filenames=jsonlyusedonthispage.js"

2. My index.cfm uses combine.cfc to compbine, minify and set the correct HTTP expiration headers on my code:

3. I gzip the resulting output back to the page if the browser supports it. See the full index.cfm below!

<cfsetting showdebugoutput="false" enablecfoutputonly="true">
<cfparam name="fileNames" default="">
<cfparam name="showRaw" default="false">

<cfset oCombine = createObject("component", "js.combine.combine").init(
enableCache: true,
cachePath: expandPath('output'),
enableETags: true,
enableJSMin: true,
enableYuiCSS: true,
skipMissingFiles: false,
enable304s: true

<cfsavecontent variable="raw">
<cfset oCombine.combine(files=fileNames)>

<cfif cgi.HTTP_ACCEPT_ENCODING contains "gzip" AND not showRaw and Len(raw) GT 0>
<cfset bos = createObject("java","") >
<cfset bos.init()>
<cfset gzipStream = createObject("java","")>
<cfset gzipStream.init(bos) >
<cfset gzipStream.write(raw.getBytes("iso-8859-1")) >
<cfset gzipStream.close()>
<cfset bos.flush()>
<cfset bos.close()>

<cfset encoder = createObject("java","sun.misc.BASE64Encoder")>
<cfset outStr= encoder.encode(bos.toByteArray())>
<cfset sOutput = toString(tobinary(outStr))>
<cfheader name="Content-Encoding" value="gzip" >
<cfheader name="Content-Length" value="#ArrayLen( sOutput.getBytes() )#" >

Some notes:
You can use this for JS and/or CSS
notice i convert the result of combine into ISO before writing it to gzip. i think this was something i did to get around some strange problems with multi-lingual utf-8 content being coverted into base 64 encoding and back again.

Wednesday, November 11, 2009

cfobjective ANZ day1

long time no post :)

Been at cfobjective anz today and here is my wrap up of day 1

Ben Forta down under! Nice preview of CF9 changes and CF Builder functions available. The main one for me was the licencing change for shared dev servers. This is new to me, but obviously not to everyone.

Social Apps with CF
Andy Welsh showed some funky framework using JQuery as the controller between CFC's and CFM views when retrieving data from social apps like Google / Flickr & Facebook.

One thing he seems to try and deal with caching of remote requests and instability in the results from facebook. its a bit scary to think that facebook is so unstable.

Im Slightly confused on its usefull ness - i think i need to read the code.

PDF Forms
Kai Koenig showed off some of the great stuf you can do with livecycle designer and coldfusion without forking out loads of money on live cycle ES.

It was great session in that it gave me an idea about using a PDF Form based workflow via email rather than sending URL's to people to go back to a website, regiser, then fill out a form. They just fill the form out and post the Form & its data back to the server directly from acrobat.

JVM Tuning
Mike Schierberl showed some tips about how to tackle a JVM memory issue with CF. I was hoping for a big checklest of JVM settings to play with, but he did give some good examples on how memory leaks can occour and how to avoid them. What i did see was hot to use some of the GC logging and memory analysing tools.

Seems i learnt alot of this stuff the hard way last week. See my CFAussie Post

Decentralised Version Control
Indy Nagpals presentation on Git and other decentralised version control tools was great. I had never heard of that before. I have a hard enough time getting all our code into SVN let alone moving to the next best ting.

git-svn looks cool as a way of working with git locally on an SVN project thats used across the team.

His talk on continuous integration was interesting to. The thing a took away there was the code needs to be 'testable code' before its worth making tests for it. So much for my 1999 vintage CF4 based code :(

Cascading View Inheritance
Geoff Bowers talking about farCry core and how its views work in an MVC setup.
havent looked at farCry in a while and the new caching stuff looks cool.
custom object types looks interesting too!

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]

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","") ]
[cfset bos.init()]
[cfset gzipStream = createObject("java","")]
[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())]

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

Wednesday, September 13, 2006

DIY Frameworks

Ive just been reading all the hype on the mxna list at the moment about Peter Bells comments on why frameworks suck. His comments really arent that frameworks suck, just that if you dot know how to use them properly or you dont understand the theory on why they work they way they do. ie. OO and patterns, you are better off building you own framework.

I liked sean corfield's comments about 'public,protected and private' programmers in regards to frameworks. Its true that there are framework builders, framework power users and just plain old users. I dont agree with Peter however that we should all go out and become DIY framework designers, but i do agree that using a tool you dont understand can cause more trouble than its worth.

Internally where i work we have gone down the path of building our own framework. However I did also just build a CMS using Model-Glue so I have perspectives from both sides of the coin. In my experience in using MG i found that i really liked its front-controlelr aspects (building composite views, event listeners, and all requests routed via index.cfm), but i had no real use for ColdSpring or Reactor. My solution was to just forget about those features and used the ones i found usefull and that saved me time. Trying to educate the team about front-controllers was hard enough, so i left the battle of ioc for another day.

As for Reactor, whilst I do like it as a framework we already have our own ORM framework we have been building for some time. So rather than ditching all that work just because the framework points me in that direction we stuck with what we knew.

The other issue i encounterd was educating the team about tracing the form submit process via the XML config file. They were all very familar with having all their processing code for each form at the top of the CFM template and explaining that you need to:
1. look in the xml file for that event
2. check what broadcasts / messages existed on that event
3. look for the listeners to that message
4. check the cfc of that listener for that message function
5. check what beans/daos it was creating / using to save the contents of the form.

..was a quite a problem. Most of their reactions were along the lines 'why can all this be just in the page, why do i have to look through so many files to find what i want'.

while pulling my hair out that i cant convince a programmer to the value of MVC architectures. I tried to do a couple of things to soften the blow of the transition from spaghetti to MVC:

  • make the xml config file less important. If a page submits to index.cfm?event=insertUser i make sure i have a controller called userController.cfc and i have an event listener called insertUser. It seemed to make it alot easier for someone not familar with ModelGlue.xml
  • in one instance i could not for the life of me get it across the routing all page request via a centrallised index.cfm was a good idea. so i came up with my own poor-man's mg framework.
    • each form submits to itself.
    • at the top of the form include a controller.cfm
    • controller.cfm creates the eqivalent of an MG controller object where page.cfm?event= maps to objController.() eg.
      page.cfm?event=insertUser == objController.insertUser()
i guess its a bit like the presentation i saw at MXDU from Robin Hilliard about a framework you have when you dont have a framework.

So yes i agree using frameworks can paint you into a corner at times if you dont understand them. However DIY frameworks are alot of work, but you can minimise them by
  • borrowing parts of other frameworks
  • building cut-down imitiations of existing frameworks

Monday, January 09, 2006

New Blog Location

Hi All

Ive deciced to move my blog away from MSN Spaces and over to blogger. Stay tuned for some new CF related posts!