Войти с помощью github

Доброго времени суток. Подскажите пожалуйста кто знает, почему в bem-components и bem-core не используется SASS, а вместо этого все манипуляции над css совершаются с помощью JS? Чем обусловлен такой подход? Хочется очень услышать аргументы.

И небольшое пожелание по поводу ваших библиотек для BEM: запилите реализацию норм грида. Спасибо

Клонирован шаблонный репозиторий - Project-stub, установлен ym

Команда - $ bem create desktop.bundles/page/page.bemjson.js создает пустой page.bemjson.js. В readme Project-stub говорится о начальном заполнении содержимым.

Как bem-tools дать понять, что необходимо *.bemjson.js заполнить содержимым, и где это содержимое найти?

Привет!

Если вы используете enb-postcss (это актуально как минимум для пользователей project-stub или bem-express), то вам необходимо сделать вот такие изменения у себя на проекте https://github.com/bem/project-stub/commit/7795a5648f29343577f962b2ab1cd09dbae29071, чтобы избежать дублирования стилей в собранных бандлах.

Клонирую себе project-stub, ставлю зависимости, добавляю вторую страницу. https://ru.bem.info/toolbox/enb/enb-bem-techs/build-merged-bundle/ — копипастю код .enb/make.js (исходный — комментирую) вызываю node_modules/.bin/enb make получаю Error: Cannot find module 'enb-css/techs/css'... ставлю https://github.com/enb/enb-css как зависимость, вызываю node_modules/.bin/enb make получаю Error: file not found: D:\projects\project-stub\desktop.bundles\contacts\contacts.bemdecl.js...

Немного странно выходит: чтобы собрать merged-бандл мне нужно сначала собирать обычный (в моем случае — постраничный), потом менять код .enb/make.js? (Данублин!)

Вопросы:

  1. Можно ли запускать node_modules/.bin/enb make с разными конфигами? ( .enb/make.js отдельно, какой-нибудь .enb/build.js) отдельно). Если да — как?
  2. Как собрать merged-бандл для project-stub без описанных выше извращений с .enb/make.js?

Хочется практического четкого примера с gulp. Много надежд после этого заявления: https://youtu.be/Ai-yt0b8iKE?t=2h4m5s (t=2h4m5s про галп) Смотрел https://ru.bem.info/forum/1138/ — размыто, нечетко, много накладок по ходу и некоторое количество «непонятной магии». Колеблюсь межу переходом к полному стеку и написанием очередного велосипеда (сейчас использую методологическую часть). Сформулировал желания, которые хотелось бы воплотить на практике или посмотреть на примеры их реализации в рамках одного проекта:

  • Написание страниц с BEM-XJST
  • Диалект Галлахера
  • Автоматически получать список стилевых файлов для компиляции на основании списка используемых на страницах блоков, управлять очередностью
  • Автоматически получать список JS-файлов для конкатенации на основании списка используемых на страницах блоков
  • Произвольный CSS-препроцессор
  • Уровни переопределения
  • Возможность использовать bem-core и bem-components (переопределять на проектном уровне)
  • Автообновление в браузере по изменению файлов в папке блока, страницах, в доп. файлах (шрифты, картинки, SVG-спрайт ect.)
  • На входе: технологии блока в папке блока, глобальные файлы
  • На выходе: папка (build/?) с готовыми страницами, картинками, одним стилевым файлом, одним JS-файлом (отправка на gh-pages?)

Возможна ли вообще такая комбинация на данный момент? Стоит ли тратить время на попытки воплотить это всё?

Привет! Я хотел вкрутить юнит тесты в проекте по инструкции https://ru.bem.info/toolbox/enb/enb-bem-specs/, но получил ошибку

Failed to start mocha: Init timeout Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL

Решил попробовать на базовом проекте (https://github.com/bem/project-stub), но получил такой же результат. Посмотрел какие файлы формируются и заметил, что в конечных файлах тестов пустые html и css файлы. Пропущена какая-то зависимость?

Смотрел доклад Владимира Гриненко, и там была показана одна из фишек, что стили определенного блока подключаются в общий файл стилей, если этот блок задействован, а если его удаляешь из файла, например index.bemjson.js, то и стили этого блока автоматически отключаются, т.к. не нужно идти и вручную инклудить/удалять нужный файл стилей блока. Задействовав сборку project-stub на gulp, заметил, что если блок подключаешь, то стили его подключаются автоматически в результирующий css-файл, но когда удаляешь этот блок, то стили всё равно остаются для данного блока, хотя он уже не нужен. Это пока не доработка проекта на gulp? Либо я что-то не так настроил? Также при переопределении блока, стили одних правил тоже остаются, пример: в common.blocks для блока button задана высота 15px, а в desktop.blocks высота для данного блока уже 10px, но оба эти правила попадут в результирующий css, хотя на вебинаре было показано, что попадет только последнее переопределенное правило, т.к. это логично, ведь оно переопределяет правило написанное выше и ему уже нет смысла находиться в файле стилей. Там правда была выполнена команда для выкатки в production, после чего все стили почистились, такая же команда есть для сборки на gulp?

Нашел сетку bem-grid https://www.npmjs.com/package/bem-grid и руководство по ее установке https://ru.bem.info/forum/959/ на project-stub. Но как я пониманию эта сетка предназначена только для ENB, а есть ли версия для gulp? Т.к. я в project-stub использую gulp. Спасибо!

Появилась необходимость собирать не только основной файл js но и подключать к нему web worker. Как Реализовать такой функционал в пределах БЭМ проекта?

Как то давно, мной был задан вопрос https://ru.bem.info/forum/793/ по реализации разделения css стилей и последующего их инлайна на html страницу.

Подход довольно простой.

  1. Собираем два разных бандла, первый critical, второй со всеми стилями.
  2. Превращаем файл critical.css в js файл, через инлайн файла module.exports = '....'
  3. Подключаем этот файл обычным require в виде элемента блока page {elem: 'css', content: require('desktop.bundles/critical/critical.css.js')}

В critical бандле подключается только один единственный блок critical (простите за каламбур) у которого в зависимостях описаны все блоки которые нужно заинлайнить.

Выложил выжимку своего конфига на enb https://gist.github.com/JiLiZART/efa6b23c478b17c4708b931a44fce996

Я использую bemtree, но для bemjson будет даже проще.

Есть у этого способа и недостатки, стили, которые инлайнятся в страницу, дублируются в бандле со всеми остальными стилями. Для решения этой проблемы я навоял вычитание deps'ов друг из друга в этом PR https://github.com/enb/enb-bem-techs/pull/190 Что поможет в дальнейшем вычитать все блоки critical бандла из основного

Проблема довольно банальна - ссылка на картинку блока из CSS файла блока не работает. Единственный работающий вариант это:

...
background-image: url(../../common.blocks/header/images/bg-header.png)
...

Фактически это абсолютный путь к блоку, в который так-же входит и путь к папке блоков common.blocks, что на мой взгляд совершенно неверно. Т.е. если я допустим захочу вынести потом этот компонент в допустим папку blog.blocks то получается надо будет бегать и пути менять. Или переименую я блок - та-же история.

Вот такой вариант:

...
background-image: url(images/bg-header.png)
...

работать отказывается

Borschik (через enb - project-stub) чё-то как-то не помог - такой путь он просто проигнорировал. Пытался крутить конфиг .borschik но без особого успеха (но тут я сильно глубоко не рыл).

Итого вопрос - как всё-таки идеологически верно указывать пути к картинкам блока в CSS-файлах блока?

Всем привет.

В общем хочется процветания БЭМ во всех его направлениях. Хочу оставить несколько идей для голосования сообщества (ну и чтобы сообщество тоже предложило свои идеи для голосования).

За время жизни project-stub накопилось много моментов, которые так или иначе привлекают или отталкивают людей. А т.к. project-stub - это практически лицо БЭМ, хочется чтобы оно было максимально дружелюбным.

Идеи для голосования положил в issues project-stub. Начинаются с символа собачки @ https://github.com/bem/project-stub/issues

Всем привет! Подскажите как правильно переопределять блоки для бандлов. Т.е. у нас есть desktop.blocks/header и touch-phone.blocks/header. Почему блок header определенный в touch-phone.bundles/index/index.bemjson.js подключаются из desktop.blocks, а не touch-phone.blocks?

Привет) Появилось время обновить бэм инструменты (когда-то проект был сделан на основе project-stub). Однако, вроде, делаю все правильно, но сборка не идет Подскажите, пожалуйста, в чем может быть ошибка?

Вот что выдает консоль: ссылка Вот репозиторий: ссылка

Добрый день! Внимательно прочитал всю доступную документацию в старом виде и в новом, несколько статей, посмотрел несколько вебинаров и лекций. Но некоторые моменты всё равно ускользнули от моего внимания и понимания. В целом эта непонятная ситуация причиняет мне физический дискомфорт. Боюсь, что для понимания многих вещей, придется просмотреть много кода, что бы найти примеры использования, а это камень в огород документации. Без ответа на эти вопросы, я буду плавать в методологии и не смогу ей воспользоваться.

Из документации я не понял:

1. Шаблонизация в браузере когда и зачем нужна? Я предполагаю, что весь HTML будет собираться на сервере, в том числе, что динамично будет отправляться клиенту. Но, коль есть возможность компилировать в браузере, хотелось бы узнать о плюсах и кейсах, когда это может понадобиться. Что, касательно ресурсов, насколько это ресурсозатратно?

2. Возможность частичной сборки и компиляции со статичными html файлами Многие элементы интерфейса - статичные, например, шапка, меню, футер, общие лейауты. Собирать их отдельно для каждого клиента - бессмысленно. Возможно ли как-то объединять уже собранный, статичный HTML и динамичные блоки?

3. Документация про сборку Я прочитал весь раздел про enb, но там скорее кейсы, чем сама архитектура. Мне непонятно, как организовать сборку для проекта в целом.

4. Как организовать сборку для дева, прода, лайв В продолжение предыдущего вопроса - для разработки и для прода требуются разные настройки. Я правильно понимаю, что разные настройки обеспечиваются разными файлами по типу make.js ?

5. Документация про декларацию Я не нашел цельной информации про декларацию (?.bemdecl.js), и всё, что я про это знаю - частички из статей про enb, из-за этого складывается ощущение, что я чего-то не догоняю.

_6. Почему и зачем есть BEMHTML и bh, какой для каких ситуаций лучше _ Я долго пытался понять - что делает bh, пока не понял, что это - еще один шаблонизатор, такой же, как BEMHTML. Так в чём же разница, и как так получилось, что есть два шаблонизатора? Какой из них под какие цели заточен? И, кстати, про bh нет документации.

_7. Где доки про BEMTREE, когда что лучше использовать _ Про BEMTREE лишь сказано, что синтаксис "Такой же, как в BEMHTML, но только с двумя режимами", при всём при том, что это - важный и основной инструмент при сборке. Очень хотелось бы увидеть примеры и объяснения, как делать шаблоны для BEMTREE.

8. Доки про SASS|LESS| любые модули Основной инструмент библиотеки для css - stylus, по историческим причинам. Хотелось бы узнать, как можно использовать другие препроцессоры. Я часто встречал мнение, что БЭМ - навязывает свой стек. Я понимаю, что это не так, просто инструменты дефолтные такие. Хотелось бы узнать, как можно в сборку включать те, что соответствуют моему стеку.

9. Контроллеры для сборки, практики BEM - штука хорошая, но кажется очень замкнутой в себе из-за того, что до конца не ясен сам процесс сборки и связь с внешним миром. Во всех статьях и гайдах говорится в-основном о статичных сайтах. И из-за этого, совсем мне не понятно, как сделать динамичный сайт, как организовать динамичную и частичную сборку, роутинг и т. д.

10. Шапка, лейаут в общем html Возможно, мой мозг еще не переключился в БЭМ-область, но мне до конца не ясно, как сделать общие части интерфейса для всех страниц сайта - каждый раз подключать header, content, footer?

11. Подключение скриптов, стилей, других библиотек. Если подключение своих скриптов, всё худо-бедно понять можно, то как подключить скрипты библиотек? Их ведь нужно указать в head (а некоторые скрипты в футере). Как же это всё делается в рамках шаблонов, страниц? Хардкодить?

12. Какие практики бандлов Из документации мне совсем не понятно что такое и для чего нужны бандлы. Как я понял - это собранные пакеты css и js, но куда их нужно пихать и зачем - непонятно.

13. Борщик Для чего борщик существует внутри enb, ведь в enb есть другие инструменты, для работы с файлами. В чем его отличие и назначение?

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

Накидал docker контейнер для запуска project-stub - https://github.com/nejtr0n/bem Возможно кому то пригодится. Запускается просто:

git clone https://github.com/nejtr0n/bem.git && cd bem
docker-compose up

При первом запуске project-stub соберётся в папку bem.

Всем привет. Данный пост адресован тем, кто хочет использовать БЭМ на сервере вплотную (а точнее NodeJS), но боится самой ноды. Я и сам сейчас занимаюсь выбором фреймворка для проекта. Изначально хотел использовать ExpressJS, но решил перейти на его "продолжение" - KoaJS (немного архитектура приятней).

Но вот наткнулся сейчас на ещё один фреймворк, после которого не смог не написать о нём сюда. AdonisJS.

Это некое воплощение Laravel (PHP) на NodeJS. Визуально всё выглядит очень легко и приятно и код даже чище, чем на PHP. Есть только один минус.

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

ExpressJS - самый старый, из-за этого и бесконечное число материалов. KoaJS - немного материалов. AdonisJS - самое меньшее кол-во материалов.

Но если вы привыкли к Yii, Laravel, RubyOnRails - то для вас AdonisJS будет прекрасным источником вдохновения для перехода на NodeJS.

Доброго всем времени суток. Долго думал о внедрении БЭМ в проекты... И сейчас назревает новый. Он ещё не утверждён, но я уже обдумываю его реализацию. Планируется следующая схема:

БЭМ (frontend) <-- REST Api --> Express (backend).

Планируется сделать "одностраничное приложение". Но как всегда у меня происходит, в голове всё выглядит как в сказке, но на практике ловлю стопор.

Для вёрстки планирую использовать project stub. Но как правильно подойти к этому моменту?

Опишу вообще как я вижу процесс в абстракции: В проекте лежит каталог bem(project-stub).

Там я верстаю страницы и показываю их заказчику, он радуется. Далее я собранные bemtree + bemhtml подключаю в продакшине. И работаю уже непосредственно с разработанным REST Api + bemtree + bemhtml. В общем стоит задача минифицировать время между вёрсткой демо страниц и продакшин.

Какие здесь подводные камни имеются и реализуемо ли это? Как настроить сборку?

Буду благодарен за ответы :)

Чтобы при сборки в desktop версию падали файлы из desktop.blocks, а в touch соответственно из touch.blocks. Ну и common.blocks был общим.

var fs = require('fs'),
  path = require('path'),
  techs = {
    // essential
    fileProvider: require('enb/techs/file-provider'),
    fileMerge: require('enb/techs/file-merge'),

    // optimization
    borschik: require('enb-borschik/techs/borschik'),

    // css
    stylus: require('enb-stylus/techs/stylus'),

    // js
    browserJs: require('enb-js/techs/browser-js'),

    // bemtree
    // bemtree: require('enb-bemxjst/techs/bemtree'),

    // bemhtml
    bemhtml: require('enb-bemxjst/techs/bemhtml'),
    bemjsonToHtml: require('enb-bemxjst/techs/bemjson-to-html')
  },
  enbBemTechs = require('enb-bem-techs'),
  merged = require('./techs/merged'),
  levels = [
    {path: 'libs/bem-core/common.blocks', check: false},
    {path: 'libs/bem-core/desktop.blocks', check: false},
    {path: 'libs/bem-components/common.blocks', check: false},
    {path: 'libs/bem-components/desktop.blocks', check: false},
    {path: 'libs/bem-components/design/common.blocks', check: false},
    {path: 'libs/bem-components/design/desktop.blocks', check: false},
    {path: 'libs/bem-forms/common.blocks', check: false},
    'common.blocks',
    'desktop.blocks'
  ];

module.exports = function(config) {
  var isProd = process.env.YENV === 'production',
    mergedBundleName = 'merged',
    pathToMargedBundleDesktop = path.join('desktop.bundles', mergedBundleName),
    pathToMargedBundleTouch = path.join('touch.bundles', mergedBundleName);

  fs.existsSync(pathToMargedBundleDesktop) || fs.mkdirSync(pathToMargedBundleDesktop);
  fs.existsSync(pathToMargedBundleTouch) || fs.mkdirSync(pathToMargedBundleTouch);

  merged(config, pathToMargedBundleDesktop);
  merged(config, pathToMargedBundleTouch);

  config.nodes('*.bundles/*', function(nodeConfig) {
    var isMergedNode = path.basename(nodeConfig.getPath()) === mergedBundleName;

    isMergedNode || nodeConfig.addTechs([
      [techs.fileProvider, {target: '?.bemjson.js'}],
      [enbBemTechs.bemjsonToBemdecl]
    ]);

    nodeConfig.addTechs([
      // essential
      [enbBemTechs.levels, {levels: levels}],
      [enbBemTechs.deps],
      [enbBemTechs.files],

      // css
      [techs.stylus, {
        target: '?.css',
        sourcemap: false,
        autoprefixer: {
          browsers: ['ie >= 10', 'last 2 versions', 'opera 12.1', '> 2%']
        }
      }],

      // bemtree
      // [techs.bemtree, { sourceSuffixes: ['bemtree', 'bemtree.js'] }],

      // bemhtml
      [techs.bemhtml, {sourceSuffixes: ['bemhtml', 'bemhtml.js']}],

      // html
      [techs.bemjsonToHtml],

      // client bemhtml
      [enbBemTechs.depsByTechToBemdecl, {
        target: '?.bemhtml.bemdecl.js',
        sourceTech: 'js',
        destTech: 'bemhtml'
      }],
      [enbBemTechs.deps, {
        target: '?.bemhtml.deps.js',
        bemdeclFile: '?.bemhtml.bemdecl.js'
      }],
      [enbBemTechs.files, {
        depsFile: '?.bemhtml.deps.js',
        filesTarget: '?.bemhtml.files',
        dirsTarget: '?.bemhtml.dirs'
      }],
      [techs.bemhtml, {
        target: '?.browser.bemhtml.js',
        filesTarget: '?.bemhtml.files',
        sourceSuffixes: ['bemhtml', 'bemhtml.js']
      }],

      // js
      [techs.browserJs, {includeYM: true}],
      [techs.fileMerge, {
        target: '?.js',
        sources: ['?.browser.js', '?.browser.bemhtml.js']
      }],

      // borschik
      [techs.borschik, {source: '?.js', target: '?.min.js', minify: isProd}],
      [techs.borschik, {source: '?.css', target: '?.min.css', tech: 'cleancss', minify: isProd}]
    ]);

    nodeConfig.addTargets([/* '?.bemtree.js', */ '?.min.css', '?.min.js']);
    isMergedNode || nodeConfig.addTargets(['?.html']);
  });
};

Как это можно сделать?

Устанавливаем project-stub

  1. Устанавливаем project-stub
git clone https://github.com/bem/project-stub.git --depth 1 --branch v1.5.0 my-bem-project
cd my-bem-project
npm install # Do not use root privilege to install npm and bower dependencies.
  1. Устанавливаем bem-grid
npm i --save-dev bem-grid
bower install --save bem-grid

!!! ВАЖНО установить двумя способами через npm и bower UPD: говорят, что работает даже с одним npm

  1. Заходим в папку проекта. Редактируем файл my-bem-project/.enb/make.js Добавляем строчку
{ path: 'libs/bem-grid/common.blocks', check: false },
// make.js
...
  enbBemTechs = require('enb-bem-techs'),
    levels = [
        { path: 'libs/bem-core/common.blocks', check: false },
        { path: 'libs/bem-core/desktop.blocks', check: false },
        { path: 'libs/bem-components/common.blocks', check: false },
        { path: 'libs/bem-components/desktop.blocks', check: false },
        { path: 'libs/bem-components/design/common.blocks', check: false },
        { path: 'libs/bem-components/design/desktop.blocks', check: false },
        { path: 'libs/bem-grid/common.blocks', check: false }, // Добавили сюда
        'common.blocks',
        'desktop.blocks'
    ];
...
  1. В этом же файле находим //css и заменяем на
// make.js
...
        //css
            [techs.stylus, {
                target: '?.stylus.css',
                sourcemap: false,
                autoprefixer: {
                    browsers: ['ie >= 10', 'last 2 versions', 'opera 12.1', '> 2%']
                }
            }],
            [require('bem-grid').enb, {
                source: '?.stylus.css',
                target: '?.css',
                config : {
                    maxWidth : '1100px',
                    gutter : '10px',
                    flex : 'flex'
                }
            }],
...
  1. Готово. Теперь можем писать так
// index.bemjson.js
...
{
    block : 'row',
    content : [
        {
            elem : 'col',
            elemMods : { mw : 6 },
            content : 'left column'
        },
        {
            elem : 'col',
            elemMods : { mw : 6 },
            content : 'right column'
        }
    ]
}
...

В итоге получим

...
<div class="row">
    <div class="row__col row__col_mw_6">left column</div>
    <div class="row__col row__col_mw_6">right column</div>
</div>
...

Старался писать как можно подробней. Источник: по ссылке

Всем привет. Хочу добавлять и переопределять стили в зависимости от платформы (desctop, touch-pad, touch-phone). Делаю так как описано в методологии https://ru.bem.info/method/filesystem/#Разделение-проекта-на-платформы Соответственно создал папки на файловой системе (desktop.blocks, touch-pad.blocks, touch-phone.blocks ) и в make.js добавил уровней:

 levels = [
    { path: 'libs/bem-core/common.blocks', check: false },
    { path: 'libs/bem-core/desktop.blocks', check: false },
    { path: 'libs/bem-core/touch.blocks', check: false },
    { path: 'libs/bem-components/common.blocks', check: false },
    { path: 'libs/bem-components/desktop.blocks', check: false },
    { path: 'libs/bem-components/touch-pad.blocks', check: false },
    { path: 'libs/bem-components/touch-phone.blocks', check: false },
    { path: 'libs/bem-components/design/common.blocks', check: false },
    { path: 'libs/bem-components/design/desktop.blocks', check: false },
    { path: 'libs/bem-components/design/touch-pad.blocks', check: false },
    { path: 'libs/bem-components/design/touch-phone.blocks', check: false },
    'common.blocks',
    'desktop.blocks',
    'touch-pad.blocks',
    'touch-phone.blocks'

];

Далее создал тестовый блок с разными стилями для разного устройства. Меняю background-color. Ничего волшебного не происходит, стили просто перекрывают друг друга независимо от платформы. Все время цвет фона, прописанный в блоке touch-phone.blocks. Вопрос - каким образом происходит определение устройства или нужно писать свои функции для этого (проект на основе сборки project-stub)?

Всем привет.

Попытался выгрузить ветку для PHP, в консоли сделал так git clone --depth 1 -b php-bem-bh https://github.com/bem/project-stub.git WEB_BEM_PHP_Yandex Клонирование в «WEB_BEM_PHP_Yandex»… remote: Counting objects: 35, done. remote: Compressing objects: 100% (29/29), done. remote: Total 35 (delta 1), reused 17 (delta 0), pack-reused 0 Распаковка объектов: 100% (35/35), готово. Проверка соединения… готово.

В файле index.php есть такая строка require "index.bh.php";, при этом самого файла index.bh.php в проекте нет.

А кто-нибудь знает, как отключить лишний js код во внешнем файле? Вроде таких технологий (browser.js) не использую.

Ребята, подскажите есть ли какие-то готовые инструменты для динамического создания CSS спрайтов (CSS sprites) внутри вашей технологии? Что лучше взять https://www.npmjs.com/package/node-sprite https://npmjs.org/package/spritesmith https://npmjs.org/package/stylus-sprite ?

Всем привет! В своем проекте использую заготовку project-stub (ветка i18n)/ Подскажите, почему в ветке i18n bower.json такой https://github.com/bem/project-stub/blob/i18n/bower.json , а в версии project-stub 1.4.0 такой https://github.com/bem/project-stub/blob/bem-core/bower.json . Будет ли ошибкой? если я обновлю bem-components с 2.3.0 до 2.4.0 и оставлю bower.json как в project-stub?

Привет, пришла и моя очередь рассказать о содеянном на минувшем хакатоне.

Основная мысль, которая преследует меня уже долгое время — возможность сборки БЭМ-проектов с помощью любого инструмента. И именно с этой идеей я пришёл в то раннее утро субботы агитировать собравшихся присоединиться ко мне, в надежде немного приблизить неизбежное будущее, в котором нет ENB.

Несмотря на невнятную речь, ко мне присоединились очень крутые ребята, без которых мы бы не продвинулись так далеко: @arikon, @zxqfox, @awinogradov, спасибо вам огромное!

Ставь задачу правильно

Утверждение «сборка БЭМ-проектов с помощью любого инструмента» звучит слишком абстрактно.

В двухдневный формат хакатона такая задача совсем не укладывалась. Надо было сформулировать что-то более конкретное. Поэтому мы решили, что критерием успеха будет сборка project-stub с помощью gulp.

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

Готовь сани летом

На самом деле основная работа была сделана заранее.

Специфика сборки БЭМ проектов заключается в организации уровней переопределения и использовании зависимостей блоков. Подробнее об этом можно почитать на bem.info.

Необходимость модульной сборки была сформулирована уже давно. На прошлогоднем хакатоне мы решили задачу интроспекции уровней — bem-walk.

Кроме того, к этому хакатону я написал прототип модуля для работы с зависимостями блоков — bem-deps.

Работа оказалась проделанной не зря. Модуль для работы с зависимостями пригодился не только нам, но и команде, занимающейся сборкой с помощью webpack. А интроспекция и вовсе оказалась нужна каждой команде.

Результаты

Проект: @bem/gulp.

Сборка project-stub: ветка feature/gulp

Ничто не опишет проект лучше, чем его API. Поэтому без слов пример того, что у нас получилось.

import gulp from 'gulp';
import bem from '@bem/gulp';
import concat from 'gulp-concat';
import merge from 'gulp-merge';
import bemhtml from 'gulp-bemhtml';
import stylus from 'gulp-stylus';
import postcss from 'gulp-postcss';
import postcssUrl from 'postcss-url';

// Создаём хелпер для сборки проекта
var project = bem({
    bemconfig: {
        /* загружаем информацию об уровнях с помощью `bem-config` */ 
    }
});

// Создаём хелпер для сборки бандла
var bundle = project.bundle({
    path: 'desktop.bundles/index',
    declPath: 'index.bemdecl.js'
});

gulp.task('css', function () {
    return bundle.src({tech: 'css', extensions: ['.css', '.styl']})
        .pipe(stylus())            
        .pipe(postcss([
            postcssUrl({ url: 'inline' })            
        ]))
        .pipe(concat(`${bundle.name()}.css`))
        .pipe(gulp.dest('desktop.bundles/index'));
});

gulp.task('js', function () {
    return
        merge(
            gulp.src(require.resolve('ym')),
            bundle.src({ tech: 'js', extensions: ['.js', '.vanilla.js', '.browser.js'] })
        )
        .pipe(concat(`${bundle.name()}.js`))
        .pipe(gulp.dest('desktop.bundles/index'));
});

gulp.task('bemhtml', function () {
    return bundle.src({ tech: 'bemhtml.js', extensions: ['.bemhtml.js', '.bemhtml'] })
        .pipe(concat(`${bundle.name()}.bemhtml.js`))            
        .pipe(bemhtml())
        .pipe(gulp.dest('desktop.bundles/index'));
});

gulp.task('build', gulp.series('css', 'js', 'bemhtml'));
gulp.task('default', gulp.series('build'));

По скорости в текущем состоянии сборка project-stub оказалась соизмеримой со сборкой на стеке ENB.

Что дальше?

Вначале мы приведём код в человеческий вид, покроем тестами и напишем примеры использования с минимальной документацией.

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

Как только всё будет готово, обязательно расскажем вам. А самое главное — будем внедрять в реальные проекты и реагировать на фидбэк.

Общие модули bem-walk и bem-deps оказались универсальными, и в каком-то смысле уже проверенными в бою. Поэтому, кроме использования их для сборки на gulp и webpack, мы планируем внедрить их в ENB.

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

Присылайте свои идеи и задавайте вопросы на форуме или в ишьюсах к репозиториям из организации gulp-bem.

Спасибо за внимание!

Привет,

хочу рассказать о результатах нашей команды на минувшев хакатоне в рамках Я 12-13 декабря.

Наша команда состояла из Бориса Сердюкова, Константина Гладких, Евгения Константинова и меня и в рамках хаккатона мы решили попробовать собрать бэм-проект project-stub на webpack. Забегая вперед, могу сказать, что это получилось и результат можно посмотреть здесь: https://github.com/just-boris/project-stub/blob/webpack/webpack.config.js

Так как webpack - модульный сборщик, который рассчитан на работу с JavaScript модулями и умеет подключать сторонние технологии как js-модули, то мы решили, что в качестве входной точки для сборки у нас будет статический bemjson файл, а на выходе было желание получить список реальных файлов, которые участвуют в сборке. Все вот это удалось свести к цепочке лоадеров:

{
  test: /\.bemjson.js$/,
  loader: 'bemdecl-to-fs!deps!bemjson?-stringify'
}

которые на выходе возвращают вот такой результат:

require('./libs/../b.js');
require('./libs/../b.styl');
// and etc

На мой взгляд, это довольно крутой результат, так нам удалось свести всю специфичность БЭМ методологии, связанную с депсами, к простой композиции лоадеров, что позволяет использовать стандартные решения для популярных технологий. Например, стили собрать можно как-то так: http://webpack.github.io/docs/stylesheets.html

Так как мы собирали проект на bem-core, то для JS модулей мы использовали ymodules-loader. Вопрос с шаблонизатором решили частично, остановились на bh и решили попробовать написать плагин для webpack, который будет превращать исходный bemjson в статический html, что сейчас работает.

БЭМ предметную область свели к общей декларации bem в рамках конфига, которая содержит информацию об уровнях переопределений с блоками и нужными технологиями.

Также в проекте есть webpack-dev-server, который вотчит изменения и кэширует результаты сборки.

Сам конфиг получился такой: https://github.com/just-boris/project-stub/blob/webpack/webpack.config.js Также решили сгруппировать наши технологии в рамках организации https://github.com/bempack

Скажу сразу, что текущие реализации лоадеров еще не готовы к использованию в продакшене, но мы работаем над этим. В планах, есть желание дополнить project-stub примерами с локализацией, дополнить лоадеры тестами и документацией. Также хочется поддержать шаблонизацию на bemhtml, когда это будет возможно.

В конце хочу поблагодарить ребят из тулзов и лего, которые консультировали нас по бэм-предметной области и создали довольно много интересных инструментов, которые упростили нам жизнь, и ребят из своей команды. Было весело :)

p.s. для интересующихся по webpack'у есть довольно хороший скринкаст: https://learn.javascript.ru/webpack-screencast