- PVSM.RU - https://www.pvsm.ru -

Вышел Bundle Transformer 1.6.2 или что изменилось за полгода?

Логотип Bundle Transformer
Bundle Transformer [1] – это разработанное мной модульное расширение для Microsoft ASP.NET Web Optimization Framework [2] (другие названия: ASP.NET Bundling and Minification, System.Web.Optimization, Microsoft.Web.Optimization и ASP.NET Optimization – Bundling). В апреле этого года я уже делал подробный обзор возможностей Bundle Transformer [3], но за это время данный продукт очень сильно изменился. Поэтому я решил написать данный обзор и рассказать об основных изменениях, которые произошли в Bundle Transformer за прошедшие полгода.

Изменения, связанные с развитием Microsoft ASP.NET Web Optimization Framework

Апрельская версия Bundle Transformer была разработана для 1-й беты Microsoft ASP.NET Web Optimization Framework (далее B/M). Уже во 2-й бете B/M произошли серьезные изменения: сильно изменился API, появилась поддержка режима отладки и была признана устаревшей возможность создания динамических bundle`ов (больше не рекомендуется использовать метод EnableDefaultBundles и класс DynamicFolderBundle). В финальной версии B/M уже не было кардинальных изменений, но добавилась одна очень полезная возможность – это поддержка CDN.

Все перечисленные выше изменения также повлияли и на Bundle Transformer.

Начиная со 2-й беты B/M рекомендуется перенести код, создающий bundle`ы, из файла Global.asax в класс BundleConfig и разместить этот класс в директории App_Start. В файле Global.asax нужно оставить только вызов метода RegisterBundles класса BundleConfig:

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

namespace BundleTransformer.Example.Mvc
{
	public class MvcApplication : System.Web.HttpApplication
	{
		protected void Application_Start()
		{
			AreaRegistration.RegisterAllAreas();

			FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
			RouteConfig.RegisterRoutes(RouteTable.Routes);
			// Запускаем создание bundle`ов
			BundleConfig.RegisterBundles(BundleTable.Bundles);
		}
	}
}

Рассмотрим создание bundle`ов и настройку их обработки с помощью Bundle Transformer на примере следующего класса BundleConfig:

using System.Web.Optimization;

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

namespace BundleTransformer.Example.Mvc
{
	public class BundleConfig
	{
		public static void RegisterBundles(BundleCollection bundles)
		{
			var cssTransformer = new CssTransformer();
			var jsTransformer = new JsTransformer();
			var nullOrderer = new NullOrderer();

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

			bundles.Add(commonStylesBundle);

			var modernizrBundle = new Bundle("~/Bundles/Modernizr");
			modernizrBundle.Include("~/Scripts/modernizr-2.*");
			modernizrBundle.Transforms.Add(jsTransformer);
			modernizrBundle.Orderer = nullOrderer;

			bundles.Add(modernizrBundle);

			var commonScriptsBundle = new Bundle("~/Bundles/CommonScripts");
			commonScriptsBundle.Include("~/Scripts/MicrosoftAjax.js",
				"~/Scripts/jquery-{version}.js",
				"~/Scripts/jquery-ui-{version}.js",
				"~/Scripts/jquery.validate.js",
				"~/Scripts/jquery.validate.unobtrusive.js",
				"~/Scripts/jquery.unobtrusive-ajax.js",
				"~/Scripts/knockout-2.*",
				"~/Scripts/TestCoffeeScript.coffee");
			commonScriptsBundle.Transforms.Add(jsTransformer);
			commonScriptsBundle.Orderer = nullOrderer;

			bundles.Add(commonScriptsBundle);

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

			bundles.Add(jqueryUiStylesDirectoryBundle);

			var scriptsDirectoryBundle = new Bundle("~/Bundles/ScriptsDirectory");
			scriptsDirectoryBundle.IncludeDirectory("~/Scripts/", "*.js");
			scriptsDirectoryBundle.Transforms.Add(new JsTransformer(
				new[] { "*.all.js", "references.js" }));

			bundles.Add(scriptsDirectoryBundle);
		}
	}
}

Главное отличие по сравнению с 1-й бетой B/M заключается в том, что для добавления файлов и директорий теперь используются методы Include и IncludeDirectory (вместо методов AddFile и AddDirectory). Кроме того, добавление трансформаций теперь производится не через конструктор класса Bundle, а через его свойство Transforms (в приведенном выше коде вы можете увидеть это на примере добавления экземпляров классов CssTransformer и JsTransformer).

Стоит отметить, что помимо класса Bundle для создания bundle`ов могут также использоваться его подклассы StyleBundle (для стилей) и ScriptBundle (для скриптов). В эти классы уже добавлены трансформации, отвечающие за минимизацию кода (экземпляры классов CssMinify и JsMinify). В нашем случае мы не можем использовать эти подклассы, потому что нам необходимо вместо экземпляров классов CssMinify и JsMinify добавить трансформации из Bundle Transformer (экземпляры классов CssTransformer и JsTransformer).

Рассмотрим регистрацию ссылок на созданные bundlе`ы в коде представлений на примере файла _Layout.cshtml:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title - Bundle Transformer Example MVC Application</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
		@Styles.Render("~/Bundles/CommonStyles")
		@Scripts.Render("~/Bundles/Modernizr")
		...
    </head>
    <body>
		...
		@Scripts.Render("~/Bundles/CommonScripts")
        @RenderSection("scripts", required: false)
    </body>
</html>

Теперь ссылки на bundle`ы добавляются в код представления с помощью метода Render (Styles.Render используется для CSS, а Scripts.Render для JavaScript). Использование метода Render не только делает добавление ссылок на bundle`ы более удобным, но и решает главную проблему ранних версий B/M – поддержку режима отладки.

B/M определяет режим, в котором находится веб-приложение, на основе следующих настроек:

  1. Значения атрибута debug элемента compilation из файла Web.config (true – режим отладки; false – режим выпуска);
  2. Значения свойства BundleTable.EnableOptimizations, которое можно указать в классе BundleConfig (true – режим выпуска; false – режим отладки). Причем значение свойства BundleTable.EnableOptimizations имеет приоритет над настройками из файла Web.config.

В режиме выпуска код файлов, входящих в bundle, объединяется и обрабатывается (применяются трансформации). На выходе получается HTML-код следующего вида:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Home Page - Bundle Transformer Example MVC Application</title>
        <link href="/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
		<link href="/Bundles/CommonStyles?v=IWN75r8IOIWnlehQ6JVPUgrb7UER075iobpzbjYTtRQ1" rel="stylesheet"/>
		<script src="/Bundles/Modernizr?v=1dm47T0PPFmcdy8ssp2EZ4h8yT2SjNhVvtdbc0MyDAs1"></script>
		...
    </head>
    <body>
		...
		<script src="/Bundles/CommonScripts?v=qWsyReB8UFAt-HPS-6MCkeDDTs2lQgYMdyCUd2V9O4o1"></script>        
    </body>
</html>

А в режиме отладки файлы, входящие в bundle, выводятся в исходном виде и по отдельности:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Home Page - Bundle Transformer Example MVC Application</title>
        <link href="/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />
		<link href="/Content/Site.css" rel="stylesheet"/>
		<link href="/Content/BundleTransformer.css" rel="stylesheet"/>
		<link href="/AlternativeContent/css/TestCssComponentsPaths.css" rel="stylesheet"/>
		<link href="/Content/themes/base/jquery.ui.core.css" rel="stylesheet"/>
		<link href="/Content/themes/base/jquery.ui.theme.css" rel="stylesheet"/>
		<link href="/Content/themes/base/jquery.ui.resizable.css" rel="stylesheet"/>
		<link href="/Content/themes/base/jquery.ui.button.css" rel="stylesheet"/>
		<link href="/Content/themes/base/jquery.ui.dialog.css" rel="stylesheet"/>
		<link href="/Content/TestTranslators.css" rel="stylesheet"/>
		<link href="/Content/TestLess.less" rel="stylesheet"/>
		<link href="/Content/TestSass.sass" rel="stylesheet"/>
		<link href="/Content/TestScss.scss" rel="stylesheet"/>
		<script src="/Scripts/modernizr-2.5.3.js"></script>
		...
    </head>
    <body>
		...
		<script src="/Scripts/MicrosoftAjax.debug.js"></script>
		<script src="/Scripts/jquery-1.8.1.js"></script>
		<script src="/Scripts/jquery-ui-1.8.23.js"></script>
		<script src="/Scripts/jquery.validate.js"></script>
		<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
		<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
		<script src="/Scripts/knockout-2.1.0.debug.js"></script>
		<script src="/Scripts/TestCoffeeScript.coffee"></script>        
    </body>
</html>

Что существенно упрощает отладку клиентского кода.

Но если вы используете препроцессоры, то при работе в режиме отладки у вас могут возникнуть проблемы. В приведенном выше коде присутствуют ссылки на файлы с расширениями .less, .sass, .scss и .coffee. Если в файле Web.config для этих расширений не зарегистрированы HTTP-хэндлеры, то содержимое этих файлов окажется необработанным и могут возникнуть ошибки на стороне клиента.

Для решения данной проблемы в библиотеки трансляторов BundleTransformer.Less, BundleTransformer.LessLite, BundleTransformer.SassAndScss и BundleTransformer.CoffeeScript были добавлены реализации соответствующих HTTP-хэндлеров. При установке трансляторов через NuGet HTTP-хэндлеры регистрируются в файле Web.config автоматически:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
	...
	<system.web>
	...
		<httpHandlers>
			<!-- Declaration of Bundle Transformer HTTP-handlers -->
			<add path="*.less" verb="GET" 
				type="BundleTransformer.LessLite.HttpHandlers.LessAssetHandler, BundleTransformer.LessLite" />
			<add path="*.sass" verb="GET" 
				type="BundleTransformer.SassAndScss.HttpHandlers.SassAndScssAssetHandler, BundleTransformer.SassAndScss" />
			<add path="*.scss" verb="GET" 
				type="BundleTransformer.SassAndScss.HttpHandlers.SassAndScssAssetHandler, BundleTransformer.SassAndScss" />
			<add path="*.coffee" verb="GET" 
				type="BundleTransformer.CoffeeScript.HttpHandlers.CoffeeScriptAssetHandler, BundleTransformer.CoffeeScript" />
			<!-- /Declaration of Bundle Transformer HTTP-handlers -->
		</httpHandlers>
	</system.web>
	<system.webServer>
		...
		<handlers>
			...
			<!-- Declaration of Bundle Transformer HTTP-handlers -->
			<add name="LessAssetHandler" path="*.less" verb="GET" 
				type="BundleTransformer.LessLite.HttpHandlers.LessAssetHandler, BundleTransformer.LessLite" 
				resourceType="File" preCondition="" />
			<add name="SassAssetHandler" path="*.sass" verb="GET" 
				type="BundleTransformer.SassAndScss.HttpHandlers.SassAndScssAssetHandler, BundleTransformer.SassAndScss" 
				resourceType="File" preCondition="" />
			<add name="ScssAssetHandler" path="*.scss" verb="GET" 
				type="BundleTransformer.SassAndScss.HttpHandlers.SassAndScssAssetHandler, BundleTransformer.SassAndScss" 
				resourceType="File" preCondition="" />
			<add name="CoffeeScriptAssetHandler" path="*.coffee" verb="GET" 
				type="BundleTransformer.CoffeeScript.HttpHandlers.CoffeeScriptAssetHandler, BundleTransformer.CoffeeScript" 
				resourceType="File" preCondition="" />
			<!-- /Declaration of Bundle Transformer HTTP-handlers -->
		</handlers>
	</system.webServer>
	...
</configuration>

Исключение составляет лишь NuGet-пакет BundleTransformer.Less: при его установке также устанавливается пакет dotless, который автоматически регистрирует свою версию HTTP-хэндлера для обработки файлов с расширением .less. Но у вас всегда есть возможность вручную заменить его на HTTP-хэндлер LessAssetHandler из BundleTransformer.Less.

Управлять настройками родных HTTP-хэдлеров трансляторов можно с помощью конфигурационного элемента /configuration/bundleTransformer/core/assetHandler из файла Web.config. В следующем коде показаны настройки HTTP-хэндлеров по умолчанию:

<configuration>
	...
	<bundleTransformer xmlns="http://tempuri.org/BundleTransformer.Configuration.xsd">
		<core>
			...
			<assetHandler clientCacheDurationInDays="365" enableCompression="true"
				useLastModifiedHeader="true" useETagHeader="true"
				serverCacheDurationInMinutes="15" useServerCacheSlidingExpiration="false"
				disableClientCacheInDebugMode="true" disableCompressionInDebugMode="true" />
			...
		</core>
	</bundleTransformer>
	...
</configuration>

где,

  • clientCacheDurationInDays="(число)". Задает продолжительность нахождения текстового содержимого обработанного файла в кэше браузера (в днях).
  • enableCompression="(true|false)". Включает GZIP/Deflate-сжатие обработанного файла.
  • useLastModifiedHeader="(true|false)". Разрешает использовать HTTP-заголовок Last-Modified для оповещения браузера об изменении обработанного файла.
  • useETagHeader="(true|false)". Разрешает использовать HTTP-заголовок ETag для оповещения браузера об изменении обработанного файла.
  • serverCacheDurationInMinutes="(число)". Задает продолжительность нахождения текстового содержимого обработанного файла в серверном кэше (в минутах).
  • useServerCacheSlidingExpiration="(true|false)". Разрешает использование скользящего времени устаревания элемента серверного кэша.
  • disableClientCacheInDebugMode="(true|false)". Отключает в режиме отладки браузерное кэширование обработанного файла.
  • disableCompressionInDebugMode="(true|false)". Отключает в режиме отладки GZIP/Deflate-сжатие обработанного файла.

Трансляторы

Bundle Transformer: LESS Lite

В конце апреля появилась облегченная версия библиотеки dotless [4] под названием DotlessClientOnly [5]. Данная библиотека содержит только LESS-компилятор, а весь функционал, связанный с ASP.NET, из нее был удален (например, HTTP-хэндлер).

BundleTransformer.LessLite [6] использует возможности DotlessClientOnly для трансляции LESS-кода в CSS. По возможностям и программному интерфейсу BundleTransformer.LessLite полностью эквивалентен BundleTransformer.Less [7]. Поэтому если в ваших проектах вся работа с LESS [8] производится только через Bundle Transformer, то лучше использовать модуль BundleTransformer.LessLite, т.к. в его основе лежит более легковесная библиотека.

Bundle Transformer: CoffeeScript

До версии 1.5.5 в BundleTransformer.CoffeeScript [9] для трансляции CoffeeScript-кода в JavaScript использовалась библиотека SassAndCoffee.JavaScript [10] версии 2.0.2.0. К сожалению, библиотека SassAndCoffee.JavaScript уже давно не развивается и поддерживает уже устаревшую версию CoffeeScript [11] (версия 1.1.3). Поэтому в новых версиях BundleTransformer.CoffeeScript от нее пришлось отказаться и реализовать собственный компилятор, поддерживающий CoffeeScript 1.3.3.

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

Основной задачей при создании Bundle Transformer было предоставить разработчику возможность выбора из нескольких минимизаторов. В ранних версиях продукта разработчику были доступны адаптеры лишь для 2-х семейств минимизаторов: Microsoft Ajax Minifier [12] и YUI Compressor [13]. В текущей же версии доступны адаптеры практически для всех популярных минимизаторов CSS- и JS-кода.

Bundle Transformer: Closure

BundleTransformer.Closure [14] содержит 2 минимизатора JS-кода: ClosureRemoteJsMinifier и ClosureLocalJsMinifier. ClosureRemoteJsMinifier производит минимизацию с помощью веб-сервиса Google Closure Compiler Service API [15] и требует постоянного подключения к Интернету. ClosureLocalJsMinifier осуществляет минимизацию средствами консольного приложения Google Closure Compiler Application [16], и требует для своей работы: виртуальную машину Java [17] и последнюю версию файла compiler.jar [18].

Bundle Transformer: JSMin

BundleTransformer.JsMin [19] содержит адаптер-минимизатор JS-кода CrockfordJsMinifier. CrockfordJsMinifier основан на C#-порте старейшего минимизатора JS-кода – JSMin [20], который был написан Дугласом Крокфордом (Douglas Crockford). Используемый C#-порт был создан на основе версии JSMin от 22 мая 2007 года.

Bundle Transformer: UglifyJS

BundleTransformer.UglifyJs [21] содержит адаптер-минимизатор JS-кода UglifyJsMinifier. UglifyJsMinifier создан на основе популярного в сообществе Node.js минимизатора JS-кода — UglifyJS [22] (сейчас поддерживается версия 1.3.3).

Bundle Transformer: Packer

BundleTransformer.Packer [23] содержит адаптер-минимизатор JS-кода EdwardsJsMinifier. EdwardsJsMinifier создан на основе JS-минимизатора Дина Эдвардса (Dean Edwards) Packer [24] версии 3.0. Главной особенностью Packer`а является то, что помимо минимизации и обфускации кода, он может еще производить сжатие кода с помощью алгоритма Base62. Base62-сжатие можно использовать, когда на веб-сервере отсутствует поддержка GZIP/Deflate-сжатия.

Bundle Transformer: CSSO

BundleTransformer.Csso содержит адаптер-минимизатор CSS-кода KryzhanovskyCssMinifier. KryzhanovskyCssMinifier основан на CSS-минимизаторе CSSO [25] (сейчас поддерживается версия 1.2.18). Данный минимизатор был создан разработчиками методологии БЭМ [26]: Сергеем Крыжановским и Виталием Харисовым. Главным отличием данного CSS-минимизатора от других средств минимизации CSS-кода — является поддержка структурной минимизации (например, с CSS-кодом производятся следующие операции: слияние блоков с одинаковыми селекторами, удаление перекрываемых свойств, частичное выделение свойств в отдельный блок, частичное слияние блоков и т.д.). Структурная минимизация дает высокую степень сжатия при минимизации кода сгенерированного «машиной» (например, препроцессором).

Хочу отметить один важный момент: CSSO написан на ECMAScript 5 и я очень долго не мог найти JS-движок для .NET, который мог бы правильно выполнить код этой библиотеки. В итоге я остановил свой выбор на реализации JS-движка V8 под .NET — Noesis Javascript .NET [27]. Данный движок частично написан на неуправляемом коде и имеет 2 версии: 32- и 64-разрядную. Из-за этой особенности реализации модуль BundleTransformer.Csso был разделен на 2 NuGet-пакета: BundleTransformer.Csso.x86 [28] и BundleTransformer.Csso.x64 [29]. Для корректной работы Noesis Javascript .NET требуются сборки msvcp100.dll и msvcr100.dll из Microsoft Visual C++ 2010. Если в вашей системе нет этих сборок, то рекомендую вам установить Microsoft Visual C++ 2010 Redistributable Package (x86 [30], x64 [31]).

Bundle Transformer: WebGrease

BundleTransformer.WG [32] содержит адаптер-минимизатор CSS-кода WgCssMinifier. WgCssMinifier производит минимизацию CSS-кода с помощью семантического CSS-минимизатора из разработанной Microsoft библиотеки WebGrease [33]. Семантический CSS-минимизатор WebGrease также, как и CSSO производит структурную минимизацию CSS-кода.

В данный момент, NuGet-пакет BundleTransformer.WG имеет статус альфа, т.к. текущая версия WebGrease (версия 1.1.0) содержит ошибку [34] и из-за этого не может использоваться в производственных версиях сайтов.

Если вы хотите узнать больше о данном минимизаторе, то рекомендую вам посмотреть видео-доклад Говарда Дёркинга «Bundling and Optimizing» [35].

Рекомендации по применению минимизаторов

Наиболее надежными минимизаторами являются минимизаторы из первой тройки: Microsoft Ajax Minifier, YUI Compressor и Google Closure Compiler (лидер по степени сжатия JS-кода). Все они обладают хорошей степенью сжатия, а обработанный ими код практически не содержит ошибок.

Новые минимизаторы, которые были разработаны под Node.js: UglifyJS и CSSO, дают более высокую степень сжатия, чем минимизаторы первой тройки (UglifyJS в некоторых случаях сжимает лучше, чем Google Closure Compiler в режиме Simple), но пока еще не обладают таким уровнем надежности.

Самые старые минимизаторы: JSMin и Packer, сейчас годятся только для сжатия самого простого JS-кода. К сожалению, они проигрывают современным минимизаторам и по степени сжатия, и по уровню надежности.

Я не сравнивал семантический минимизатор CSS-кода WebGrease с другими минимизаторами из-за специфики ошибки, содержащейся в нем. Но по общим наблюдениям, мне кажется, что он обладает большей степенью сжатия кода, чем CSSO.

Настройки

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

<?xml version="1.0" encoding="utf-8"?>
<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.LessLite.Configuration.LessLiteSettings" />
			<section name="sassAndScss" 
				type="BundleTransformer.SassAndScss.Configuration.SassAndScssSettings" />
			<section name="microsoftAjax"
				type="BundleTransformer.MicrosoftAjax.Configuration.MicrosoftAjaxSettings" />
			<section name="yui" type="BundleTransformer.Yui.Configuration.YuiSettings" />
			<section name="closure" 
				type="BundleTransformer.Closure.Configuration.ClosureSettings" />
			<section name="uglify" 
				type="BundleTransformer.UglifyJs.Configuration.UglifySettings" />
			<section name="packer" 
				type="BundleTransformer.Packer.Configuration.PackerSettings" />
			<section name="csso" type="BundleTransformer.Csso.Configuration.CssoSettings" />
		</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"
			useEnableOptimizationsProperty="true">
			<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" />
					<add name="KryzhanovskyCssMinifier" 
						type="BundleTransformer.Csso.Minifiers.KryzhanovskyCssMinifier, BundleTransformer.Csso" />
					<add name="WgCssMinifier" 
						type="BundleTransformer.WG.Minifiers.WgCssMinifier, BundleTransformer.WG" />
				</minifiers>
				<translators>
					<add name="NullTranslator"
						type="BundleTransformer.Core.Translators.NullTranslator, BundleTransformer.Core" 
						enabled="false" />
					<add name="LessTranslator" 
						type="BundleTransformer.LessLite.Translators.LessTranslator, BundleTransformer.LessLite"
						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" />
					<add name="ClosureRemoteJsMinifier" 
						type="BundleTransformer.Closure.Minifiers.ClosureRemoteJsMinifier, BundleTransformer.Closure" />
					<add name="ClosureLocalJsMinifier"
						type="BundleTransformer.Closure.Minifiers.ClosureLocalJsMinifier, BundleTransformer.Closure" />
					<add name="CrockfordJsMinifier"
						type="BundleTransformer.JsMin.Minifiers.CrockfordJsMinifier, BundleTransformer.JsMin" />
					<add name="UglifyJsMinifier" 
						type="BundleTransformer.UglifyJs.Minifiers.UglifyJsMinifier, BundleTransformer.UglifyJs" />
					<add name="EdwardsJsMinifier" 
						type="BundleTransformer.Packer.Minifiers.EdwardsJsMinifier, BundleTransformer.Packer" />
				</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>
			<assetHandler clientCacheDurationInDays="365" enableCompression="true"
				useLastModifiedHeader="true" useETagHeader="true"
				serverCacheDurationInMinutes="15" useServerCacheSlidingExpiration="false"
				disableClientCacheInDebugMode="true" disableCompressionInDebugMode="true" />
		</core>
		<less useNativeMinification="false" severity="0" />
		<sassAndScss useNativeMinification="false" />
		<microsoftAjax>
			<css allowEmbeddedAspNetBlocks="false" colorNames="Strict" commentMode="Important" 
				ignoreErrorList="" indentSize="4" minifyExpressions="true" 
				outputMode="SingleLine" blocksStartOnSameLine="NewLine" preprocessorDefineList="" 
				termSemicolons="false" severity="0" />
			<js allowEmbeddedAspNetBlocks="false" collapseToLiteral="true" 
				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" blocksStartOnSameLine="NewLine"
				preprocessorDefineList="" preserveFunctionNames="false" 
				preserveImportantComments="true" removeFunctionExpressionNames="true" 
				removeUnneededCode="true" renamePairs="" strictMode="false" 
				stripDebugStatements="true" termSemicolons="false" severity="0"/>
		</microsoftAjax>
		<yui>
			<css compressionType="Standard" removeComments="true"
				lineBreakPosition="-1" />
			<js compressionType="Standard" obfuscateJavascript="true"
				preserveAllSemicolons="false" disableOptimizations="false"
				ignoreEval="false" severity="0" lineBreakPosition="-1"
				encoding="UTF8" threadCulture="en-us" />
		</yui>
		<closure>
			<js>
				<remote 
					closureCompilerServiceApiUrl="http://closure-compiler.appspot.com/compile" 
					compilationLevel="Simple" prettyPrint="false" excludeDefaultExterns="false" 
					severity="0" />
				<local 
					javaVirtualMachinePath="" closureCompilerApplicationPath="" 
					compilationLevel="Simple" prettyPrint="false" 
					languageSpec="EcmaScript3" thirdParty="true"
					processJqueryPrimitives="false" processClosurePrimitives="false"
					severity="0" />
			</js>
		</closure>
		<uglify>
			<js>
				<parser strictSemicolons="false" />
				<mangler mangle="true" topLevel="false" defines="" 
					except="" noFunctions="false" />
				<squeezer makeSequences="true" deadCode="true" unsafe="false" />
				<codeGenerator beautify="false" indentStart="0" indentLevel="4" 
					quoteKeys="false" spaceColon="false" asciiOnly="false" />
			</js>
		</uglify>
		<packer>
			<js shrinkVariables="true" base62Encode="false" />
		</packer>
		<csso>
			<css disableRestructuring="false" />
		</csso>
	</bundleTransformer>
	<!-- /Bundle Transformer configuration settings -->
	...
</configuration>

В предыдущем обзоре [3] я уже описывал структуру конфигурационной секции bundleTransformer, поэтому на этот раз ограничусь лишь перечислением новых секций:

  • closure – настройки модуля BundleTransformer.Closure
  • uglify – настройки модуля BundleTransformer.UglifyJs
  • packer – настройки модуля BundleTransformer.Packer
  • csso – настройки модуля BundleTransformer.Csso

Названия и возможные значения свойств перечисленных выше конфигурационных секций также не нуждаются в пояснениях, т.к. практически полностью совпадают с конфигурационными свойствами исходных минимизаторов. Также напоминаю, что для конфигурационной секции bundleTransformer реализована поддержка IntelliSense:

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

Заключение

В заключении я хотел бы отметить некоторые важные моменты, касающиеся B/M и Bundle Transformer.

Многие считают, что B/M может работать только с ASP.NET MVC, но это не так. Вы можете использовать B/M и в других ASP.NET-фреймворках: Web Forms и Web Pages (в разделе ссылки указаны статьи, в которых рассказывается, как это можно сделать).

Текущие версии B/M и Bundle Transformer написаны под .NET Framework 4.0, поэтому ничто не мешает вам использовать их в ASP.NET MVC 3 и ASP.NET Web Forms 4.0.

Ссылки

  1. Страница Bundle Transformer [1] на CodePlex
  2. Страница Microsoft ASP.NET Web Optimization Framework [2] на CodePlex
  3. Видео-доклад Говарда Дёркинга «Bundling and Optimizing» [35]
  4. Видео-доклад Говарда Дёркинга «Build high-performing HTML 5 applications easily with ASP.NET 4.5» [37]
  5. Учебник Рика Андерсона «Bundling and Minification» [38]
  6. Статья Рика Андерсона «Adding Bundling and Minification to Web Forms» [39] (перевод [40])
  7. Статья Рика Андерсона «Adding Web Optimization to a Web Pages Site» [41] (перевод [42])
  8. Статья Говарда Дёркинга «Keeping in touch with the Web optimization team» [43]

Автор: Taritsyn


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/15714

Ссылки в тексте:

[1] Bundle Transformer: http://bundletransformer.codeplex.com/

[2] Microsoft ASP.NET Web Optimization Framework: http://aspnetoptimization.codeplex.com/

[3] обзор возможностей Bundle Transformer: http://taritsyn.wordpress.com/2012/04/17/bundle-transformer-modulnoe-rasshirenie-dlja-asp-net-bundling-and-minification/

[4] dotless: http://www.dotlesscss.org/

[5] DotlessClientOnly: http://nuget.org/packages/DotlessClientOnly

[6] BundleTransformer.LessLite: http://nuget.org/packages/BundleTransformer.LessLite

[7] BundleTransformer.Less: http://nuget.org/packages/BundleTransformer.Less

[8] LESS: http://lesscss.org/

[9] BundleTransformer.CoffeeScript: http://nuget.org/packages/BundleTransformer.CoffeeScript

[10] SassAndCoffee.JavaScript: http://github.com/xpaulbettsx/SassAndCoffee

[11] CoffeeScript: http://coffeescript.org/

[12] Microsoft Ajax Minifier: http://ajaxmin.codeplex.com/

[13] YUI Compressor: http://developer.yahoo.com/yui/compressor/

[14] BundleTransformer.Closure: http://nuget.org/packages/BundleTransformer.Closure

[15] Google Closure Compiler Service API: http://developers.google.com/closure/compiler/docs/gettingstarted_api

[16] Google Closure Compiler Application: http://developers.google.com/closure/compiler/docs/gettingstarted_app

[17] виртуальную машину Java: http://www.java.com/download/

[18] compiler.jar: http://closure-compiler.googlecode.com/files/compiler-latest.zip

[19] BundleTransformer.JsMin: http://nuget.org/packages/BundleTransformer.JsMin

[20] JSMin: http://www.crockford.com/javascript/jsmin.html

[21] BundleTransformer.UglifyJs: http://nuget.org/packages/BundleTransformer.UglifyJs

[22] UglifyJS: http://github.com/mishoo/UglifyJS

[23] BundleTransformer.Packer: http://nuget.org/packages/BundleTransformer.Packer

[24] Packer: http://dean.edwards.name/packer/

[25] CSSO: http://github.com/css/csso

[26] БЭМ: http://bem.github.com/bem-method/pages/beginning/beginning.ru.html

[27] Noesis Javascript .NET: http://javascriptdotnet.codeplex.com

[28] BundleTransformer.Csso.x86: http://nuget.org/packages/BundleTransformer.Csso.x86

[29] BundleTransformer.Csso.x64: http://nuget.org/packages/BundleTransformer.Csso.x64

[30] x86: http://www.microsoft.com/en-us/download/details.aspx?id=5555

[31] x64: http://www.microsoft.com/en-us/download/details.aspx?id=14632

[32] BundleTransformer.WG: http://nuget.org/packages/BundleTransformer.WG

[33] WebGrease: http://nuget.org/packages/WebGrease

[34] ошибку: http://aspnetoptimization.codeplex.com/workitem/2

[35] «Bundling and Optimizing»: http://channel9.msdn.com/Events/aspConf/aspConf/Bundling-and-Optimizing

[36] Image: http://taritsyn.files.wordpress.com/2012/09/bundle_transformer_configuration_section_intellisense.png

[37] «Build high-performing HTML 5 applications easily with ASP.NET 4.5»: http://visualstudiolaunchstaging.social27.com/vs2012vle/Theater?sid=1760

[38] «Bundling and Minification»: http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

[39] «Adding Bundling and Minification to Web Forms»: http://blogs.msdn.com/b/rickandy/archive/2012/08/14/adding-bundling-and-minification-to-web-forms.aspx

[40] перевод: https://www.pvsm.ru/post/150863/

[41] «Adding Web Optimization to a Web Pages Site»: http://blogs.msdn.com/b/rickandy/archive/2012/08/15/adding-web-optimization-to-a-web-pages-site.aspx

[42] перевод: https://www.pvsm.ru/post/150946/

[43] «Keeping in touch with the Web optimization team»: http://codebetter.com/howarddierking/2012/08/16/keeping-in-touch-with-the-web-optimization-team/