Сравнение эффективности минимизаторов CSS- и JavaScript-кода (Сентябрь 2013)

f192bee7b3bef80c35dcb45f24bb448f

При подготовке данного сравнительного обзора были учтены следующие пожелания читателей:

  1. В предыдущем обзоре в качестве исходных файлов использовались: bootstrap.cssи bootstrap.js из Twitter Bootstrap 2.3.2, из-за чего достоверность результатов была низкой. В новом же обзоре размер выборки был увеличен: для сравнения были отобраны 7 JS-файлов и 5 CSS-файлов из 10 популярных Open Source-проектов.
  2. Теперь в сравнении минимизаторов CSS-кода также участвуют встроенные средства минимизации препроцессоров LESS и Sass.
  3. Как известно, Bundle Transformer минимизирует каждый файл по отдельности и затем производит объединение минимизированного кода в один файл. Данный механизм сделан для того, чтобы предотвратить повторную минимизацию предварительно минимизированных файлов. Другие аналогичные библиотеки сначала объединяют код файлов, а затем минимизируют этот объединенный файл. Поэтому для полноты картины мы произведем 2 сравнения: сначала сравним эффективность минимизаторов на файлах, полученных путем объединения минимизированного кода, а затем на файлах, полученных путем минимизации объединенного кода файлов.

Как и в предыдущем обзоре, для минимизации файлов мы будем использовать модули Bundle Transformer, а для измерения размеров полученных файлов – расширение YSlow.

Сравнение минимизаторов CSS-кода

Сравним следующие алгоритмы минимизации CSS-кода:

Таблица 1. Информация об адаптерах и алгоритмах минимизации CSS-кода

Адаптер Алгоритм минимизации Сайт исходной библиотеки
YuiCssMinifier YUI CSS Compressor for .Net 2.3.0.0 http://yuicompressor.codeplex.com
MicrosoftAjaxCssMinifier Microsoft Ajax CSS Minifier 4.97 http://ajaxmin.codeplex.com
KryzhanovskyCssMinifier CSSO 1.3.8 http://github.com/css/csso
WgCssMinifier WebGrease Semantic CSS Minifier 1.5.2 http://webgrease.codeplex.com
CleanCssMinifier Clean-css 1.1.1 http://github.com/GoalSmashers/clean-css
LessTranslator LESS 1.4.2 (режим сжатия соответствует настройкам исходной библиотеки с опцией compress равной true) http://lesscss.org
SassAndScssTranslator Sass 3.2.10 (режим сжатия соответствует настройкам исходной библиотеки с опцией :style равнойcompressed) http://sass-lang.com

Для того, чтобы использовать адаптеры-трансляторы LessTranslator иSassAndScssTranslator в качестве минимизаторов, нужно изменить расширения исходных CSS-файлов на .less (и .scss соответсвенно) и присвоить конфигурационному свойству useNativeMinification значение равное true.

В качестве исходных файлов мы будем использовать:

  1. bootstrap.css из Twitter Bootstrap 3.0.0
  2. jquery-ui-1.10.3.custom.css из jQuery UI 1.10.3
  3. animate.css из Animate.css от 15.08.2013
  4. hint.css из Hint.css 1.3.0
  5. zocial.css из Zocial CSS social buttons от 02.12.2012

Размер объединенного файла составляет 296,2 КБ, а после применения GZip-сжатия — 98,7 КБ.

Таблица 2. Результат применения алгоритмов CSS-минимизации к каждому файлу по отдельности

Адаптер Размер после минимизации, КБ Экономия Размер после минимизации с GZip-сжатием, КБ Экономия при GZip-сжатии
в КБ в % в КБ в %
YuiCssMinifier 239,7 56,5 19,07 79,9 18,8 19,05
MicrosoftAjaxCssMinifier 238,7 57,5 19,41 79,5 19,2 19,45
KryzhanovskyCssMinifier 234,1 62,1 20,97 78,0 20,7 20,97
WgCssMinifier
CleanCssMinifier 240,6 55,6 18,77 80,2 18,5 18,74
LessTranslator 240,0 56,2 18,97 80,0 18,7 18,95
SassAndScssTranslator 241,2 55,0 18,57 80,4 18,3 18,54

Таблица 3. Результат применения алгоритмов CSS-минимизации к объединенному файлу

Адаптер Размер после минимизации, КБ Экономия Размер после минимизации с GZip-сжатием, КБ Экономия при GZip-сжатии
в КБ в % в КБ в %
YuiCssMinifier 239,7 56,5 19,07 79,9 18,8 19,05
MicrosoftAjaxCssMinifier 238,7 57,5 19,41 79,5 19,2 19,45
KryzhanovskyCssMinifier 232,4 63,8 21,54 77,4 21,3 21,58
WgCssMinifier
CleanCssMinifier 240,6 55,6 18,77 80,2 18,5 18,74
LessTranslator 240,0 56,2 18,97 80,0 18,7 18,95
SassAndScssTranslator 241,2 55,0 18,57 80,4 18,3 18,54

4e8e0bf693f91f89e23703fe2f76cbf7

Рис. 1. Экономия за счет использования алгоритмов CSS-минимизации (в процентах)

Из графика хорошо видно, что, как и в прошлый раз, наилучший результат показал минимизатор CSSO (CSS Optimizer) от компании Яндекс. Но не обошлось и без ложки дегтя: дополнительный выигрыш в 0,57% при сжатии объединенного файла, был получен за счет удаления двух комментариев вида: /*! какой-нибудь текст */. Как правило, в таких комментариях содержится информация о версии библиотеки и ее разработчиках. CSSO оставляет лишь первый такой комментарий, а остальные удаляет (см. UPD2).

Microsoft Ajax CSS Minifier снова показал хороший результат по сравнению своим основным конкурентом — YUI CSS Compressor for .Net.

Больше всего меня удивил новичок — Clean-css от компании Goal Smashers!. От столь популярного в Node.js-сообществе CSS-минимизатора (Clean-css используется пакетом grunt-contrib-cssmin) я ожидал большей степени сжатия. По эффективности минимизации он расположился между встроенными минимизаторами препроцессоров LESS и Sass.

Новая версия структурного минимизатора от компании Microsoft — WebGrease Semantic CSS Minifier до сих пор содержит в себе критические ошибки:

  1. Не может обрабатывать директиву @charset и правило @-o-keyframes.
  2. Обнуляет дробные значения, которые меньше единицы.

Поэтому WebGrease Semantic CSS Minifier опять выбывает из борьбы.

Из графика практически не видно, что файлы, полученные путем минимизации файла с объединенным кодом (исключение составляет файл, обработанный с помощью CSSO), по размеру немного меньше файлов, собранных из отдельно минимизированных файлов. Меньший размер таких файлов объясняется двумя причинами:

  1. Были удалены лишние переводы строк, разделяющие код отдельных файлов.
  2. Несколько директив @charset были объединены в одну.

Поэтому можно сделать вывод: что минимизация файла с объединенным кодом практически не дает выигрыша в размере файла.

Сравнение минимизаторов JS-кода

Сравним следующие алгоритмы минимизации JS-кода:

Таблица 4. Информация об адаптерах и алгоритмах минимизации JS-кода

Адаптер Алгоритм минимизации Сайт исходной библиотеки
CrockfordJsMinifier JSMin от 29.03.2013 http://github.com/douglascrockford/JSMin
YuiJsMinifier YUI JS Compressor for .Net 2.3.0.0 http://yuicompressor.codeplex.com
ClosureLocalJsMinifier Closure Compiler Application от 26.08.2013 (режим Simple) http://developers.google.com/closure/compiler/docs/gettingstarted_app
MicrosoftAjaxJsMinifier Microsoft Ajax JS Minifier 4.97 http://ajaxmin.codeplex.com
UglifyJsMinifier UglifyJS 2.4.0 http://github.com/mishoo/UglifyJS2

Если вы уже заметили, то в приведенном выше списке отсутствует адаптер-минимизаторEdwardsJsMinifier. Поскольку поддерживаемый им алгоритм минимизации Packer 3.0 не менялся с 2007 года, то я решил не включать его в данный обзор.

В качестве исходных файлов мы будем использовать:

  1. bootstrap.js из Twitter Bootstrap 3.0.0
  2. jquery-ui-1.10.3.custom.js из jQuery UI 1.10.3
  3. MicrosoftAjax.debug.js из Microsoft AJAX Framework 4.0.0.0
  4. knockout-2.3.0.debug.js из Knockout 2.3.0
  5. jsrender.js из JsRender 1.0.0-beta
  6. linq.js из LINQ for JavaScript 2.2.0.2
  7. moment.js из Moment.js 2.1.0

Размер объединенного файла составляет 1218,9 КБ, а после применения GZip-сжатия — 406,3 КБ.

Таблица 5. Результат применения алгоритмов JS-минимизации к каждому файлу по отдельности

Адаптер Размер после минимизации, КБ Экономия Размер после минимизации с GZip-сжатием, КБ Экономия при GZip-сжатии
в КБ в % в КБ в %
CrockfordJsMinifier 713,5 505,4 41,46 237,8 168,5 41,47
YuiJsMinifier 593,0 625,9 51,35 197,6 208,7 51,37
ClosureLocalJsMinifier 525,4 693,5 56,90 175,1 231,2 56,90
MicrosoftAjaxJsMinifier 527,7 691,2 56,71 175,9 230,4 56,71
UglifyJsMinifier 531,1 687,8 56,43 177,0 229,3 56,44

Таблица 6. Результат применения алгоритмов JS-минимизации к объединенному файлу

Адаптер Размер после минимизации, КБ Экономия Размер после минимизации с GZip-сжатием, КБ Экономия при GZip-сжатии
в КБ в % в КБ в %
CrockfordJsMinifier 713,4 505,5 41,47 237,8 168,5 41,47
YuiJsMinifier 593,0 625,9 51,35 197,6 208,7 51,37
ClosureLocalJsMinifier 525,3 693,6 56,90 175,1 231,2 56,90
MicrosoftAjaxJsMinifier 527,7 691,2 56,71 175,9 230,4 56,71
UglifyJsMinifier 533,1 685,8 56,26 177,7 228,6 56,26

2522125fab9147210b715bb39ad0190a

Рис. 2. Экономия за счет использования алгоритмов JS-минимизации (в процентах)

Из приведенных выше данных видно, что минимизатор Closure Compiler от компании Google по-прежнему на первом месте.

Microsoft Ajax JS Minifier на этот раз обогнал UglifyJS и по праву занял второе место.

Вообще, UglifyJS меня очень сильно удивил тем, что при минимизации файла с объединенным кодом размер результирующего файла не только не уменьшился, а наоборот увеличился. Что говорит о некоторых недоработках в алгоритме.

YUI JS Compressor for .Net сильно отстал от первой тройки минимизаторов, что свидетельствует об устаревании его алгоритма.

Несмотря на то, что JSMin до сих развивается, принципы, заложенные в нем, остались прежними: никакого вмешательства в логику скрипта, только удаление комментариев и пробельных символов. Поэтому в данном обзоре JSMin является даже не участником, а выполняет роль нижней границы.

Также как и в случае с CSS-минимизаторами мы получили совсем незначительный выигрыш от минимизации файла с объединенным кодом.

Заключение

Как и в прошлый раз, битву минимизаторов выиграли поисковые гиганты — Яндекс и Google. Приятно сознавать, что лучший CSS-минимизатор был создан в российской компании.

Несмотря на серьезные проблемы с минимизатором WebGrease Semantic CSS Minifier, компания Microsoft добилась серьезных успехов при разработке семейства минимизаторов Microsoft Ajax Minifier.

Все исходные и минимизированные файлы доступны по адресу —https://www.dropbox.com/s/k232cloh87sn9pr/css-and-js-minifiers-sep-2013-files.zip.

UPD1: Переделал графики на отображение процентов.

UPD2: По поводу «ложки дегтя» в CSSO был получен комментарий от Сергея Крыжановского (разработчика CSSO). На самом деле это не недоработка, а просто особенность структурной минимизации: при изменении структуры таблицы стилей такие комментарии могут отделиться от кода, к которому они относятся, и просто «повиснуть» в таблице стилей. Поэтому и сохраняется только первый комментарий. Здесь ситуация похожа на аналогичную ситуацию с Closure Compiler, который при структурной минимизации JS-кода удаляет вообще все комментарии.

UPD3: Попробовал провести тесты с CSS-минимизатором Closure Stylesheets. Сначала протестировал последнюю доступную версию бинарника — closure-stylesheets-20111230.jar и получил ошибку при минимизации файла bootstrap.css. Потом собрал из исходников самую последнюю версию (коммит 86bb800d79a3) и опять получил ошибку при минимизации файла bootstrap.css:

Compiler parsing error: Parse error in C:\!closure-stylesheets\bootstrap.css at line 1658 column 19:
  margin-top: 1px \9;
                  ^

com.google.common.css.compiler.ast.GssParserException: Parse error in C:\!closure-stylesheets\bootstrap.css at line 1658 column 19:
  margin-top: 1px \9;
                  ^

        at com.google.common.css.compiler.ast.GssParserCC.parse(GssParserCC.java:176)
        at com.google.common.css.compiler.ast.GssParser.parse(GssParser.java:46)

        at com.google.common.css.compiler.commandline.DefaultCommandLineCompiler.parseAndPrint(DefaultCommandLineCompiler.java:104)
        at com.google.common.css.compiler.commandline.DefaultCommandLineCompiler.compile(DefaultCommandLineCompiler.java:94)
        at com.google.common.css.compiler.commandline.DefaultCommandLineCompiler.execute(DefaultCommandLineCompiler.java:129)
        at com.google.common.css.compiler.commandline.ClosureCommandLineCompiler.executeJob(ClosureCommandLineCompiler.java:290)
        at com.google.common.css.compiler.commandline.ClosureCommandLineCompiler.main(ClosureCommandLineCompiler.java:356)
Caused by: com.google.common.css.compiler.ast.ParseException: Encountered " <BAD_TOKEN> "\\ "" at line 1658, column 19.
Was expecting one of:
    ";" ...
    "/" ...
    "=" ...
    "}" ...
    "," ...
    <S> ...
    <IMPORTANT_SYM> ...
    <ATKEYWORD> ...

        at com.google.common.css.compiler.ast.GssParserCC.generateParseException(GssParserCC.java:3756)
        at com.google.common.css.compiler.ast.GssParserCC.jj_consume_token(GssParserCC.java:3635)
        at com.google.common.css.compiler.ast.GssParserCC.ruleSet(GssParserCC.java:464)
        at com.google.common.css.compiler.ast.GssParserCC.block(GssParserCC.java:2856)
        at com.google.common.css.compiler.ast.GssParserCC.start(GssParserCC.java:2903)
        at com.google.common.css.compiler.ast.GssParserCC.parse(GssParserCC.java:174)
        ... 6 more

 

Кроме того, попытался также минимизировать jquery-ui-1.10.3.custom.css иanimate.css, и снова получил ошибки.

Поэтому Closure Stylesheets, также как и WebGrease Semantic CSS Minifier, не может участвовать сравнительных тестах данного обзора.

Ccылка на архив с исходными и минимизированными файлами —https://www.dropbox.com/s/k232cloh87sn9pr/css-and-js-minifiers-sep-2013-files.zip.