How to minify a filtered javascript file using maven?
I have a javascript file that is used to track events using Google analytics. I have created different accounts for the staging and production environment. The script to invoke GA code has a place holder for my account Id. The account Ids have been specified in the filter files. Using the webResources element in the maven-war plugin, we are able to successfully replace the property in the final WAR file.
Now, we are also using maven-yuicompressor plugin to minify and aggregate all our javascript files. The problem is that if I attach the execution of minify goal to the package phase, the WAR is created before the Javascript has been minified. If I attach the minify goal to anything earlier, the filter has been not applied till the time of minification producing an invalid file.
So, I am looking for a way to run the minify goal between the WAR plugin copying the filtered JS files and creating the WAR file. Here are the relevant portions of my pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<webResources>
<resource>
<directory>src/main/webapp/js</directory>
<targetPath>js</targetPath>
<filtering>true</filtering>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<goals>
<goal>compress</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<linebreakpos>-1</linebreakpos>
<nosuffix>true</nosuffix>
<force>true</force>
<aggregations>
<aggregation>
<output>${project.build.directory}/${project.build.finalName}/js/mysite-min.js</output>开发者_如何学运维
<inputDir>${project.build.directory}/${project.build.finalName}/js</inputDir>
<includes>
<include>jquery-1.4.2.js</include>
<include>jquery-ui.min.js</include>
<include>ga-invoker.js</include>
</includes>
</aggregation>
</aggregations>
</configuration>
</plugin>
Great question, great anwser by artbristol, which i voted up. It helped me a lot. For future reference i post a complete solution:
- Put your Javascript files into
src/main/resources/js
(or whatever fits your needs) - Put your CSS files into
src/main/resources/css
(or whatever fits your needs) - Resources plugin is filtering your javascript resources and copies them to
target/classes/js/
- Yui is picking up the files at target/classes/js/ and aggregates them to
src/main/webapp
- You can test your setup with
jetty:run
. Jetty is picking up the compressed and aggregated files insrc/main/webapp
- war plugin at package phase is picking up your files under
src/main/webapp
- optional put a SCM ignore file like
.svnignore
or.cvsignore
file intosrc/main/webapp
to excludeall.js
from your favourite SCM tool.
The excludes section is necessary to avoid compressing anything in src/main/resources and src/main/webapp. yui should just pickup already filtered files for aggregation.
<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>
<goals>
<goal>compress</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>*/*</exclude>
</excludes>
<force>true</force>
<nosuffix>true</nosuffix>
<removeIncluded>true</removeIncluded>
<aggregations>
<aggregation>
<insertNewLine>true</insertNewLine>
<output>${project.basedir}/src/main/webapp/js/all.js</output>
<includes>
<include>${project.build.directory}/classes/js/file1.js</include>
<include>${project.build.directory}/classes/js/file2.js</include>
</aggregation>
<aggregation>
<insertNewLine>true</insertNewLine>
<output>${project.basedir}/src/main/webapp/css/all.css</output>
<includes>
<include>${project.build.directory}/classes/css/file1.css</include>
<include>${project.build.directory}/classes/css/file2.css</include>
</aggregation>
</aggregations>
</configuration>
</plugin>
Why would you want filtering of css files?
i use it to reference my images like this
div.header {
background-image: url(/img/background.${project.version}.png)
}
Maven filters my project version into my css files. Any incoming request on our imageserver is filtered like this
protected void doHttpFilter ( HttpServletRequest request, HttpServletResponse response, FilterChain chain ) throws IOException, ServletException
{
String uri = request.getRequestURI();
if (isStaticRequest(uri))
{
String uriWithoutVersion = stripVersionString(uri);
String versionRequested = getVersionString(uri);
if (version.equals(versionRequested))
{
response.setHeader(CACHE_CONTROL_HEADER_NAME, CACHE_CONTROL_HEADER_VALUE);
response.setHeader(EXPIRES_HEADER_NAME, EXPIRES_HEADER_VALUE);
}
RequestDispatcher dispatcher = request.getRequestDispatcher(uriOhneVersionsnummer);
dispatcher.forward(request, response);
} else {
chain.doFilter(request, response);
return;
}
}
this way the browser caches each file forever. but when i upload a new version all file reference have a new version number, so the browser is fetching the image or css again. this helped us a lot to reduce traffic.
Can you put the filtered js files in src/main/resources/filtered-js, use the resources plugin instead, which binds to process-resources
, then point the webresources config of the maven-war-plugin to target/classes/filtered-js
?
I am using Maven Minify Plugin to compress the javascript and css files. It also merges these files into one single file.This is working fine
I have used maven-timestamp plugin to put a unque suffix to these file as a browser cache solution.This is also working fine
The thing i am stuck with is how to replace all the reference of the js and css with the ones newly created at the build execution time.
I am looking into maven-replace-plugin for the same. It can remove all instances.It can replace with new values. But I need to keep one instance of the newly merged-minified js and css.
<plugins>
<plugin>
<groupId>com.keyboardsamurais.maven</groupId>
<artifactId>maven-timestamp-plugin</artifactId>
<version>1.0</version>
<configuration>
<propertyName>timestamp</propertyName>
<timestampPattern>ddMMyyyyHHmm</timestampPattern>
</configuration>
<executions>
<execution>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/resources/themes</outputDirectory>
<resources>
<resource>
<includes>
<include>**/*.vm</include>
</includes>
<directory>${basedir}/src/main/resources/themes</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.samaxes.maven</groupId>
<artifactId>maven-minify-plugin</artifactId>
<version>1.3.5</version>
<executions>
<execution>
<id>default-minify</id>
<phase>process-resources</phase>
<configuration>
<cssSourceDir>../resources/themes/XXXX/default/template-resources/stylesheet</cssSourceDir>
<cssSourceIncludes>
<cssSourceInclude>**/*.css</cssSourceInclude>
</cssSourceIncludes>
<cssFinalFile>style.css</cssFinalFile>
<jsSourceDir>../resources/themes/XXXX/default/template-resources/js</jsSourceDir>
<jsSourceIncludes>
<jsSourceInclude>*.js</jsSourceInclude>
</jsSourceIncludes>
<jsSourceFiles>
<jsSourceFile>/libs/json.js</jsSourceFile>
</jsSourceFiles>
<jsFinalFile>script.js</jsFinalFile>
<suffix>-${timestamp}</suffix>
</configuration>
<goals>
<goal>minify</goal>
</goals>
</execution>
</executions>
</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>
<includes>
<include>target/resources/themes/XXXX/default/templates/velocity/**/*.vm</include>
</includes>
<replacements>
<replacement>
<token><![CDATA[<link rel="stylesheet" href="/storefront/template-resources/stylesheet/]]>([a-zA-Z0-9\-\_]*.css)<![CDATA[" type="text/css"/>]]>([])</token>
<value></value>
</replacement>
<replacement>
<token><![CDATA[<link rel="stylesheet" href="/storefront/template-resources/stylesheet/powerreviews]]>([a-zA-Z0-9\-\_]*.css)<![CDATA[" type="text/css"/>]]></token>
<value></value>
</replacement>
<replacement>
<token><![CDATA[<script type="text/javascript" src="/storefront/template-resources/js/]]>([a-zA-Z0-9\-\_\.]*.js)<![CDATA["></script>]]></token>
<value></value>
</replacement>
<replacement>
<token><![CDATA[<script type="text/javascript" src="/storefront/template-resources/js/libs/]]>([a-zA-Z0-9\-\_\.]*.js)<![CDATA["></script>]]></token>
<value></value>
</replacement>
</replacements>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>dist</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
精彩评论