Не даем бандлам испортить вам жизнь

от автора


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

Я видел разные способы группировки скриптов, но, честно говоря, ни один из них мне до конца не нравился. Как все-таки группировать скрипты так, чтобы было сложнее всего в них запутаться и не приходилось бы заморачиваться по поводу конфликтов разных бандлов на одной странице? Для себя я придумал подход, который, на мой взгляд, упросит жизнь. Очень буду рад здоровой критике и полезным советам.

Начнем с того, что попробуем проанализировать парочку подходов для группировки скриптов:
Первый подход — объединение в группы по общему назначению скриптов.

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(     "~/Scripts/jquery-{version}.js"));  bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(     "~/Scripts/jquery-ui-{version}.js"));  bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(     "~/Scripts/jquery.unobtrusive*",     "~/Scripts/jquery.validate*")); 

Достаточно просто и проблем быть не должно, но этого подхода не достаточно. Кастомные скрипты тоже как-то нужно сгруппировать. Здесь и возникает второй подход — объединение скриптов в какой-то базовый бандл.

bundles.Add(new ScriptBundle("~/Scripts/base").Include(     "~/Scripts/placeholder.js",     "~/Scripts/modernizr-*",     "~/Scripts/my-custom-script-1",     "~/Scripts/my-custom-script-2)); 

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

Я для себя выбрал следующий путь:
1. На каждый лэйаут — 1 бандл.
Называю бандл таким же именем, как и сам лэйаут и решаю головную боль с тем, что подключать, куда подключать и сколько подключать.

2. Бандлы подключаются только на лэйаутах.
В итоге: сколько лэйаутов — столько и одноименных бандлов.

Если здесь у вас возникла буря негодований, то попридержите их до конца пути, когда сложится целостная картина.

3. Вводим понятие групп, которое будет являться просто массивом строк.
В группу объединяем все необходимые скрипты для какого-то конкретного функционала. Вот пример группы скриптов для рендеринга отчетов с графиками на svg холстах:

var reportScriptGroup = new[] {     "~/Scripts/jquery-{version}.js",     "~/Scripts/raphael.js",     "~/Scripts/Custom/charts.js",     "~/Scripts/Custom/report.js" }; 

Предположим, что в этом же лэйауте вам необходима клиентская валидация, добавляем группу для валидации:

var validationScriptGroup = new[] {     "~/Scripts/jquery-{version}.js",     "~/Scripts/jquery.validate.js",     "~/Scripts/jquery.validate.unobtrusive.js",     "~/Scripts/Custom/jquery.custom.validate.js" }; 

Обратите внимание на наличие jquery-{version}.js в обоих группах, но это нам не мешает добавить обе группы в один и тот же бандл. Он сам позаботится о том, чтобы сделать дистинкт.

bundles.Add(new ScriptBundle("~/Scripts/_DashboardLayout")         .Include(baseScriptGroup)         .Include(validationScriptGroup)         .Include(reportScriptGroup)     ) ); 

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

Напишем нехитрый метод для исключения скрипта из группы:

private static string[] Exclude(this IEnumerable<string> input, params string[] items) {     var output = input;     foreach (var item in items)     {         output = output.Where(x => x != item).ToArray();     }      return output.ToArray(); } 

А бандл для него будет выглядеть вот так:

bundles.Add(new ScriptBundle("~/Scripts/_PrintLayout")         .Include(baseScriptGroup.Exclude("~/Scripts/Custom/fading.js"))         .Include(reportScriptGroup)     ) ); 

Вот и все. Таким образом можно просто объединять группы в бандл. Захотелось подключить графики — добавил в бандл группу с графиками. Захотел валидацию — добавь и ее.

Считаете ли вы такой подход полезным?

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

Никто ещё не голосовал. Воздержавшихся нет.

ссылка на оригинал статьи http://habrahabr.ru/post/231125/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *