bem-site / bem-forum-content-ru

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

Должен ли i-bem__dom_init_auto.js подключаться последним? #315

Open h4 opened 9 years ago

h4 commented 9 years ago

Продолжаю переводить наш проект на bem-core с собственным сборщиком и шаблонизацией на twig.

Вчера убил кучу времени в попытках заставить инициализироваться блоки. Не хотели ни в какую. Сегодня решил поставить i-bemdom_init_auto.js самым-самым последним среди подключаемых js-файлов — и всё завелось. Но это несколько неудобно, потому что мы подключаем js в виде 3-4 бандл-файлов и не хочется делать ещё один для i-bemdom_init_auto.js.

Есть какие-то варианты решения проблемы?

qfox commented 9 years ago

@h4 Про бандлы: см. enb-bembundle, дока не очень, но часть проблем решает, там не много кода. Еще часть технологий уехало в enb-bem-techs, т.е. там осталось только самое про бандлы.

А twig вы и на морде запускаете? Я на днях баловался со сборкой шаблонов смарти в виде матчеров. Там же тоже кастомный синтаксис? Решил сначала компилировать, а потом склеивать, или сначала склеивать, а потом компилировать?

h4 commented 9 years ago

Вот нет у нас enb и не будет в обозримом будущем, поэтому хочется понять механику работы (но не закопаться по уши в исходники, желательно).

qfox commented 9 years ago

@h4 Ах...

У нас просто есть свой сборщик, меня уже тошнит в него правки делать лезть. Ни тестов, ничего.

В общем, тогда я советую вам реализовать must/should обработку, без них очень тяжело. Еще у нас загрузка явная загрузка файлов есть в разные бандлы, как переходный вариант. Вот так выглядит deps.json (не deps.js) для блоков страниц:

{
  "must": [
    { "type": "js", "file": "jquery.js" },
    { "type": "css", "file": "base.less" },
    "i-bem"
  ],
  "should": [
    "еще-блок"
  ]
}

Правда, этот i-bem у нас еще из bem-bl года 2013.

h4 commented 9 years ago

@zxqfox так, а что там с i-bem__dom_init_auto.js-то? Должен он быть самым последним загружен или нет?

qfox commented 9 years ago

Ну и по по поводу исходной проблемы: я бы взял код _init_auto и реализовал инициализацию блоков после загрузки бандлов. Сам _init_auto нужен для инициализации после загрузки страницы, но т.к. вы это делаете уже после domready и вообще неизвестно когда — нужно это руками делать.

Для тестов можно попробовать вызвать $('.block').bem('block') после вставки в дом.

qfox commented 9 years ago

Честно говоря, про последним — первый раз слышу. Там есть магия, но она другого порядка. https://github.com/bem/bem-core/blob/v2/common.blocks/i-bem/__dom/i-bem__dom.js#L1511-L1524 — вот такое там есть. Но это, скорее, наоборот — первым надо загружать. https://github.com/bem/bem-core/blob/v2/common.blocks/i-bem/__dom/_init/i-bem__dom_init_auto.js — хотя, по коду — явно надо после отрисовки запускать.

У тебя modules сам нормально встал? Мало ли ему чего-то не хватает и он раньше времени отрабатывает?

qfox commented 9 years ago

Идея есть: jquery часто грузится асинхронно и резолвится, естественно, после domready. Если вы грузите его синхронно и резолвите сразу — modules может запустить этот код раньше времени. Я даже про это issue видел в bem-core. @tadatuta ставил, @dfilatov правил.

h4 commented 9 years ago

Покрутил всё в разные стороны. Получил только вот такое работающее решение для ситуации, когда есть собранный файл lib.js в котором все библиотеки, включая i-bem и параллельно загружаемый project.js в котором все наши блоки.

/**
 * i-bem__dom_init_auto.js
 */

modules.require(
    ['jquery', 'next-tick'],
    function($, nextTick) {

        $(function() {
            nextTick(function() {
                modules.require(['i-bem__dom_init'], function(init) {
                    init();
                });
            });
        });
});

Как я понял — в modules.require «замораживается» состояние свойства BEMDOM.blocks на момент декларации и поэтому не получалась нормальная инициализации.

А на самом деле — я уапще ничего не понял, и require в require меня не очень радует.

tadatuta commented 9 years ago

@h4 lib.js и project.js именно загружаются параллельно или все-таки последовательно, но приходится ждать nextTick, чтобы начать работать с модулями из lib.js? Если первое, то нельзя ли от этого отказаться? Если второе, то используется ли у вас последняя версия bem-core (2.6.0)? Там, как верно заметил @zxqfox, эту проблему Дима поправил и умозрительно тебе должно быть достаточно добавить в project.js вызов init руками:

modules.require(['i-bem__dom_init'], function(init) {
    init();
});
h4 commented 9 years ago

"bem-core": "2.6.0",

Скрипты грузятся параллельно, вот так. Ну и самое главное, инититься хочется из lib.js, а не из project.js, потому что проектных файлов как-таковых несколько.

2015-04-03 13-42-52 3

h4 commented 9 years ago

Вот так не работает

modules.require(
    ['jquery', 'i-bem__dom_init'],
    function($, init) {
        $(function() {
            init();
        });
    });

Объявленные блоки не инитятся.

Вот так — всё ок.

modules.require(
    ['jquery'],
    function($) {

        $(function() {
            modules.require(['i-bem__dom_init'], function(init) {
                init();
            });
        });
    });
tadatuta commented 9 years ago

@h4 получается, что файл А должен вызвать инициализацию, когда проэвалились файлы B и C, при этом код из А ничего о существовании B и C знать не должен? o_0

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

// cc @dfilatov

h4 commented 9 years ago

В итоге, сейчас у нас свой i-bem__dom_init_auto.js, такого вот содержимого:

modules.require(['jquery', 'i-ajax-setup'],

function($) {
    $(function() {
        modules.require(['i-bem__dom', 'i-bem__dom_init'], function(BEMDOM, init) {
            init(BEMDOM.doc);
        });
    });
});