System.Web.Bem - БЭМ-инфрастурктура для ASP.NET MVC.
-
Убедитесь, что на компьютере, где будет выполняться сборка проекта, установлен node.js (при этом для работы приложения устанавливать node.js не обязательно).
-
Установите пакет System.Web.Bem в свой проект ASP.NET MVC.
PM> Install-Package System.Web.Bem -Pre
- Верните из метода контроллера экземпляр класса
BemhtmlResult
, передав ему в конструктор нужный bemjson.
using System.Web.Bem;
...
public class DefaultController : Controller
{
public ActionResult Index()
{
return new BemhtmlResult(new { block = "p-index" });
}
}
БЭМ (Блок-Элемент-Модификатор) - это придуманная в Яндексе методология разработки веб-приложений, в основе которой лежит компонентный подход. БЭМ - это также набор инструментов для удобной разработки в соответствии с принципами методологии. БЭМ помогает быстрее разрабатывать сайты и поддерживать их долгое время.
Согласно правилам БЭМ, приложение состоит из независимых блоков, которые лежат в отдельных папках. Каждый блок реализован в нескольких технологиях (шаблоны, стили, клиентский код). Чтобы код блоков мог работать в приложении, блоки собирают в бандлы.
Декларация бандла - файл с перечислением блоков, которые должны попасть в бандл. На основе декларации сборщик собирает бандл, учитывая зависимости блоков и уровни переопределения. Бандл собирается отдельно для каждой технологии. Во время работы приложения бандл шаблонов используется для формирования html (на сервере и клиенте), бандлы js и css подключаются на страницы и используются на клиенте.
System.Web.Bem - БЭМ-инфрастурктура для ASP.NET MVC проектов. При установке в проект NuGet пакета System.Web.Bem:
- добавляется папка
Bem
с файловой структурой БЭМ проекта; - из npm ставится сборщик БЭМ-проектов enb и настройки для сборки БЭМ-бандлов при компиляции ASP.NET MVC проекта;
- подключается C# библиотека
System.Web.Bem
для серверной шаблонизации во время работы приложения.
<Project root> // корневая папка проекта
├─ Bem // папка БЭМ-проекта
│ ├─ .enb
│ │ └─ make.js // конфиг сборщика enb
│ ├─ desktop.blocks // уровень переопределения, внутри находятся блоки
│ │ ├─ block-1
│ │ ├─ block-2
│ │ │ ...
│ │ └─ block-n
│ │ ├─ block-n.bemhtml.js // реализация блока block-n в технологии bemhtml.js (шаблоны)
│ │ ├─ block-n.css // реализация блока block-n в технологии css
│ │ │ ... // ...
│ │ └─ block-n.js
│ ├─ desktop.bundles // папка с бандлами проекта
│ │ ├─ bundle-1
│ │ ├─ bundle-2
│ │ │ ...
│ │ └─ bundle-n
│ │ └─ bundle-n.bemdecl.js // декларация бандла bundle-n
│ └─ levels.js // список уровней переопределения
│ ...
├─ Controllers // Controllers, Models, Views - стандартные папки ASP.NET MVC
├─ Models
├─ Views
│ ...
├─ package.json // конфиг npm
└─ Web.config // конфиг вашего приложения
Внимание! Для сборки проекта необходимо, чтобы на компьютере был установлен node.js. Для работы приложения на сервере устанавливать node.js нет необохдимости.
Чтобы код блоков мог работать в приложении, блоки собирают в бандлы. Сборка бандла выполняется на основе декларации - специального файла, где перечислены блоки, которые должны попасть в бандл. Пример декларации бандла:
exports.blocks = [
{ name: 'block1' },
{ name: 'block2' }
];
Декларации находятся в папке /Bem/desktop.bundles
, каждый бандл в своей папке. Имя файла декларации должно соответствовать имени бандла и иметь расширение bemdecl.js
. Например, декларация бандла default
должна находиться в файле /Bem/desktop.bundles/default/default.bemdecl.js
.
Сборка выполняется специальной утилитой enb, которая добавляется в проект при установке NuGet пакета System.Web.Bem. Во время установки пакета настраивается автоматический запуск enb при сборке всего проекта через MsBuild. Таким образом, когда вы собираете ASP.NET MVC проект в Visual Studio, вместе с компиляцией c# кода будет запущена и сборка БЭМ-бандлов. Во время сборки ищутся все декларации внутри /Bem/desktop.bundles
и для каждой из них собираются бандлы технологий (шаблоны, js, css).
Бандлы технологий имеют имя <bundle_name>.<tech_ext>
и сохраняются в папку, где находится декларация. Например, файл шаблонов (bemhtml.js) для бандла default
будет иметь путь /Bem/desktop.bundles/default/default.bemhtml.js
. Таким образом, после сбоки проекта вы будете наблюдать примерно такую картину:
<Project root>
├─ Bem
│ ├─ ...
│ └─ desktop.bundles
│ ├─ default
│ │ ├─ default.bemdecl.js // декларация бандла
│ │ ├─ default.bemhtml.js // бандл с шаблонами
│ │ ├─ default.js // бандл с клиентским кодом
│ │ └─ default.css // бандл со стилями
│ │ └─ ... // бандлы других технологий
│ └─ ...
└─ ...
Во время работы приложения бандл шаблонов используется для формирования html (на сервере и клиенте), бандлы js и css подключаются на страницы и используются на клиенте. Во время серверной шаблонизации будет использоваться бандл с шаблонами, указанный в настройках приложения. Бандлы js и css нужно самостоятельно подключить на страницу.
BEMHTML - специальный шаблонизатор, который удобно использовать в БЭМ-проектах.
При установке NuGet пакета System.Web.Bem в проект будет добавлена .NET библиотека для шаблонизации BEMHTML шаблонов на стороне сервера во время работы приложения. Чтобы передать на клиент страницу, сформированную с помощью bemhtml шаблонов, просто верните из контроллера экземпляр класса BemhtmlResult
, передав ему в конструктор нужный bemjson.
using System.Web.Bem;
...
public class DefaultController : Controller
{
public ActionResult Index()
{
return new BemhtmlResult(new { block = "p-index" });
}
}
Если нужно внутри Razor-шаблона вставить БЭМ-блок, используйте хелпер @Html.Bem
, передав ему нужный bemjson.
@Html.Bem(new { block = "my-block", data = Model })
В разделе bemSettings
файла Web.config вы можете настраивать, каким способом будут выбираться бандлы с bemhtml шаблонами для http-запросов. Возможны 3 варианта мэппинга запросов на бандлы:
- Один общий бандл на всё приложение - его название можно задать в параметре
DefaultBundle
(по умолчаниюdefault
):
<bemSettings Mapper="Single" DefaultBundle="index" />
- Отдельный бандл для каждого серверного контроллера:
<bemSettings Mapper="ByController" />
Название бандла определяется по названию контроллера: слова разделяются дефисами, приводятся к нижнему регистру, удаляется суффикс "controller" и добавляется префикс p-
(например, MainPageController
→ p-main-page
).
- Собственный мэппер - есть возможность написать свой класс мэппера и указать его название в параметре
Mapper
:
<bemSettings Mapper="MyApplication.MyNamespace.InnerNamespace.MyMapperClass" />
Класс мэппера должен быть унаследован от базового класса System.Web.Bem.BundleMappers.Mapper и реализовывать метод abstract string GetBundleName(ControllerContext context)
, получающий на вход контекст запроса и возвращающий название бандла. Также, при желании, можно переопределить метод virtual string GetBundlePath(string bundleName)
, возвращающий по названию бандла путь к файлу с bemhtml шаблонами (по умолчанию формируется путь <RootDir>\<bundleName>\<bundleName>.bemhtml.js
)
Также в настройках можно задать корневую папку для БЭМ-бандлов проекта (по умолчанию, ~/Bem/desktop.bundles
):
<bemSettings RootDir="~/public" />
Вы можете подключать в свой проект сторонние библиотеки с блоками и использовать их. Для этого скопируйте файлы блоков в свой проект и добавьте новые папки с блоками в список уровней переопределения.
Рекомендуется размещать сторонние библиотеки блоков в папке /Bem/libs
. Например:
└─ Bem
└─ libs // сторонние библиотеки блоков
├─ my-ext-block-library // папка библиотеки
│ ├─ common.blocks // уровень переопределения
│ │ ├─ block1
│ │ └─ block2
│ ├─ desktop.blocks // уровень переопределения
│ └─ ...
│ ...
└─ other-ext-block-library // папка библиотеки
Список уровней переопределения находится в файле /Bem/levels.js
.
├─ Bem
│ ├─ desktop.blocks
│ ├─ desktop.bundles
│ ├─ libs // сторонние библиотеки блоков
│ └─ levels.js // список уровней переопределения
└─ ...
По сути это список папок, из которых будут браться файлы блоков при сборке. Необходимо добавить в него папки уровней переопределения скопированных вами внешних библиотек. Для приведенного выше примера структуры файловой системы должно получиться примерно так:
module.exports = [
{ path: 'libs/my-ext-block-library/common.blocks', check: false },
{ path: 'libs/my-ext-block-library/desktop.blocks', check: false },
{ path: 'libs/other-ext-block-library/common.blocks', check: false },
...
'desktop.blocks'
];
Для удобства подключения в NuGet были выложены библиотеки bem-core и bem-components. Чтобы добавить их в свой проект установите NuGet пакеты bem-core, bem-components:
Install-Package bem-core
Install-Package bem-components
Уровни переопределения библиотек bem-core и bem-components уже перечислены в файле levels.js
, но по умолчанию закомментированы. Раскомментриуйте их.