Как вы автоматизируете минификацию Javascript для своих веб-приложений Java?

122

Мне интересно услышать, как вы предпочитаете автоматизировать минификацию Javascript для своих веб-приложений Java. Вот несколько аспектов, которые меня особенно интересуют:

  • Как это интегрируется? Является ли он частью вашего инструмента сборки, фильтра сервлета, отдельной программы, обрабатывающей файл WAR, или чего-то еще?
  • Это легко включать и выключать ? Очень несмешно пытаться отладить минифицированный скрипт, но разработчику также полезно иметь возможность проверить, что минификация ничего не нарушает.
  • Работает ли он прозрачно , или у него есть какие-либо побочные эффекты (помимо тех, которые присущи минификации), которые я должен учитывать в своей повседневной работе?
  • Какой минификатор он использует?
  • В нем отсутствуют какие-либо функции, о которых вы можете подумать?
  • Что вам нравится в этом?
  • Что тебе в этом не нравится?

Это в основном будет служить справочником для моих будущих проектов (и, надеюсь, другие SOer тоже найдут его информативным), так что все виды инструментов интересны.

(Обратите внимание, что вопрос не в том, какой минификатор лучше . У нас уже есть много таких.)

gustafc
источник
это выглядит действительно интересно, не слышал об этом. Все инструменты, которые я нашел в результате быстрого поиска, - это ручные инструменты, которые запускаются один раз. Было бы неплохо, если бы был плагин для ant или maven. Надеюсь, у кого-то есть хороший ответ.
Джей,
И, похоже, кто-то это сделал - проверьте ответ
dfa

Ответы:

65

Итоговый пост

Если вы публикуете что-то новое в этой теме, отредактируйте это сообщение, чтобы оно было связано с вашим.

gustafc
источник
Компрессор minify-maven и maven yui не очень хорошо работал с функциями ES6 на момент
DPM
13

Мы используем задачу Ant для минимизации файлов js с помощью YUICompressor во время производственной сборки и помещения результата в отдельную папку. Затем мы загружаем эти файлы на веб-сервер. Вы можете найти несколько хороших примеров интеграции YUI + Ant в этом блоге .

Вот пример:

<target name="js.minify" depends="js.preprocess">
    <apply executable="java" parallel="false">
        <fileset dir="." includes="foo.js, bar.js"/>
        <arg line="-jar"/>
        <arg path="yuicompressor.jar"/>
        <srcfile/>
        <arg line="-o"/>
        <mapper type="glob" from="*.js" to="*-min.js"/>
        <targetfile/>
    </apply>
</target>
серг
источник
2
Сниппет; отлично. Вы перенастраиваете свои script srcсборки на dev или просто копируете неминифицированные файлы в сжатый каталог / js?
gustafc
Просто для производства загружайте сжатые файлы поверх исходных в public_html / js. Хорошо то, что нет никакого кодирования или изменения пути между локальным и производственным, плохо то, что вам нужно выполнить некоторую ручную загрузку и перезапись (я уверен, что это можно автоматизировать, но для нас это не стоит того, загрузка несколько файлов js время от времени не слишком большая проблема).
serg 04
Я использовал ваш код, но он создает миниатюрный файл в корне моего проекта, я установил, <fileset dir="${generatedScriptsDir}" includes="**/*.js"/>но он не работает. Как я могу создать файл в формате ${generatedScriptsDir}?
Vadorequest
попробуйте добавить атрибут dir к тегу apply. убедитесь, что «$ {generatedScriptsDir}» был создан как «свойство» с назначенным местом назначения
Rajasri.J
12

Я думаю, что одним из лучших и правильных инструментов для работы является wro4j. Проверьте https://github.com/wro4j/wro4j

Он делает все, что вам нужно:

  • Держите веб-ресурсы проекта (js и css) хорошо организованными
  • Объедините и минимизируйте их во время выполнения (используя простой фильтр) или во время сборки (используя плагин maven)
  • Бесплатно и с открытым исходным кодом: выпущено по лицензии Apache 2.0
  • несколько инструментов минификации, поддерживаемых wro4j: JsMin, компрессор Google Closure, YUI и т. д.
  • Очень проста в использовании. Поддерживает фильтр сервлетов, простую конфигурацию Java или Spring
  • Поддержка мета-фреймворков Javascript и CSS: CoffeeScript, Less, Sass и т. Д.
  • Проверка: JSLint, CSSLint и т. Д.

Может работать как в отладочном, так и в производственном режимах. Просто укажите все файлы, которые он должен обработать / предварительно обработать, а все остальное он сделает.

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

<script type="text/javascript" src="wro/all.js"></script>
SZ Quadri
источник
2
Похоже, действительно отличный инструмент. Спасибо за обновление!
gustafc 01
Добавляет ли он управление версиями к файлам ресурсов для принудительного обновления на стороне клиента? Мне не удалось найти никакой документации по этой функции.
Цян
Единственное, чего мне очень не хватает в wro4j, так это префикса css.
inafalcao
Можно ли обслуживать статический контент (созданный wroна сервере приложений) с apacheвеб-сервера?
HybrisHelp
8

Я написал макросы муравьев для компилятора Google Closure и компрессора Yahoo и включаю этот файл в разные веб-проекты.

<?xml version="1.0" encoding="UTF-8"?>
<!-- CSS and JS minifier. -->
<!DOCTYPE project>
<project name="minifier" basedir=".">

  <property name="gc" value="compiler-r1592.jar" />
  <property name="yc" value="yuicompressor-2.4.6.jar" />

  <!-- Compress single js with Google Closure compiler -->
  <macrodef name="gc-js">
    <attribute name="dir" />
    <attribute name="src" />
    <sequential>
      <java jar="${gc}" fork="true">
        <!--
        - - compilation_level WHITESPACE_ONLY | SIMPLE_OPTIMIZATIONS | ADVANCED_OPTIMIZATIONS
        Specifies the compilation level to use. Default: SIMPLE_OPTIMIZATIONS
        - - warning_level QUIET | DEFAULT | VERBOSE
        Specifies the warning level to use.
        -->
        <arg line="--js=@{dir}/@{src}.js" />
        <arg line="--js_output_file=@{dir}/@{src}-min-gc.js" />
      </java>
    </sequential>
  </macrodef>

  <!-- Compress single js with Yahoo compressor -->
  <macrodef name="yc-js">
    <attribute name="dir" />
    <attribute name="src" />
    <sequential>
      <java jar="${yc}" fork="true">
        <arg value="@{dir}/@{src}.js" />
        <arg line="-o" />
        <arg value="@{dir}/@{src}-min-yc.js" />
      </java>
    </sequential>
  </macrodef>

  <!-- Compress all js in directory with Yahoo compressor -->
  <macrodef name="yc-js-all">
    <attribute name="dir" />
    <sequential>
      <apply executable="java" parallel="false">
        <fileset dir="@{dir}" includes="*.js" excludes="*-min*.js" />
        <arg line="-jar" />
        <arg path="${yc}" />
        <srcfile />
        <arg line="-o" />
        <mapper type="glob" from="*.js" to="@{dir}/*-min-yc.js" />
        <targetfile />
      </apply>
    </sequential>
  </macrodef>

  <!-- Compress all css in directory with Yahoo compressor -->
  <macrodef name="yc-css-all">
    <attribute name="dir" default="${build.css.dir}" />
    <sequential>
      <apply executable="java" parallel="false">
        <fileset dir="@{dir}" includes="*.css" excludes="*-min*.css" />
        <arg line="-jar" />
        <arg path="${yc}" />
        <arg line="-v --line-break 0" />
        <srcfile />
        <arg line="-o" />
        <mapper type="glob" from="*.css" to="@{dir}/*-min.css" />
        <targetfile />
      </apply>
    </sequential>
  </macrodef>
</project>
  • Интеграция: <import file="build-minifier.xml" />в вашем build.xml вызовите обычные задачи ant:<gc-js dir="${build.js.dir}" src="prototype" /> <yc-js-all dir="${build.js.dir}" />

  • На выбор два минификатора: компилятор Google Closure и компрессор Yahoo, вы должны скачать их вручную и поместить рядом с xml файлом.

  • Минификаторы пропускают уже сжатые файлы (заканчивающиеся на -min*)

  • Обычно я делаю три версии скрипта: несжатый (например prototype.js) для отладки, сжатый с помощью компилятора закрытия ( prototype-min-gc.js) для рабочего сервера, сжатый с помощью Yahoo ( prototype-min-yc.js) для устранения неполадок, потому что компилятор закрытия использует рискованные оптимизации и иногда создает недопустимый сжатый файл, а компрессор Yahoo более безопасен

  • Компрессор Yahoo может минимизировать все файлы в каталоге с помощью одного макроса, компилятор Closure не может

Виктор
источник
8

Я пробовал два способа:

  1. используя фильтр сервлетов. В рабочем режиме фильтр активируется и сжимает любые данные, привязанные к URL-адресу, например * .css или * .js.
  2. с использованием maven и yuicompressor-maven-plugin ; компрессия выполняется una-tantum, (при сборке производства войны )

Конечно, последнее решение лучше, поскольку оно не потребляет ресурсы во время выполнения (мое веб-приложение использует движок приложений Google) и не усложняет код вашего приложения. Итак, предположим этот последний случай в следующих ответах:

Как это интегрируется? Является ли он частью вашего инструмента сборки, фильтра сервлета, отдельной программы, обрабатывающей файл WAR, или чего-то еще?

используя maven

Легко ли включать и отключать? Очень несмешно пытаться отладить минифицированный скрипт, но разработчику также полезно иметь возможность проверить, что минификация ничего не нарушает.

вы активируете его только при сборке финальной войны; в режиме разработки вы видите несжатую версию ваших ресурсов

Работает ли он прозрачно, или у него есть какие-либо побочные эффекты (помимо тех, которые присущи минификации), которые я должен учитывать в своей повседневной работе?

абсолютно

Какой минификатор он использует?

Компрессор YUI

В нем отсутствуют какие-либо функции, о которых вы можете подумать?

нет, это очень полный и простой в использовании

Что вам нравится в этом?

он интегрирован с моим любимым инструментом (maven), а плагин находится в центральном репозитории (хороший гражданин maven)

dfa
источник
Плагин Maven - приятно. Жаль, что все мои текущие проекты используют ant :)
gustafc
вы можете создать цель, которая создаст «производственный файл войны», используя задачу YUI ant
dfa
4

Думаю, вам нужна библиотека сжатия, например тег Granule.

http://code.google.com/p/granule/

Он gzip и комбинирует javascripts, обернутые тегом g: compress с использованием разных методов, также имеет задачу Ant.

пример кода:

<Г: компресс>
  <script type = "text / javascript" src = "common.js" />
  <script type = "text / javascript" src = "closure / goog / base.js" />
  <Скрипт>
       goog.require ( 'goog.dom');
       goog.require ( 'goog.date');
       goog.require ( 'goog.ui.DatePicker');
  </ Скрипт>
  <script type = "text / javascript">
      var dp = new goog.ui.DatePicker ();
      dp.render (document.getElementById ( 'DatePicker'));
  </ Скрипт>
</ Г: компресс>
...

Энди Белл
источник
Да, выглядит неплохо.
gustafc
3

Я действительно удивлен, что никто не упомянул JAWR - https://jawr.github.io

Он довольно зрелый и поддерживает все ожидаемые стандартные функции и многое другое. Вот как это согласуется с превосходными критериями ОП.

Как это интегрируется? Является ли он частью вашего инструмента сборки, фильтра сервлета, отдельной программы, обрабатывающей файл WAR, или чего-то еще?

Первоначально он выполнял обработку / тяжелую работу при запуске приложения, а обслуживание было основано на сервлете . Начиная с 3.x они добавили поддержку интеграции во время сборки .

Поддержка JSP и Facelets предоставляется через настраиваемую библиотеку тегов JSP для импорта обработанных ресурсов. В дополнение к этому реализован загрузчик JS-ресурсов, который поддерживает загрузку ресурсов со статических HTML-страниц .

Легко ли включать и отключать? Очень несмешно пытаться отладить минифицированный скрипт, но разработчику также полезно иметь возможность проверить, что минификация ничего не нарушает.

debug=onОпция доступна для использования перед запуском приложения и пользовательские GETпараметры могут быть заданы в отдельных запросах в производстве для переключения режима отладки выборочно во время выполнения для указанного запроса.

Какой минификатор он использует?

Для JS он поддерживает YUI Compressor и JSMin, для CSS я не уверен.

В нем отсутствуют какие-либо функции, о которых вы можете подумать?

SASSна ум приходит поддержка. Тем не менее, он поддерживает LESS.

Амр Мостафа
источник
2

Наш проект справился с этим несколькими способами, но мы продолжаем использовать YUI Compressor в наших различных итерациях.

Изначально у нас был сервлет, обрабатывающий сжатие для JavaScript при первом обращении к этому конкретному файлу; затем он был кэширован. У нас уже была система для обработки пользовательских файлов свойств, поэтому мы просто обновили наши файлы конфигурации, чтобы поддерживать включение или отключение компрессора в зависимости от среды, в которой мы работали.

Теперь среды разработки никогда не используют сжатый JavaScript для отладки. Вместо этого мы обрабатываем сжатие в нашем процессе сборки при экспорте нашего приложения в файл WAR.

Наш клиент никогда не высказывал опасений по поводу сжатия, и разработчики не замечают этого, пока не решат отладить JavaScript. Так что я бы сказал, что это довольно прозрачно с минимальными побочными эффектами.

doomspork
источник
Как вы используете компрессор YUI в процессе сборки? Плагин Maven или что-то еще?
gustafc
1
Извините, в настоящее время мы используем Ant. Вот полезная ссылка для Ant Task: blog.gomilko.com/2007/11/29/yui-compression-tool-as-ant-task
doomspork
1

Это сработало для меня: https://bitbucket.org/m6_russell_francis/yui-compressor-ant-task/wiki/Home

<!-- minimize all static *.css & *.js content -->
<target name="static-content-minify">

    <taskdef name="yuicompressor"
             classname="com.metrosix.yuicompressor.anttask.YuiCompressorTask">
        <classpath>
            <pathelement location="${jar.yui.compressor}"/>
            <pathelement location="${jar.yui.anttask.compressor}" />
        </classpath>
    </taskdef>

    <yuicompressor todir="${build.static.content.min}" charset="utf-8" 
        preserveallsemicolons="true" munge="true" >
        <fileset dir="${src.static.content}">
            <include name="**/*.css"/>
            <include name="**/*.js"/>
        </fileset>
    </yuicompressor>
</target>
Обратный Тарзан
источник
Я получил $ {jar.yui.compressor} с search.maven.org: search.maven.org/…
Обратный Тарзан
1

Я пишу фреймворк для управления веб-активами, который называется Humpty . Он стремится быть проще и современнее, чем jawr или wro4j, за счет использования WebJars и ServiceLoaders.

Как это интегрируется? Является ли он частью вашего инструмента сборки, фильтра сервлета, отдельной программы, обрабатывающей файл WAR, или чего-то еще?

При разработке сервлет обрабатывает активы по мере необходимости. Затем активы будут предварительно скомпилированы перед производством и помещены в общую папку, так что единственная используемая часть - это создание правильных включений в HTML.

Легко ли включать и отключать? Очень несмешно пытаться отладить минифицированный скрипт, но разработчику также полезно иметь возможность проверить, что минификация ничего не нарушает.

Это будет сделано путем переключения между режимами разработки и производства.

Работает ли он прозрачно, или у него есть какие-либо побочные эффекты (помимо тех, которые присущи минификации), которые я должен учитывать в своей повседневной работе?

Я считаю, что это прозрачно, но я настоятельно рекомендую использовать WebJars.

Какой минификатор он использует?

Какой бы плагин вы не использовали в пути к классам. В настоящее время собираюсь написать плагин для компилятора Google Closure.

В нем отсутствуют какие-либо функции, о которых вы можете подумать?

Все еще пре-релиз, хотя я использую его в продакшене. Плагин maven по-прежнему требует большой работы.

Что вам нравится в этом?

Простота простого добавления зависимости для настройки фреймворка

Что тебе в этом не нравится?

Это мой ребенок, мне все это нравится;)

Мванджи Эзана
источник
1

Действительно поздно на вечеринку, но подумал, что это может помочь кому-то, все еще ищущему другой ответ:

После попытки использовать YUI Compressor я был разочарован тем, что он несовместим с более поздними версиями jQuery и Prism (двумя основными сторонними JS-библиотеками, которые мне понадобились для моего проекта, которые я хотел сжать в один файл). Поэтому я решил использовать Terser , это форк Uglify-JS, поддерживающий ES6 +. Мне не удалось запустить его напрямую с помощью <exec>задачи, но использование метода командной строки Windows работает, по крайней мере, для Win 10 (не говоря уже о том, что иначе он не может работать, но это был очень простой обходной путь). Больше ничего добавлять в системную переменную Path не нужно (поскольку Node.JS обычно добавляется во время установки). Сначала я использую <concat>задачу ANT, чтобы создать большой несжатый файл. Используйте, <fileset>поскольку это сохранит порядок (в любом случае, если это важно).

<concat destfile="${js-big-file}" encoding="UTF-8" outputencoding="UTF-8" fixlastline="true">
   <filelist refid="js-input-filelist"/>
</concat>

Затем используйте <exec>задачу для запуска любой программы NPM, например Terser. На странице руководства Apache по этой задаче указано, что это обходной путь Windows для запуска файлов .bat, но он действительно позволяет запускать практически любое приложение командной строки (даже те, которые <exec>загадочным образом не могут найти иначе).

<exec executable="cmd">
   <arg value="/c"/>
   <arg value="terser"/>
   <arg value="${js-big-file}" />
   <arg value="-o" />
   <arg value="${smaller-js-file}"/>  
</exec>

Интеграция? Он является частью сценария сборки ANT (плагин DITA Open Toolkit для поддержки пользовательского JavaScript, среди прочего - не веб-приложение Java как таковое, а использующее Java для создания вывода HTML5), поэтому интеграция была не чем иным, как добавлением этих задачи на новую цель (есть еще код, касающийся установки значений по умолчанию и проверки входных параметров!).

Легко включить / отключить?В моем случае у меня есть параметр, который я передаю сборке ANT, чтобы включить сборку и минимизацию файла JS. Так что да, он выполняет эту цель, только если я установил для параметра значение «Да». Это довольно просто настроить в сборке ANT.

Прозрачный Пока что это не влияет ни на один из нескольких JS-файлов, которые я включаю. Некоторые из них являются моими собственными (и я ни в коем случае не эксперт по JS), а некоторые, как я уже упоминал, являются общими библиотеками JS.

Minifier Terser , но вы можете использовать практически любой минифицированный с вводом из командной строки этим методом.

Отсутствие функций? Terser работает только с JavaScript. Если я хочу сделать то же самое для моих файлов CSS (что я и делаю), я использую YUI Compressor.

Like That это активный проект, имеющий хорошую поддержку. Кроме того, текущая реализация (вызов только через ANT<exec> цель ) позволяет мне менять минификаторы, если мне понадобится что-то еще в будущем.

Не нравится Это требует Node.JS. Ничего против Node.JS, заметьте, просто этому конкретному проекту в противном случае он не нужен. Я бы предпочел использовать для этого файл Java .jar, например YUI Compressor (я могу легко распространить его с помощью плагина, если мне это нужно).

Джейсон Коулман
источник
Приглашаются и опоздавшие! Я согласен, что иметь проект, который зависит от двух разных сред программирования (Java + Node), утомительно. Тем не менее, неудивительно, что большая часть работы с Javascript происходит в сообществе Node, так что тут особо нечего делать, а Терсер, похоже, сейчас набирает обороты. Спасибо за ваш вклад!
gustafc