«1. Обзор

В этой статье показано, как минимизировать ресурсы Javascript и CSS на этапе сборки и обслуживать полученные файлы с помощью Spring MVC.

Мы будем использовать YUI Compressor в качестве базовой библиотеки минификации и плагин YUI Compressor Maven, чтобы интегрировать его в наш процесс сборки.

2. Настройка плагина Maven

Во-первых, нам нужно объявить, что мы будем использовать плагин компрессора в нашем файле pom.xml и выполнить цель сжатия. Это сожмет все файлы .js и .css в папке src/main/webapp, так что foo.js будет минимизирован как foo-min.js, а myCss.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>

Наш каталог src/main/webapp содержит следующие файлы:

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

После выполнения пакета mvn clean сгенерированный файл 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. Сохранение имен файлов прежними

На этом этапе, когда мы запускаем mvn clean package, плагин создает foo-min.js и myCss-min.css. Поскольку мы изначально использовали foo.js и myCss.css при обращении к файлам, наша страница по-прежнему будет использовать исходные неминифицированные файлы, поскольку минифицированные файлы имеют другие имена, чем исходные.

Чтобы избежать использования как foo.js/foo-min.js, так и myCss.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>

Теперь, когда мы запускаем mvn clean package, у нас будут следующие файлы в сгенерированном файле WAR:

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

4. Конфигурация плагина WAR

Сохранение имен файлов имеет побочный эффект. Это приводит к тому, что подключаемый модуль WAR перезаписывает уменьшенные файлы foo.js и myCss.css исходными файлами, поэтому у нас нет уменьшенных версий файлов в окончательном выводе. Файл foo.js содержит следующие строки перед минификацией:

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

Когда мы изучаем содержимое файла foo.js в сгенерированном WAR-файле, мы видим, что он имеет исходное содержимое, а не уменьшенное содержимое. Чтобы решить эту проблему, нам нужно указать каталог 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>

Здесь мы указали каталог min в качестве выходного каталога для минифицированных файлов и настроили подключаемый модуль WAR, чтобы включить его в окончательный вывод.

Теперь у нас есть минифицированные файлы в сгенерированном WAR-файле с их исходными именами файлов foo.js и myCss.css. Мы можем проверить foo.js, чтобы увидеть, что теперь он имеет следующее уменьшенное содержимое:

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

5. Исключение уже уменьшенных файлов

Сторонние библиотеки Javascript и CSS могут иметь уменьшенные версии, доступные для загрузки. Если вам случится использовать один из них в своем проекте, вам не нужно обрабатывать их снова.

Включение уже минифицированных файлов приводит к появлению предупреждающих сообщений при сборке проекта.

Например, 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);})

Чтобы исключить уже минимизированные файлы из процесса, настройте подключаемый модуль компрессора с параметром exclude следующим образом:

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

Это исключит все файлы во всех каталогах, имена файлов которых заканчиваются на min.js. Выполнение пакета mvn clean теперь не выдает предупреждающих сообщений, и сборка не пытается минимизировать уже минифицированные файлы.

6. Заключение

В этой статье мы описали хороший способ интеграции минификации файлов Javascript и CSS в ваш рабочий процесс Maven. Чтобы обслуживать эти статические ресурсы с помощью приложения Spring MVC, см. нашу статью «Обслуживание статических ресурсов с помощью Spring».

Вы можете найти код этой статьи на GitHub.