Комплектация в ASP.NET

ASP.NET — это технология, позволяющая повысить производительность. С выходом ASP.NET 4.5 ее стек сделал огромный шаг вперед, добавив автоматизированную комплектацию веб-ресурсами, что сделало его легким и гибким в работе.

В этой статье я хотел бы рассмотреть комплектацию элементов в ASP.NET. Я расскажу вам, как полностью настроить комплектации для любого проекта ASP.NET.

В ASP.NET 4.5
фреймворк получил новое пространство имен System.Web.Optimization. Давайте посмотрим, как это работает.

Настройка

В этой статье я начину с пустого проекта ASP.NET MVC. Таким образом, я могу сосредоточиться на том, что нужно для того, чтобы настроить автоматизированную комплектацию. Те же основные шаги применяются и в WebForms. В этой статье я буду использовать Razor и C#.

После нажатия на соответствующие кнопки для создания нового проекта добавьте эти пакеты в консоли NuGet Package Manager:

PM> Install-Package Microsoft.AspNet.Mvc
PM> Install-Package jQuery
PM> Install-Package Bootstrap
PM> Install-Package Microsoft.AspNet.Optimization

Я хотел бы обратить ваше внимание на пакет NuGet под названием Microsoft.AspNet.Optimization. Если вы работаете с уже существующим проектом ASP.NET, этот пакет NuGet сделает вашу работу более простой. После того, как он будет установлен, все, что вам нужно сделать, это создать остальную часть структуры.

С этим пакетом для веб-оптимизации вы получаете инструмент для автоматизации управления веб-ресурсами. Официальную документацию вы можете найти на MSDN.

Теперь добавьте папку с именем App_Start в основной проект, если ее там еще нет. Нам нужно задать комплектацию, добавив этот статический класс:

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
    }
}

Маршрутизация задается с помощью любого существующего проекта, так что я не буду на этом останавливаться.

Для того чтобы ASP.NET знал о вашей новой сконфигурированной комплектации, сделайте следующее в Global.asax:

public class Global : HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

ASP.NET является событийно ориентированной технологией. Вы можете представить ее себе, как IIS-сервер, который ожидает новые события. В нашем случае клиентских запросов браузера через HTTP.

Когда приложение впервые запускается, ASP.NET вызывает Application_Start в Global.asax. Application_Start — это место где вы должны задать конкретные пакеты, которые вы хотите использовать в вашем приложении.

В конце концов, мое решение задается следующим образом:

мое решение задается следующим образом

Отслеживание трафика

Пришло время добавить пакеты и посмотреть, как они отобразятся на работе браузера. Добавьте следующий код в BundleConfig, статический класс я упомянул ранее:

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new StyleBundle("~/bundle/bootstrap-styles")
            .Include("~/Content/bootstrap.css")
            .Include("~/Content/bootstrap-theme.css")
            .Include("~/Content/Site.css"));
        bundles.Add(new StyleBundle("~/bundle/Home/Index-styles")
            .Include("~/Content/StyleSheet1.css")
            .Include("~/Content/StyleSheet2.css")
            .Include("~/Content/StyleSheet3.css"));

        bundles.Add(new ScriptBundle("~/bundle/bootstrap-scripts")
            .Include("~/Scripts/bootstrap.js")
            .Include("~/Scripts/jquery-{version}.js")
            .Include("~/Scripts/modernizr-{version}.js"));
        bundles.Add(new ScriptBundle("~/bundle/Home/Index-scripts")
            .Include("~/Scripts/JavaScript1.js")
            .Include("~/Scripts/JavaScript2.js")
            .Include("~/Scripts/JavaScript3.js"));
    }
}

Ваши конкретные потребности могут быть разными. Приведенный выше метод принимает BundleCollection в качестве параметра. Обратите внимание, что BundleTable.Bundles передается из Global.asax. После этого я создаю набор стилей и скриптов, которые соответствуют моим потребностям.

Я использую директиву {version}, чтобы указать движку комплектации использовать любую версию JQuery, которая встречается в моих решениях. В конфигурации JQuery Release .min.js будет добавляться к комплектации, а в Debug нет.

Это дает мне гибкость среды разработки при работе с JQuery. Я могу заменять различные версии JQuery, и на моих установках комплектации это не отразится. Этот же прием применим к любой другой клиентской библиотеке.

Так как я задаю свои собственные пакеты, я могу подогнать ресурсы под конкретные экраны.

Я поместил пакеты ~/bundle/bootstrap-styles и ~/bundle/bootstrap-scripts на главную страницу _Layout.cshtml. Поскольку это сложный элемент с большим количеством начальных загрузок, я не буду описывать его в этой статье.

Вот как теперь выглядит моя страница Razor Index.cshtml:

@{
    ViewBag.Title = "Index";
}

@Styles.Render("~/bundle/Home/Index-styles")
<h2>Hello World</h2>
<p>
    Be sure to check out glyphs like these:
    <span class="glyphicon glyphicon-plus"></span>.
</p>
@Scripts.Render("~/bundle/Home/Index-scripts")

Все просто. После того, как пакеты определены, я могу поместить их в любом месте моего приложения. Я следую простой конвенции {Controller}/{Action}, чтобы определить комплектацию. Вы можете сделать то же самое.

Если вы увидите, что выводится ошибка страницы Razor, так как он не может найти Styles.Render или Scripts.Render, убедитесь в том, что вы включили их в файле Web.config, который находится в папке Views:

<system.web.webPages.razor>
  ...
  <pages pageBaseType="System.Web.Mvc.WebViewPage">
    <namespaces>
      ...
      <add namespace="System.Web.Optimization"/>
    </namespaces>
  </pages>
  </system.web.webPages.razor>
</system.web.webPages.razor>

Это указывает движку Razor включить пространство имен System.Web.Optimization при визуализации динамического HTML. Вы можете также включить любые другие пространства имен, которые необходимы для вашего конкретного проекта. Это даст вам возможность полностью не квалифицировать каждое расширение Razor.

Теперь давайте посмотрим на сетевой трафик:

сетевой трафик

Красный цвет означает, что браузер простаивает. Желтый — когда браузер делает запрос. Синий — время, необходимое для получения ответа от сервера.

В большинстве современных браузеров, вы можете сделать около шести запросов одновременно. Если вам нужно больше, чем шесть запросов, браузеру придется ждать. Самый верхний запрос — это динамический HTML, который я должен получить от сервера.

Почему это важно?

Что понять, как это все работает, вы можете представить себе язык программирования серверной стороны C #, как космический корабль. Во время космического путешествия при увеличении скорости вы будете наблюдать эффект замедления времени.

Пока бэк-энд работает локально на вашем сервере можно предположить, что он будет делать все с высокой производительностью. Но, когда запрос передается по каналам HTTP, это совсем другая история.

Я представляю себе сетевой протокол HTTP, как повозку, которую должен тянуть мул. Независимо от того, насколько хорошо или плохо оптимизирована ваша серверная часть, все равно HTTP будет работать медленнее.

Таким образом, было бы хорошо загрузить корзину мула большим количеством провизии, прежде чем он отправится через весь город. Постоянная отправка запросов и получение ответов снова и снова это верный способ убить производительность.

HTTP запросы потребляют много ресурсов. Ваша главная цель состоит в том, чтобы уменьшить количество обращений по HTTP.

Подключения

Чтобы подключить комплектацию во фреймворке необходимо произвести следующее изменение в файле Web.config папки вашего решения:

<compilation debug="false" targetFramework="4.5" />

Вы можете также жестко установить это с помощью:

BundleTable.EnableOptimizations = true;

Когда вы жестко устанавливаете это в C #, данное указание будет иметь приоритет над Web.config. В стандартной настройке вы можете использовать изменение в файле Web.config для его включения в режим Release. Тогда вам больше не нужно будет пытаться отладить минимизированный JavaScript-код.

Давайте посмотрим на трафик после подключения комплектации:

трафик после подключения

Здорово. Ресурсы начинают загружаться, как только загрузился динамический HTML. Теперь я в полной мере задействую возможности браузера, так как теперь запрашиваются ровно шесть ресурсов. Обратите внимание, что последний ресурс не запускается, пока все другие ресурсы не будут выданы. Это происходит потому, что это веб-шрифт, и он связан с CSS пакетом.

Кэширование

Когда комплектация подключена, вы получаете дополнительную выгоду от того, что ресурсы кэшируются в браузере приблизительно в течение одного года. Если ваши ресурсы изменятся до того, строка запроса, добавляемая в конец, изменится. Это, по сути, приводит к тому, что какие-то ресурсы браузеру больше не будут нужны. Это часто называют кэш-перебором.

Например, вот как будут выглядеть наши скомплектованные ресурсы:

/bundle/bootstrap-styles?v=epi1k_G4Tsd0o4dXIOJcBg5gefY7ieCSx0AUDxqm78U1
/bundle/Home/Index-styles?v=uxFDb5XiuKadZOyd2DKyzUU-mh3OUTNuikUDUlL7e_Q1
/bundle/Home/Index-scripts?v=Giv511fvuZRlJKLjJDPqmIxOhmtht9zFlW7lvvTMf0Y1
/bundle/bootstrap-scripts?v=j4YIBwFVDdtvOMWp63GzkWLSoYrcw0ertU_njZLALnk1

Строка запроса, добавляемая в конец, это хэш из конкретного содержимого каждого пакета. Когда содержимое внутри пакета изменяется, хэш, добавляемый, как строка запроса, также изменится.

Вы можете проверить заголовки HTTP:

Вы можете проверить заголовки

Срок кэширования HTTP заголовка Expires истекает через один год.

Заключение

ASP.NET — это крутая технология, созданная, чтобы сделать вашу жизнь проще. То, что мне нравится в ней больше всего, это то, как движок выводит для нас тэги <link> и <style>. Я всегда больше всего волновался по тому поводу, что эти теги будут расставлены кругом. А это настоящий кошмар для управления веб-ресурсом.

Я надеюсь, что вы теперь понимаете, как полностью задать автоматизированную комплектацию для вашего проекта. Обязательно посмотрите простое демо, демонстрирующее основы этого метода, которое размещено на GitHub.

Что вы думаете о функции комплектации ASP.NET? Есть ли у вас какие-либо собственные рекомендации по повышению производительности?

Перевод статьи «Bundling in ASP.NET» был подготовлен дружной командой проекта Сайтостроение от А до Я.