# Методология сборки БЭМ-проекта

Любой проект, построенный по БЭМ-методологии, имеет разветвленную файловую структуру. Причина этого — компонентный подход. [Блоки](../key-concepts/key-concepts.ru.md#Блок) в БЭМ могут быть реализованы в одной или нескольких [технологиях](../key-concepts/key-concepts.ru.md#Технология-реализации). Каждая технология находится в отдельном файле. Как следствие, чтобы получить из отдельных файлов блоков общие файлы проекта, необходимо применить сборку. Для этого можно использовать любой из существующих [инструментов сборки](#Инструменты-для-сборки).

Пример организации файловой структуры БЭМ-проекта:

```files
blocks/                 # Уровень проекта
    input/              # Директория блока `input`
        input.css       # Реализация блока `input` в технологии CSS
        input.js        # Реализация блока `input` в технологии JavaScript
    icon/
        icon.css

library/                # Уровень библиотеки
    input/
        input.js        # Базовая реализация блока `input` в технологии JavaScript
    button/
```

> Подробнее о том, зачем разделять реализацию блока на отдельные файлы читайте в документе [Организация файловой системы БЭМ-проекта](../filesystem/filesystem.ru.md).

Сборка решает следующие задачи:
* объединяет отдельные [файлы реализаций](../filesystem/filesystem.ru.md#Реализация-блока-разделяется-на-отдельные-файлы), разложенные по файловой системе;
* подключает в проект только нужные блоки, [элементы](../key-concepts/key-concepts.ru.md#Элемент) и [модификаторы](../key-concepts/key-concepts.ru.md#Модификатор) из имеющихся в файловой системе;
* учитывает порядок подключения файлов в проект.

## Основные этапы сборки

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

* [перечислить блоки, элементы и модификаторы, участвующие в построении страницы](#Определение-списка-блоков-элементов-и-модификаторов-для-создания-страницы)
* [указать зависимости используемых БЭМ-сущностей](#Поиск-зависимостей)
* [объединить исходные файлы](#Определение-порядка-подключения-БЭМ-сущностей-в-сборку)

### Результаты сборки

В результате сборки можно получить разные финальные наборы файлов:

* файлы для отдельной страницы (например, `hello.css` и `hello.js`);
* общие файлы для всего проекта (например, один `project.css` и `project.js`);
* файлы для фрагмента страницы, такого как `шапка` или `подвал`, которые используются на разных страницах проекта (например, `header.css` и `header.js`). Общая часть собирается отдельно и подключается при сборке.

Такие наборы файлов, полученные в результате сборки, в БЭМ-методологии принято называть **бандлами**.

> Обратите внимание, в документе сборка рассматривается на примере **страницы** — частного случая бандла.

В файловой системе результаты сборки отдельных файлов автоматически помещаются в директорию с названием страницы (например, `hello`):

```files
blocks/                 # Директория, содержащая блоки

bundles/                # Директория, содержащая все результаты сборки (опционально)
    hello/              # Директория страницы `hello` (создается вручную)
```

Пример файловой системы БЭМ-проекта до выполнения сборки:

```files
blocks/                 # Директория, содержащая блоки

bundles/                # Директория, содержащая все результаты сборки
    hello/              # Директория страницы `hello`
        hello.decl.js   # Список БЭМ-сущностей, необходимых для страницы `hello`
```

Пример файловой системы БЭМ-проекта после выполнения сборки:

```files
blocks/                 # Директория, содержащая блоки

bundles/                # Директория, содержащая все результаты сборки
    hello/              # Директория страницы `hello`
        hello.decl.js   # Список БЭМ-сущностей, необходимых для страницы `hello`
        hello.css       # Собранный CSS-файл страницы `hello`
        hello.js        # Собранный JavaScript-файл страницы `hello`
```

При сборке в проект могут быть включены:

* все БЭМ-сущности с файловой системы (что значительно увеличивает объем результирующего кода);
* только необходимые для построения страницы БЭМ-сущности в строго определенном порядке.

Для сборки в проект только нужных БЭМ-сущностей используются (опционально):

* [Декларация](#Определение-списка-блоков-элементов-и-модификаторов-для-создания-страницы) — определяет список БЭМ-сущностей, необходимых для создания страницы.
* [Зависимости](#Поиск-зависимостей) — определяют БЭМ-сущности, необходимые для реализации блока.
* [Уровни переопределения](#Определение-порядка-подключения-БЭМ-сущностей-в-сборку) — определяют порядок подключения БЭМ-сущностей в сборку.

### Определение списка блоков, элементов и модификаторов для создания страницы

Чтобы начать сборку страницы, инструмент сборки должен узнать все ее составляющие.

![Декларация](build__declaration.png)

Первый этап сборки — формирование списка необходимых БЭМ-сущностей. Рассмотрим на примере, для чего и как создается такой список.

В проект подключена библиотека, из которой на странице используются несколько блоков. Нет необходимости включать всю библиотеку в сборку. Достаточно составить список нужного по описанию страницы. Это можно сделать автоматически и вручную. На основании этого списка в сборку попадут только перечисленные блоки. В БЭМ-методологии такой список называется [декларацией](../declarations/declarations.ru.md).

Основная задача декларации определить, что и в каком порядке подключать в сборку.

> Подробнее о [способах построения декларации](../declarations/declarations.ru.md#Способы-управления-декларациями).

### Поиск зависимостей

В БЭМ-методологии многие блоки строятся на основании других блоков. Так, например, блок формы поиска (`search-form`) построен с помощью блоков `input` (поле ввода) и `button` (кнопка). Нет необходимости реализовывать блок повторно, если он уже представлен в библиотеке. Новый блок можно построить на основании существующего.

![Пример составного блока](build__search-form.png)

Чтобы создать блок с помощью другого, уже существующего блока, необходимо указать зависимости между ними. Так, приведенный в примере блок `search-form` зависит от `input` и `button`.

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

Существует несколько способов указать зависимости:

* Непосредственно в коде блока.

  * В CSS зависимости можно определять с помощью директивы [@import](http://htmlbook.ru/css/import).
  * В JavaScript можно декларировать зависимости с помощью модульной системы (например, [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD), [CommonJS](http://www.commonjs.org/)) или импортов ([ECMAScript 2015](http://ecmascript.org)).

* В отдельном файле.

  > В БЭМ-платформе для указания зависимостей используется технология [DEPS](https://ru.bem.info/technology/deps/).

  ```files
  blocks/
      input/
          input.css
          input.js
          input.deps.js   # Файл с зависимостями блока `input`
      button/
          button.css
          button.js
  ```

### Определение порядка подключения БЭМ-сущностей в сборку

Порядок подключения БЭМ-сущностей в сборку зависит от:

* **указанных зависимостей**

  Зависимости определяют, в каком порядке дополнительная сущность должна попасть в сборку.

* **используемых уровней переопределения**

  Важно соблюдать порядок подключения [уровней](../key-concepts/key-concepts.ru.md#Уровень-переопределения) в сборку. Если сравнить уровни со слоями, то базовый слой – это исходная реализация блока, например, полученная из библиотеки, а каждый последующий слой накладывается сверху и дополняет (наследует) или изменяет базовую реализацию. Поэтому важно, чтобы в сборку сначала попадала исходная реализация, а затем изменения со всех уровней переопределения.

На схеме показан принцип использования уровней переопределения при сборке: с уровня `common` подключаются общие компоненты для всех платформ, а с уровней `desktop` и `touch` — компоненты, специфичные для каждой из платформ.

![Уровни переопределения](build__levels.png)

Подробно об использовании уровней переопределения читайте в примерах:

* [Переопределение блоков библиотеки](../filesystem/filesystem.ru.md#Подключение-библиотеки)
* [Разделение проекта на платформы](../filesystem/filesystem.ru.md#Разделение-проекта-на-платформы)

## Инструменты для сборки

Выбор инструмента для сборки зависит от сложности БЭМ-проекта, наличия в нем уровней переопределения и использования зависимостей.

БЭМ-методология не ограничивает выбор инструмента — можно использовать любые сборщики (например, Gulp, Grunt, Brunch, Broccoli), отвечающие требованиям вашего проекта.

> Пример сборки БЭМ-проекта с помощью [Gulp](http://gulpjs.com/) — [Декларативный JavaScript по БЭМ](https://ru.bem.info/events/beminar-july-2015/).

В БЭМ-платформе используется сборщик [ENB](https://ru.bem.info/tools/bem/enb-bem/), который подходит для сборки БЭМ-проектов любой сложности.

> Пример сборки БЭМ-проекта с помощью [ENB](https://ru.bem.info/tools/bem/enb-bem/) — [Создаем свой проект на БЭМ](https://ru.bem.info/tutorials/start-with-project-stub/).
