Incorporating a Javascript/CSS plugin into a Maven build process using the Maven Minify plugin.

Posted by & filed under Uncategorized.

Finally, I was able to get a javascript minify plugin working.  http://maven-samaxes-plugin.googlecode.com/svn-history/r123/sites/maven-minify-plugin/index.html

It uses YUI compressor under the hoods.  It combines Javascript into one file, CSS into another file and then uses the YUI compressor to minify the two files.  To preserve comments in the minified file, use /*! sequence at the start of a multiline comment.  If the order of the Javascript includes needs to be preserved use the jsSourceFiles configuration property.  Similar for CSS, use cssSourceFiles property.

Minifier can be used in combination with another plugin, the Google replacer plugin.  Replacer, as its name implies, replaces a token in a file.  In this case I replace the CSS and JS references in a JSP file with a reference to the new minified files.  This allows us to continue to develop with source, but minifies what goes into the war.  In order to use this, the war assembler plugin must be bound to the same execution phase.  Version 2.0.1 of the maven-war-plugin was used, newer version requires a slightly different configuration.  Note: Certain regex tokens cause a StackOverflowError exception.  See configuration below for what worked for me.

There were two other plugins that minify as well that I haven’t fully explored.
http://alchim.sourceforge.net/yuicompressor-maven-plugin/index.html
http://mojo.codehaus.org/webminifier-maven-plugin/

Example:

<plugins>
    ...
    <plugin>
        <groupId>com.samaxes.maven</groupId>
        <artifactId>maven-minify-plugin</artifactId>
        <version>1.2</version>
        <executions>
            <!-- added for making the replace plugin run in the exploded phase -->
            <execution>
                <phase>process-resources</phase>
                <goals>
                    <goal>minify</goal>
                </goals>
            </execution>
        </executions>                
        <configuration>
            <webappSourceDir>${basedir}/src/main/webapp</webappSourceDir>
            <webappTargetDir>${project.build.directory}/${project.build.finalName}</webappTargetDir>
            <cssSourceDir>css</cssSourceDir>
            <jsSourceDir>js</jsSourceDir>
            <cssSourceFiles>
                <param>file1.css</param>
                ...
                <param>filen.css</param>
            </cssSourceFiles>
            <jsSourceFiles>
                <param>file1.js</param>
                ...
                <param>filen.js</param>
            </jsSourceFiles>
            <cssFinalFile>style.css</cssFinalFile>
            <jsFinalFile>script.js</jsFinalFile>
            <linebreak>-1</linebreak>
            <nomunge>true</nomunge>
            <verbose>false</verbose>
            <preserveAllSemiColons>true</preserveAllSemiColons>
            <disableOptimizations>false</disableOptimizations>
            <bufferSize>4096</bufferSize>
        </configuration>
    </plugin>

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.0.1</version>
        <executions>
            <!-- added for making the replace plugin run in the exploded phase -->
            <execution>
                <id>prepare-war</id>
                <phase>prepare-package</phase>
                <goals>
                    <goal>exploded</goal>
                </goals>
            </execution>
        </executions>    
        <configuration>
            <warSourceExcludes>**/source1.css,**/source2.css,**/sourceN.css,**/source1.js,**/source2.js,**/sourceN.js</warSourceExcludes>
        </configuration>                            
      </plugin>

    <plugin>
        <groupId>com.google.code.maven-replacer-plugin</groupId>
        <artifactId>replacer</artifactId>
        <version>1.5.0</version>
        <executions>
            <execution>
                <phase>prepare-package</phase>
                <goals>
                    <goal>replace</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <file>target/${project.build.finalName}/WEB-INF/includes/styles.jsp</file>
           <regexFlags>
                <regexFlag>MULTILINE</regexFlag>
                <regexFlag>DOTALL</regexFlag>
           </regexFlags>
            <replacements>
                <replacement>
                    <token>&lt;!--replaceCSS.*replaceCSSEnd--&gt;</token>
                    <value>&lt;link rel="stylesheet" type="text/css" href="css/web-style.min.css"/&gt;</value>
                </replacement>
                <replacement>
                    <token>&lt;!--replaceJS.*replaceJSEnd--&gt;</token>
                    <value>&lt;script type="text/javascript" src="js/web-script.min.js" &gt;&lt;/script&gt;</value>
                </replacement>                        
            </replacements>
        </configuration>
    </plugin>
    ...
</plugins>