varScoper 1.30 release with CF Builder extension

varScoper 1.30 is now available to download on RIAForge. This release fixes over 17 reported issues and also works properly on both Railo and OpenBD.

Additionally, Raymond Camden's ColdFusion builder extension code has been integrated. Hopefully the consolidation will make life easier for everyone. You can either install the zip, or import the extension if it's already unpacked. In case you haven't used it yet, this feature allows you to right click on a file or folder in CF Builder and run varScoper directly from the IDE.

At the moment, this release will not correctly identify variables based on CF9 syntax (LOCAL scope and ability to identify var anywhere in a function). The test cases are in place and I'll be working on it soon. As a result you will notice the unit test will throw an error if you aren't running cf9.

Thanks again to Ray, Pat Santora, and everyone else who has reported issues. If you have any problems, please report them at RIAForge and I will get to them eventually.

I'll be at webdu on Thurs/Fri

I'm excited to say that I'll be attending webdu here in Sydney on Thursday and Friday this week. Looking forward to an impressive lineup of speakers.

I'm new to Sydney, so please don't be a stranger and introduce yourself, here's a picture of what I look like.

Also, I just found out about code-wars as well, not sure what to make of it, but sounds like a blast, I'll see you there.

Moving to Sydney

At 10:30pm tonight I will be getting on a plane to relocate to Sydney, Australia. The bags are packed, and I'm looking forward to the next exciting chapter in my life. As of Monday, my company was acquired by Thomson Reuters, and I will be working as an independent consultant for them.

I'm looking forward to getting involve with all of you in the CF community when I arrive. Don't be a stranger, please introduce yourselves as I hardly know anyone there. I'm really hoping that I can win a pass to @webdu in their twitter competition, it would be a great opportunity to make some connections. If you're on twitter I wouldn't mind a shameless plug for a ticket :) (@mikeschierberl).

Additionally, if you are in Sydney, I'd love recommendations on things to do/see from a locals perspective. I've been there a few times, but I will be coming with a clean slate and an open mind.

Deploying cached CSS and JS with Ant

If you are using YSlow or an equivalent tool you're probably aware of some of the best practices to follow to optimize client-side load times. In this post I'm going to outline a quick and easy approach that we use at Planitax to deploy static content using Ant.

The best practices that I hope to address with this build strategy are...
1) Add an Expires or a Cache-Control Header
2) Minify JavaScript and CSS

Both of these are pretty straightforward, but it's easy to run into problems when deploying updates to content that might have an expire date in the future. You might run into this problem when you make changes to js, css, or images in your application. If a browser has cached content locally, the user might see stale images, or worse yet experience errors due to out of date javascript or css files.

When we developed a deployment strategy we wanted an approach that was transparent to the end user, easy to build, and had minimal impact on developers checking in code. We needed to meet the following criteria.

  • Content should be able to have a Expire date at any point in the future
  • Content can be deployed to QA/Production at any time using a one step build
  • Webserver should automatically apply expires headers to static assets without additional deployment steps.
  • Developers should always be able to check into a single repository location. Branching/Deploying should not require a copy of a file to be checked in.
  • Developers should not be required to run a build target in order to see changes to static content.
  • js/css should be minified on production deployments, but not in the source code repository.


From these requirements we came up with a strategy that looked something like this.

  • Static assets that can be cached will always live in the /assets folder off the application root. Content will be organized into subfolders for /assets/js, /assets/css, and /assets/images.
  • Developers will work with expires headers turned off for these folders so changes will appear immediately.
  • Developers will check files in directly to this location. The repository location will always be /assets.
  • When deploying to QA/Production, a copy of the static assets will be created with a new version identifier. This copy will also be minified as part of the deploy step.
  • The application will be able to determine the correct copy of static content to use regardless of the deployment environment.
  • QA/Production web servers will automatically add an expires header to any content located in the /assets folder.

The first step was to build an ant target that would take care of creating a new folder, copying the assets and minifying content appropriately. We use JSMin to minify our JS. In order to execute this example you will need to download the JSMin Ant Task from Google Code. Note, when setting up your taskdef, the classpath attribute should point to the relative location that you have saved the .jar file. For this example it will be in the /lib subfolder off of root.

<taskdef name="jsmin" classname="net.matthaynes.jsmin.JSMin_Task" classpath="./lib/jsmin.0.2.3.jar" />

   <target name="jsmin">
<!-- tstamp creates variables for date and time of current execution -->
      <tstamp />
      <copy todir="./assets/js${DSTAMP}${TSTAMP}" includeEmptyDirs="true" preservelastmodified="true" overwrite="false" failonerror="true" verbose="true">
         <fileset dir="./assets/js">
            <include name="**/*.*" />
         </fileset>
      </copy>
      <jsmin destdir="./assets/js${DSTAMP}${TSTAMP}" force="true">
         <fileset dir="./assets/js" includes="*.js" />
      </jsmin>
   </target>

This code creates a folder with a name that looks something like this... ./assets/js200901141546 , it's named this way so we can do alpha sorts easily as you will see in the next step. We don't check this folder in to source control.

Note: You can adapt this code for css or images by modifying the copy command, if you only need to copy/minify JS you might be able to get by without the copy command.

The next step is to make your application aware of the correct folder to be used. This is easy to do with a cfdirectory based on the naming convention we used above. First we will create a variable that identifies the most recent/current folder created by the name that contains the timestamp. The nice thing about this is that it will identify the correct folder for prod servers as well as developers who only have a ./assets/js folders. It does not require developers to run the build target in order to see changes.

<cfdirectory
         action="list"
         directory="#expandPath('./assets/')#"
         name="jsDirectoryList"
         filter="js*"
         sort="name desc" >

         
<cfset application.jsAssetsSubFolder = jsDirectoryList.name>

The only tricky part is to make sure that all your links to assets include the new variable that you have created. Your links will look something like this...

<cfoutput>
   <script type="text/javascript" src="./assets/#application.jsAssetsSubFolder#/script.js"></script>
</cfoutput>

I'm sure there are countless ways to approach this, and your deployment strategy may differ significantly based on your environment, and or application. I'm interested to see how others have approached this and other deployment tasks.

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.9.002. Contact Blog Owner