- Keep the original CSS and JavaScript in my source tree readable.
- Convert about 15 or so CSS files (one for each neighborhood of the web site) and a half a dozen JavaScript files (versioned as 0.1, 0.2, 0.3, etc.) as part of an automated build.
- Deploy the compressed (or minified) versions of all the CSS and JavaScript files to staging and then to production.
Scanning what was out there, I settled on Yahoo's YUI Compressor, a decent fit because it's available as a Java program that I could run as part of my builds, which are currently based on Apache Ant (I'm in the process now of switching to Gradle, but that's a topic for another time).
So, on to the challenge.
I started with Adam Presley's blog entry, which details how to use YUI's Ant task to minify one CSS file and one JavaScript file, and generalized it to work on a set of CSS and JavaScript files. The other pre-requisite is the ant contrib library (to pick up the foreach task for iterating over a set of files).
Assumptions:
- CSS files are in a source directory (the property css.src.dir below), and are built (i.e. minified / compressed) into a second build directory (the property css.build.dir below), without changing the file name.
- Ditto for the JavaScript files (compress from scripts.src.dir to scripts.build.dir).
Here's a snippet of the code I came up with:
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<property environment="env"/>
<property name="src.dir" value="${basedir}/src"/>
<property name="scripts.src.dir" value="${src.dir}/scripts"/>
<property name="css.src.dir" value="${src.dir}/css"/>
<property name="compressorJar" value="${basedir}/lib/yuicompressor-2.4.2.jar"/>
<!-- Build areas -->
<property name="build.dir" value="${basedir}/bin"/>
<property name="scripts.build.dir" value="${build.dir}/scripts"/>
<property name="css.build.dir" value="${build.dir}/css"/>
<!-- Staging directory to copy files -->
<property name="static.deploy" value="${basedir}/../staging/static"/>
<!-- Prepares the build directory -->
<target name="prepare" >
<mkdir dir="${build.dir}"/>
<mkdir dir="${css.build.dir}"/>
<mkdir dir="${scripts.build.dir}"/>
</target>
<target name="minifyCSS" depends="minifyCSSCheck" unless="no.minify">
<echo message="minifying CSS: ${css.base.file}" />
<java jar="${compressorJar}" fork="true" failonerror="true">
<arg value="--line-break" />
<arg value="4000" />
<arg value="-o" />
<arg value="${css.build.dir}/${css.base.file}" />
<arg value="${css.src.dir}/${css.base.file}" />
</java>
</target>
<target name="minifyCSSCheck">
<basename property="css.base.file" file="${css.file}"/>
<uptodate property="no.minify" srcfile="${css.src.dir}/${css.base.file}" targetfile="${css.build.dir}/${css.base.file}"/>
</target>
<target name="minifyJavaScript" depends="minifyJavaScriptCheck" unless="no.minify">
<echo message="minifying JavaScript: ${script.base.file}" />
<java jar="${compressorJar}" fork="true" failonerror="true">
<arg value="--line-break" />
<arg value="4000" />
<arg value="--type" />
<arg value="js" />
<arg value="--preserve-semi" />
<arg value="-o" />
<arg value="${scripts.build.dir}/${script.base.file}" />
<arg value="${scripts.src.dir}/${script.base.file}" />
</java>
</target>
<target name="minifyJavaScriptCheck">
<basename property="script.base.file" file="${script.file}"/>
<uptodate property="no.minify" srcfile="${scripts.src.dir}/${script.base.file}" targetfile="${scripts.build.dir}/${script.base.file}"/>
</target>
<target name="minify">
<foreach target="minifyCSS" param="css.file">
<path>
<fileset dir="${css.src.dir}" includes="**.css"/>
</path>
</foreach>
<foreach target="minifyJavaScript" param="script.file">
<path>
<fileset dir="${scripts.src.dir}" includes="**.js"/>
</path>
</foreach>
</target>
Iteration over all of the files to be minified is taken care of by the minify task.
Note that this implementation still forks a JVM for each and every file that is minified.
I like it
ReplyDeleteThanks
Compressor
I like it
ReplyDeleteThanks
Compressor