Главная > .NET > Bundle Transformer – модульное расширение для ASP.NET Bundling and Minification

Bundle Transformer – модульное расширение для ASP.NET Bundling and Minification

Логотип Bundle Transformer

Одним из наиболее популярных нововведений в ASP.NET MVC 4 и ASP.NET 4.5 стала библиотека, производящая минимизацию и объединение кода CSS- и JavaScript-файлов — ASP.NET Bundling and Minification (другие названия: System.Web.Optimization, Microsoft.Web.Optimization и ASP.NET Optimization — Bundling). Если вы еще не знакомы с данным продуктом, то рекомендую прочитать статью Дэвида Хайдена «ASP.NET MVC 4 Bundling and Minification of CSS and JavaScript» и посмотреть выступление Скотта Гатри «A look at ASP.NET MVC 4». Во многом ASP.NET Bundling and Minification напоминает уже присутствующие на рынке продукты для проведения клиентской оптимизации: Combres и Cassette.

ASP.NET Bundling and Minification написан под .NET Framework 4 и поэтому его можно использовать в проектах, написанных на старых версиях ASP.NET (MVC 3 и Web Forms 4.0). Для этого нужно просто установить NuGet-пакет System.Web.Optimization 1.0.0-beta.

Основным преимуществом ASP.NET Bundling and Minification перед другими аналогичными продуктами является механизм динамической обработки папок (dynamic folder bundles). Данный механизм работает следующим образом — в файле Global.asax регистрируются специальные связки «суффикс-обработчик-шаблон имени файла»:

var css = new DynamicFolderBundle("css", new CssMinify(), "*.css");
BundleTable.Bundles.Add(css);

var js = new DynamicFolderBundle("js", new JsMinify(), "*.js");
BundleTable.Bundles.Add(js);

Теперь с помощью этих суффиксов можно производить обработку содержимого директорий, достаточно только добавить в URL директории соответствующий суффикс:

<link href="@BundleTable.Bundles.ResolveBundleUrl("~/Content/css")" 
    rel="stylesheet" type="text/css" />
<script src="@BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")"></script>

Хочу заметить, что для регистрации представленных выше связок «суффикс-обработчик-шаблон имени файла» существует специальный метод:

BundleTable.Bundles.EnableDefaultBundles();

ASP.NET Bundling and Minification имеет модульную архитектуру и поддерживает возможность расширения путем замены стандартных модулей. Например, обработчики CssMinify и JsMinify можно заменить на свои собственные реализации. Пользовательский обработчик должен реализовывать интерфейс IBundleTransform из пространства имен System.Web.Optimization.

К сожалению, текущая версия продукта (1.0.0 Beta) имеет ряд недостатков:

  1. Сложность отладки клиентского кода. При обработке код ресурсов (CSS- и JS-файлов) всегда объединяется и минимизируется, что усложняет процесс его отладки.
  2. В CSS-коде не преобразуются относительные пути в абсолютные. При объединении нескольких CSS-файлов в один, теряется информация о местоположении этих файлов в файловой системе и приводит к тому, что относительные ссылки на рисунки и другие компоненты таблиц стилей становятся «битыми». Чтобы избежать такой ошибки нужно перед объединением кода произвести преобразование относительных путей в абсолютные. Например, в коде файла /AlternativeContent/css/TestCssComponentsPaths.css указан путь к рисунку ../images/icons/disc.png, который перед объединением кода должен быть преобразован в /AlternativeContent/images/icons/disc.png.
  3. Производится повторная минимизация кода. Если значение свойства EnableFileExtensionReplacements объекта типа Bundle равно true (значение по умолчанию), то при обработке ресурсов используются их предварительно-минимизированные версии (файлы с расширениями *.min.css и *.min.js). К сожалению, во время обработки код этих файлов подвергается повторной минимизации, что является избыточной операцией и снижает надежность кода (например, минимизированные версии многих популярных JS-библиотек перед публикацией тестируются с помощью юнит-тестов, написанных для полных версий библиотек).

Изучив все возможности текущей версии продукта, и выявив ее основные недостатки, я решил написать для ASP.NET Bundling and Minification расширение под названием Bundle Transformer.

Обзор основных возможностей Bundle Transformer

Bundle Transformer – это Open Source-проект, исходные коды которого опубликованы на сайте CodePlex, а дистрибутивы можно загрузить через NuGet.

Основная идея данного проекта – это модульность. Многие популярные менеджеры ресурсов, такие как: Combres, SquishIt и Cassette, при установке добавляют в проект сразу несколько минимизаторов (например, Microsoft Ajax Minifier, YUI Compressor и Google Closure Compiler) и трансляторов с промежуточных языков (LESS, Sass/SCSS и CoffeeScript). В большинстве случаев, в проектах требуется только два минимизатора (по одному для каждого типа ресурсов), а трансляторы могут и вовсе не понадобиться. Модульная архитектура Bundle Transformer позволяет разработчику устанавливать только те компоненты, которые ему действительно необходимы.

Рассмотрим основные модули Bundle Transformer:

Ядро

Bundle Transformer Core – это каркас Bundle Transformer, возможности которого наращиваются с помощью дополнительных модулей. В Bundle Transformer Core реализованы собственные версии обработчиков – классы CssTransformer и JsTransformer, которые заменяют стандартные реализации — классы CssMinify и JsMinify.

Перечислю их основные возможности:

  1. Автоматическое удаление дублирующихся ресурсов.
  2. Автоматическое удаление ненужных ресурсов (в параметре ignorePatterns конструкторов классов CssTransformer и JsTransformer можно указать шаблоны путей к файлам, которые требуется удалить из списка).
  3. Выбор нужных версий ресурсов в зависимости от режима работы веб-приложения.
  4. Преобразование относительных путей в CSS-коде в абсолютные (только в CssTransformer).
  5. Объединение кода обработанных ресурсов.

Остановлюсь более подробно на 3-м пункте. В режиме отладки производится выбор отладочных версий ресурсов, а в режиме выпуска – минимизированных. Причем выбор производится с учетом JS-файлов c расширениями в стиле Microsoft (отладочные версии таких файлов имеют расширение *.debug.js). Файлы с расширениями в стиле Microsoft определяются на основе специального списка, который можно изменить в файле Web.config. Значение данного конфигурационного свойства по умолчанию соответствует следующему XML-коду:

<configuration>
    ...
    <bundleTransformer
        xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
        <core jsFilesWithMicrosoftStyleExtensions="MicrosoftAjax.js,
MicrosoftMvcAjax.js,MicrosoftMvcValidation.js,knockout-$version$.js" ...>
            ...
        </core>
        ...
    </bundleTransformer>
</configuration>

Рассмотрим, как производится выбор нужных версий файлов. Например, мы зарегистрировали следующие файлы:

/Content/Site.css
/Scripts/jquery-1.6.2.js
/Scripts/knockout-2.1.0beta.js

В режиме отладки будут выбраны отладочные версии файлов:

/Content/Site.css
/Scripts/jquery-1.6.2.js
/Scripts/knockout-2.1.0beta.debug.js

А в режиме выпуска — минимизированные:

/Content/Site.min.css
/Scripts/jquery-1.6.2.min.js
/Scripts/knockout-2.1.0beta.js

Bundle Transformer Core не производит минимизацию кода «на лету», для этой цели нужно использовать минимизаторы, которые устанавливаются в качестве дополнительных модулей. Тем не менее, такого функционала может быть достаточно, если в проекте производится предварительная минимизация ресурсов (например, с помощью задач MSBuild, реализованных на базе Microsoft Ajax Minifier и YUI Compressor for .NET, или VS-расширения Minifier). Стоит также отметить, что при выборе предварительно-минимизированных версий ресурсов Bundle Transformer Core помечает их специальным флагом, который запрещает последующую минимизацию кода.

Минимизаторы

Минимизаторы – это дополнительные модули, которые реализованы как адаптеры (классы, реализующие интерфейс IMinifier из пространства имен BundleTransformer.Core.Minifiers) для минимизаторов сторонних производителей. На данный момент доступно 2 набора адаптеров:

  1. Bundle Transformer Microsoft Ajax содержит 2 адаптера-минимизатора: MicrosoftAjaxCssMinifier (для минимизации CSS-кода) и MicrosoftAjaxJsMinifier (для минимизации JS-кода). Данные адаптеры производят минимизацию кода средствами библиотеки Ajax Minifier Library (Microsoft Ajax Minifier).
  2. Bundle Transformer YUI содержит 2 адаптера-минимизатора: YuiCssMinifier (для минимизации CSS-кода) и YuiJsMinifier (для минимизации JS-кода). Данные адаптеры производят минимизацию кода средствами библиотеки YUI Compressor for .NET.

Трансляторы

В последнее время стали популярны CSS-препроцессоры (LESS, Sass/SCSS и Stylus) и языки, транслируемые в JavaScript (CoffeeScript и Kaffeine). Все эти промежуточные языки добавляют «синтаксический сахар», который улучшает читаемость кода и уменьшает его размер.

В Bundle Transformer существует специальный тип дополнительных модулей – трансляторы. Трансляторы также как и минимизаторы являются адаптерами (классы, реализующие интерфейс ITranslator из пространства имен BundleTransformer.Core.Translators). Сейчас реализованы адаптеры-трансляторы только для наиболее распространенных промежуточных языков:

  1. Bundle Transformer LESS содержит адаптер-транслятор LessTranslator, производящий трансляцию LESS-кода в CSS средствами библиотеки dotless.
  2. Bundle Transformer Sass and SCSS содержит адаптер-транслятор SassAndScssTranslator, который производит трансляцию Sass- и SCSS-кода в CSS средствами библиотеки SassAndCoffee.Ruby.
  3. Bundle Transformer CoffeeScript содержит адаптер-транслятор CoffeeScriptTranslator, который осуществляет трансляцию CoffeeScript-кода в JavaScript средствами библиотеки SassAndCoffee.JavaScript.

Установка NuGet-пакетов

Последняя версия Bundle Transformer написана для предварительной версии ASP.NET Bundling and Minification (System.Web.Optimization 1.0.0 Beta) и поэтому сама находится в статусе бета-версии. К сожалению, процесс установки предварительных версий библиотек через NuGet отличается от процесса установки финальных версий. До выхода версии NuGet 1.7 установка предварительных версий была возможна только с помощью Package Manager Console:

Установка NuGet-пакета BundleTransformer.MicrosoftAjax с помощью Package Manager Console

При установке предварительных версий библиотек из консоли необходимо всегда указывать ключ –Pre:

PM> Install-Package BundleTransformer.MicrosoftAjax –Pre

При обновлении таких библиотек также нужно указывать ключ –Pre:

PM> Update-Package BundleTransformer.MicrosoftAjax -Pre

Начиная с NuGet 1.7 появилась возможность устанавливать предварительные версии библиотек с помощью диалога Manage NuGet Packages. В данном диалоговом окне появился выпадающий список, в котором можно выбрать режим отображения предварительных версий:

Отображение предварительных версий библиотек в диалоговом окне Manage NuGet Packages

Примеры использования

Рассмотрим пример регистрации статических bundle`ов в файле Global.asax:

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

using BundleTransformer.Core.Orderers;
using BundleTransformer.Core.Transformers;

public class MvcApplication : System.Web.HttpApplication
{
    ...
    protected void Application_Start()
    {
        ...
        var cssTransformer = new CssTransformer();
        var jsTransformer = new JsTransformer();
        var nullOrderer = new NullOrderer();

        var commonStylesBundle = new Bundle("~/CommonStyles", cssTransformer);
        commonStylesBundle.AddFile("~/Content/Site.css");
        commonStylesBundle.AddFile("~/Content/BundleTransformer.css");
        commonStylesBundle.AddFile("~/AlternativeContent/css/
TestCssComponentsPaths.css");
        commonStylesBundle.AddFile("~/Content/themes/base/
jquery.ui.core.css");
        commonStylesBundle.AddFile("~/Content/themes/base/
jquery.ui.theme.css");
        commonStylesBundle.AddFile("~/Content/themes/base/
jquery.ui.resizable.css");
        commonStylesBundle.AddFile("~/Content/themes/base/
jquery.ui.button.css");
        commonStylesBundle.AddFile("~/Content/themes/base/
jquery.ui.dialog.css");
        commonStylesBundle.AddFile("~/Content/TestTranslators.css");
        commonStylesBundle.AddFile("~/Content/TestLess.less");
        commonStylesBundle.AddFile("~/Content/TestSass.sass");
        commonStylesBundle.AddFile("~/Content/TestScss.scss");
        commonStylesBundle.Orderer = nullOrderer;

        BundleTable.Bundles.Add(commonStylesBundle);

        var modernizrBundle = new Bundle("~/Modernizr", jsTransformer);
        modernizrBundle.AddFile("~/Scripts/
modernizr-2.0.6-development-only.js");
        modernizrBundle.Orderer = nullOrderer;

        BundleTable.Bundles.Add(modernizrBundle);

        var commonScriptsBundle = new Bundle("~/CommonScripts", jsTransformer);
        commonScriptsBundle.AddFile("~/Scripts/MicrosoftAjax.js");
        commonScriptsBundle.AddFile("~/Scripts/jquery-1.6.2.js");
        commonScriptsBundle.AddFile("~/Scripts/jquery-ui-1.8.11.js");
        commonScriptsBundle.AddFile("~/Scripts/jquery.validate.js");
        commonScriptsBundle.AddFile("~/Scripts/
jquery.validate.unobtrusive.js");
        commonScriptsBundle.AddFile("~/Scripts/jquery.unobtrusive-ajax.js");
        commonScriptsBundle.AddFile("~/Scripts/knockout-2.1.0beta.js");
        commonScriptsBundle.AddFile("~/Scripts/AjaxLogin.js");
        commonScriptsBundle.AddFile("~/Scripts/TestCoffeeScript.coffee");
        commonScriptsBundle.Orderer = nullOrderer;

        BundleTable.Bundles.Add(commonScriptsBundle);
        ...
    }
}

В приведенном выше коде создаются 3 статических bundle`а, в которые затем добавляются отдельные файлы. Экземпляры классов CssTransformer и JsTransformer производят обработку CSS- и JS-файлов. Экземпляр класса NullOrderer отключает встроенный механизм сортировки и сохраняет ресурсы отсортированными в порядке их объявления.

При создании статических bundle`ов мы указали их виртуальные пути, которые затем можно использовать в коде представлений:

@using System.Web.Optimization

<!DOCTYPE html>
<html>
    <head>
        ...
        <link href="@BundleTable.Bundles.ResolveBundleUrl("~/CommonStyles")" 
            rel="stylesheet" type="text/css" />
        <script src="@BundleTable.Bundles.ResolveBundleUrl("~/Modernizr")">
        </script>
        ...
    </head>
    <body>
        ...
        <script src="@BundleTable.Bundles.ResolveBundleUrl("~/CommonScripts")">
        </script>
    </body>
</html>

Кроме того, в статические bundle`ы можно добавлять не только отдельные файлы, но и содержимое директорий:

var jqueryUiStylesDirectoryBundle = new Bundle("~/JqueryUiStylesDirectory", 
    new CssTransformer(new[] { "*.all.css", "jquery.ui.base.css" }));
jqueryUiStylesDirectoryBundle.AddDirectory("~/Content/themes/base/", "*.css");

BundleTable.Bundles.Add(jqueryUiStylesDirectoryBundle);

var scriptsDirectoryBundle = new Bundle("~/ScriptsDirectory", 
    new JsTransformer(new[] { "*.all.js", "_references.js" }));
scriptsDirectoryBundle.AddDirectory("~/Scripts/", "*.js");

BundleTable.Bundles.Add(scriptsDirectoryBundle);

В приведенном выше примере в конструкторы классов CssTransformer и JsTransformer передаются списки шаблонов путей к файлам, которые нужно удалить из Bundle`а.

Рассмотрим пример регистрации динамических bundle`ов:

var css = new DynamicFolderBundle("css",
    new CssTransformer(new[] { "*.all.css", "jquery.ui.base.css" }), "*.css");
BundleTable.Bundles.Add(css);

var js = new DynamicFolderBundle("js",
    new JsTransformer(new[] { "*.all.js", "_references.js" }), "*.js");
BundleTable.Bundles.Add(js);

var less = new DynamicFolderBundle("less", 
    new CssTransformer(new[] { "TestLessImport.less" }), "*.less");
BundleTable.Bundles.Add(less);

var sass = new DynamicFolderBundle("sass",
    new CssTransformer(new[] { "TestSassImport.sass" }), "*.sass");
BundleTable.Bundles.Add(sass);

var scss = new DynamicFolderBundle("scss",
    new CssTransformer(new[] { "TestScssImport.scss" }), "*.scss");
BundleTable.Bundles.Add(scss);

var coffee = new DynamicFolderBundle("coffee", 
    new JsTransformer(), "*.coffee");
BundleTable.Bundles.Add(coffee);

В приведенном выше коде мы создали 6 динамических bundle`ов для каждого подтипа ресурсов (предполагается, что установлены соответствующие адаптеры-трансляторы).

Наверное, многие из вас скажут: «Зачем регистрировать 6 динамических bundle`ов, когда можно зарегистрировать только 2 (с суффиксами css и js)». К сожалению, это невозможно сделать из-за того, что в параметре searchPattern конструктора DynamicFolderBundle нельзя указывать несколько шаблонов имен файлов. Количество bundle`ов можно сократить до 3-х, если объединить bundle`ы с суффиксами css, less, sass и scss в один, указав шаблон вида "*.*ss", но это ненадежный вариант.

Более удобным был бы вариант создания 2-x bundle`ов с шаблонами: "*.css;*.less;*.sass;*.scss" и "*.js;*.coffee", но, к сожалению, в текущей версии ASP.NET Bundling and Minification такая возможность не предусмотрена. Поэтому я разместил на сайте ASP.NET User Voice заявку на добавление соответствующего функционала. При желании вы можете проголосовать за данную заявку и тем самым увеличить шансы на реализацию данного функционала в следующей версии ASP.NET Bundling and Minification.

Указанные при создании динамических bundle`ов суффиксы теперь можно использовать в представлениях:

@using System.Web.Optimization

<!DOCTYPE html>
<html>
    <head>
        ...
        <link href="@BundleTable.Bundles.ResolveBundleUrl("~/Content/css")" 
            rel="stylesheet" type="text/css" />
        <link href="@BundleTable.Bundles.ResolveBundleUrl("~/
AlternativeContent/css/css")" 
            rel="stylesheet" type="text/css" />
        <link href="@BundleTable.Bundles.ResolveBundleUrl("~/Content/themes/
base/css")" 
            rel="stylesheet" type="text/css" />
        <link href="@BundleTable.Bundles.ResolveBundleUrl("~/Content/less")" 
            rel="stylesheet" type="text/css" />
        <link href="@BundleTable.Bundles.ResolveBundleUrl("~/Content/sass")" 
            rel="stylesheet" type="text/css" />
        <link href="@BundleTable.Bundles.ResolveBundleUrl("~/Content/scss")" 
            rel="stylesheet" type="text/css" />
        <script src="@BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")">
        </script>
        ...
    </head>
    <body>
        ...    
        <script src="@BundleTable.Bundles.ResolveBundleUrl("~/Scripts/coffee")">
        </script>
    </body>
</html>

Улучшенный процесс отладки

Bundle Transformer учитывает в каком режиме выполняется веб-приложение (отладка или выпуск). В режиме отладки минимизация кода ресурсов отключена.

Режим работы ASP.NET-приложения задается в файле Web.config:

<system.web>
    <compilation debug="false" targetFramework="4.0">
    ...

Значение атрибута debug определяет режим, в котором находится веб-приложение: true – отладка или false – выпуск.

Для удобства разработки классы CssTransformer и JsTransformer поддерживают методы, имитирующие локальное переключение режима работы веб-приложения: ForceDebugMode (в режим отладки) и ForceReleaseMode (в режим выпуска).

var jsTransformer = new JsTransformer();
jsTransformer.ForceReleaseMode();

var cssTransformer = new CssTransformer();
cssTransformer.ForceDebugMode();
...

Метод ForceReleaseMode позволяет переключить CssTransformer или JsTransformer в режим выпуска даже во время отладки кода с помощью отладчика Visual Studio.

На последнем этапе обработки bundle`а происходит объединение кода входящих в него ресурсов. Объединенный код сложно отлаживать, т.к. непонятно где начинается и заканчивается код конкретного ресурса.

Для облегчения отладки объединенного кода необходимо внести следующие изменения в файл Web.config:

<configuration>
    ...
    <bundleTransformer>
        <core enableTracing="true" ...>
            ...
        </core>
        ...
    </bundleTransformer>
</configuration>

Если значение атрибута enableTracing равно true, то на этапе объединения код каждого отдельного ресурса будет оборачиваться в регион.

Пример региона в CSS-коде:

/*#region URL: /Content/Site.css */
html {
    background-color: #e2e2e2;
    margin: 0;
    padding: 0;
}
...
/*#endregion*/

Пример региона в JS-коде:

//#region URL: /Scripts/AjaxLogin.js
$(function () {
    // Cache for dialogs
    var dialogs = {};
    ...
});
//#endregion

В следующей версии ASP.NET Bundling and Minification появятся специальные хелперы для работы с bundle`ами в коде представлений, напоминающие по функциональности хелпер CombresLink из Combres. В режиме отладки будут выводиться ссылки на отдельные ресурсы, а в режиме выпуска – ссылки на объединенный код ресурсов. Более подробно о данном нововведении можно прочитать в комментарии Говарда Дёркинга на сайте ASP.NET User Voice.

Настройки

Начиная с версии 1.2.1 Beta из файла Web.config были удалены настройки Bundle Transformer, которые являлись настройками по умолчанию. Текущие настройки Bundle Transformer эквивалентны следующему варианту файла Web.config (в случае, когда установлены все дополнительные модули):

<configuration>
    <configSections>
        <!-- Declaration of Bundle Transformer configuration section group -->
        <sectionGroup name="bundleTransformer">
            <section name="core" 
                type="BundleTransformer.Core.Configuration.CoreSettings" />
            <section name="less" 
                type="BundleTransformer.Less.Configuration.LessSettings" />
            <section name="sassAndScss" 
                type="BundleTransformer.SassAndScss.Configuration.
	SassAndScssSettings" />
            <section name="microsoftAjax" 
                type="BundleTransformer.MicrosoftAjax.Configuration.
	MicrosoftAjaxSettings" />
            <section name="yui" 
                type="BundleTransformer.Yui.Configuration.YuiSettings" />
            ...
        </sectionGroup>
        <!-- /Declaration of Bundle Transformer configuration section group -->
    </configSections>
    ...
    <!-- Bundle Transformer configuration settings -->
    <bundleTransformer
        xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
        <core enableTracing="false"
            jsFilesWithMicrosoftStyleExtensions="MicrosoftAjax.js,
MicrosoftMvcAjax.js,MicrosoftMvcValidation.js,knockout-$version$.js">
            <css defaultMinifier="NullMinifier">
                <minifiers>
                    <add name="NullMinifier" 
                        type="BundleTransformer.Core.Minifiers.NullMinifier, 
BundleTransformer.Core" />
                    <add name="MicrosoftAjaxCssMinifier" 
                        type="BundleTransformer.MicrosoftAjax.Minifiers.
MicrosoftAjaxCssMinifier, BundleTransformer.MicrosoftAjax" />
                    <add name="YuiCssMinifier" 
                        type="BundleTransformer.Yui.Minifiers.YuiCssMinifier, 
BundleTransformer.Yui" />
                </minifiers>
                <translators>
                    <add name="NullTranslator" 
                        type="BundleTransformer.Core.Translators.
NullTranslator, BundleTransformer.Core" 
                        enabled="false" />
                    <add name="LessTranslator" 
                        type="BundleTransformer.Less.Translators.
LessTranslator, BundleTransformer.Less" 
                        enabled="true" />
                    <add name="SassAndScssTranslator" 
                        type="BundleTransformer.SassAndScss.Translators.
SassAndScssTranslator, BundleTransformer.SassAndScss" 
                        enabled="true" />
                </translators>
            </css>
            <js defaultMinifier="NullMinifier">
                <minifiers>
                    <add name="NullMinifier" 
                        type="BundleTransformer.Core.Minifiers.NullMinifier, 
BundleTransformer.Core" />
                    <add name="MicrosoftAjaxJsMinifier" 
                        type="BundleTransformer.MicrosoftAjax.Minifiers.
MicrosoftAjaxJsMinifier, BundleTransformer.MicrosoftAjax" />
                    <add name="YuiJsMinifier" 
                        type="BundleTransformer.Yui.Minifiers.YuiJsMinifier, 
BundleTransformer.Yui" />
                </minifiers>
                <translators>
                    <add name="NullTranslator" 
                        type="BundleTransformer.Core.Translators.
NullTranslator, BundleTransformer.Core" 
                        enabled="false" />
                    <add name="CoffeeScriptTranslator" 
                        type="BundleTransformer.CoffeeScript.Translators.
CoffeeScriptTranslator, BundleTransformer.CoffeeScript" 
                        enabled="true" />
                </translators>
            </js>
        </core>
        <less useNativeMinification="false" />
        <sassAndScss useNativeMinification="false" />
        <microsoftAjax>
            <css allowEmbeddedAspNetBlocks="false" colorNames="Strict"
                commentMode="Important" ignoreErrorList="" 
                indentSize="4" minifyExpressions="true" 
                outputMode="SingleLine" preprocessorDefineList="" 
                termSemicolons="false" severity="4" />
            <js allowEmbeddedAspNetBlocks="false" collapseToLiteral="true" 
                combineDuplicateLiterals="false" 
                debugLookupList="Debug,$Debug,WAssert,Msn.Debug,Web.Debug"
                evalTreatment="Ignore" ignoreConditionalCompilation="false" 
                ignoreErrorList="" indentSize="4" 
                inlineSafeStrings="true" knownGlobalNamesList="" 
                localRenaming="CrunchAll" macSafariQuirks="true" 
                minifyCode="true" noAutoRenameList="$super" 
                outputMode="SingleLine" preprocessorDefineList="" 
                preserveFunctionNames="false" preserveImportantComments="true" 
                removeFunctionExpressionNames="true" removeUnneededCode="true" 
                renamePairs="" strictMode="false" 
                stripDebugStatements="true" termSemicolons="false" 
                severity="0" />
        </microsoftAjax>
        <yui>
            <css compressionType="StockYuiCompressor" removeComments="true" 
                lineBreakPosition="-1" />
            <js compressionType="YuiStockCompression" isVerboseLogging="true" 
                isObfuscateJavascript="true" preserveAllSemicolons="false" 
                disableOptimizations="false" isEvalIgnored="false"
                lineBreakPosition="-1" />
        </yui>
    </bundleTransformer>
    <!-- /Bundle Transformer configuration settings -->
    ...
</configuration>

Классы CssTransformer и JsTransformer имеют несколько перегруженных версий конструктора, которые принимают в качестве параметров: адаптер-минимизатор и/или список адаптеров-трансляторов. Если при создании экземпляров вышеперечисленных классов такие параметры не передаются, то минимизатор по умолчанию и список активных трансляторов для соответствующего типа ресурсов определяются на основе настроек в файле Web.config, которые задаются в дочерних элементах элемента core: css и js. Оба элемента имеют дочерние элементы minifiers и translators, в которых регистрируются адаптеры-минимизаторы и, соответственно, адаптеры-трансляторы. В элементах css и js также определен атрибут defaultMinifier, в котором можно указать имя минимизатора по умолчанию. Список активных трансляторов определяется на основе значений атрибута enabled (true – активен, false — неактивен) элементов add (дочерние элементы элемента translators), которые отвечают за регистрацию соответствующих трансляторов.

В элементах less и sassAndScss задаются настройки одноименных адаптеров-трансляторов. Если значение атрибута useNativeMinification равно true, то минимизация кода ресурса, обрабатываемого транслятором, производится средствами самого транслятора.

В элементах microsoftAjax и yui определяются настройки соответствующих адаптеров-минимизаторов CSS- и JS-кода. Я не буду описывать настройки каждого адаптера-минимизатора, потому что названия и возможные значения их конфигурационных свойств совпадают с конфигурационными свойствами исходных минимизаторов. Кроме того, начиная с версии 1.2.1 Beta в файле Web.config для конфигурационной секции bundleTransformer была реализована поддержка IntelliSense:

Поддержка IntelliSense при редактировании конфигурационной секции bundleTransformer в файле Web.config

Заключение

Bundle Transformer уже обладает достаточно большим количеством возможностей, но развитие продукта на этом не заканчивается. В ближайших планах стоит реализация адаптеров-минимизаторов на базе Google Closure Compiler и JSMin.

Ссылки

  1. Страница Bundle Transformer на CodePlex
  2. ASP.NET MVC 4 Beta Released!
  3. A look at ASP.NET MVC 4
  4. ASP.NET MVC 4 Bundling and Minification of CSS and JavaScript
  5. Improve System.Web.Optimization.Bundle
  6. What’s New in ASP.NET and Web Development in Visual Studio 11. Exercise 4: Bundling and Minification
  7. Modern Web Development — Part 6. Packaging Assets
  1. www
    18.04.2012 в 02:58

    нафига такие сложности городить — все решить можно с помощью хэндлеров или модулей!

  2. 18.04.2012 в 10:58

    Честно говоря, не вижу никаких сложностей в подходе Microsoft.

    Я не имею ничего против полностью автоматического процесса клиентской оптимизации, который можно производить с помощью таких средств, как RequestReduce (http://requestreduce.com). Но нужно учитывать, что в некоторых проектах требуется более тонкая настройка данного процесса и решения подобные ASP.NET Bundling and Minification подходят для них больше.

  1. No trackbacks yet.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: