bem-site / bem-forum-content-ru

Content BEM forum for Russian speak users
MIT License
56 stars 6 forks source link

Вопрос по BEMTREE и project-stub merged #1317

Open webhive opened 7 years ago

webhive commented 7 years ago

Поставил project-stub из merged ветки. В нём есть 3 места где закомментировано использование bemtree. Соответственно раскомментировал, но bemtree-файлы почему-то не подхватываются.

/desktop.bundles/index/index.html 75ms
23:25:20.359 - build started
23:25:20.366 - [rebuild] [desktop.bundles/index/index.bemjson.js] file-provider
23:25:20.367 - [isValid] [desktop.bundles/index/index.bemdecl.js] bemjson-to-bemdecl
23:25:20.370 - [rebuild] [desktop.bundles/index/index.levels] levels
23:25:20.372 - [isValid] [desktop.bundles/index/index.deps.js] deps
23:25:20.374 - [rebuild] [desktop.bundles/index/index.files] files
23:25:20.374 - [rebuild] [desktop.bundles/index/index.dirs] files
23:25:20.375 - [isValid] [desktop.bundles/index/index.bemhtml.js] bemhtml
23:25:20.375 - [isValid] [desktop.bundles/index/index.html] bemjson-to-html
23:25:20.375 - build finished - 23ms

Даже упоминания нет. Соответственно вопрос - что делать?

tadatuta commented 7 years ago

Вообще это странно. Я только что проделал эти же действия

diff --git a/.enb/make.js b/.enb/make.js
index 8289757..e37b58b 100644
--- a/.enb/make.js
+++ b/.enb/make.js
@@ -25,7 +25,7 @@ var techs = {
         browserJs: require('enb-js/techs/browser-js'),

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

         // bemhtml
         bemhtml: require('enb-bemxjst/techs/bemhtml'),
@@ -63,7 +63,7 @@ module.exports = function(config) {
             }],

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

             // bemhtml
             [techs.bemhtml, {
@@ -109,6 +109,6 @@ module.exports = function(config) {
             [techs.borschik, { source: '?.css', target: '?.min.css', minify: isProd }]
         ]);

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

и у меня вот такой результат:

15:24:25.914 - build started
15:24:25.934 - [rebuild] [desktop.bundles/index/index.bemjson.js] file-provider
15:24:25.991 - [rebuild] [desktop.bundles/index/index.levels] levels
15:24:25.992 - [rebuild] [desktop.bundles/index/index.bemdecl.js] bemjson-to-bemdecl
15:24:26.042 - [rebuild] [desktop.bundles/index/index.deps.js] deps
15:24:26.048 - [rebuild] [desktop.bundles/index/index.files] files
15:24:26.049 - [rebuild] [desktop.bundles/index/index.dirs] files
15:24:26.366 - [rebuild] [desktop.bundles/index/index.bemtree.js] bemtree
15:24:26.367 - [rebuild] [desktop.bundles/index/index.bemhtml.bemdecl.js] deps-by-tech-to-bemdecl
15:24:26.384 - [rebuild] [desktop.bundles/index/index.browser.js] browser-js
15:24:26.385 - [rebuild] [desktop.bundles/index/index.bemhtml.deps.js] deps
15:24:26.386 - [rebuild] [desktop.bundles/index/index.bemhtml.files] files
15:24:26.386 - [rebuild] [desktop.bundles/index/index.bemhtml.dirs] files
15:24:26.393 - [rebuild] [desktop.bundles/index/index.browser.bemhtml.js] bemhtml
15:24:26.398 - [rebuild] [desktop.bundles/index/index.js] file-merge
15:24:26.572 - [rebuild] [desktop.bundles/index/index.css] enb-postcss
15:24:26.577 - [rebuild] [desktop.bundles/index/index.bemhtml.js] bemhtml
15:24:26.647 - [rebuild] [desktop.bundles/index/index.html] bemjson-to-html
15:24:26.650 - [rebuild] [desktop.bundles/index/index.min.js] borschik
15:24:26.794 - [rebuild] [desktop.bundles/index/index.min.css] borschik
15:24:26.795 - build finished - 1917ms

Но вообще, если нужно по BEMTREE генерировать статические HTML-страницы, то имеет смысл использовать https://github.com/tadatuta/bem-bemtree-static-project-stub (это примерно тот же project-stub + технология для генерации страничек с учетом BEMTREE).

webhive commented 7 years ago

Попробовал на чистом project-stub (не merged). Раскомментировано всё как у вас. С виду вывод такой-же. Создал блок test в папке common.blocks.

test.bemtree.js

block('test').content()(function(){
    return {
      tag: 'h1',
      content: 'Hello!'
    }
})

Добавляю его в bemjson index-a

...
            block: 'header',
            content: [
                'header content goes here',
                { block: 'test' }
            ]
...

В итоговом html-е получаю .... <div class="test"></div> ...., т.е. я так понимаю bemtree файл не отработал. Насколько я понимаю вывод должен быть .... <div class="test"><h1>Hello!</h1></div> ....

Или чего-то я ещё упустил?

PS: bem-bemtree-static-project-stub уже ковырял, но не помогло

DjonyBastone commented 7 years ago

У меня на project-stub тоже не собирает из index.bemjson.js, после того как де-комментировал про bemtree

bem-bemtree-static-project-stub предлагает по умолчанию index.bemdecl.js в котором вызывается root и всё... нет bemjson'а

Ребята, может у вас там рабочий проект... и вся среда разработки закешировалось!? ))))))))

А если без шуток. Пожалуйста дайте рабочий пример... не первый раз прошу - не ответили. С открытым сердцем, готов помочь - чем могу, хоть про bemtree запилить статью про стартовый проект, или еще чего. Но особо не чем делиться, пишу 5ую простыню в 5000 строк bemjson'а

webhive commented 7 years ago

нет bemjson'а

Ну он как раз должен сгенерироваться с помощью bemtree. Вот тока не работает оно почему-то.

webhive commented 7 years ago

@tadatuta Но вообще, если нужно по BEMTREE генерировать статические HTML-страницы, то имеет смысл использовать https://github.com/tadatuta/bem-bemtree-static-project-stub (это примерно тот же project-stub + технология для генерации страничек с учетом BEMTREE).

Всё чудесатее и чудесатее. Вопрос - почему в .enb\make.js нет addTarget для bemtree? А в project-stub есть?

Второй момент - bem-bemtree-static-project-stub использует bemdecl вместо bemjson-а, но если я пробую сделать так-же на project-stub-е то получаю ошибку.

Что-то тут видимо в enb накручено не так, но я в виду неопытности не могу сообразить в чём проблема.

Блин - сижу сверяю диффом make.js -ы. Бред какой-то.

webhive commented 7 years ago

Ёёёёёперный театр - сколько же там магии и ручного кода. Заставил я это дело пинками работать, перетащив часть конструкций из bem-bemtree-static-project-stub. Но ..... просто слов нет и тут вместо своего тестового блока с нехитрым именем test получаю на выходе блок с именем root. Занавес!!! Как оказалось в bem-bemtree-static-project-stub подключается своя вручную писана технология .enb/techs/bemtree-to-html.js в которой прошито

...
return BEMHTML.apply(BEMTREE.apply({ block: 'root' }));
...

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

Ну и насколько я понял раз уж @tadatuta для bemtree вручную код пишет, то видимо на enb по умолчанию с bemtree работать никак.

tadatuta commented 7 years ago

@webhive Причина о том, что не бывает никакого «по умолчанию». Есть конкретные задачи и для них специфичные решения.

Если говорить именно в контексте ENB, то с точки зрения сборки самого BEMTREE-бандла нет вообще ни малейших отличий от сборки BEMHTML. Отличия есть в источнике данных и в том, что именно хочется сгенерировать в результате.

В частности, если нужно собирать по одной HTML-странице на основе BEMTREE, то не обязательно что-либо делать руками, можно просто брать https://github.com/tadatuta/bem-bemtree-static-project-stub, репозиторий для того и существует (блок root, разумеется, не является чем-то обязательным, это просто произвольное название, которое написано вот тут, его можно заменить на то, что больше нравится).

Есть другая схема: когда на вход некоторая модель данных, а на выход произвольная структура HTML-страниц. Так, например, генерируется bem.info по вот такой модельке.

Еще вариант — когда сайт динамический. Для такого подхода можно использовать репозиторий https://github.com/bem/bem-express.

Все три варианта используют BEMTREE, но используют по-разному. Поэтому сделать что-то по-умолчанию и не получится.

Ну и, наконец, не вижу ничего военного в том, чтобы написать под себя технологию для ENB. Если смотреть на https://github.com/tadatuta/bem-bemtree-static-project-stub/blob/master/.enb/techs/bemtree-to-html.js, то там менее двух десятков строк кода, остальное JSDoc. По смыслу там написано буквально следующее: возьми BEMTREE-бандл, передай в него данные, то, что получится передай в BEMHTML, а результат запиши на диск.

В коде это еще проще, чем текстом:

BEMHTML.apply(BEMTREE.apply({ block: 'root' }));

Ну и оставшиеся вопросы:

почему в .enb\make.js нет addTarget дляbemtree? А в project-stub есть?

Потому что технология получения HTML сама автоматически потребует сгенерировать BEMTREE-бандл. Указывать его в таргетах явно не обязательно (хотя и можно).

bem-bemtree-static-project-stub использует bemdecl вместо bemjson-а, но если я пробую сделать так-же на project-stub-е то получаю ошибку

Тут может быть 2 причины:

  1. Если стартовать с bemdecl-а, то нужно его и провайдить тут https://github.com/bem/project-stub/blob/master/.enb/make.js#L53 (и не нужно генерировать на следующей строке).
  2. Технология https://github.com/bem/project-stub/blob/master/.enb/make.js#L76 из пакета enb-bemxjst ожидает на вход готовый BEMJSON. Если хочется использовать для генерации HTML-страниц BEMTREE, нужна соответствующая технология.

Такая уж ли это прямо магия? ;)

tadatuta commented 7 years ago

@DjonyBastone

bem-bemtree-static-project-stub предлагает по умолчанию index.bemdecl.js в котором вызывается root и всё... нет bemjson'а

Ну как так-то? Там в качестве примера из коробки рисуется шапка с логотипом:

  1. Стартует все с root, он генерирует обвязку страницы: https://github.com/tadatuta/bem-bemtree-static-project-stub/blob/master/common.blocks/root/root.bemtree.js
  2. Затем в шаблоне page рисуются верхнеуровневые блоки header, main и footer внутри <body>: https://github.com/tadatuta/bem-bemtree-static-project-stub/blob/master/common.blocks/page/page.bemtree.js
  3. В header-е добавляется логотип: https://github.com/tadatuta/bem-bemtree-static-project-stub/blob/master/common.blocks/header/header.bemtree.js

Возможно, проблема в том, что при создании собственных блоков они не указываются в депсах? В отличии от сборки по готовому BEMJSON-файлу, BEMTREE-шаблоны сначала необходимо собирать, поэтому депсы приходится писать руками (примеры там же рядом с bemtree-шаблонами).

webhive commented 7 years ago

@tadatuta Причина о том, что не бывает никакого «по умолчанию».

Не вполне соглашусь. В качестве примера сошлюсь на себя :-) Про сборку всё понятно - в смысле как оно работает, вернее даже как оно должно работать. Я немного про другое. Вот беру я project-stub - ну не нужен мне bemtree (пока). Поигрался я и хочу подключить bemtree. Ну вроде как в теории всё понятно - надо подключить технологию и типа оно заработает - вау - да там и в make.js строчки закомментареные. Расскоментариваем и ничего .... далее идет куча вопросов - может я bemtree файл неправильный сделал, может не туда его положил, может ещё чего. Далее начинаю ползать по bem проектам на github-е и сравнивать make.js -ы. Самое безобразное-то, что отличие-то там где его и не ждали.

bemjsonToHtml: require('./techs/bemtree-to-html')

Названия не смущают? В обоих проектах вызывается [techs.bemjsonToHtml] но вот только внутренности разные. Это ли не магия?

Тут может быть 2 причины:

На самом деле вот разница: https://github.com/bem/project-stub/blob/master/.enb/make.js#L54

В project-stub bemdecl генерируется из bemjson.

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

tadatuta commented 7 years ago

@webhive На самом-то деле при раскомментировании строк про сборку bemtree в project-stub, бандл с bemtree-шаблонами собирается. Тут все честно.

А вот дальше начинается кастомщина про то, как собиранный бандл использовать: собрать из каждого бандла отдельный HTML или одного бандла много разных, записать его на диск или отдавать на каждый запрос динамически и так далее.

В обоих проектах вызывается [techs.bemjsonToHtml] но вот только внутренности разные. Это ли не магия?

Это скорее неудачный копипаст. Стоит поправить, с радостью приму pull request ;)

В project-stub bemdecl генерируется из bemjson.

Прикол в том, что при желании эту схему можно сохранить и с BEMTREE. Например, использовать исходный bemjson-файл вместо захардкодженного в технологии блока root в качестве стартового контекста при вызове BEMTREE.apply().

Тут нет «правильного» решения, есть решения для конкретной задачи.

DjonyBastone commented 7 years ago

@tadatuta

С deps вообще нет проблем, напишу их сколько надо, хоть тысячу

Вопрос в том:

belozer commented 7 years ago

@DjonyBastone проблема ещё актуальна?

По поводу deps. Вот для примера такой граф построения страницы (который описал @tadatuta https://github.com/bem-site/bem-forum-content-ru/issues/1317#issuecomment-294950202)

              header - logo
            /
root - page - main
            \ 
              footer

root - это просто вспомогательный "захардкоженный" блок. По факту это может быть любой блок, откуда начать построение. Данный блок генерирует блок page, значит в его зависимостях должен быть данный блок.

// blocks/root/root.deps.js
[{
    shouldDeps : [
        { block : 'page' }
    ]
}];

Далее шаблонизатор попадает в блок page, который генерирует header, main, footer.

// blocks/page/page.deps.js
[{
    shouldDeps : [
        { block : 'header' },
        { block : 'main' },
        { block : 'footer' }
    ]
}];

При попадании в header генерируется logo, значит укажем его в зависимостях.

// blocks/header/header.deps.js
[{
    shouldDeps : [
        { block : 'logo' }
    ]
}];

deps файлы нужны для того, чтобы собрать нужные шаблоны. Если нужного шаблона не будет в сборке, то шаблонизатор не сможет обработать дерево (и соответственно ничего не построится).

По факту все зависимости можно указать в одном месте (например root), но это очень плохая (даже ужасная) практика.

// blocks/root/root.deps.js
[{
    shouldDeps : [
        { block : 'page' },
        { block : 'header' },
        { block : 'main' },
        { block : 'footer' },
        { block : 'logo' }
    ]
}];
belozer commented 7 years ago

По поводу построения нужных страниц, @tadatuta а действительно... Как генерировать нужные страницы?

Раз https://github.com/tadatuta/bem-bemtree-static-project-stub/blob/master/.enb/make.js#L75

Два https://github.com/tadatuta/bem-bemtree-static-project-stub/blob/master/.enb/techs/bemtree-to-html.js#L33

Тут что-то странное.

DjonyBastone commented 7 years ago

@belozer Вопрос актуальный.

И так как ответа нет, и сам не сообразил - то, забросил это дело, всю разработку по бэм. Если будет решение - продолжу... нет - дак, нет. Захожу периодически на форум, в надежде увидеть для себя ответ.

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

belozer commented 7 years ago

@DjonyBastone архитектурно нет ничего сложного :) Просто из коробки решения не самые удачные для старта, к сожалению... Проблема в том, что они часто запутывают или ведут в тупик (как project-stub). На следующих выходных постараюсь собрать стартовый набор для разработки (с выжимкой граблей, которые отгрёб за время изучения). Надеюсь он тебе поможет :)

DjonyBastone commented 7 years ago

Это очень хорошая идея!!!

Если что смогу помочь с документацией, вдруг потребуется.

Есть опыт - доходчиво оформлять инструкции, минирегламенты, руководства

webhive commented 7 years ago

архитектурно нет ничего сложного :)

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

то, забросил это дело

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

belozer commented 7 years ago

@webhive @DjonyBastone Накидал "своё видение" стартового набора для обучения бэм разработке. https://github.com/bem-contrib/bem-starter-kit

Он во многом похож на репозиторий @tadatuta, практически идентичен. Основная его идея приучить работать с deps и bemtree на ранних этапах и при этом сохранить простоту project-stub.

Из плюсов данного подхода:

Из минусов:

Как выглядит flow:

Шаг 1.

Создаётся бандл/страница bundles/my-page/my-page.bemjson.js, в которой описывается блок page и его содержание.

В общем на этом этапе сохраняется простота project-stub. Всё что объявлено в этом bemjson подтягивается из файловой системы автоматически (например блок greeting).

Шаг 2.

Чтобы не городить длинные полотна из bemjson разбиваем проект по блокам со своими зависимостями, т.е. работает эта схема https://github.com/bem-site/bem-forum-content-ru/issues/1317#issuecomment-299576350 Основная идея не захломлять вёрстку кучей вложенности (https://github.com/bem/project-stub/issues/159#issuecomment-240557915)

В общем как-то так. Всё просто.

Технические/промежуточные бандлы типа декларций я постарался отделить точкой в начале имени файла, чтобы они прятались системой от глаз.

Так выглядит собранный бандл (без промежуточных файлов)

bundles
└── index
    ├── index.bemhtml.js
    ├── index.bemjson.js
    ├── index.bemtree.js
    ├── index.browser.js
    ├── index.css
    ├── index.html
    ├── index.js
    ├── index.min.css
    └── index.min.js

П.Н. И не стоит забывать что это только один из вариантов настройки сборки, не более :) Но с заложенными принципами, которые нужны при любой настройке сборки.

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

webhive commented 7 years ago

Я конечно дико извиняюсь, но действительно в чём тут принципиально отличие от project-stub? И опять в качестве примера один тривиальный бандл. Таких примеров полно и с ними как раз проблем нет.

Сделайте внятный пример с как минимум 2-мя разными бандлами, где будет допустим общий header/footer, но разный контент.

Создаётся бандл/страница bundles/my-page/my-page.bemjson.js

Опять у нас bemjson "first-class citizen" на входе у нас данные, а bemjsоn надо ещё сгенерировать. Давайте уж перейдём к реальным примерам из реальной жизни, а не абстрактным вещам "берём bemjson и он прекрасно превращается в html".

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

Чтоб подлить масла в огонь подкину идею - теперь выложите проект на сервер и чтоб там оно работало и на реальные запросы отвечало в динамике. Не просто сгенерированный html отдавать как статику, а чтоб весь цикл отрабатывал data -> bemtree -> bemhtml -> html. Насколько я понял придётся писать свою middleware и внутри вызывать bemtree и bemhtml из библиотеки, а не пользоваться сборщиком. И вот там ещё больше ада, хотя опять на одной простой страничке с одним блоком всё вроде бы и нормально, но шаг влево шаг вправо и начинаются проблемы.

Итого прорезюмирую - такие примитивные примеры как у вас смысла не имеют. Времена когда для демонстрации хватало вывести "Hello world!" уже давно прошли.

Сделайте реальный пример на полном стэке -- data -> bemtree -> bemhtml -> html где бандлы состоят и общих блоков и своих уникальных, типа классического общий header/footer + свой контент. Причём копипаста блоков header/footer не считается.

belozer commented 7 years ago

@webhive спасибо за отзыв. Не всё совсем так, как ты описал. Этот кит немного хитрей и больше представляет собой "статический" набор для вёрстки, которую потом намного проще подключить к динамике.

bemjson в данном случае выступает точкой для построения всего дерева.

data + bemjson(root) -> bemtree -> bemjson -> bemhtml -> html

На сервер выкладывать не буду, а вот функцию для рендера данных добавлю.

DjonyBastone commented 7 years ago

@belozer спасибо большое!!!

Еще не ознакомился, на неделе обкатывать буду. Будут вопросы обязательно напишу!

По документации параллельно прилагать усилия?