Monday, March 31, 2014

Minify javascript and css files with maven

Before you deploy to production, you want to minimize js and css files. This is easy to do with maven.
In addition you can also provide each of these minimized files a unique suffix

In your pom.xml, specify your build timestamp format:
<properties>
       <maven.build.timestamp.format>yyyyMMdd_HHmm</maven.build.timestamp.format>
       <timestamp>${maven.build.timestamp}</timestamp>
</properties>


In your build section, set resource filtering to true.

Now you can use the yui compressor maven plug in to compress the files you want:

<build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>yuicompressor-maven-plugin</artifactId>
                <version>1.1</version>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>compress</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <suffix>-${maven.build.timestamp}</suffix>
                    <jswarn>false</jswarn>
                    <nomunge>false</nomunge>
                    <excludes>
                        <exclude>**/datatables/script/*.js</exclude>
                        <exclude>**/datatables/css/*.css</exclude>
                    </excludes>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <!-- The regex  is to exclude js and css files that have not been minimized-->
                    <packagingExcludes>
                        %regex[script/((?!-).)*.js],
                        %regex[css/((?!-).)*.css]
                    </packagingExcludes>
                    <!-- add the time stamp to the end of the war -->
                    <classifier>${maven.build.timestamp}</classifier>
                </configuration>
            </plugin>
        </plugins>
    </build>

Note that in this case I have excluded some 3rd party (datatables, a table plugin for jquery) js and css files. 

In the maven war plug in, you can now exclude the uncompressed files, so only the compressed files are packaged into the war

By adding the timestamp as a suffix, you ensure that the latest js and css are served by the server. The disadvantage of this is you need to specifically add the timestamp value in your JSP files. This can be done like this:

In your resources file (usually messages.properties) add:

build.timestamp=${timestamp}

Since you have provided resource filtering with the <resources> tag, the timestamp property from your pom is now available in the JSP via the message.props resource file.

<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<spring:message var="timestamp" code="build.timestamp"/>
<script type="text/javascript" charset="utf-8" src="/resources/script/yourFile-${timestamp}.js"></script>