Web page performance is critical to keeping customers and visitors moving along on your site. Slow responses typically result in frustrated users, unhappy customers and worse, abandoned orders. It is important to reduce the number of requests generated by a web page in order to increase its actual and perceived performance.

One critical way is to reduce the number of external files loaded by a page. Another one is to reduce their size through compression. This post aims to take this concept a step further by automating this tedious process using open-source libraries.

Example

This example will accomplish the task by executing the following steps:

  1. Create a temporary directory, /build
  2. Compress each JS file into {original}-min.js files
  3. Compress each CSS file into {original}-min.css files
  4. Concatenate all compressed JS files into /js/complete.js
  5. Concatenate all compressed CSS files into /css/complete.css

Requirements

  • Make sure Apache Ant has been installed on your system.
  • Get a copy of the sample project from my public Git repository. This project already contains the open-source libraries necessary, YUI compressor and YUI compressor Ant task.
  • Setup a system variable, COMPRESSOR_HOME that points to the location of the sample project’s /lib directory.
    • On Windows, right click My Computer and select properties. Then click the “Environment Variables” button under the advanced tab. Add a new system variable, COMPRESSOR_HOME, and set its value to your local path, for example: C:\Documents and Settings\username\Desktop\yui-compression-sample\lib
    • On Mac OSX and Linux, update ~/.profile or similar file and add export COMPRESSOR_HOME=~/YourProjectDir/yui-compression-sample/lib

Examine the configuration

Take a look at the contents of build.xml. The first portion defines variables and locations of the libraries.

<!-- tells Ant to refer to your environment vars -->
<property environment="env" />
<!-- defines location of libraries -->
<property name="lib.dir" value="${env.COMPRESSOR_HOME}" />
<!-- defines output directory -->
<property name="build.dir" value="build" />
<!-- output files, one for JS one for CSS -->
<property name="final_js" value="${basedir}/js/complete.js" />
<property name="final_css" value="${basedir}/css/complete.css" />
<!-- define nicknames for libraries -->
<property name="yui-compressor" location="${lib.dir}/yuicompressor-2.4.2.jar" />
<property name="yui-compressor-ant-task" location="${lib.dir}/yui-compressor-ant-task-0.5.jar" />
<!-- adds libraries to the classpath -->
<path id="yui.classpath">
	<pathelement location="${yui-compressor}" />
	<pathelement location="${yui-compressor-ant-task}" />
</path>
<!-- define tasks -->
<taskdef name="yui-compressor" classname="net.noha.tools.ant.yuicompressor.tasks.YuiCompressorTask">
	<classpath refid="yui.classpath" />
</taskdef>

The second portion of build.xml defines the Ant targets to be executed. These tell YUI compressor how the source files are to be processed.

<!-- targets -->
<target name="concat">
	<!-- concatenates all compressed JS files into one -->
	<concat destfile="${final_js}" force="true" fixlastline="true">
		<fileset dir="${build.dir}" includes="**/*.js" />
		<fileset dir="${build.dir}" includes="**/widgets/*.js" />
	</concat>
	<!-- concatenates all compressed CSS files into one -->
	<concat destfile="${final_css}" force="true" fixlastline="true">
		<fileset dir="${build.dir}" includes="**/*.css" />
		<fileset dir="${build.dir}" includes="**/flexgrid/*.css" />
	</concat>
</target>
<target name="compress">
	<!-- compresses each JavaScript and CSS file -->
	<!-- and saved as {original_name}-min.{extension} -->
	<yui-compressor
		warn="false"
		munge="true"
		preserveallsemicolons="false"
		fromdir="${basedir}"
		todir="${build.dir}"
	/>
</target>
<!-- deletes the temporary directory and all its contents -->
<target name="clean">
	<delete dir="${build.dir}"/>
</target>
<!-- creates the temporary directory -->
<target name="start">
	<mkdir dir="${build.dir}" />
</target>
<target name="main" depends="start,compress,concat,clean" />

What does this do?

If you are new to Ant you are probably wondering why the tasks are defined in reverse order of execution. This is just a personal preference and it does not affect execution.

The order of execution is controlled by the main task. This is the task Ant runs when a target is not passed to it. The attribute depends tells Ant the order in which the tasks must be executed.

Give it a try

All you have to do to execute the entire operation is open a command prompt (or a terminal window on OS X), change into the project directory where build.xml lives and type ant and hit Enter. You should see some output that looks like this:

claude$ ant
Buildfile: build.xml
start:
     [echo] Building JS-CSS-Compression-and-Concat-Sample with Apache Ant version 1.7.1 compiled on April 8 2010 - System Java 1.6
    [mkdir] Created dir: /Users/claude/Documents/www/yui-compression-sample/build
compress:
[yui-compressor] [53%] global-print.css [920] ---> global-print-min.css [488]
[yui-compressor] [80%] global.css [11895] ---> global-min.css [9564]
[yui-compressor] [79%] style.css [1148] ---> style-min.css [910]
[yui-compressor] [64%] googlemaps-yelp-ext.js [6604] ---> googlemaps-yelp-ext-min.js [4270]
[yui-compressor] [70%] split-filepath.js [814] ---> split-filepath-min.js [576]
[yui-compressor] [73%] ContactForm.js [4711] ---> ContactForm-min.js [3461]
[yui-compressor] [57%] InfoTabs.js [1160] ---> InfoTabs-min.js [669]
[yui-compressor] [55%] InfoWindow.js [1228] ---> InfoWindow-min.js [686]
[yui-compressor] [68%] Intraday.js [9559] ---> Intraday-min.js [6536]
[yui-compressor] [68%] MediaCenter.js [5728] ---> MediaCenter-min.js [3906]
[yui-compressor] [JavaScript] Compressed 7 files to 67% (29KB to 19KB, saving 10KB)
[yui-compressor] [CSS] Compressed 3 files to 78% (13KB to 10KB, saving 3KB)
[yui-compressor] Compressed 10 files to 70% (42KB to 30KB, saving 12KB)
concat:
     [echo] Building /Users/claude/Documents/www/yui-compression-sample/js/complete.js
     [echo] Building /Users/claude/Documents/www/yui-compression-sample/css/complete.css
clean:
   [delete] Deleting directory /Users/claude/Documents/www/yui-compression-sample/build
main:
BUILD SUCCESSFUL
Total time: 1 second

What Now?

Change your HTML code to point to the newly created complete.js and complete.css instead of the individual files. Your page will load and render faster.

Squeeze even more performance out of your site by implementing other best practices. Get a copy of High Performance Web Sites by Steve Souders and read Yahoo’s rules for exceptional performance.

Watch Steve Souders’ presentation at Google Tech Talks. Audio problems are fixed 5 minutes in. Skip the first 90 seconds to listen to Steve.

This article has 1 comments

  1. Will Jones

    This was definitely a great resource to help me get started with Ant and the YUI Comporessor. Thank you very much!

Comments are closed.