Блоки как кирпичи и бандлы как дома

Опубликовано 1/15/2014

Некотрое время назад мой знакомый, который делает проект на полном стеке БЭМ (BEM-CSS, i-bem.js и BEMHTML-шаблоны), задал мне несколько вопросов об использовании BEM project stub. Отвечая на вопрос, я пообещала опубликовать ответ в виде текста, потому что многие вещи вокруг БЭМ не проговариваются, считаясь слишком простыми — и ошибочно!

Вопрос был о конфигурационном файле .bem/make.js, который нужен при использовании bem tools для сборки страниц. Строчки 12 и 13 описывают регулярные выражения для blocks и bundles. Не сразу понятно, что это значит.

Вообще эти выражения нужны, чтобы распознать папки на файловой системе. Те, которые заканчиваются на .blocks — для блоков, а те, что заканчиваются на .bundles — для бандлов (страниц). Под эти выражения, например, подходят папки desktop.blocks и desktop.bundles из project-stub.

Для чего нужна папка desktop.blocks, должно быть понятно. Поскольку БЭМ — модульный паттерн, необходимо место для хранения модулей, то есть блоков. Каждый блок — это директория, содержащая все файлы, нужные для каждого конкретного интерфейсного модуля.

Вот, например, набор блоков одного проекта.

Папка desktop.bundles нуждается в пояснении. Она содержит страницы – результат использования блоков. Каждая страница помещена в отдельную директорию, внутри которой располагаются все файлы, нужные для страницы. Можно снова посмотреть пример из предыдущего проекта.

Разница в том, что файлы блоков созданы разработчиком, а файлы бандлов созданы bem tools. Для блоков это знакомые нам CSS, JavaScript и иногда шаблоны.

├── desktop.blocks/
│   ├── goods/
│   │   ├── goods.bemhtml
│   │   ├── goods.css
│   │   ├── goods.deps.js
│   │   └── goods.ie.css

Проводя параллели для БЭМ (и любого другого модульного паттерна) в реальном мире, можно сказать, что блок — это кирпичик.

Файлы бандлов — это тоже файлы, нужные для браузера: CSS, JavaScript, HTML. Ни один из них не написан разработчиком, они созданы bem tools. Можете посмотреть внутрь файлов и убедиться, что код абсолютно "роботный".

├── desktop.bundles/
│   ├── index/
│   │   ├── _index.css
│   │   ├── _index.js
│   │   ├── index.bemjson.js
│   │   └── index.html

Для понимания bem tools представьте, что это строительный кран. Он берет строительные блоки и возводит из них дом.

Хотя, кроме *.js, *.css и *.html файлов, всё-таки есть один файл, написанный разрабочиком. Это index.bemjson.js — JSON описание того, что за блоки нужны на странице и какова их древовидная структура. Звучит логично, ведь только человек знает, что нужно показать на странице. Всё остальное делают bem tools. Получив информацию о том, какие блоки нужны для страницы, они берут их код из desktop.blocks и формируют с их помощью страницу.

Продолжая пример со строительством дома, можно сказать что page.bemjson.js — это чертеж.

Но почему же bem tools нужно регулярное выражение в настройках?

Это несложно. Все папки, которыми оперирует bem tools — это уровни переопределения. Должно быть легче, если представлять уровень как набор сущностей. Уровень блоков представлен папкой desktop.blocks, а уровень страниц — папкой desktop.pages. В конфигурационной папке .bem/levels/ есть инструкции, по которым bem tools понимают, что делать с уровнями разных типов.

Выделяя в проекте блоки и бандлы, можно делать разные наборы блоков и разные бандлы, собранные из этих наборов. Например, блоки для desktop и touch версий сайта могут храниться в одном репозитории. И страницы, собранные из таких блоков — тоже.

├── desktop.blocks/
├── desktop.bundles/
├── touch.blocks/
└── touch.bundles/

Возвращаясь к примерам из реального мира, не только кирпичики могут быть модулями, но и детальки LEGO.

Из них также можно построить дом. Немножечко другой, конечно.

Если пойти дальше, вы можете выделить код блоков, общий для всех платформ, и хранить его отдельно.

├── common.blocks/
├── desktop.blocks/
├── desktop.bundles/
├── touch.blocks/
└── touch.bundles/

С такой структурой desktop версия формируется из кода блоков уровней common.blocks и desktop.blocks, а touch версия — из уровней common.blocks и touch.blocks.

И в заключении, я не перестаю радоваться идее проекта BEM project stub. Сама постоянно использую его, начиная новые проекты. Туториал о старте проекта на полном стеке БЭМ показывает, как именно. Так же БЭМ использует и знакомый, задавший мне вопрос. Я никогда раньше не подозревала, что project stub позволяет начать работы с БЭМ без знания всего того, что описано выше. :-)

Кстати, написав все это, я поняла, что описание основ БЭМ для меня несложно и занимает разумное время. При этом (я надеюсь!), это очень полезно для других. Так что спрашивайте всё, что вы хотите знать.