2010-11-30

Using YUI compressor in an ant build process

Style sheets can get really large, really quickly. To make things easier to find, I split my CSS files out into major pieces of functionality. Instead of having to search through one giant style sheet of doom to find the rule that changes how a form field appears, I can open the style sheet for that bit of functionality. Many of my forms are customized, so each might have its own style sheet.

So I may have a bunch of CSS files in my styles directory:
  • general.css
  • login.css
  • signup.css
  • profile.css
Each rule in each of those files is namespaced by adding an ID attribute to the page's body tag, a class attribute to the body tag, or both. Then to deploy, the files need to be joined. I used to just concatenate the files together, but the YUI compressor does a great job making the files smaller that I started using that as well.

Every page on my site requires /styles/c.css. To generate that file from the components, I use some ant rules.

First, I make sure that I've download the YUI compressor. Since I have more than one project that uses this same system, I download the YUI compressor to a common location. And since I'm too lazy to worry about setting up my build environment on any system that I use I've included the rules to actually download the library. This target will only download the library once. If you override the yuicompressor property you can move the jar to wherever you want. I stick mine in tmp.

<property name="yuicompressor"
    value="/tmp/yuicompressor.jar" />
<available file="${yuicompressor}"
    property="yuicompressor.exists" />
<target name="yui-compressor-download"
        unless="yuicompressor.exists"
        description="Download and unpack YUI compressor">
    <echo message="Downloading YUI compressor" />
    <exec executable="wget">
        <arg value="--no-clobber" />
        <arg value="--no-verbose" />
        <arg value="--output-document=/tmp/yuicompressor.zip" />
        <arg value="http://yui.zenfs.com/releases/yuicompressor/yuicompressor-2.4.6.zip" />
    </exec>
    <unzip src="/tmp/yuicompressor.zip" dest="/tmp">
        <patternset>
            <include name="**/build/yuicompressor-2.4.6.jar" />
        </patternset>
    </unzip>
    <move file="/tmp/yuicompressor-2.4.6/build/yuicompressor-2.4.6.jar"
          tofile="${yuicompressor}" overwrite="true" />
    <delete file="/tmp/yuicompressor.zip" />
    <delete dir="/tmp/yuicompressor-2.4.6" />
</target>

Then, to actually build the combined and shrunk CSS file, I use a rule like this:

<uptodate property="compile-css.notRequired" targetfile="c.css">
    <srcfiles dir="styles" includes="**/*css" />
</uptodate>
<target name="compile-css" depends="yui-compressor-download"
        unless="compile-css.notRequired">
    <echo message="Compressing CSS" />
    <concat append="no" destfile="style-combined.css" force="no">
        <file file="styles/general.css" />
        <file file="styles/login.css" />
        <file file="styles/signup.css" />
        <file file="styles/profile.css" />
    </concat>
    <java jar="${yuicompressor}" fork="true">
        <arg value="style-combined.css" />
        <arg value="--charset=UTF-8" />
        <arg value="--verbose" />
        <arg value="-o" />
        <arg value="c.css" />
    </java>
    <delete file="style-combined.css" />
</target>
If the YUI compressor has not been downloaded, it will call the download rule for it. Then it concatenates all of the styles together and compresses them. The uptodate rule makes sure that it only runs if one of the files has changes.
Update: Changed the YUI version number to the newest version and re-added the code that actually builds the CSS. Not sure where it went.

1 comment: