Статьи

Автор: Николай Мациевский aka sunnybear
Опубликована: 21 января 2008

JavaScript: жать или не жать?

После публикации статьи на тему архивирования JS/CSS-файлов для последующей выдачи клиенту, я задумался на тему, какой же метод минимизации (minify) следует использовать. В докладе на конференции ClientSide'2007 не удалось установить четкого критерия, чем и как лучше всего сжимать JavaScript-файлы. Данная заметка посвящена рассмотрению как раз этой проблемы.

Задача

В качестве цели исследования был закреплен анализ всех известных средств статической минимизации JavaScript-кода, после чего нужно было ответить на три основных вопроса:

  • Имеет ли смысл пользоваться каким-либо минимизатором JS-кода?
  • Есть ли среди них универсальное средство, показывающее лучшие результаты в подавляющем большинстве случаев?
  • Если такого средства нет, то каковы критерии использования набора инструментов?

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

График сжатия JS-файлов

Инструменты и методика

Всего удалось обнаружить 5 кардинально разных средств для минимизации JavaScript-файлов, которые могут работать как автономные приложения (в расчете на то, что их можно будет далее запускать по событию или по расписанию, ориентируясь, в общем, на автоматизацию процесса публикации файлов на production-сервере).

  1. JSMin. Наиболее широко распространенный минимизатор, основывается на простых правилах, портирован на множество языков, в том числе, и на сам JavaScript.
  2. JavaScript::Minifier. Отдельный перловый модуль, по степени сжатия очень близок к JSMin, однако генерирует отличный от первого синтаксис.
  3. Dojo ShrinkSafe aka Rhino. Первоначально разрабатывался как Rhino, затем был включен в состав Dojo. Запускается как jar-модуль.
  4. Dean Edwards Packer. Достаточно широко известный инструмент от не менее известного Dean Edwards. Портирован на некоторые языки, в том числе, на PHP4/5.
  5. YUI Compressor. В представлении также не нуждается, именно на его основе проведена оптимизации сайтов Yahoo. Для анализа использовалась версия 2.2.5. Запускается как jar-модуль.

Для анализа были найдены несколько достаточно больших и широко используемых JS-файлов (возможно, вы их загружали в этом месяце или даже используете из кеша каждый день) разных размеров и степеней изначального сжатия. Далее их размеры со ссылками на источники: 853, 5857, 8867, 9580, 21414, 22015, 39686, 43099, 83879, 95285, 124136, 289446.

Все исходные файлы сжимались всеми представленными инструментами, затем архивировались. Затем все полученные данные нужно было выстроить в какой-то последовательности, которая бы выявляла характер и преимущества сжатия файлов сторонними средствами. Критерием для такой последовательности была выбрана изначальная «сжимаемость» файлов (то, насколько они хорошо архивируются). Очевидно, что если файл уже достаточно плохо архивируется, то предварительное его сжатие каким-либо минимизатором ситуацию улучшить не должно (такие файлы обычно оформлены в довольно минималистичном стиле, и из них уже удалены все комментарии). Что и подтвердилось на конкретных примерах.

Результаты

Сами графики, собственно. Что на них изображено? Выведен выигрыш (в процентах) относительно несжатого файла (по оси ординат отложены проценты). По оси абсцисс отложены размеры исходных файлов. Внимание: файлы не расположены по размеру. Данные упорядочены по общей степени сжатия.

Вначале по каждому инструменту отдельный график: выведены показатели для простой минимизации файлов, также для минимизации с последующим архивированием. Серым пунктиром показана степень сжатия (в процентах) файла при помощи простого gzip'а.

JSMin:

График сжатия JS-файлов с помощью JSMin/gzip

JavaScript::Minify:

График сжатия JS-файлов с помощью JavaScript::Minify/gzip

Dojo ShrinkSafe:

График сжатия JS-файлов с помощью Rhino/gzip

Dean Edwards Packer:

График сжатия JS-файлов с помощью Packer/gzip

YUI Compressor 2.2.5:

График сжатия JS-файлов с помощью YUI/gzip

Далее все инструменты на одном графике (без архивирования). Заметен явный выигрыш Packer'а без архивирования.

График сжатия JS-файлов

При архивировании, однако, все минимизаторы ведут себя примерно одинаково.

График сжатия JS-файлов

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

График сжатия JS-файлов относительно GZIP

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

Выводы

Во-первых, стоит указать на практически идентичное поведение JSMin и JavaScript::Minifier, скорее всего, они действуют по достаточно похожему алгоритму, однако, последний обладает скрытым потенциалом (при более подробном рассмотрении файлов, полученных вследствие работы второго, оказалось, что они могут быть уменьшены еще), но он работает в несколько раз дольше аналогов (3–5 секунд против 0,3–0,5 для Packer'а на PHP).

Во-вторых, файлы, которые меньше 1Кб или при архивировании дают выигрыш меньше 70%, смысла минимизировать не имеет. Минимизация дает в таком случае результат, сравнимый с нулем. Если с сервера отдаются небольшие (до 20Кб в несжатом виде) архивированные файлы (.gz), то имеет смысл по умолчанию их минимизировать с помощью JSMin.

В-третьих, если на сервере не поддерживается сжатие скриптов, то отдавать лучше версию, минимизированную с помощью Packer'а, в таком случае выигрыш довольно значительный (естественно, если размер файла больше 1Кб). Такая минимизация, в среднем, показала 50% преимущество относительно несжатого файла.

В-четвертых, во всех остальных случаях (сервер отдает достаточно большие gzip'ованные файлы, которые хорошо архивируются) стоит использовать YUI Compressor (в среднем, показал 6% преимущество относительно простого gzip).

Все полученные файлы можно также скачать единым архивом здесь (всего 12х12 = 144 файла).

В качестве послесловия

Хочется отметить, что при минимизации JS-файлов нужно следить за тем, чтобы функционал не уменьшился вследствие этой самой минимизации. Для проверки JS-файлов на работоспособность и общую адекватность существует проект JSLint, который, я так понимаю, сравнивает исходный файл с набором спецификаций по синтаксису и выдает сообщения об обнаруженных ошибках. Однако у общественности нет однозначного отношения к данному проекту, да и тема тестирования JS-приложений требует отдельного рассмотрения.

Читать дальше

Ссылки по теме

Все комментарии (habrahabr.ru)