【问题标题】:How to minify a filtered javascript file using maven?如何使用 maven 缩小过滤后的 javascript 文件?
【发布时间】:2011-08-29 11:25:44
【问题描述】:

我有一个 javascript 文件,用于使用 Google 分析跟踪事件。我为登台和生产环境创建了不同的帐户。调用 GA 代码的脚本有一个占位符作为我的帐户 ID。帐户 ID 已在过滤器文件中指定。使用 maven-war 插件中的 webResources 元素,我们能够成功地替换最终 WAR 文件中的属性。

现在,我们还使用 maven-yuicompressor 插件来缩小和聚合我们所有的 javascript 文件。问题是,如果我将 minify 目标的执行附加到 package 阶段,WAR 是在 Javascript 被缩小之前创建的。如果我将缩小目标附加到任何较早的内容,则直到缩小时才会应用过滤器,从而产生无效文件。

所以,我正在寻找一种在 WAR 插件复制过滤的 JS 文件和创建 WAR 文件之间运行缩小目标的方法。以下是我的 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>

【问题讨论】:

  • 可以绑定到prepare-package ?
  • 正如我之前提到的,在包阶段之前附加到任何东西都不起作用,因为直到那时还没有应用过滤器。 war 插件复制 Web 资源并将过滤器应用为打包阶段本身的一部分。

标签: javascript maven filter minify


【解决方案1】:

我正在使用 Maven Minify 插件来压缩 javascript 和 css 文件。它还将这些文件合并到一个文件中。这工作正常

我已经使用 maven-timestamp 插件为这些文件添加了一个独特的后缀作为浏览器缓存解决方案。这也可以正常工作

我坚持的事情是如何将所有 js 和 css 的引用替换为在构建执行时新创建的引用。

我也在研究 maven-replace-plugin。它可以删除所有实例。它可以替换为新值。但我需要保留一个新合并的缩小 js 和 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>

【讨论】:

  • 对于缓存清除,您可能希望使用 MD5 校验和而不是时间戳。使用时间戳,每次构建时,无论您是否更改 JS 和 CSS,您的缓存都会失效。
【解决方案2】:

好问题,artbristol 的好答案,我投了赞成票。这对我帮助很大。为了将来参考,我发布了一个完整的解决方案:

  • 将您的 Javascript 文件放入 src/main/resources/js(或任何适合您需要的文件)
  • 将您的 CSS 文件放入 src/main/resources/css(或任何适合您需要的文件)
  • Resources 插件正在过滤您的 JavaScript 资源并将它们复制到 target/classes/js/
  • Yui 正在获取 target/classes/js/ 中的文件并将它们聚合到 src/main/webapp
  • 您可以使用jetty:run 测试您的设置。 Jetty 正在提取src/main/webapp 中的压缩和聚合文件
  • 打包阶段的war插件正在获取src/main/webapp下的文件
  • 可选择将 SCM 忽略文件(如 .svnignore.cvsignore 文件放入 src/main/webapp 以从您最喜欢的 SCM 工具中排除 all.js

excludes 部分是必要的,以避免压缩 src/main/resources 和 src/main/webapp 中的任何内容。 yui 应该只拾取已过滤的文件进行聚合。

<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>

为什么要过滤 css 文件?

我用它来引用我这样的图像

div.header {
  background-image: url(/img/background.${project.version}.png)
}

Maven 将我的项目版本过滤到我的 css 文件中。我们图像服务器上的任何传入请求都会被过滤这样

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;
    }
}

这样浏览器会永久缓存每个文件。但是当我上传新版本时,所有文件引用都有一个新版本号,所以浏览器再次获取图像或 css。 这对我们减少流量有很大帮助。

【讨论】:

    【解决方案3】:

    能不能把过滤后的js文件放到src/main/resources/filtered-js,改用资源插件,绑定process-resources,然后把maven-war-plugin的webresources配置指向target/classes/filtered-js ?

    【讨论】:

    • 你已经打败了我来发布答案。我昨天做了类似的事情。我让 yuicompressor 插件保持附加到 process-resources 阶段,这是默认设置,但将其输出配置为转到 target/js。然后我用maven-war插件的webResources配置过滤了这个目录的内容,放到target//js中。仍然必须将您的答案标记为正确的答案。
    猜你喜欢
    • 1970-01-01
    • 2012-12-18
    • 2021-03-28
    • 2012-08-03
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    相关资源
    最近更新 更多