Объединение и минификация файлов на примере ASP.NET Core MVC. Bundling and Minification

Дата публикации: 05.04.2019. Категория: ASP.NET Core MVC
Последнее обновление: 20.01.2020

Обсудим далеко не новую, но при этом очень важную и актуальную тему - объединение и минификация статичных файлов (css, js) в веб-приложении. Рассмотрим весь процесс оптимизации на примере простейшего веб-приложения типа ASP.NET Core MVC.

К слову сказать, объединение (связывание) и минификация – это общий процесс, применимый к сайтам любых типов, независимо от того, на каком языке программирования они написаны. Изучив этот вид оптимизации, Вы сможете применять его, используя ваши рабочие среду разработки и сопутствующие инструменты.

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

  1. Посмотрим на обычное веб-приложение и отметим проблемы, которые можно решить, применив объединение и минификацию файлов;
  2. Определим понятие, что такое объединение и минификация, смысл их использования;
  3. Оптимизируем веб-приложение, применив данный подход;
  4. Проанализируем результат и сравним с тем, что было в начале;
  5. Добавим кэширование для статичных файлов;
  6. Подготовим веб-приложение к публикации, сделав соответствующие настройки.

Инструменты и технологии, которые мы будем использовать в данном примере:

Чтобы быстрее разобраться в сути вопроса, давайте сразу перейдем к практике и посмотрим на существующую проблему. Для этого в Visual Studio создадим новое веб-приложение типа ASP.NET Core MVC. В качестве шаблона будем использовать стандартный пред подготовленный (Model-View-Controller), чтобы можно было сразу запустить приложение в работу.

Создание нового проекта типа ASP.NET Core MVC
Создание нового проекта типа ASP.NET Core MVC

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

Содержимое папки wwwroot
Содержимое папки wwwroot

Подключим все эти файлы в нашем приложении в мастер-странице (лишний код скрыт):

~/Views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
    ...
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
    <link rel="stylesheet" href="~/css/style.css" />
    ...
</head>
<body>
    ...
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js"></script>
    <script src="~/js/custom.js"></script>
    ...
</body>
</html>

После этого запустим веб-приложение и проанализируем сетевой трафик:

Анализ сетевого трафика
Анализ сетевого трафика

Мы видим, что к серверу было отправлено девять запросов, всего передано 730 КБ данных, время на полную загрузку страницы составило 590 мс. Также представлен список всех статичных переданных файлов.То есть на каждый файл отдельный запрос к серверу.

Как мы можем оптимизировать наше веб-приложение в данный момент? Мы можем уменьшить объем передаваемых данных по сети, а также мы можем сократить количество запросов к серверу, чем меньше, тем лучше.

В этом нам поможет использование объединения и минификации статичных файлов. Другими словами, мы можем сократить количество файлов и сжать их содержимое.

Объединение и минификация файлов (Bundling and Minification)

Объединение (bundling) – это соединение нескольких файлов одного типа в один общий файл.
Минификация (minification) – это сокращение содержимого файла путем удаления лишних пробелов, комментариев, заменой длинных обозначений на короткие.

В нашем веб-приложении мы с легкостью можем применить данный вид оптимизации. Объединим все файлы стилей CSS в один, объединим все файлы скриптов JS в один, а также сократим содержимое этих файлов, тем самым они будут меньше весить.

Для начала нам нужно настроить Visual Studio, а именно установить расширение «Bundler & Minifier».

Extensions -> Manage Extensions -> Online -> В поиске запрос "bundler"
Extensions -> Manage Extensions -> Online -> В поиске запрос "bundler"

Установка будет поставлена в очередь и потребуется перезагрузка среды Visual Studio.

После того, как дополнение установлено и готово к работе, мы можем начать процесс объединения и минификации файлов.

Начнем с CSS-файлов. Для этого в Solution Explorer выделяем все нужные файлы. После этого в контекстном меню выбираем пункт Bundle and Minify Files. Будет предложено дать название новому файлу и выбрать место для его сохранения.

Объединяем и минифицируем выбранные файлы
Объединяем и минифицируем выбранные файлы

В этом примере я обозвал файл bundleCss.css и сохранил его в новой папке content.

После первого применения минификации в корне проекта появится конфигурационный файл bundleconfig.json, в котором можно более гибко настроить правила связывания и минификации.

Результат объединения и минификации CSS-файлов
Результат объединения и минификации CSS-файлов

Подобным образом поступаем и с файлами скриптов JS - bootstrap.bundle.js, custom.js, site.js.

Однако библиотеку jquery.js включать в бандл не надо. Этот скрипт должен подключаться отдельным файлом в отдельном запросе для правильной работы и обязательно перед всеми остальными скриптами. Вместо этого мы просто скопируем его из папки \lib\jquery\dist\ в новую папку content.

В результате структура файлов будет выглядеть таким образом:

Все бандлы лежат в отдельной папке content
Все бандлы лежат в отдельной папке content

Обратите внимание, чтобы были созданы минифицированные версии файлов с расширением .min. Именно это версии файлов мы будем подключать в мастер-странице.

Содержание файла JS до и после минификации
Содержание файла JS до и после минификации
Обратите внимание, что расширение «Bundler & Minifier» автоматически отслеживает все изменения в указанных для него файлах. Так, при сохранении любых изменений в исходном файле, конечный бандл будет пересобран, что очень удобно.

Нам осталось подключить в мастер-странице новые минифицированные бандлы:

~/Views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
    ...
    <link rel="stylesheet" href="~/content/bundleCss.min.css" />
    ...
</head>
<body>
    ...
    <script src="~/content/jquery.min.js"></script>
    <script src="~/content/bundleJs.min.js"></script>
    ...
</body>
</html>

После этого перезапустим веб-приложение и вновь проанализируем сетевой трафик:

Анализ сетевого трафика после оптимизации веб-приложения
Анализ сетевого трафика после оптимизации веб-приложения

Количество запросов сократилось с девяти до пяти. Объем переданных данных с 730 КБ до 350 КБ. Время полной загрузки страницы сократилось с 590 мс до 440 мс.

Таким образом, некоторые показатели изменились примерно в два раза. В нашем простом примере это не сильно заметно, однако в реальных больших проектах разница может достигать сотен процентов.

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

Кэширование статичных файлов

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

Кэширование – процесс, при котором сохраняется копия полученного файла после отправки запроса на сервер. Если файл имеется в кэше, то все последующие запросы к серверу перехватываются, и выполняется загрузка копии файла из кэша.

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

Давайте в нашем веб-приложении укажем, какие файлы кэшировать и как управлять кэшированием этих файлов.

Во-первых, добавим в коде специальный атрибут ко всем тег-хелперам, которые подключают статичные файлы:

<link rel="stylesheet" href="/content/bundleCss.min.css" asp-append-version="true" />

asp-append-version="true" – данный атрибут добавляет к имени файла подстроку, содержащую контрольную сумму, которая отражает «версию» файла. В результате конечный HTML-код будет выглядеть следующим образом:

<link rel="stylesheet" href="/content/bundleCss.min.css?v=dkymHvTKJi-S47EBy_hrOtFIrpqvibgzaYqvwQ5DP-g" />

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

Во-вторых, добавим специальный HTTP-заголовок (HTTP Header) Cache-Control в ответах сервера, который будет использоваться для задания инструкций как кэшировать файлы.

Для этого в файле Startup.cs  в методе Configure() изменим настройку, которая позволяет обслуживать статичные файлы в приложении, следующим образом:

Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //... остальной код ...
    var fileOptions = new StaticFileOptions
    {
        OnPrepareResponse = (context) => context.Context.Response.Headers[HeaderNames.CacheControl] = "public, max-age=604800"
    };
    app.UseStaticFiles(fileOptions);
    //... остальной код ...
}

Значение заголовка "public, max-age=604800" означает, что файлы разрешено кэшировать на любом уровне, будь то конечный браузер пользователя, или публичный прокси-сервер. При этом файл считается актуальным на протяжении семи дней (604800 секунд).

Для нашего примера такая простая политика кэширования подходит. Однако в реальных проектах к этому вопросу стоит подходить очень внимательно. Более подробную информацию по этой теме можно найти в интернете, например, в блоге Google.

К имени файлов добавлена версия. В ответах сервера добавлен заголовок Cache-Control
К имени файлов добавлена версия. В ответах сервера добавлен заголовок Cache-Control

Настройка публикации проекта

Последнее, что осталось настроить в нашем веб-приложении – это правила публикации проекта. Мы объединили и минифицировали нужные нам статичные файлы. Теперь именно они используются и подключаются в коде приложения.

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

Открываем файл проекта на редактирование и добавляем следующие директивы:

Редактирование файла проекта
Редактирование файла проекта
WebApplication4.csproj
<ItemGroup>
    <Content Update="wwwroot\**" CopyToPublishDirectory="Never" />
    <Content Update="wwwroot\content\**" CopyToPublishDirectory="Always" />
</ItemGroup>

В этом коде мы запрещаем к публикации все внутреннее содержимое папки wwwroot, сделав исключение для папки content и всего ее содержимого.

Содержимое папки wwwroot после публикации проекта
Содержимое папки wwwroot после публикации проекта

 

Вернуться наверх
наверх