Минимизация Javascript кода и CSS с помощью Microsoft Ajax Minifier

    Скачивание объёмных ресурсов, связанных с веб-страницей, таких как JavaScript файлы и CSS, влияет не только на скорость загрузки страницы, но и увеличивает трафик, проходящий от сервера к клиентскому браузеру. Последнее обстоятельство особенно важно в подключениях с ограниченным тарифом или при размещении сайта на хостинге с заранее оговоренным объёмом исходящих данных.

    Один из способов борьбы с лишними байтами – сжатие данных на сервере и передача gzip'ированного потока браузеру, который уже распаковывает его во время отрисовки страницы. Обсуждение данного способа не входит в данную статью. Я бы хотел рассказать о способе уменьшения данных с помощью удаления всех незначащих символов из сопутствующих веб-странице файлов: JavaScript и CSS – минимизации.

    При написании клиентских функций и стилей сайта программист/дизайнер использует отбивку строк пробелами или табами для улучшения читабельности текста и простоты сопровождения. Удобнее отловить ошибку, возникшую в середине 100-а строчного файла, когда код структурирован и отформатирован привычным для данного языка способом. Правила CSS и функции JavaScript будут работать точно так же, разместим мы их все в одну строку или, поместив каждое правило на отдельной строке.

    Данные изыски читабельности являются просто лишними, когда сайт выходит на просторы Интернета. С другой стороны, при наличии нескольких файлов, требующих минимизации, процесс трансформации удобочитабельных файлов в минимизированный формат — дело не из лёгких и требует автоматизации.

    16-го февраля 2010-го Microsoft выпустили четвёртую версию своей утилиты под названием Microsoft Ajax Minifier, задача которой упростить и автоматизировать трансформацию читабельных файлов JavaScript и CSS – в минимизированный формат. Эта утилита может применяться как из командной строки или из собственной программы на языке .NET (не входит в данную статью), так и с помощью системы MSBuild при разработке в Microsoft Visual Studio (я работаю с VS 2008).

    После установки пакета Microsoft Ajax Minifier появляется возможность добавить задачу для MSBuild'а в проекты, созданные на основе встроенных веб-проектов, например ASP.NET Web Application. Сайты, добавленные в студию как Web site – не подходят, так как не обладают .proj файлом, в котором устанавливаются задачи MSBuild'а.
    1. Выбрать пункт Unload Project в контекстном меню проекта сайта.
    2. В контекстном меню уже отгруженного проекта выбрать Edit project name; Visual Studio отобразит файл *.proj для редактирования.
    3. Прописать следующий код внутри тега <Project>:
      1. <Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks"/>
      2. <Target Name="AfterBuild">
      3.     <ItemGroup>
      4.         <JS Include="**\*.js" Exclude="**\*.min.js;Scripts\*.js"/>
      5.     </ItemGroup>
      6.     <ItemGroup>
      7.         <CSS Include="**\*.css" Exclude="**\*.min.css"/>
      8.     </ItemGroup>
      9.     <AjaxMin
      10.         JsSourceFiles="@(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js"
      11.         CssSourceFiles="@(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".min.css"/>
      12. </Target>
      * This source code was highlighted with Source Code Highlighter.

    4. Пункт контекстного меню данного проекта Reload Project – возвратит сайт в лоно Visual Studio и, теперь, можно сделать Build (или Rebuild) для проверки работоспособности.
    5. Важно заставить студию отображать файлы, не включённые в проект (меню Project, Show All Files).
    6. Также важно нажать на Refresh после компиляции проекта, иначе студия не покажет минимизированные файлы, добавленные задачей MSBuild'а.
    7. Если нигде не закралась ошибка – минимизированные файлы будут отображены в файловой структуре проекта как не принадлежащие данному проекту. Выбор включать ли их проект – за вами. Поскольку я просто копирую файлы с компьютера разработчика на FTP – сгенерированные файлы у меня в проект не включены.


    Для тех, кто не знаком с языком MSBuild'а – краткое пояснение п. 3:
    1. Для включения новых задач, установленных вместе с Microsoft Ajax Minifier
      <Import Project="$(MSBuildExtensionsPath)\Microsoft\MicrosoftAjax\ajaxmin.tasks"/>

      * This source code was highlighted with Source Code Highlighter.

    2. Объявление задания, запускаемого после успешного компилирования проекта
      <Target Name="AfterBuild">

      * This source code was highlighted with Source Code Highlighter.

    3. Декларирование групп файлов, над которыми мы хотим произвести трансформацию – минимизировав их. Теги <JS> и <CSS> – название групп файлов. Эти названия определяются вами, можно написать <JS> или <JSFiles>, или, даже, <MinimizeThis>. В данном случае мы хотим минимизировать все файлы с окончанием .js и .css в проекте, кроме тех которые заканчиваются на .min.js или .min.css, или находятся в папке Scripts.
      1. <ItemGroup>
      2.   <JS Include="**\*.js" Exclude="**\*.min.js;Scripts\*.js"/>
      3. </ItemGroup>
      4. <ItemGroup>
      5.   <CSS Include="**\*.css" Exclude="**\*.min.css"/>
      6. </ItemGroup>
      * This source code was highlighted with Source Code Highlighter.

    4. Запускаем задание на минимизацию. Группы JavaScript и CSS файлов для минимизации обозначается именами, указанными в предыдущих строках (<JS> и <CSS>). Файлы, подлежащие минимизации, и расширение для ново-утрамбованных файлов указанны в атрибутах JsSourceExtensionPattern, CssSourceExtensionPattern и JsTargetExtension, CssTargetExtension, соответственно.
      <AjaxMin JsSourceFiles="@(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js" CssSourceFiles="@(CSS)" CssSourceExtensionPattern="\.css$" CssTargetExtension=".min.css"/>

      * This source code was highlighted with Source Code Highlighter.



    Задача имеет ряд дополнительных параметров:
    1. JsCollapseToLiteral="true|false"

      * This source code was highlighted with Source Code Highlighter.

      Переводит new Object() в {}, new Array() в [].
    2. JsCombineDuplicateLiterals="true|false"

      * This source code was highlighted with Source Code Highlighter.

      Подставляет локальную переменную вместо повторяющихся строковых или цифровых значений в коде.
    3. JsEvalTreatment="MakeAllSafe|Ignore|MakeImmediateSafe"

      * This source code was highlighted with Source Code Highlighter.

      Указывает, возможно, ли применить методику переименования функций и локальных переменных в коде, использующем eval. Следует избегать данной установки, когда природа кода в eval не ясна или может измениться.
    4. JsIndentSize="number"

      * This source code was highlighted with Source Code Highlighter.

      Когда JsOutputMode=«MultipleLines», указывает количество пробелов для отбивки вложенных конструкций.
    5. JsInlineSafeStrings="true|false"

      * This source code was highlighted with Source Code Highlighter.

    6. JsLocalRenaming="CrunchAll|KeepAll|KeepLocalizationVars"

      * This source code was highlighted with Source Code Highlighter.

      Степень применения методики переименования локальных переменных и функций. Когда JsLocalRenaming=«KeepLocalizationVars», переменные, начинающиеся с L_, не будут переименованы.
    7. JsMacSafariQuirks="true|false"

      * This source code was highlighted with Source Code Highlighter.

      Поддержка требований движка JavaScript в Safari под Mac.
    8. JsOutputMode="SingleLine|MultipleLines"

      * This source code was highlighted with Source Code Highlighter.

      Позволяет минимизировать код, сохраняя некую читабельность, хотя все остальные методики минимизации (переименование локальных переменных, например) – будут всё равно применены.
    9. JsRemoveFunctionExpressionNames="true|false"

      * This source code was highlighted with Source Code Highlighter.

    10. JsRemoveUnneededCode="true|false"

      * This source code was highlighted with Source Code Highlighter.

      Убирает код, который не участвует в процессе выполнения программы (unreachable code).
    11. JsStripDebugStatements="true|false"

      * This source code was highlighted with Source Code Highlighter.

      Изымает обращение к: debugger, $Debug, Debug, Web.Debug или Msn.Debug, WAssert.
    12. CssColorNames="Strict|Hex|Major"

      * This source code was highlighted with Source Code Highlighter.

      Указывает на возможность подстановки имени цвета вместо RGB кода, если данное имя короче (CssColorNames=«Strict»).
    13. CssCommentMode="None|All|Hacks"

      * This source code was highlighted with Source Code Highlighter.

      Указывает на возможность минимизации за счёт CSS комментариев. CssCommentMode=«Hacks», например, оставит в коде только условно комментированные CSS-хаки.
    14. CssExpandOutput="true|false"

      * This source code was highlighted with Source Code Highlighter.

      Позволяет минимизировать код, сохраняя некую читабельность, когда код будет представлен в несколько строк, вместо одной.
    15. CssSeverity="number"

      * This source code was highlighted with Source Code Highlighter.

      Указывает, какие неточности CSS будут выведены как ошибки.
    16. CssTermSemicolons="true|false"

      * This source code was highlighted with Source Code Highlighter.

      Управляет расстановкой точки с запятой после правил CSS.


    Следует иметь в виду, что компилирование такого проекта — с задачами Microsoft Ajax Minifier — требует установки данной утилиты на все машины, участвующие в процессе компиляции.

    Ссылки:
    1. Сайт Microsoft Ajax Minifier: http://aspnet.codeplex.com/releases/view/40584
    2. Учимся пользоваться Microsoft Ajax Minifier: http://www.asp.net/ajaxlibrary/AjaxMinQuickStart.ashx
    3. Параметры задачи MSBuild'а для Microsoft Ajax Minifier: http://www.asp.net/ajaxLibrary/AjaxMinTask.ashx


    В продолжение темы хочу написать статью об использовании следующего поколения клиентских библиотек от Microsoft — Microsoft Ajax Library, в связке с обычными и минимизированными файлами JavaScript, в зависимости от конфигурации.
    Поделиться публикацией

    Комментарии 6

      0
      Интересно посмотреть сравнение с другими упаковщиками, типа yui compressor или гугловым.
        0
        С решением от Google я не работал, но вот, по сравнению с YUI Compressor'ом, – Microsoft Ajax Minifier имеет очень интересную особенность: элегантная отработка функций внутри if'ов.

        1. if (firstPredicate && secondPredicate)
        2. {
        3.     alert("Everything is true");
        4. }
        * This source code was highlighted with Source Code Highlighter.


        Превращается в:

        1. firstPredicate && secondPredicate && alert("Everything is true");
        * This source code was highlighted with Source Code Highlighter.


        То есть, когда выполнение функции зависит от «успеха» всех условий оператора – сам вызов функции становится частью логической цепочки (присоединяется как последнее условие). Таким образом, использую оптимизацию логических вычислений, вызов функции происходит только тогда, когда все остальные предикаты выдали true. По-моему, – элегантное и чистое решение, экономящее не только символы перевода строк, но и ключевое слово if, вместе с круглыми и фигурными скобками.

        Не пиар! Интересный ресурс для сравнения работы YUI Compressor'а и Microsoft Ajax Minifier'а: http://www.lotterypost.com/js-compress.aspx (правда, версия Minifier'а старовата).

        _________
        Текст подготовлен в ХабраРедакторе
        0
        В клиентскую оптимизацию перенести не получается?
          0
          В смысле в блог «Клиентская оптимизация» — нет. То ли я не знаю как это сделать, то ли не хватает кармы.
            0
            да, я про блог. Может быть, кто еще подкинет (там вроде 5 нужно — одного голоса не хватает)
              0
              Спасибо. Пока поищу, заодно, как переносить статьи в общие блоги.

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

        Самое читаемое