Минимизация и обфускация Javascript

05 Сен 2008
Опубликовано VladSavitsky

Решение

Минимизация скрипта — это удаление из кода всех несущественных символов с целью уменьшения объема файла скрипта и ускорения его загрузки. В минимизированном коде удаляются все комментарии и незначащие пробелы, переносы строк, символы табуляции. В случае с Javascript, это уменьшает время загрузки страницы, т.к. размер файла уменьшается. Две самых популярных утилиты для минимизации javascript — JSMin и YUI Compressor.

Обфускация является альтернативным способом сокращения исходного кода. Также, как минимизация, она удаляет пробельные символы и вырезает комментарии, но в дополнение она измененяет сам код. К примеру, во время обфускации имена функций и переменных заменяются на более короткие, что делает код более компактным, но менее читабельным. Обычно этот прием используется для усложнения реверс-инжиниринга программы. Но обфускация помогает также уменьшить код настолько, насколько это не получится сделать одной минимизацией. С выбором средства для обфускации javascript не все так ясно, но я думаю, что самая распространенная утилита для этого — Dojo Compressor (ShrinkSafe).

Минимизация javascript — безопасный и довольно простой процесс. С другой стороны, обфускация из-за своей сложности может вносить в код баги. Обфускация также требует правки вашего кода для выделения в нем API-функций и других элементов. которые не должны быть изменены. Это также делает более сложной отладку в продакшне. Я никогда не видел, чтобы минимизация кода создавала в нем баги, но вот при обфускации такое случалось. Среди первой десятки американский сайтов при минимизации в среднем достигалось 21% сжатие, тогда как при обфускации — 25%. И хотя обфускация позволяет добиться большего сжатия, я все же рекомендую применять минимизацию кода, так как она не добавит в ваш код ошибок и полученный скрипт проще будет отлаживать.

Варианты решений

JSMin

JSMin - это маленькая консольная утилита (33 Кб), которая получает на вход код JavaScript, а на выходе выдаёт код JavaScript с удаленными комментариями и переносами строк.
Код остаётся работоспособен и не принимает вид одной строки - я так думаю, потому, что в JavaScript концом оператора может считаться как точка с запятой, так и конец строки, а в последнем случае слепить две строки означает нарушить работоспособность программы.

В среднем файл сжимается на 40-50%.
Доступные кодировки: ASCII и UTF-8.

Использование JSMin

Внимательный читатель, думаю, заметил, что “получает на вход код JavaScript” - сие означает, что надо передать параметром не имя файла, а его текст.

Такой командой мы передаём этому скрипту текст входного файла, и указываем, куда сложить вывод:

jsmin.exe < in.js > out.js

Можно “жать” все файлы с Си-подобным синтаксисом: не только JavaScript и Си, но и РНР, и даже CSS.

Dojo ShrinkSafe

Страница проекта Dojo ShrinkSafe

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

Этих проблем можно избежать, сжимая код с помощью Dojo Compressor (alex.dojotoolkit.org/shrinksafe), использующий Rhino (мозилловский JavaScript-движок, написанный на Java) для построения дерева, которое оптимизируется перед работой с файлами. С работой Dojo Compressor справляется неплохо, ресурсов отнимает немного. Расширив наш процесс сборки билда с помощью этого инструмента, мы можем забыть об экономии, писать пространные комментарии, вставлять сколько угодно пробелов и т. д. На рабочем коде это нисколько не отразится.

Пример сжатия

Исходный код:

function MyClass(){
    this.foo = function(argument1, argument2){
        var addedArgs = parseInt(argument1)+parseInt(argument2);
        return addedArgs;
    }
    var anonymousInnerFunction = function(){
        // do stuff here!
    }
}
function MyFunc(){
    // this is a top-level function
}
// we've got multiple lines of whitespace here

Команда сжатия:

java -jar custom_rhino.jar -c infile.js > outfile.js 2>&1

Минимизированная версия кода:

function MyClass(){
this.foo=function(_1,_2){
var _3=parseInt(_1)+parseInt(_2);
return _3;
};
var _4=function(){
};
}
function MyFunc(){
}

Исходный код занимал 321 байт, а минимизированный - 140 байт. Уменьшение - 56%.

Online ShrinkSafe

Онлайн обфускация: http://shrinksafe.dojotoolkit.org/
Отличие от Online Packer в том, что JS-файл загружается на сервер, а не вставляется в форму и обрабатывается средствами JavaScript.

YUI Compressor

Страница проекта: Yahoo! UI Library: YUI Compressor
Использует парсер javascript, который написан на языке java и называется Rhino.
Патченный Rhino сжимает за счет двух основных операций:

  • убирает лишние пробельные символы и комментарии
  • заменяет имена локальных переменных на более короткие

YUI Compressor также может сжимать CSS.

Требования

  • Установленная Java
  • Желательно, чтобы исполняемый файл java был на текущем пути (PATH)

Использование YUI Compressor

  • Скачать YUI Compressor с сайта разработчика (~900Кб)
  • Распаковать
  • Работа с YUI Compressor происходит в режиме командной строки. Перейти в директорию, где находится yuicompressor-x.y.z.jar, то есть в build
  • Скопировать файл, который нужно сжать в папку, где находится yuicompressor-x.y.z.jar
  • Выбрать команду:
    • Сжать без обфускации
    • Сжать c обфускацией

Сжать c обфускацией

java -jar yuicompressor-x.y.z.jar myfile.js -o myfile-min.js

Сжать без обфускации

java -jar yuicompressor-x.y.z.jar --type js --nomunge --preserve-semi --disable-optimizations -o имя_сжатого_файла.js имя_сжимаемого_файла.js

--type js
Опция указывает на тип сжимаемого файла. Может принимать значение js или css.

--nomunge
Означает только уменьшение JavaScript’а. Обфускация (obfuscate), т.е. перекодировка функций с целью нечитабельности кода не происходит.

--preserve-semi
Указывает на сохранение ненужных ";". Нам нужно, чтобы код максимально соответствовал оригиналу.

--disable-optimizations
Отключить оптимизацию кода. Опять же: нам нужно максимальное соответствие оригиналу.

-o имя_сжатого_файла.js
Здесь нужно указать название файла, который получится после сжатия.

Если русские символы криво сжимаются - используйте опцию "charset".

Дополнительные опции

Есть ряд полезных опций, о которых Вы узнаете, запустив:

java -jar yuicompressor-x.y.z.jar -h

Packer

Страница проекта: http://dean.edwards.name/download/#packer
Рекомендуют использовать для обфускации javascript, но не для сжатия.

Утилита Packer доступна на нескольких языках программирования

Packer имеет смысл использовать для сжатии javascript в двух случаях:

  1. Вы не хотите использовать gzip-компрессию, например, чтобы избежать глюков старых браузеров при распаковке javascript
  2. Вы хотите обфусцировать код, сделать его непонятным

Принцип работы утилиты Packer

Packer делает следующее:

  1. Сжимает javascript регулярными выражениями
  2. Использует алгоритм архивации со словарем

Например, напустим PHP-версию на скрипт:

function somefunc() {
    var test = 5
    var myTest = 7
 
    /* go go go!!! */
    go(myTest)
}

Результат сжатия (все в одну строку):

eval(function(p,a,c,k,e,d){e=function(c){return c};if(!''.replace(/^/,String)){while(c--){d[c]=k[c]||c}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('3 6(){1 2=5 1 0=7 4(0)}',8,8,'myTest|var|test|function|go||somefunc|'.split('|'),0,{}))

При загрузке javascript распаковывается автоматически запуском eval.

Совместная работа Packer и gzip

Packer использует сжатие, родственное zip, gzip, но хуже.

Если Вы уже используете gzip-компрессию javascript, то архивация Packer+gzip наоборот увеличит размер скрипта, по сравнению с простым gzip.

Нагрузка на процессор клиента

При сжатии большого скрипта eval тоже будет очень большой. Распаковка создаст серьезную нагрузку на процессор. Это будет особенно ощутимо на старых CPU.

Online Packer

Это реализация Packer на javascript.
На странице Online Packer нужно вставить JS-код в форму и получить в другом поле обработанный код, который можно скопировать и вставить в файл.

Вывод

Быстрое решение
Если вам нужно сжать 1-2 файла, то самым быстрым и простым вариантом будет использовать онлайн-утилиты. Лучшая из которых - Online ShrinkSafe.

Использование Java и командной строки
2 скрипта написаны на Java: YUI Compressor и Dojo ShrinkSafe. Оба решения являются достойными. Dojo ShrinkSafe выделяет то, что используется Rhino (мозилловский JavaScript-движок, написанный на Java) для построения дерева, которое оптимизируется перед работой с файлами.

Использование с собственном скрипте
Если нужно использовать упаковку с своем коде, то можно использовать JSMin и Packer, которые реализованы на нескольких языках программирования.

Реализации JSMin:

  • скопилированный MS-DOS.exe файл
  • исходный код на C (можете сами компилировать)
  • исходный код на C#
  • исходный код на Java
  • исходный код на JavaScript
  • исходный код на Perl
  • исходный код на PHP
  • исходный код на Python
  • исходный код на OCAML
  • исходный код на Ruby

Полезные рецепты по этой теме

Использованные материалы

Полезные ссылки

Комментарии

отличный материал...
вот еще штучка для удобства:
---------------
- в TC (Total Commander), на панели инструментов добавить кнопку
- Можно просто "перекинуть" туда "yuicompressor-х.х.х.jar"
- Нажать ПКМ (правой кнопкой мышки) на созданной кнопке "Изменить"
- В поле параметры вписать: ?%P%N -o %P%O-min.%E
- если не требуется чтобы появлялось окно при нажатии на кнопку (для проверки), уберите знак вопроса...
---------------
использование:
- перейдите к вашему (*.js) файлу
- и нажмите на кнопку в TC
следите за тем чтобы не было файла с именем *-min.js. А то мало-ли что ;-)

F^[a].t | Окт 21st, 2009 в 5:15 после полудня
 
 
 

RSS-лента новостей

Dries Buytaert по-русски
]]>Русский поиск Drupal]]>

Перенос сайта из Joomla в Drupal
Перенос сайта из WordPress в Drupal

]]> Drupal - это бесплатная система управления контентом с открытым исходным кодом ]]>