Задача
Некоторые Javascript-файлы имеют излишне большой размер. Они содержат много комментариев и других символов, которые совсем не нужны для правильной работы скрипта. Нужно удалить все лишнее из js-файлов.
Решение
Минимизация скрипта — это удаление из кода всех несущественных символов с целью уменьшения объема файла скрипта и ускорения его загрузки. В минимизированном коде удаляются все комментарии и незначащие пробелы, переносы строк, символы табуляции. В случае с Javascript, это уменьшает время загрузки страницы, т.к. размер файла уменьшается. Две самых популярных утилиты для минимизации javascript — JSMin и YUI Compressor.
Обфускация является альтернативным способом сокращения исходного кода. Также, как минимизация, она удаляет пробельные символы и вырезает комментарии, но в дополнение она измененяет сам код. К примеру, во время обфускации имена функций и переменных заменяются на более короткие, что делает код более компактным, но менее читабельным. Обычно этот прием используется для усложнения реверс-инжиниринга программы. Но обфускация помогает также уменьшить код настолько, насколько это не получится сделать одной минимизацией. С выбором средства для обфускации javascript не все так ясно, но я думаю, что самая распространенная утилита для этого — Dojo Compressor (ShrinkSafe).
Минимизация javascript — безопасный и довольно простой процесс. С другой стороны, обфускация из-за своей сложности может вносить в код баги. Обфускация также требует правки вашего кода для выделения в нем API-функций и других элементов. которые не должны быть изменены. Это также делает более сложной отладку в продакшне. Я никогда не видел, чтобы минимизация кода создавала в нем баги, но вот при обфускации такое случалось. Среди первой десятки американский сайтов при минимизации в среднем достигалось 21% сжатие, тогда как при обфускации — 25%. И хотя обфускация позволяет добиться большего сжатия, я все же рекомендую применять минимизацию кода, так как она не добавит в ваш код ошибок и полученный скрипт проще будет отлаживать.
Варианты решений
- JSMin (http://javascript.crockford.com/jsmin.html)
- Dojo ShrinkSafe (http://dojotoolkit.org/docs/shrinksafe)
- Online ShrinkSafe (http://shrinksafe.dojotoolkit.org/)
- YUI Compressor (http://developer.yahoo.com/yui/compressor/)
- Packer (http://dean.edwards.name/download/#packer)
- Online Packer (http://dean.edwards.name/packer/)
JSMin
JSMin - это маленькая консольная утилита (33 Кб), которая получает на вход код JavaScript, а на выходе выдаёт код JavaScript с удаленными комментариями и переносами строк.
Код остаётся работоспособен и не принимает вид одной строки - я так думаю, потому, что в JavaScript концом оператора может считаться как точка с запятой, так и конец строки, а в последнем случае слепить две строки означает нарушить работоспособность программы.
В среднем файл сжимается на 40-50%.
Доступные кодировки: ASCII и UTF-8.
Использование JSMin
Внимательный читатель, думаю, заметил, что “получает на вход код JavaScript” - сие означает, что надо передать параметром не имя файла, а его текст.
Такой командой мы передаём этому скрипту текст входного файла, и указываем, куда сложить вывод:
Можно “жать” все файлы с Си-подобным синтаксисом: не только JavaScript и Си, но и РНР, и даже CSS.
Dojo ShrinkSafe
К сожалению, подавляющее большинство этих скриптов либо не слишком эффективны, либо в определенных случаях разрушают код (а иногда - и то и другое вместе). Без подробного грамматического разбора упаковщику трудно отличить комментарий от похожей конструкции, размещенной в закавыченной строке. Кроме того, с помощью регулярных выражений не так-то просто оценить, какая из переменных имеет ограниченный контекст, так что некоторые техники сокращения имен переменных могут разрушить сам код.
Этих проблем можно избежать, сжимая код с помощью Dojo Compressor (alex.dojotoolkit.org/shrinksafe), использующий Rhino (мозилловский JavaScript-движок, написанный на Java) для построения дерева, которое оптимизируется перед работой с файлами. С работой Dojo Compressor справляется неплохо, ресурсов отнимает немного. Расширив наш процесс сборки билда с помощью этого инструмента, мы можем забыть об экономии, писать пространные комментарии, вставлять сколько угодно пробелов и т. д. На рабочем коде это нисколько не отразится.
- Страница проекта Dojo ShrinkSafe
- Скачать Dojo ShrinkSafe
- Есть поддержка Юникода
- Требуется java для работы
Пример сжатия
Исходный код:
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
Команда сжатия:
Минимизированная версия кода:
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, Packer и Online Packer можно узнать в полной версии статьи Минимизация и обфускация Javascript.
Вывод
Быстрое решение
Если вам нужно сжать 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
Продолжение статьи Минимизация и обфускация Javascript на Drupal CookBook.ru
Комментарии
спасибо за статью.
одно важное замечание: когда указываете названия проектов или утилит, давайте ссылку на оригинал (хомяк) этого проекта/утилиты.
beerman, спасибо за замечание. Я как-то даже не подумал, что это может сбивать с толку...
Я так понял, что речь идёт о ссылка в разделе "Варианты". Правильно?
Идея была в том, чтобы сделать оглавление разделов статьи (как, например, в Википедии), чтобы улучшить навигацию. Когда статья маленькая, что это не имеет значения, а для большой это уже необходимость.
Википедия автоматом создает оглавление, если больше чем 3 раздела есть в статье...
Ок. Ладно. Как можно это исправить/улучшить/изменить?
В разделе "Варианты" я в скобках буду давать URL проекта, чтобы можно было сразу перейти туда. Да. Это хорошая мысль.
Спасибо.
PS
Может быть модуль стоит написать для автоматических оглавлений?!...
чутка неверно, обфускация придумана не для уменьшения кода а для кодирования
http://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%84%D1%83%D1%81%D0%BA%D0%B0%...
если надо сжать js
Сжать можно до такой степени, что прочитать очень сложно.
Самый простенький пример html компрессор. маленькая утилитка. 56% это мало.
спасибо, полезно
Цитата из той же Википедии:
Цели обфускации
Обратите внимание на п.2!
Википедию пишут простые люди...
Я бы добавил еще
4. Нарушение авторских прав программистов и его скрытие.
То, что Википедию пишут простые люди, не значит, что они не правы или ошибаются.
А по поводу нарушения авторских прав - похоже, что вы правы. Этот момент я совершенно упустил из виду.
Ок. По GPL нужно оставить информацию об авторе - значит нужно так и сделать, а номера версий и прочие комментарии можно вычистить.
эммм.... вообще то ребята из nowpublic.com сделали какие то плагины для друпал 5 в эту сторону.
и они выложены на drupal.org
Поискал у них на сайте и не нашёл. Ilya1st, можно прямую ссылочку?
http://drupal.org/project/sf_cache - оно.
Уважаемый Влад, не путайте яйца с яйчницой. обфускация в первую очередь это кодирование, а уменьшение кода может являться побочным эффектом, и то не всегда. Обфускация была придумана для увеличения хоть какой то стойкости прикладных (написанных не скриптовым языком) программ от взлома деассемблерами.Первый вроде память не изменяет-где была применена этакая функция это asp. Посмотрите как это работает. А вот zend guard - разрабатывался для php как акселератор, преобразующий скрипт в псевдо байт код-заявленное зендом ускорение примерно 20%, реально меньше. Побочный эффект-уменьшение размера файла и кодирование. Но так как кодирование побочный эффект- то взлом достаточно простой.
Добавлю простой пример обфускации--
$var=$abcdf + $bcdr; --исходник
$var=$ab_f +$bc_r --итог
Здравствуйте. Сначала кратко: вот ссылка где можно взять стабильный компрессор:
http://www.russkiy-rim.ru/public/soft/jscompressor.html
Теперь подробнее: Нужно было сжать один .js файл. Стал я пользоваться всеми этими онлайн-компрессорами, котоых так много в сети. Нашел даже один платный!! И во всех них нашел какие-то баги. Вот пример кода, который сжимается неправильно простым компрессором
if(boolean)var varname=smth
else if (boolean) ..
Короче не понравилось мне это и я написал свой собственный компрессор. В нем удалось избежать многих проблем. Единственное, прога будет портить код при регулярных выражениях вида /a = b/g (ну без кавычек). Но все же более стабильная чем большинство онлайн-компрессоров. Не удивляйтесь - сайт, на котором лежит дистрибутив посвящен наружной рекламе
Друзья, смею обрадовать вас. Теперь по той же ссылке доступна новая версия - которая ко всему прочему сжимает локальные переменные и не портит регулярные выражения, записанные без кавычек.
Я тестировал программу на довольно больших кусках кода. Но вот маленький примерчик, с которым она легко справляется:
function test() {
var varOut/*a*/ = "opa";
function testIn(param) {
var str = varOut+"2, param: "+param;
return str.replace(/ p/i, '');
}
alert(testIn("!"));
}
Если кто-то пришлет мне код, на котором моя программа спотыкается - буду очень благодарен.