Kim Rudolph

The following code snippets help configuring the automatic process of merging, compressing and uniquely naming CSS and JS files. The current git revision hash is used as the unique identifier. The benefit: Uniquely named assets can be configured with a Never expire policy. Any asset updates will result in a new filename and only then the client has to fetch the assets again.

Get the Current Revision Hash

The buildnumber-maven-plugin is capable to extract the current git hash version of the project. A property named gitHash is available in the pom file and during resource filtering.

...
<build>
  ...
  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>buildnumber-maven-plugin</artifactId>
    <executions>
      <execution>
        <id>git-hash</id>
        <phase>generate-resources</phase>
        <goals>
          <goal>create</goal>
        </goals>
        <configuration>
          <format>{0}</format>
          <items>
            <item>scmVersion</item>
          </items>
          <buildNumberPropertyName>gitHash</buildNumberPropertyName>
        </configuration>
      </execution>
    </executions>
  </plugin>
  ...
</build>
...

Merge and Compress Assets

Requests for resources should be kept at a minimum and also the overall size should be small to actually deliver a fast page loading time. The minify-maven-plugin does both, merging and compressing/optimizing. The final filenames for the CSS and/or JS files are enriched with the gitHash property.

...
<build>
  ...
  <plugin>
    <groupId>com.samaxes.maven</groupId>
    <artifactId>minify-maven-plugin</artifactId>
    <executions>
      <execution>
        <id>default-minify</id>
        <configuration>
          <jsEngine>CLOSURE</jsEngine>
          <cssSourceDir>resources/css</cssSourceDir>
          <cssSourceFiles>
            <cssSourceFile>style-1.css</cssSourceFile>
            <cssSourceFile>style-2.css</cssSourceFile>
          </cssSourceFiles>
          <cssFinalFile>style-${gitHash}.css</cssFinalFile>
          <jsSourceDir>resources/js</jsSourceDir>
          <jsSourceFiles>
            <jsSourceFile>script-1.js</jsSourceFile>
            <jsSourceFile>script-2.js</jsSourceFile>
          </jsSourceFiles>
          <jsFinalFile>script-${gitHash}.js</jsFinalFile>
        </configuration>
        <goals>
          <goal>minify</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
  ...
</build>
...

Pack Only the Needed Files

To exclude all asset files but the style-xxx.min.css and the script-xxx.min.js, the unwanted files have to be listed as warSourceExcludes in the maven-war-plugin.

...
<build>
  ...
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-war-plugin</artifactId>
      <configuration>
        <warSourceExcludes>**/style-1.css,**/style-2.css,**/style-${gitHash}.css,**/script-1.js,**/script-2.js,**/script-${gitHash}.js</warSourceExcludes>
      </configuration>
    </plugin>
  ...
</build>
...

A proxy for static files to serve assets without using the Tomcat/GlassFish/… resources would be even better.

Access the Revision Hash at Runtime

As the git hash is needed to reference the CSS and JS files, the gitHash property can be used as a filter replacement in a properties file in src/main/resources with the content git_hash=${gitHash}. The actual filtering has to be activated in the resources section of the pom file.

...
<build>
  ...
  <resources>
    <resource>
      <directory>src/main/java</directory>
    </resource>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
      <includes>
        <include>**/*.properties</include>
      </includes>
    </resource>
  </resources>
  ...
</build>
...

Depending on the web framework, that git_hash value has to be made available as a template parameter. For example, the spring framework provides the @PropertySource annotation to load properties in the Environment scope, which can then be read in a HandlerInterceptor.

Actually Use the Assets

The generated style-xxx.min.css and the script-xxx.min.js can be referenced in a template file using that git_hash parameter.

<link href="path/to/style-${git_hash}.min.css" rel="stylesheet">
<script type="text/javascript" src="path/to/script-${git_hash}.min.js"></script>