Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
webhive opened this issue Apr 17, 2017 · 21 comments
Open

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

webhive opened this issue Apr 17, 2017 · 21 comments

Comments

@webhive
Copy link

webhive commented Apr 17, 2017

Поставил 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
Copy link
Member

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

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
Copy link
Author

webhive commented Apr 18, 2017

Попробовал на чистом 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
Copy link

DjonyBastone commented Apr 18, 2017

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

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

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

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

@webhive
Copy link
Author

webhive commented Apr 18, 2017

нет bemjson'а

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

@webhive
Copy link
Author

webhive commented Apr 18, 2017

@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
Copy link
Author

webhive commented Apr 18, 2017

Ёёёёёперный театр - сколько же там магии и ручного кода. Заставил я это дело пинками работать, перетащив часть конструкций из 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
Copy link
Member

@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
Copy link
Member

@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
Copy link
Author

webhive commented Apr 18, 2017

@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
Copy link
Member

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

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

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

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

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

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

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

@DjonyBastone
Copy link

DjonyBastone commented Apr 19, 2017

@tadatuta

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

Вопрос в том:

  • если на каждой странице, блок main со своим контентом(наполнением).
    Что нужно сделать, для того что бы сработало?
    а именно:
  • структура файлов
  • и какой код в каком месте должен быть, что бы позвать страницу, и что бы в ней содержался нужный main

@belozer
Copy link

belozer commented May 5, 2017

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

По поводу deps.
Вот для примера такой граф построения страницы (который описал @tadatuta #1317 (comment))

              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
Copy link

belozer commented May 5, 2017

По поводу построения нужных страниц, @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
Copy link

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

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

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

@belozer
Copy link

belozer commented May 7, 2017

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

@DjonyBastone
Copy link

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

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

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

@webhive
Copy link
Author

webhive commented May 8, 2017

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

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

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

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

@belozer
Copy link

belozer commented May 14, 2017

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

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

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

  • Простота project-stub
  • BEMTREE из коробки
  • Работа с deps файлами сразу, а не тогда, когда ад в bemjson

Из минусов:

  • Пока нет доки :)
  • Не обкатано на новичках

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

Шаг 1.

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

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

Шаг 2.

Чтобы не городить длинные полотна из bemjson разбиваем проект по блокам со своими зависимостями, т.е. работает эта схема #1317 (comment) Основная идея не захломлять вёрстку кучей вложенности (bem/project-stub#159 (comment))

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

  • bemtree бандлы собираются в файл bundles/my-page.bemtree.js
  • bemhtml бандлы собираются в файл bundles/my-page.bemhtml.js
  • browser.js бандлы собираются в файл bundles/my-page.browser.js (js и min.js это склееные browser.js + bemhtml.js)
    и т.д.

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

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

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
Copy link
Author

webhive commented May 14, 2017

Я конечно дико извиняюсь, но действительно в чём тут принципиально отличие от 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
Copy link

belozer commented May 14, 2017

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

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

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

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

@DjonyBastone
Copy link

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

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants