Ускорение билда asp.net MVC в 10 раз или RazorGenerator как альтернатива MvcBuildViews

Долгое время одним из первых шагов после создания нового MVC-сайта у меня было редактирование .csproj и добавление магического элемента

<MvcBuildViews>true</MvcBuildViews>

Напомню, что этой директивой включается компиляция Razor-вьюшек, таким образом об ошибках в .cshtml файлах можно узнать не в рантайме (при открытии веб-странички), а во время компиляции проекта. Опция, безусловно, очень удобная, но очень сильно замедляющая процесс сборки. Так, при отключенной опции наш средних размеров MVC-проект собирается за 1 секунду, а со включенной — за 10 секунд (в проекте всего лишь чуть больше 100 cshtml файлов).
Такая немаленькая задержка очень серьезно сказывается на разработке — по сути при каждом билде можно легко успеть «переключиться» на браузер и пролистать пару страничек :)

Таким образом от MvcBuildViews очень захотелось отказаться, но при этом не потерять возможность обнаружения ошибок во вьюшках во время компиляции.
Проблему решил замечательный RazorGenerator от Дэвида Эббо. РазорГенератор интегрируется в качестве Custom Tool для Visual Studio и преобразует каждую вьюшку в соответствующий c#-код, который и компилируется в момент компиляции проекта и выдает ошибки абсолютно аналогичные MvcBuildViews. При этом время компиляции с RazorGenerator’ом составляет(в нашем случае) ту же 1 секунду, что и без него (с отключенным MvcBuildView). Итоговый выигрыш — в 10 раз (10 сек — компиляция + MvcBuildViews, 1 сек — компиляция + RazorGenerator).

Внедрение RazorGenerator’а очень просто и подробно расписано на странице проекта:

  1. Устанавливаем расширение «Razor Generator» для Visual Studio (Tools->Extension Manager->Online Gallery, набрать «Razor Generator» в поиске и установить)
  2. Устанавливаем NuGet-пакет RazorGenerator.MVC — он добавит собственный ViewEngine, который будет обрабатывать скомпилированные вьюшки
  3. Для обработки всех существующих вьюшек в Nuget-консоли вводим «Enable-RazorGenerator» (либо вручную для каждой вьюшки вписываем в поле Custom Tool — «RazorGenerator»
  4. Компилируем проект и радумеся в разы ускорившемуся процессу сборки

С какими проблемами я столкнулся при внедрении RazorGenerator:

  • Если у вас есть какие-то Razor-хэлперы в App_Code — то у них для сгенерированных c# файлов будет стоять Build ActionContent. Естественно, они при этом не будут компилироваться. Необходимо вручную поменять Build Action на Compile
  • Еще про хэлперы в App_Code — для их использования необходимо будет добавить @using YourProjectNamespace.App_Code в каждую вьюшку, где они используются (ну или добавить неймспейс один раз в VIEWS/web.config system.web.webPages.razor/pages/namespaces плюс аналогично в Areas/web.config, если такая папка у вас есть)
  • Почему-то RazorGenerator-у не нравилось использование статических методов от String с заглавной буквы (например, String.IsNullOrEmpty). Впрочем, изменение буквы с заглавной на строчную решило проблему (String.Empty стал string.Empty и все заработало)
  • Одинаковые имена у вью-моделей и вьюшек. У меня был один случай, когда вью-модель называлась StageView и вьюшка для него называлась StageView.cshtml. Во вьюшке первыми же строками шло:
    @using IndexingImage.Mvc.HomeController
    @model StageView
    

    Сгенеренный РазорГенератором код выглядел при этом так:

    public class StageView : System.Web.Mvc.WebViewPage<StageView>
    

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

    @model IndexingImage.Mvc.HomeController.StageView
    

К слову, у RazorGenerator’a есть и еще один полезный сайд-эффект: поскольку компиляция вьюшек происходит одновременно с компиляцией проекта, то при запуске проекта отсутствует задержка при первом открытии веб-страниц (в норме именно в этот момент обычно происходит компиляция .cshtml файлов).

Удачи с использованием RazorGenerator’a!
Остались вопросы — добро пожаловать в комментарии.

P.S. Из минусов — расширение Razor Generator должны будут поставить себе все разработчики.

Опубликовать в Facebook
Опубликовать в Google Plus

1 комментарий

  1. У меня вообще директива @model Blabla сгенерировалась как Write(model). WTF?

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

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