Введение
Google Closure Compiler - уникальный инструмент, разработанный Google для сжатия и обфускации собственного javascript.
У него есть ряд интересных особенностей, которые отличают его от прочих упаковщиков.
Вместе с этим, инструмент это достаточно сложный. Основные его фичи скрываются в продвинутом режиме сжатия, для применения которого нужны соответствующие навыки и стиль программирования.
Google Closure Compiler написан на языке Java, причем так, что его достаточно просто расширить - конечно, если вам знакомы понятия компилятора, синтаксического дерева и понятен Java.
Официальная документация находится на http://code.google.com/intl/ru/closure/compiler/docs/overview.html.
На момент написания этой статьи, она, как и сам компилятор, еще в процессе разработки. Во всяком случае, такие слова я слышал от разработчиков компилятора, да и общее состояние текстов и кода на это похоже.
В этом введении мы разберем основные опции компилятора и осуществим компиляцию простых примеров.
Существует 3 способа запуска компилятора:
- Через веб-интерфейс. То есть, зайти на страничку, ввести или загрузить код и скомпилировать его с нужными опциями. Результат появится в текстовом поле.
Этот способ удобен, чтобы поиграться с оптимизациями, понять от чего чего бывает, не более.
Документация по этому способу: http://code.google.com/intl/ru/closure/compiler/docs/gettingstarted_ui.html.
- Через веб-сервис. Этот способ подразумевает отправку POST-запроса на адрес http://closure-compiler.appspot.com/compile. В параметрах запроса описаны флаги компиляции и передан код.
Ответом будет сжатый javascript, либо ошибки компиляции.
Этот способ удобен тем, что на веб-сервис google выкладывает, как правило, последнее стабильное API. Это убирает необходимость в хранении и обновлении компилятора.
Документация по этому способу находится на http://code.google.com/intl/ru/closure/compiler/docs/gettingstarted_ui.html.
- Через приложение. Google Closure Compiler является приложением, написанным на языке java, и распространяется как в виде jar-файла, так и в виде исходных кодов SVN: http://closure-compiler.googlecode.com/svn.
Этот способ - самый гибкий. Он не только не требует наличия интернет,
но и допускает использование собственной сборки компилятора, которая использует внутренние опции, недоступные для флагов.
Сделаем небольшое упражнение по сжатию javascript-файла при помощи приложения Google Closure Compiler.
Для него вам понадобится Java Runtime Environment версии 6.
Этот пример содержит основные шаги для сжатия с использованием Google Closure Compiler.
- Создайте директорию с названием
closure-compiler .
Скачайте файл компилятора compiler.jar и сохраните его в директории closure-compiler .
- Создайте javascript-файл
hello.js :
/* простая функция */
function hello(longName) {
alert('Hello, ' + longName);
}
hello('New User');
Сохраните его в директории closure-compiler .
-
Скомпилируйте javascript-файл. Для этого запустите из директории closure-compiler следующую команду:
java -jar compiler.jar --js hello.js --js_output_file hello-compiled.js
Она сгенерирует новый файл hello-compiled.js , который содержит следующий код:
function hello(a){alert("Hello, "+a)}hello("New User");
Заметьте, что компилятор удалил комментарии, пробелы и лишнюю точку с запятой. Кроме того, он заменил параметр longName на более короткое имя a . В результате получили намного меньший javascript-файл.
Чтобы убедиться, что получившийся файл работает корректно, подключите hello-compiled.js в HTML наподобие следующего:
<html>
<head><title>Hello World</title></head>
<body>
<script src="hello-compiled.js"></script>
</body>
</html>
Загрузите этот HTML-файл в браузер и вы должны увидеть дружеский привет!
Полный список флагов будет выведен при запуске:
java -jar compiler.jar --help
Он довольно длинный и, поначалу, большинство опций будут непонятны.
В этом разделе мы разберем самые основные опции сжатия, которые позволят сразу же делать основные операции по оптимизации javascript.
- --js
- Входной javascript-файл. Этот флаг может повторяться много раз с разными файлами:
--js script1.js --js script2.js ...
В результате получится объединенный сжатый файл.
Все флаги, которые допускают многократное использование, объявляются именно так. То есть, аргументы идут не через запятую, не через точку с запятой, а именно так: много раз один и тот же флаг.
- --js_output_file
- Имя файла для результата сжатия. По умолчанию: выводит в стандартный поток вывода.
- --check_types
- Включает проверку типов компилятором. По умолчанию - выключена. В любом случае, компилятор проверит синтаксическую правильность кода и выдаст ошибку в случае лишних скобок, незакрытых комментариев и т.п.
Более подробно о проверке типов вы можете прочитать в статье Объявление и проверка типов в примерах
- --compilation_level
- Уровень оптимизации, один из: WHITESPACE_ONLY, SIMPLE_OPTIMIZATIONS, ADVANCED_OPTIMIZATIONS. По умолчанию: SIMPLE_OPTIMIZATIONS.
Этот уровень подразумевает безопасные оптимизации и работает сходным образом с ShrinkSafe и YUI Compressor.
WHITESPACE_ONLY - простейший уровень для вырезания комментариев, пробелов и проверки кода на корректность.
Основные оптимизации раскрыты в статьях Оптимизации стандартного режима и Продвинутые оптимизации.
- --formatting
- Определяет форматирование выходного файла. Для печати сжатого файла в более-менее понятном виде, с форматированием и отступами, используйте значение
--formatting PRETTY_PRINT .
Чтобы ответить на этот вопрос, необходимо перечислить основные способы сжатия javascript. Их всего несколько:
- Удаление комментариев, лишних пробелов и прочего мусора через регулярные выражения.
Этот способ использовался в первых компрессорах, таких как JSMin и packer. Позволяет сжать код за счет очистки от заведомо лишних вещей.
- Архивация типа недо-gzip.
Из обычного файла можно сделать исполняемый самораспаковывающийся архив. Аналогично можно поступить с javascript. На этом основан известный упаковщик packer от Dean Edwards. При использовании этого способа код сжимается простеньким алгоритмом компрессии (сжатие со словарем), а то что получится - оборачивается в разархивирующий eval.
Получается такой недо-gzip. Вроде архивация, но слабая. Поэтому этот способ не рекомендуется использовать одновременно с реальным gzip: получится двойное сжатие слабым, а затем сильным алгоритмом. В результате - размер больший, чем просто gzip.
Кроме того, на браузер ложится дополнительная нагрузка по разархивации полученного javascript.
- Сжатие, основанное на структуре кода и сокращении символов.
Этот способ - самый последний. Его используют компрессоры ShrinkSafe, YUI Compressor и Google Closure Compiler.
При сжатии этим методом оптимизатор сначала читает javascript в синтаксическое дерево. Затем он проходит по полученному дереву, заменяет локальные переменные на более короткие и производит оптимизации. Потом по оптимизированному дереву оптимизатор генерирует код, уже с оптимизациями.
Этот способ заведомо превосходит и делает ненужным первый, т.к. знание о структуре кода, получаемое из синтаксического дерева - более правильное и полное, чем из регэкспов.
Google Closure Compiler, как и другие оптимизаторы последнего поколения, не использует регекспов и не производит архивацию (да, с этим прекрасно справляется серверный gzip).
В чем же отличия Google Closure Compiler от других аналогичных оптимизаторов, таких как ShrinkSafe и YUI Compressor?
Отличие кроется в подходе к оптимизации.
В то время как YUI Compressor использует локальные оптимизации, то Google Closure Compiler использует комплексный анализ кода.
Он выполняет гораздо больше оптимизаций, чем и обусловлен лучший результат.
Кроме того, у Google Closure Compiler есть продвинутые оптимизации, аналога которым в других оптимизаторах нет. Есть там и расширенная проверка типов и множество других интересных возможностей, за более подробным описанием которых вы можете обратиться к другим статьям этого раздела.
YUI Compressor работает безопаснее и стабильнее для некоторых видов синтаксических конструкций (eval/with/CC, см. подробнее в статье Оптимизации стандартного режима), но если понимать, что происходит, то и Google Closure Compiler может быть не менее безопасен.
На момент написания статьи, Google не опубликовала утилит для сжатия CSS, а вот YUI Compressor это умеет. Так что выбрасывать его пока рановато.
Но вот для сжатия javascript лучше Google Closure Compiler найти что-либо сложно. Во всяком случае, в открытом доступе
Для сборки компилятора подойдет практически любая ОС, т.к. используются только кросс-платформенные инструменты.
Чтобы собрать компилятор самостоятельно, его исходный код можно получить из SVN. Если у вас установлен стандартный SVN-клиент, то для этого подойдет команда:
svn co http://closure-compiler.googlecode.com/svn/trunk compiler
Последняя версия компилятора будет сохранена в директорию compiler .
Чтобы собрать компилятор, вам понадобится JDK версии 6 и установленный ANT.
Установка ANT довольно проста и описана в статье Installing Ant.
Для запуска достаточно запустить ant в директории с файлом сборки build.xml . После этого готовый к использованию jar-файл будет лежать в директории build .
Если после этого введения какие-то базовые вещи что-то осталось неясными - напишите в комментариях, отвечу. Спасибо.
|
Есть ли прога для компиляции js файлов, а то неудобно через командную строку
Не что не мешает написать bat'ник. Вот мой:
:: ищем js-сценарии в папке source
FOR /R %%i IN (source/*.js) DO (
:: скармливаем их компилятору
java -jar compiler.jar ^
--js source/%%~ni%%~xi ^
--js_output_file compiled/%%~ni-min.js ^
--compilation_level SIMPLE_OPTIMIZATIONS ^
--formatting PRETTY_PRINT
)
Результат сохраняется в папку compiled
Использую WebStorm
вызываем Настройки (ctrl+alt+s)
далее "File Watchers" справа жмем плюс и выбираем closure compiler
Нужно только указать путь до батника и минимум настроек (webStorm по дефолту знаком с Google Closure, sass, YuI - поэтому настраивать почти ничего не нужно)
Очень интересует, разумно ли его применять динамически, прямо на сервере? Раньше я использовал jsmin и минимизировал нагрузку на сервер с помощью кэширования на стороне сервера (если есть кэшированный файл с подходщим контентом, то отдаем его; если нет, генерируем динамически вывод, чистим jsmin'ом, сжимаем, отдаем и попутно создаем файл кэша) - такая тактика хорошо себя показала. Сразу поясню: такие извращения нужны для удобства разработки - в ручную жать 30-40 файлов тяжело.
30-40 файлов??? Что за фигня - если это на одну страницу - то клейте их не задумываясь. Если на разные, то кто Вам мешает написать sh или bat для автоматизации.
Т.е. для сжатия нужна установленная Java-машина, я правильно понимаю? Нет ли у них онлайн сервиса?
2 GreatRash:
On-line compiler:
http://closure-compiler.appspot.com/home
Описание (очень краткое):
http://code.google.com/intl/ru/closure/compiler/docs/gettingstarted_ui.h...
Также можно читать здесь: http://code.google.com/intl/ru/closure/compiler/
Можете мне, нубу в Java, пошагово объяснить, как собрать компилятор?
Я чекаутнул с помощью черепашки исходники, с указанного адреса.
Поставил ant
Запустил ant в контексте директории, в которой лежит build.bat - а он мне
Unable to locate tools.jar. Expected to find it in C:\Program Files\Java\jre7\li
b\tools.jar
Buildfile: c:\GCC\build.xml
rhino:
properties:
init:
compile:
compile-most:
BUILD FAILED
c:\GCC\build.xml:99: The following error occurred while executing this line:
c:\GCC\lib\rhino\build.xml:45: The following error occurred while executing this
line:
c:\GCC\lib\rhino\src\build.xml:38: Unable to find a javac compiler;
com.sun.tools.javac.Main is not on the classpath.
Perhaps JAVA_HOME does not point to the JDK.
It is currently set to "C:\Program Files\Java\jre7"
Total time: 0 seconds
Что я не так делаю?
Недостаточно иметь JRE, для компиляции надо скачать и установить JDK. Судя по сообщениям, у тебя только JRE установлен.
Вот у меня стоит задача удаления dead code из jscript при этом не переименовывать переменные, объекты, функции и т.п. Как можно его заставить сделать "простую оптимизацию", но без переименования? Заранее благодарен.
в точности с "Zenitchik", в Java, непонимаю ничего, с трудом перевариваю джи-ес, но вот то что ссылки битые, то видно всем, ведь инфа старая. Просьба, удалтите старые-битые ссылки! этот синий цвет очень глаза режет... А вообще заинтересовался данной серией статей о компиляторе так как столкнулся с подобным на лён-джи-ес.
Первый случай, когда documentFragment применим - это возврат множества узлов из функции. Можно это сделать возвращением массива, а можно вернуть documentFragment: run 3
Можете мне, нубу в Java, пошагово объяснить, как собрать компилятор?
Я чекаутнул с помощью черепашки исходники, с указанного адреса.
Поставил ant
Запустил ant в контексте директории, в которой лежит build.bat - а он мне
Unable to locate tools.jar. Expected to find it in C:\Program Files\Java\jre7\li
b\tools.jar super mario bros
Buildfile: c:\GCC\build.xml
rhino:
properties:
init:
compile:
compile-most:
BUILD FAILED
c:\GCC\build.xml:99: The following error occurred while executing this line:
c:\GCC\lib\rhino\build.xml:45: The following error occurred while executing this
line:
c:\GCC\lib\rhino\src\build.xml:38: Unable to find a javac compiler;
com.sun.tools.javac.Main is not on the classpath.
Perhaps JAVA_HOME does not point to the JDK.
It is currently set to "C:\Program Files\Java\jre7"
Total time: 0 seconds
Что я не так делаю?