Minification of JS and CSS Assets with Maven – 用Maven对JS和CSS资产进行最小化处理

最后修改: 2016年 7月 12日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

This article shows how to minify Javascript and CSS assets as a build step and serve the resulting files with Spring MVC.

本文展示了如何在构建步骤中对Javascript和CSS资产进行最小化处理,并通过Spring MVC提供所需文件。

We will use YUI Compressor as the underlying minification library and YUI Compressor Maven plugin to integrate it into our build process.

我们将使用YUI Compressor作为底层压缩库,并使用YUI Compressor Maven插件将其集成到我们的构建过程中。

2. Maven Plugin Configuration

2.Maven插件的配置

First, we need to declare that we will use the compressor plugin in our pom.xml file and execute the compress goal. This will compress all .js and .css files under src/main/webapp so that foo.js will be minified as foo-min.js and myCss.css will be minified as myCss-min.css:

首先,我们需要声明我们将在pom.xml文件中使用压缩机插件,并执行compress目标。这将压缩src/main/webapp下的所有.js.css文件,这样foo.js将被压缩为foo-min.jsmyCss.css将被压缩为myCss-min.css

<plugin>
   <groupId>net.alchim31.maven</groupId>
    <artifactId>yuicompressor-maven-plugin</artifactId>
    <version>1.5.1</version>
    <executions>
        <execution>
            <goals>
                <goal>compress</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Our src/main/webapp directory contains the following files:

我们的src/main/webapp目录包含以下文件。

js/
├── foo.js
├── jquery-1.11.1.min.js
resources/
└── myCss.css

After executing mvn clean package, the generated WAR file will contain the following files:

在执行mvn clean package后,生成的WAR文件将包含以下文件。

js/
├── foo.js
├── foo-min.js
├── jquery-1.11.1.min.js
├── jquery-1.11.1.min-min.js
resources/
├── myCss.css
└── myCss-min.css

3. Keeping the Filenames the Same

3.保持文件名不变

At this stage, when we execute mvn clean package, foo-min.js and myCss-min.css are created by the plugin. Since we have originally used foo.js and myCss.css when referring to the files, our page will still use the original non-minified files, as the minified files have different names than the original.

在这个阶段,当我们执行mvn clean package时,foo-min.jsmyCss-min.css被插件创建。由于我们在引用文件时最初使用了foo.jsmyCss.css,我们的页面仍将使用原始的非minified文件,因为minified文件的名称与原始文件不同。

In order to prevent having both foo.js/foo-min.js and myCss.css/myCss-min.css and have the files minified without changing their names, we need to configure the plugin with nosuffix option as follows:

为了防止同时出现foo.js/foo-min.jsmyCss.css/myCss-min.css,并在不改变文件名的情况下将其最小化,我们需要用nosuffix选项配置该插件。

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

Now when we execute mvn clean package, we will have the following files in the generated WAR file:

现在当我们执行mvn clean package时,我们将在生成的WAR文件中拥有以下文件。

js/
├── foo.js
├── jquery-1.11.1.min.js
resources/
└── myCss.css

4. WAR Plugin Configuration

4.WAR插件配置

Keeping the filenames the same has a side effect. It causes the WAR plugin to overwrite the minified foo.js and myCss.css files with the original files, so we don’t have the minified versions of the files in the final output. foo.js file contains the following lines before minification:

保持文件名不变有一个副作用。它导致WAR插件用原始文件覆盖已减化的foo.jsmyCss.css文件,所以我们在最终输出中没有这些文件的减化版本。foo.js文件在最小化前包含以下几行。

function testing() {
    alert("Testing");
}

When we examine the contents of the foo.js file in the generated WAR file, we see that it has the original content instead of the minified content. To solve this problem, we need to specify a webappDirectory for the compressor plugin and reference this from within WAR plugin configuration.

当我们检查生成的WAR文件中的foo.js文件的内容时,我们看到它的内容是原始内容,而不是被压缩的内容。为了解决这个问题,我们需要为压缩器插件指定一个webappDirectory,并在WAR插件配置中引用它。

<plugin>
    <groupId>net.alchim31.maven</groupId>
    <artifactId>yuicompressor-maven-plugin</artifactId>
    <version>1.5.1</version>
    <executions>
        <execution>
            <goals>
                <goal>compress</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <nosuffix>true</nosuffix>
        <webappDirectory>${project.build.directory}/min</webappDirectory>
    </configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
    <webResources>
        <resource>
            <directory>${project.build.directory}/min</directory>
        </resource>
    </webResources>
</configuration>
</plugin>

Here we have specified the min directory as the output directory for the minified files and configured the WAR plugin to include this in the final output.

在这里,我们指定了min目录作为最小化文件的输出目录,并配置了WAR插件,使其包括在最终输出中。

Now we have the minified files in the generated WAR file, with their original filenames foo.js and myCss.css. We can check foo.js to see that it has the following minified content now:

现在,我们在生成的WAR文件中看到了被最小化的文件,它们的原始文件名是foo.jsmyCss.css。我们可以检查foo.js,看到它现在有以下的最小化内容。

function testing(){alert("Testing")};

5. Excluding Already Minified Files

5.排除已被最小化的文件

Third-party Javascript and CSS libraries may have minified versions available for download. If you happen to use one of these in your project, you don’t need to process them again.

第三方的Javascript和CSS库可能有最小化的版本可供下载。如果你碰巧在你的项目中使用了其中的一个,你不需要再次处理它们。

Including already minified files produces warning messages when building the project.

包括已经被粉碎的文件在构建项目时产生警告信息。

For example, jquery-1.11.1.min.js is an already minified Javascript file and it causes warning messages similar to the following during the build:

例如,jquery-1.11.1.min.js是一个已经最小化的Javascript文件,它在构建过程中会导致类似以下的警告信息。

[WARNING] .../src/main/webapp/js/jquery-1.11.1.min.js [-1:-1]: 
Using 'eval' is not recommended. Moreover, using 'eval' reduces the level of compression!
execScript||function(b){a. ---> eval <--- .call(a,b);})
[WARNING] ...jquery-1.11.1.min.js:line -1:column -1: 
Using 'eval' is not recommended. Moreover, using 'eval' reduces the level of compression!
execScript||function(b){a. ---> eval <--- .call(a,b);})

To exclude already minified files from the process, configure the compressor plugin with an excludes option as follows:

要从这个过程中排除已经被粉碎的文件,请用excludes 选项配置压缩器插件,如下所示。

<plugin>
    <groupId>net.alchim31.maven</groupId>
    <artifactId>yuicompressor-maven-plugin</artifactId>
    <version>1.5.1</version>
    <executions>
        <execution>
            <goals>
                <goal>compress</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <nosuffix>true</nosuffix>
        <webappDirectory>${project.build.directory}/min</webappDirectory>
        <excludes>
            <exclude>**/*.min.js</exclude>
        </excludes>
    </configuration>
</plugin>

This will exclude all files under all directories whose filenames end with min.js. Executing mvn clean package doesn’t produce warning messages now and the build doesn’t try to minify already minified files.

这将排除所有目录下文件名以min.js结尾的所有文件。现在执行mvn clean package不会产生警告信息,并且构建时不会尝试对已经被最小化的文件进行最小化。

6. Conclusion

6.结论

In this article, we have described a nice way to integrate minification of Javascript and CSS files into your Maven workflow. To serve these static assets with your Spring MVC application, see our Serve Static Resources with Spring article.

在本文中,我们介绍了一种将Javascript和CSS文件的最小化整合到Maven工作流中的好方法。要在Spring MVC应用程序中提供这些静态资产,请参阅我们的Serve Static Resources with Spring文章。

You can find the code for this article on GitHub.

你可以在GitHub上找到这篇文章的代码。