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

Доброе время суток, у вас исчезла с сайта документация на BH, осталась только на гитхабе, вы собираетесь отказываться от BH?

Товарисчи! Подскажите где посмотреть последний вебинар про шаблонизаторы.

Добрый день! Какие есть практики создания статичных, кэшируемых частей сайта, что бы генерировать только изменяемые части/подставлять данные? Или это не так уж и затратно каждый раз заново генерировать страницу?

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

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

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 есть другие инструменты, для работы с файлами. В чем его отличие и назначение?

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

Так как у нас сервер на ноде, возникает вопрос, насколько оправданно собирать bemtree бандлы с bem-xjst внутри. Кажется проще подключить их на старте приложения и досыпать шаблоны из собранных бандлов через compile. Что думаете?

Здравствуйте. Скажите почему apply для разных модов работает не единообразно?

({
   block:'block',
   tag:"tag",
   content:"content" 
})

block('block')(
    content()(function(){return apply('content') + '!'}),
    tag()(function(){return apply('tag') + '!'})
)
<undefined! class="block">content!</undefined!>

BEMHTML.apply({block: 'name', content: 'cont'}) ни чего не возвращает

2 года назад) некий @tadatuta на хакатоне написал тулзу для блогов из маркдауна и бэм-стека. Так вот после 2х лет забвения понадобилась мне тулза подобная чтобы на один манер собирать доки, блог, просто странички и тд. В общем случился форк, перерождение и отличный швейцарский нож для статики на bem-xjst и makrdown. https://github.com/awinogradov/bemark

На бэминаре я задавал вопрос, связанный с "картой" для bemtree, сейчас постараюсь его более конкретно расписать.

На файловой системе у нас блоки расположены на плоскости.

блок-1
блок-2
блок-3
...
блок-N

но при построении, плоская структура превращается в иерархическую.

BEMTREE | BEMJSON | HTML

Приходит новый разработчик... И хватается руками за голову. Ему необходимо перекопать проект (если он знаком с БЭМ), в поисках того, как всё устроено.

Но мы показываем ему картину мира: blocks И просмотр кода в браузере|bemtree становится понятным. При данном визуальном представлении можно абстрагироваться над всеми отвлекающими факторами (тегами, кавычками, скобками, bemjson) и видеть цельную картину из блоков.

CSS

Но вот наш новобранец решает что ему не нравится блок header, мысли у него локальные... Он и меняет стили блока header, думая про popup. Но мы говорим ему: "Стой друг! Мысли глобальней - возьми картину мира, картину мест использования данного блока (зависимостей независимых блоков)": blocks

Теперь разработчик оценивает масштабы и к изменением подходит более обдуманно.

JS

Ну и на последок он решился сделать свой блок и написать ему бизнес-логику для браузера. И мы ему опять таки говорим: "Дружище лови себе памятку по компонентам. Наследуйся от блоков, в них уже многое реализовано!" i-bem

Это всё абстракция и выдуманные примеры, но хочется сделать БЭМ ещё понятней для новых членов команды. Вот я и задавал вопрос, используются ли подобные подходы в Яндекс?

Хочется избавиться от написания bemjson в js файлах блоков. Учитывая, что на клиенте уже есть BEMHTML, кажется вес js не должен сильно увеличиться.

Всем привет! Есть блок с курсами валют. Естественно хотелось бы получать данные для него непосредственно в его bemtree-шаблоне, а не собирать все эти данные до начала сборки и пробрасывать их абсолютно всем блокам, но если честно так и не разобрался, как это можно сделать? Так же была идея сделать немного иначе - запрашивать данные для блока уже с клиента, т. е. по-факту при построении страницы отправляем пустой блок, он при инициализации на клиенте запросил уже сам данные у сервера, тот формирует ответ в контексте блока. Второй вариант мне кажется даже правильней, так как не задерживается отправка всей страницы на время получения данных блока-виджета, но все же хотелось узнать, какой подход использовать лучше? Ну и все-таки хотелось бы подсмотреть где-то вариант асинхронного получения данных внутри bemtree-шаблона

Новый вебинар по БЭМ совсем скоро!

17 мая в 19:00 мы поговорим об использовании BEMHTML и BEMTREE. Расскажем, как все это можно использовать с любыми источниками данных (файловой системой, базой данных, HTTP API или бэкендом на любом языке).

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

Затронем работу как на сервере, так и на клиенте.

Обратите внимание, трансляция начнется в 19:00 17 мая на отдельной странице.

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

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

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

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

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

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

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

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

Странное поведение bemhtml. Шаблон:

block('comment-editor').elem('clear').replace()(
    { block : 'input', elem : 'clear', mix : { block : 'comment-editor', elem : 'clear' } }
);

bemhtml output:

<span class="input__clear"></span>

bh.js:

module.exports = function (bh) {
    bh.match('comment-editor__clear', function(ctx){
        return { block : 'input', elem : 'clear', mix : { block : 'comment-editor', elem : 'clear' } };
    });
}

bh.js output:

<span class="input__clear comment-editor__clear"></span>

Как видно, примиксованый блок не появляется. При этом замечена закономерность: Если в миксе или в возвращаемом блоке заменить { elem : 'clear' } на любой другой - микс начинает появляться в коде. Ошибка воспроизводится только когда в блоке и миксе есть одинаковые элементы.

JFYI

Оно работает, но возникают большие накладные расходы (результат приходит до 10 раз дольше) Маршалинг (для небольшого bemjson) и создания треда (один раз), кажется, не могут оправдать такой задержки.

https://gist.github.com/a-x-/aad7596e2a31bf20f988db1893805a77

Рис. Профайлинг этой балалайки на одном из самых больших шаблонов, который используется на клиенте в Яндекс.Картинках, который я смог найти:

bemhtml.js

// perf

// classic: 0.1ms..0.2ms
console.time('domik result');
BEMHTML.apply({ block: 'domik' });
console.timeEnd('domik result');

// parallel: fire: 0.1ms, result: 0.5..1ms (x10 slower)
console.time('domik result');console.time('domik fire')
BemhtmlWorkerApply({ block: 'domik' }, html => { console.timeEnd('domik result'); console.log('ololo', html); })
console.timeEnd('domik fire');

Хочется чтобы tmpl-specs не падали на шаблонах с i18n. В обычной сборке i18n доступен из this.i18n(). А как сделать, чтобы также было в шаблонах? В шаблонах тоже получается доступно но через this.require('i18n'). Но так не работает в enb server. Для сборки используем enb-bemxjst-i18n

Привожу конфиг

Подскажите, как в шаблоне добавить к блоку модификатор. В bh было просто ctx.mod('name', 'val')

Допустим у нас есть блок phones, в котором несколько item. Есть несколько элементов: title,description,image, button. Элемент button в свою очередь содержит блок button из bem-components.

В index.bemjson.js описываем следующим образом

...
{
            block: 'phones',
            phones: [
                {
                    title: 'Apple iPhone 4S 32Gb',
                    image: 'http://mdata.yandex.net/i?path=b1004232748_img_id8368283111385023010.jpg',
                    price: '259',
                    url: '/'
                },
                {
                    title: 'Samsung Galaxy Ace S5830',
                    image: 'http://mdata.yandex.net/i?path=b0206005907_img_id5777488190397681906.jpg',
                    price: '73',
                    url: '/'
                }
           ]
}
...

В phones.bemhtml следующим

...
block('phones')(
    content()(function() {
        return this.ctx.phones.map(function(item){
            return [
                {
                    elem: 'item',
                    content: [
                        {
                            elem: 'title',
                            content: item.title
                        },
                        {
                            elem: 'image',
                            url: item.image
                        },
                        {
                            elem: 'price',
                            content: item.price
                        },
                        {
                            elem: 'button',
                            content: 
                                 {
                                     block: 'button',
                                     url: item.url,
                                     text: 'Купить',
                                  }
                         }
                    ]
                }
            ];
        });
    })
);
...

Вопрос: Как сделать так, чтобы кнопка отображалась только тогда, когда это необходимо? То есть могут быть элементы item с кнопкой, а могут быть и без кнопки. Как сделать внутреннюю логику никак не могу понять. Вариант с добавлением модификатора, который делает display:none мне не нравится. Думаю лучше будет реализовать как-то иначе.

Задача научиться рендерить Virtual DOM из текущих шаблонов на bemhtml

Состав команды: @nik-kor @amel-true @khvostov @voischev @awinogradov. Все супер котаны!)

Результат

  1. Написали движок для рендера bemhtml шаблонов и положили аккуратно в PR https://github.com/bem/bem-xjst/pull/235. Экспортит атрибуты в виде массива вида ['div', {...attrs}, content, ...anotherContent].
  2. Сделали адаптер для React https://github.com/bem-contrib/react-xjst, который использует бандл из шаблонов в bemhtml и инстанс React для создания Virtual DOM , с помощью библиотеки react-dom.
  3. Начали доставлять bem-components в React, используя bemhtml шаблоны и стили. Собирается с помощью Webpack и специального лоадера для него https://github.com/alfa-bank-dev/bem-loader, который резолвит все нужное по депсам через bem-deps. Можно дописывать bemhtml шаблоны на уровне проекта как и раньше;)
  4. Запилили песочницу для bem-xjst с переключателем движков: BEMHTML, BEMTREE, VIDOM – https://github.com/bem/bem-xjst/pull/238. Одни шаблоны на все времена, тестить, сравнивать, все, что душе угодно можно делать.
  5. Так же планировали поработать над интеграцией с Redux. Но так сложилось, что задача решилась автоматически. На уровне React ничего не изменилось, поэтому данные как и раньше доезжают до компонентов, где формируется bemjson для функции рендера.

Превью готовых компонентов http://awinogradov.github.io/react-xjst-example/ и песочницы http://vladkhvo.github.io/.

Далее

Зарелизить react-components – библиотеку, которая использует шаблоны и стили из bem-components, но логику React в БЭМ-терминах.

Ура?;) Теперь мы имеем одни шаблоны и стили для параллельных стеков. Поддерживаем в одном месте и в ус не дуем! Предположительно можно написать подобных адаптеров и для других технологий;)

Есть блок, и он содержит в себе какие-то данные. Нужно сформировать другую структуру данных чтобы передать её в дочерний блок. Для этого я написал функцию но не хочу держать её в файле bemtree Как мне её вынести отдельно. Так чтобы можно было подключить и использовать только для данного блока? Cборщик enb

Какой из вариантов вернее?

Первый
{
         block: 'row', //bem-grid row
         mix: {block: 'someelse'}, // добавляю падинги 
         content: [
              {
                  elem: 'col',
                  elemMods: {mw: 12},
                  content:
                       {
                            block: 'someelse',
                            elem: 'heading', // элемент блока someelse
                            content: 'Какой-то заголовок секции'
                       }
             },
             {
                 elem: 'col', 
                 elemMods: {mw: 6}, 
                 content: 
                     {
                         block: 'someelse',
                         mix: {block: 'box'},
                         elem: 'item',
                         content: 'some content'
                     }
             }
         ]
}
Второй
{
    block: 'row', //bem-grid row
    content: {
         block: 'someelse',
         content: [
              {
                  block: 'row',
                  elem: 'col',
                  elemMods: {mw: 12},
                  content:
                       {
                            elem: 'heading', // элемент блока someelse
                            content: 'Какой-то заголовок секции'
                       }
             },
             {
                 block: 'row',
                 elem: 'col', 
                 elemMods: {mw: 6}, 
                 content: 
                     {
                         mix: {block: 'box'},
                         elem: 'item',
                         content: 'some content'
                     }
             }
         ]
     }
}

В первом мы примиксовываем стили, во втором вкладываем блок "someelse" в строку "row".


В первом случае приходится потом постоянно объявлять блок при создании элементов блока

...
block: 'someelse', 
elem: 'item'
...

во втором случае приходится объявлять

...
block: 'row', 
elem: 'col'
...

Как быть? Может быть скинете примеры реализации в уже рабочих проектах?


Вы меня конечно простите, если я задаю тупые вопросы. Просто я хочу докопаться до сути, чтобы потом двигать БЭМ в массы.

А как сейчас с поддержкой модификаторов без значений в i-bem, bem-xjst?

Судя по этой странице: https://ru.bem.info/technology/i-bem/v2/i-bem-js-mods/#mods-api i-bem, например, уже поддерживает. Только в bem-core?

Добрый день. Прошу сделать урок по bem-xjst. Я вот честно не врубаюсь как пользоваться. Спасибо.

Ситуация следующая, есть код:

    onElemSetMod: {
        'formating': {
            'type': {
                '1': function (elem, modName, modVal, prevModVal) {
                    console.log(BEMHTML.apply({block : 'input',val : 'bla'}));
                    console.log(BEMHTML.apply);
                    BEMDOM.update(elem,
                        '<div></div>'
                    )
                },
                '2': function (elem, modName, modVal, prevModVal) {
                    console.log(1)
                }
            }
        }
    }
}))

});

в котором BEMHTML.apply выдает мне пустую строку. Проверив весь свой код, случайно обнаружил следующую строку в файле \node_modules\enb-bemxjst\techs\bemhtml.js:

var code = 'exports.apply = function () { return ""; };',

Не могли бы Вы помочь разрешить эту проблему.

Версия bemjxst наверное пятая

{
    elem : 'slide-title',
    mix: {
        block : 'title',
        elemMods : { level : 1 } // Работает
    },
    content : item.title,
},
{
    elem : 'slide-title',
    mix: {
        block : 'title',
        mods : { level : 1 } // Не работает
    },
    content : item.title,
},

Всем привет! Задача выглядит таким образом: во входящем дереве имеем некие блоки inner-one и inner-two. В шаблонах этих блоков оборачиваю их в блок wrapper примерно так:

block('inner-one')(
    def().match(function() { return !this._innerInit })(function () {
        var ctx = this.ctx;
        return local({ _innerInit : true })(function() {
            return applyCtx({
                block : 'wrapper',
                content : ctx
            });
        })
    })
);

все отлично и прекрасно, если бы не одно но - в шаблоне wrapper-a для верстки имеем вот такой код

block('wrapper')(
    match(function() { return this.isFirst(); })(
        cls()('first')
    )
);

Проблема оказалась вот в чем - во время достроения дерева позиция у inner-one имеет значение 1, а wrapper-у присваевается уже 2. Соответственно дополнительный класс не проставляется. Читал, что позиция учитывает преобразования дерева в шаблоне по пустой моде и моде content. Второй вариант отметаем сразу, с первым так и не смог разобраться. Пробовал использовать шаблон

block('inner-one')(
    match(this._mode === '')(function () {
        return applyCtx({
            block : 'wrapper',
            content : this.ctx
        });
    })
);

но получаю обратную вложенность, т. е. wrapper вложен в inner-one. Пока как временный хак сделал так

block('inner-one')(
    def().match(function() { return !this._innerInit })(function () {
        var ctx = this.ctx,
            position = this.position - 1;
        return local({ _innerInit : true })(function() {
            return applyCtx({position : position}, {
                block : 'wrapper',
                content : ctx
            });
        })
    })
);

но восторга он у меня не вызывает. Каким образом можно "по-правильному" обойти момент с позицией? Ну или вложить блок в другой в шаблоне по пустой моде?

Давно не пользовался bemhtml и bemtree. Подскажите, как в bemtree пробросить переменную, например тему, чтобы она была доступна во вложенных шаблонах? В bh это было ctx.tParam(). Как в bemtree? Также, хотелось бы узнать пару хороших практик в bemtree

Сейчас, у нас, если блок имеет логику на priv его можно встроить только в priv'ах же

Предлагаемое решение: регистрировать декларации блоков в неком хранилище в BEMPRIV, а вызываться они должны автоматически неявно на этапе XJST В этих привах не должно создаваться BEMJSON'а, только маппинги данных и какая-нибудь хитрая логика.

XJT/BEMS - Xtendable (almost)-json RawData --> BEMJSON Transformation based on Block Elem Mod State concept (BEMS — not BEViS, 42th BEM concept fork)

https://gist.github.com/a-x-/39242cb6ee00231900f0

Как мне сейчас кажется, BEMTREE — это BEMHTML с другим расширением файлов для описания комбинация блоков в отличии от BEMHTML, который должен описывать независимые блоки

В нашем проекте он не используется и не понятно нужен ли