Делаем сайт на bem-tools, который будет состоять из нескольких статических страниц.
У всех страниц есть общие блоки - шапка, подвал, меню. Шапка и подвал - одинаковые, меню на разных страница отличается лишь выделенным пунктом.
Чтобы добавить на очередную страницу такие блоки, мы тупо копируем куски bemjson из одной страницы в другую.
Подскажите, как можно избежать копипаста?
Спасибо Вам, будет очень полезным.
А можно ли будет через include подключать и выполнять priv.js?
если сайт статический, то можно просто сделать блок b-foot который будет разворачиваться в нужный тебе bemjson. костыльненько, но работает
в динамиеском проекте с приватными шаблонами это вообще не нужно: у тебя шаблон итак возвращает bemjson, а одна строка типа blocks['b-foot']() не кажется копипастом уж стращным
Возможно, я чего-то не знаю
Речь о динамическом проекте. Обычно это бывает так:
- проект верстается;
- пишутся priv.js вместе с бэкендом;
- приходит пора менять что-то в вёрстке, для этого меняются блоки/бандлы... это дело утверждается менеджером/дизайнером;
- всё, что поменялось в вёрстке переносится в priv.js (щасто копипастом).
Когда много бандлов и внесённых правок, вёрстка всё чаще и чаще местами начинает не совпадать с тем, что формирует бэкенд. Живёт вёрстка отдельно, обычно потому, что есть фронтендер который умеет верстать/писать клиентские скрипты/писать шаблоны и бэкендер.
Хочется, чтобы во время вёрстки можно было сразу использовать priv.js в bemjson и подставлять в них data-рыбу, тогда при последующих правках изменять придётся не bemjson, а priv.js и копипаста не будет.
Раньше пробовал подключать в bemjson бандлы priv.js через require как в CommonJS, но это не работало... есть ли сейчас какая-то возможность написать blocks['b-foot']() внутри bemjson?
я кажется чего-то не понимаю как у вас устроено
что значит "верстается"? отдельно обычная статика? верстка должна делаться сразу в bem терминах и структуре, откуда у вас копипаст?
схема примерно такая
/запрос, поход за данными >
data попадает в >
корневой priv.js, дальше, потом запускаются рекурисвно все вложенные шаблоны, данные обрабатываются и возвращается bemjson >
накладывается bemhtml и отдается html в браузер
выглядит примерно так
это контент блока b-page
https://gist.github.com/tyv/ece5814c47f27fad6505
в этих блоках в свою очередь зовутся другие блоки, каждый из которых возвращаяет bemjson.
ну или может быть такой вариант
https://gist.github.com/tyv/39bcf34b7ec634a0a35d
каждый из вызываемых блоков выглядит рпимерно так
https://gist.github.com/tyv/613bee232c4b074592c8
при такой схеме копипасту вообще неоткуда браться
Всё происходит именно так, как вы и описали, разница лишь в подходе к разработке проекта. Попытаюсь объяснить как у нас происходит, и зачем нужна отдельно статика.
Прекрасно понимаю, что такой подход имеет минусы, и возможно не имеет право на существование, но реалии таковы, что отказаться от него не так просто, ну и разговор в целом не о подходе.
И так, у нас есть несколько человек: дизайнер, фронтедер и бэкендер. Разделение довольно условное и чёткой границы того, что должен уметь каждый нету, но смысл в том, что каждый умеет делать что-то, что не умеет делать другой (например, фронтендер обладает знаниями вёрстки под ie6, но не умеет работать с базами данных; а бэкендер, наоборот хорошо ладит с базами, и даже мастерски оптимизирует SQL-запросы, но о вёрстке у него представление поверхостное). В связи с этим у каждого есть некая область которой занимается только он, а именно, дизайнер рисует макетики в фотошопе, фронтендер берёт макетики, верстает их и передаёт получившееся дальше (под вёрсткой я понимаю создание статики, т.е. всё делается в БЭМ-терминах - создаются блоки, пишутся bemhtml шаблоны и создаются bemjson бандлы), бэкендер делает оставшиеся манипуляции и пишет priv.js на основе бандлов в bemjson.
Если подытожить сказанное выше, то процесс выглядит так: 1) дизайн, 2) вёрстка, 3) программирование.
На втором этапе ещё нет никакого бэкенда, и это первая причина того, зачем нужна отдельно статика. bem-tools/borschik собирает css/js/bemhtml/priv технологии, основываясь на бандлах/статике, и это причина номер 2. Когда проект сделан, и надо вносить какие-то правки, они делаются в статике, потому что совсем не факт, что до бэкенда они дойдут в том же виде, в каком изначально планировались, попросту говоря надо просто пощупать вёрстку/изменение дизайна на тестовых данных, а потом уже писать бэкенд под это дело, и это причина номер 3.
В итоге почти один и тот же bemjson содержится как в бандлах статики, так и в priv.js. На мой взгляд, было бы логично хранить всё только в priv.js, а для статики вызывать их, подставляя рыбу.
Могу предположить, что у вас в командах люди одновременно могут делать и фронтенд и бекэнд, и после дизайна одновременно происходит и программирование и вёрстка, и дизайнеры/менеждеры, дают задания, которые не надо будет потом переделывать на бэкенде, но как вы обходите причину номер 2, я понять не могу.
Очень надеюсь, что хоть как-то объяснил проблему
Накидал пример того, что хочется на основе project-stub. Основной смысл в файле https://github.com/andrew blond/project-stub/blob/m aster/desktop.bundles/ind ex/index.bemjson.js.
Да, вопрос про причину номер 2 был именно в этом, спасибо.
Но в целом пытался объяснить проблему, когда удобнее было бы отдельно держать и статику и бэкенд, а от копипаста избавиться за счёт include в bemjson.
Есть ли какие-то технические сложности реализовать include/require для bemjson-технологии? вроде как nodejs дружит с require...
сейчас думаю про то, чтобы сделать кастомный шаблон b-page, где сразу захардкодить общие для всех страниц шапку и подвал.
(псевдокод)
block b-page body: [
{ block: 'b-head'},
this.ctx.content,
{block: 'b-menu'},
{block: 'b-foot'}]
правда не могу разобраться с техникой - как это можно сделать, не копипастя весь https://github.com/bem/be
если трюк получится, то с меню можно будет поступить аналогично, закодив данные и логику отображения выделенного пункта в bemhtml, прокидывая идентификатор текущей страницы из bemjson через какой-нибудь 'i-global'.
но пихать логику в bemjson, по правде говоря, совсем не хочется, иначе в перспективе либо получатся server side includes, либо надстройка с анемичным шаблонизатором, либо php, либо lisp (во что совсем не верится). поэтому пусть данные остаются данными.
Вы про логику подключения? не очень понимаю почему server side includes, ведь bemjson будет выполняться только при bem make/server и к релизному серверу никак относиться не будет. На мой взгляд, это как, import в css, довольно полезно и безобидно.
У bemhtml другие задачи, а именно, он отвечает за преобразование контекстно-ориентированных данных в html. Например, в bemhtml-шаблонах можно сказать что блок состоит из 10 вложенных в друг друга тегах, чтобы скруглённые уголки работали в ie6.
А вот задачу агрегации блоков хорошо решает priv.js. Всё, что вы хотели сделать можно выразить через него.
blocks['b-page']=function(data) {
return [
blocks['b-head'](data.head),
data.content,
blocks['b-menu'](data.menu),
blocks['b-foot'](data.foot),
]
}
т.е. основная причина — отсутствие данных.
если ваш фронтенд-разработчик пишет bemhtml и клиентский js, ему не составит труда превратить какой-то json в bemjson внутри приватных шаблонов.
таким образом пока нет данных нужно договориться о том какие они будут, каким-то образом "подсунуть" рыбу и, после того как бекенд разработчик подготовит правильные данные, просто их подменить.
Проблема в том как подсунуть?
если да, то решить ее кажется просто, хоть с файловой системы json прочтите.
ну и таким образом вы откажетесь от статики (она вообще не очень нужна, это почти как html руками писать), а декларации нужно разнести по deps.js файлам блоков.
мне кажется, если смешать bemjson и priv.js, то получится опять priv.js . вероятно, такую задачу лучше решать со стороны bem server, научив выполнять priv.js, нежели смешиванием уровней абстракции. %)
Не сказал бы, что получится priv.js, видимо, нечто новое и отличное от bemjson. Научить bem server выполнять priv.js не получится по двум причинам: во-первых он ничего не знает о данных, во-вторых он не знает об отношении между приватными шаблонами. Исходя из этого можно, разве, что придумать ещё одну технологию в которой пробрасывать рыбные данные и отношение между priv.js шаблонами, которая будет генерировать bemjson, который уже будет работать как надо.
Ниже писали о bemjson.raw, может быть это оно и есть.
Вам правильно показалось priv.js предназначен для преобразования данных (json) в контекстно-ориентированные (bemjson). Но если бэкенда нету, то вам просто не надо использовать priv.js, bemhtml же может использоваться решая свои задачи (bemjson -> html).
можете рассказать, какой вы вкладываете смысл в bemjson.raw?
Вы всё правильно поняли, причина действительно в отсутствии данных. Но проблема не совсем в том, как "подсунуть" рыбу. Когда мы используем bemjson, от bem-tools больше пользы: во-первых файлы деклараций пишутся автоматически, и по ним собираются css/js/bemhtml/priv.js; во-вторых мы можем пользоваться bem-server, собирая только те бандлы, которые верстаем. А для каждой правки вёрстки запускать bem make очень не хочется.
Получается, что сама статика, как таковая, не нужна, просто хочется сохранить преимущества от использования bem-tools.
декларации должны быть в каждом отдельном блоке, свои, а не одни на весь проект/бандл. Иначе смысл модульности теряется
Согласен, но надо же ручками в каждом бандле написать список используемых блоков (хотя это тоже впринципе не страшно)?
Но вот как использовать bem server при таком подходе?
дождаться когда будет поддержка priv.js
оуу, ну тогда всё круто!
BEM.blocks получается хранит все priv.js шаблоны? Он же вроде содержит все инициализированные блоки... Наверное, я не в том контектсе на это смотрю.
Где правильнее хранить priv.js шаблоны? Я пока выбрал App.priv[].
И я не вижу никаких проблем в использовании bemhtml для избравления от копипаста между bemjson, если проект полностью статичный.
Если хочется добавить больше идеологии (tm), можно разнести шаблоны про оформление и шаблоны про копипаст на разные уровни переопределения.
А как сделать, если я на клиенте получаю data-ориентированный json от API, и хочу получить bemjson?
Или стоит сделать отдельно получение bemjson от сервера, что-то типа /posts/1.bemjson ?
Спасибо!
Как добавить техлоногию priv.js http://clubs.ya.ru/bem/re plies.xml?parent_id=2557& item_no=2544&with_parent= 1#reply-bem-2557
присоединяюсь к вопросу
Если же преобразование dataJson -> bemJson должно происходить как на клиенте, так и на сервере и хочется избежать копипаста, есть смысл в написании технологии common.js, которая бы собиралась и в клиентский js и в серверный.
Спасибо!
Чтобы работал код, приведенный в примере, необходимо либо подключать его на страницу, либо написать технологию, которая бы включала скомпилированные шаблоны в страничный js файл перед кодом клиентского js (для экономии http-реквестов).
При чем BEMHTML это объект типа Function, я понимаю. В данном случае на клиент заранее приходит шаблон в BEMHTML.
У меня проблема была как раз с тем, как собрать компилятор bemhtml-шаблонов ( github.com:bem/bl-core-bemhtml, который вы уже спрятать успели ), чтобы он работал на клиенте.
i-bem собрался, но bemhtml лежит где-то отдельно
bemjson для сборки i-bem:
({
block: 'b-page',
head: [
{ block: 'i-jquery', elem: 'core' },
]
})
Может быть тут просто какие-то элементы надо объявнить, чтобы BEMHTML на клиенте появился? Не шаблон, но сам компилятор, который создает эти BEMHTML объекты.
UPD: Просто во многих местах об этом говорят, и вроде как это возможно, но я не нашел (может искал плохо), как именно выгрузить компилятор в браузер. Это ведь реально?
А почему не подходит вариант с предварительной компиляцией или в крайнем случае компиляцией на сервере и отправкой результата аяксом?
Оно может и подходит, но это потребует дополнительных вливаний времени в настройку сервера (там все еще нет ноджс), енвайронмента, и доработку внутренней архитектуры приложения в части вывода шаблонов через v8js или подготовленных с его помощью. В общем, это кажется сильно менее реальным, чем верстать с bem tools и после рендерить шаблоны на клиенте.
С другой стороны, такой подход заставит выгружать все deps нужных блоков для отрисовки, что тоже не очень хорошо. Надо думать. Спасибо