11

So I'm trying something I thought would be rather simple, I basically want maven to minify all my js and css files for me before building a war. My plugins look like this:

         <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <version>1.0.0</version>
            <configuration>
                <manifestLocation>META-INF</manifestLocation>
                <instructions>
                    <Export-Package>!test.impl,test*</Export-Package>
                    <Import-Package>*</Import-Package>
                    <!--
                       add ,plugin.xml if it's present i.e.
                       src/main/resources,plugin.xml
                    -->
                    <Include-Resource>src/main/resources</Include-Resource>
                </instructions>
            </configuration>
        </plugin>

        <plugin>
            <groupId>net.alchim31.maven</groupId>
            <artifactId>yuicompressor-maven-plugin</artifactId>
            <version>1.1</version>
            <executions>
                <execution>
                    <goals>
                        <goal>compress</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <nosuffix>true</nosuffix>
            </configuration>
        </plugin>

The problem is that the YUI plugin does correctly minify the files, but just before the war is built it looks like it copies over all the files from my main source directory and thus wipes out the changes the YUI plugin had done.

I'm calling maven by the following: mvn compile war:war. I've been playing around for awhile with different settings, but so far I haven't found a way around this.

What I would like is for just after the war has copied over the files it needed from the src directory it would run the YUI plugin, but I tried all the permutations of phases on the YUI plugin, but that didn't seem to make any difference.

I've googled around, but pretty much everything I've read so far seems to indiciate that I should just need to drop the YUI plugin in there like I have and everything should magically work. So far I haven't seem to have found the magic.

Zipper
  • 7,034
  • 8
  • 49
  • 66
  • This case may have solution but the plugin version 1.5.1 has a bug because it cannot be configured for some simple cases. Say we want to configure webappDirectory and sourceDirectory. If sourceDirectory is configured different from the default then the plugin executes compression twice once with the configured value and then with the default value which defeats the purpose of sourceDirectory configuration. I haven't been able to compress from a directory that had to have changes made before compression. – user250343 Aug 22 '20 at 15:46

5 Answers5

25

The accepted answer doesn't work.

Much better is this answer (as pointed out by koga in his comment): https://stackoverflow.com/a/11495021/11451

Here is what I ended up doing:

Step 1: minify the css and js

<plugin>
    <groupId>com.samaxes.maven</groupId>
    <artifactId>minify-maven-plugin</artifactId>
    <version>1.7.2</version>
    <executions>
        <execution>
            <phase>prepare-package</phase>
            <goals>
                <goal>minify</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <charset>UTF-8</charset>
        <skipMerge>true</skipMerge>
        <cssSourceDir>resources</cssSourceDir>
        <jsSourceDir>resources</jsSourceDir>
        <jsEngine>CLOSURE</jsEngine>
        <nosuffix>true</nosuffix>
        <webappTargetDir>${project.build.directory}/minify</webappTargetDir>
        <cssSourceIncludes>
            <cssSourceInclude>**/*.css</cssSourceInclude>
        </cssSourceIncludes>
        <cssSourceExcludes>
            <cssSourceExclude>**/*.min.css</cssSourceExclude>
        </cssSourceExcludes>
        <jsSourceIncludes>
            <jsSourceInclude>**/*.js</jsSourceInclude>
        </jsSourceIncludes>
        <jsSourceExcludes>
            <jsSourceExclude>**/*.min.js</jsSourceExclude>
        </jsSourceExcludes>
    </configuration>
</plugin>

Step 2: overwrite css and js in the war with minified files

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <webResources>
            <resource>
                <directory>${project.build.directory}/minify</directory>
            </resource>
        </webResources>
    </configuration>
</plugin>
Community
  • 1
  • 1
Kristof Neirynck
  • 3,934
  • 1
  • 33
  • 47
  • Just a notice for anyone: Depending on your use-case, you may not actually need to package JS/CSS in your WAR if you're deploying static content to static content servers. In this case, you can use a Maven profile to minify first then deploy immediately after. – Christopher Schneider May 30 '17 at 18:18
  • Can you please suggest me the same for html compression?? – Aniket Apr 08 '19 at 12:03
  • Nice ! It works fine for me, even without the "excludes" sections. – Tigger Jun 08 '21 at 15:57
6

Use the war generator and add the configuration to exclude the sources file. Example:

    <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>${war-plugin.version}</version>
              <configuration> 
                <warSourceExcludes>js/**/*.js</warSourceExcludes> 
            </configuration> 
    </plugin>

After that you need to include your target files to your war. You do this by setting the "prepare-package" phase of maven lifecycle (I'm using Minify plugin) and adding the files on Minify configuration (jsSourceIncludes,cssSourceIncludes,...)

For example:

         <plugin>
            <groupId>com.samaxes.maven</groupId>
            <artifactId>minify-maven-plugin</artifactId>
            <version>1.7.2</version>
            <executions>
              <execution>
                <id>default-minify</id>
                <goals>
                    <goal>minify</goal>
                </goals>
               <phase>prepare-package</phase>
                <configuration>
                     <jsSourceDir>/js</jsSourceDir>
                     <jsSourceIncludes>
                        <jsSourceInclude>/**/*.js</jsSourceInclude>
                     </jsSourceIncludes>
                </configuration>
              </execution>
            </executions>
          </plugin>
Rokoala
  • 441
  • 7
  • 14
  • 1
    Found a better solution in another post: http://stackoverflow.com/questions/11494943/yuicompressor-maven-plugin-and-maven-war-plugin – Rokoala May 06 '14 at 19:32
5

What happens is that the config above is running the compressor on the process-resources phase, but then the package phase overwrites these files with the original ones.

By changing the phase to package, it should work:

<execution>
    <phase>package</phase>
    <goals>
        <goal>compress</goal>
    </goals>

Now the compression is done after the files where copied to target in order to build the WAR content.

The reason why this is happening is that only compressing files without concatenating them or renaming them with a suffix is not the most common use case for the plugin.

Normally we want to compress and concatenate files into only one file, and give it a new name.

The new name is usually something like originalname-min.css / original.name-min.js where .min is the suffix, so removing the nosuffix option on the config above would also work.

Edit: Log example

[INFO] --- yuicompressor-maven-plugin:1.1:compress (default) @ yui-compressor-test -
[INFO] prettify.css (817b) -> prettify.css (617b)[75%]
[INFO] total input (1510b) -> output (1134b)[75%]
Angular University
  • 42,341
  • 15
  • 74
  • 81
  • I tried the package but that did not seem to work. It doesn't appear that the compress ran at all. All of the files are the unpacked files. We will probably eventually run separate min files, but I was trying the simplest thing first since I didn't want to edit the html files and change all the includes. – Zipper Nov 06 '13 at 23:37
  • By running only mvn clean install with or without package on a minimal project, I get maven logs saying the compressor run (see post edit above), with compressions percentages etc. Do you get similar logs or nothing at all? I saw that with the config above in a WAR project the output of the plugin was overwritten with the package phase. – Angular University Nov 07 '13 at 00:39
  • If no logs for the compressor show up at all on maven logs, could it be that the plugin is configured as part of a maven profile that is not active? – Angular University Nov 07 '13 at 00:44
  • You are correct, the problem is that I was using the command mvn compile war:war since I didn't want to go through the whole process of everything, and I thought the war:war would cause the package to occur anyway, but it doesn't look like it does. – Zipper Nov 07 '13 at 02:58
  • 2
    This actually didn't end up working, it does correctly minify the files on the file system, but it builds the war file before it minifies. I tried changing the phase to prepare-package, but that did not work either. – Zipper Nov 07 '13 at 17:23
3

as stated above maven-war-plugin overwrites files created by minify plugin. it seems that this cannot be changed. however wanted behavior may be achieved by simply changing project structure.

here example what I did with my project. I'm using minify-maven-plugin and spring framework, static files are stored in static directory.

1) move static directory from src/main/webapp to src/main/resources

2) change minify plugin config in pom.xml. so source points to resources and target points to classes:

<webappSourceDir>src/main/resources</webappSourceDir>
<webappTargetDir>target/classes</webappTargetDir>
<jsSourceDir>static</jsSourceDir>
<cssSourceDir>static</cssSourceDir>

3) change spring config. so spring is serving static files from class path:

<mvc:resources location="classpath:/static/" mapping="/static/**"/>

and now

mvn clean && mvn package

produces correct war with minified files inside /WEB-INF/classes/static

yuliskov
  • 1,379
  • 15
  • 16
2

You should take a look to Minify Maven Plugin which sounds like the thing you need.
Let me know if you need any help configuring it.

Samuel Santos
  • 391
  • 1
  • 11
  • Need some help on my [question here](https://stackoverflow.com/questions/28765094/how-to-properly-use-minify-maven-plugin-to-minify-js-and-css-in-angularjs-app) please –  Feb 27 '15 at 12:27