Задать вопрос
  • Как организовать файлы в библиотеке компонентов?

    qfox
    @qfox
    Ответы есть у меня
    У нас есть блок "Кнопка", у нее есть дочерний элемент "Кнопка__иконка" и модификатор "Кнопка--Иконка-Слева"(уменьшает отступ слева, чтоб иконка смотрелась лучше).
    У этой кнопки есть три модификатора размера (sm,m,l). У каждого размера будет разный отступ слева при модификаторе "Кнопка--Иконка-Слева".


    Легко решается через CSS Custom Properties и типографские константы
    --sm, --m, --l при этом выставляют эти константы, а другие модификаторы и элементы их используют в нужных им местах.

    Добавим изменение размера "Кнопка__иконка" для разных размеров кнопки (если это иконочный шрифт можно использовать font-size всей кнопки, но мы как современные используем svg иконки и размер нужно задавать вручную).


    Лучше делать враппер над иконкой, чтобы не завязываться на svg или нет.
    Если библиотека компонент общая — ситуации могут быть разные.
    Такая структура более менее:
    <Button>
      <Button__icon><Icon ... /></Button__icon>
      <Button__body>Текст на кнопке</Button__body>
    </Button>


    Если иконка есть — выводим `Button__icon`, если нет — не выводим. Стили вешаем на `Button__icon`.

    Для кастомизации — оставляем `Button__body`, потом пригодится в кастомных `Select`.

    В идеале нужна структура, чтоб видеть все связи (пример выше), для быстрого доступа к нужному свойству, но также инструмент, который умеет удалять не нужные стили по связям. Удалив элемент "Кнопка__иконка" в сборку не должны попасть модификаторы "Кнопка--Иконка-Слева" разных размеров.

    Может кто то встречался с решением или рекомендациями по данному вопросу.


    Звучит как сборка стилей по зависимостям из bemjson/jsx. Технически, есть возможность даже из html получить bemjson и инициировать для него сборку css/js.
    Процесс будет выглядеть примерно так:
    const fs = require('fs');
    const miss = require('mississippi');
    const html2bemjson = require('html2bemjson');
    const bemjsonToDecl = require('bemjson-to-decl');
    const src = require('gulp-bem-src');
    const gconcat = require('gulp-concat');
    const vfs = require('vinyl-fs');
    
    src(
        ['path/to/blocks'],
        bemjsonToDecl.convert(
            html2bemjson(
                String(fs.readFileSync('path/to/your.html')))),
        'css',
        { // дополнительные настройки
            skipResolvingDependencies: false, // отключаем зависимости
            {
                'path/to/blocks': { scheme: 'nested' } // у 'path/to/blocks' схема nested 
            }
        }
    ).pipe(gconcat('path/to/your.css')).pipe(vfs.dest('.'))

    Ну и всё
    Ответ написан
    3 комментария
  • Как сочетать BEM и динамический контент?

    qfox
    @qfox
    Ответы есть у меня
    У вас здесь 2 проблемы:
    • нужны ли классы для динамического контента;
    • как, если нужно, модифицировать структуру динамического контента.

    Проблема структуры не относится к BEM, она относится к семантике и SEO.

    Если же не смотреть на структуру и тэги (использовать ли small внутри или span, заворчивать ли в article) — то вопрос в сущности нужны ли классы на динамическом контенте или нет. Учитывая, что контент динамический, и нет необходимости иметь классы на тэгах, то допустимо сделать каскад на тэги от некоторого блока: например, dynamic-content или content, text.

    Почему именно теги? Потому что WYSIWYG по умолчанию генерирует теги. Но вы можете использовать какие-то доп. инструменты, которые подправят итоговый html, расставят классы и т.д. (например, с помощью инструментов типа https://github.com/posthtml/posthtml ).

    При необходимости можно дополнительно пометить стили тегов классами.

    <div class="text">
      <h1>Caption <small>Some Foo Bar</small></h1>
      <article>
        <p>Lorem ipsum...</p>
        <div class="text__p">Dolor sit...</div>
      </article>
    </div>


    .text h1, .text__title { /* main title styles */ }
    .text h1>small, .text__sub-title { /* sub-title styles */ }
    .text p, .text__p { /* paragraph styles */ }


    Таким образом вы инкапсулируете все пользовательские стили в одном месте (одном блоке) и не имеете проблем с созданием контента.
    Ответ написан
    2 комментария
  • Как создать блок по метoдологии BEM?

    qfox
    @qfox
    Ответы есть у меня
    Блок должен находится на уровне переопределения. Например: app.blocks.
    Удобнее блоку сделать свою папку (и все блоки хранить каждый в своей папке): app.blocks/hello-world
    У блока должна быть какая-то реализация. Например, css: app.blocks/hello-world/hello-world.css

    Возвращаясь к вопросу:
    mkdir ./app.blocks/hello-world/ -p
    touch ./app.blocks/hello-world/hello-world.css


    Либо, если хотите использовать bem-tools:
    npm i bem-tools
    bem create level app.blocks
    bem create block -l app.blocks hello-world
    Ответ написан
    1 комментарий
  • Полный цикл жизни проекта: html,css,js > php, шаблоны, изменения, переиспользование?

    qfox
    @qfox
    Ответы есть у меня
    Текущий подход достаточно заморочен, если знаешь все прелести БЭМ.

    Сейчас мы делаем:
    0. Дизайнер нарисовал макет
    1. Верстаем руками html: a.html
    2. пишем руками стили: a.css
    3. пишем руками js: a.js
    4. Это все передаем бекендеру и он:
    5. Доверстывает хтмл и разбивает на шаблоны, из a.html получает A.tmpl, B.tmpl, C.tmpl, ...
    6. Дописывает стили в своих файлах, а часто еще и разбивает их на части: A.scss, B.scss, ...
    7. Дописывает js, и тоже часто разбивает: A.js, B.js, C.js
    8. Какой-то бэкенд собирает из кусков шаблонов страницу, и часто создает css, js только из нужных кусков

    А дальше: Пришел новый макет. И что делать?

    И БЭМ в данном случае решает проблему, поскольку у него есть стек технологий, позволяющий верстальщику работать сразу с шаблонами и разобранными js/css(less/sass/stylus) файлами.

    На практике получается так:
    0. Макет.
    1. Верстальщик смотрит на макет, и разбивает его на куски (компоненты) сразу;
    2. Пишет bemjson (или jsx) вместо html;
    3. Создает шаблоны, стили и js для каждого из блоков;
    4. Передает это все бэкенд программисту (обычно через гит, потому что так удобнее);
    5. Бэкендер без изменений использует эти файлы для генерации страницы, и просто генерирует описанный верстальщиком bemjson (или jsx).

    И, О МАГИЯ, они могут работать над проектом параллельно, даже если придет новый макет.

    C php действительно есть нюансы, которые сложно разглядеть, просто потому, что нет большого кол-ва пользователей и стек не устоялся.
    Мы у себя используем велосипед, который собирает все сам, и почти готовы перейти на enb используя bh-php.
    Большая проблема, как оказалось, использование декларативных шаблонизаторов — верстальщики не сразу въезжают что и как. Но когда въехали — я не знаю тех, кто возвращается на императивные (типа мусташей, джейдов, smarty, etc.).

    Можно начать с https://github.com/bem/project-stub/tree/php-bem-bh и позадавать вопросы на форуме https://ru.bem.info/forum/ — люди поделятся своими историями.
    Ответ написан
    Комментировать
  • Правильно ли так использовать модификатор?

    qfox
    @qfox
    Ответы есть у меня
    Да, вполне рабочий вариант.
    Ответ написан
    Комментировать
  • Эта верстка соответствует бэм принципам?

    qfox
    @qfox
    Ответы есть у меня
    Нет ;-)

    col-md-6 new-left — лучше унести в модификаторы b-layout

    informers — это разметка? лучше как элемент разметки тогда.

    b-inline — тоже скорее к разметке относится, лучше в элементом в b-layout или в специальный блок для разметки

    auth-line — явно элемент auth-form, я бы сделал .form.form_auth или form_type_auth, а этот элемент — form__field.

    ну и дальше в том же духе.
    Ответ написан
    Комментировать
  • Как при запуске генератора bem-stub выбрать все опции?

    qfox
    @qfox
    Ответы есть у меня
    Пробелом!

    > Как переключиться чтобы выбрать невидимые опции?

    Стрелками вверх-вниз
    Ответ написан
    1 комментарий
  • Дзен BEM: где держать .bemjson?

    qfox
    @qfox
    Ответы есть у меня
    В bemjson описывается структура в блоках/элементах и данные страницы, бандлы — это, суть, ваши страницы.
    Кажется, теперь очевидно, что bemjson нужно класть в папки бандлов.

    Для чего он нужен? Для того, чтобы знать как собирается страница и из чего она состоит. Фактически, из этого файла собираются все артефакты, а процесс сборки выглядит так:
    1. Собираются все названия блоков и элементов, описанных в файле bemjson;
    2. Из блоков собираются файлы *.deps.js и общий список нужных файлов дополняется блоками из этих файлов, и таких же файлов этих блоков (рекурсивно);
    3. Полный список файлов записывается как bemdecl.js;
    4. Собираются все описанные в сборке технологии (файлы js/css/шаблоны);
    5. Если сборка была из bemjson — генерируется еще и html из bemjson и шаблонов (иначе — просто шаблоны);
    6. Минификация и обфускация css/js файлов (или же еще и компиляция less/stylus/sass в css, es6/coffee в js, etc.).

    Как-то так)
    Ответ написан
    5 комментариев
  • Как организовать архитектуру javascript-генератора форм с использованием шаблонизатора и БЭМ методологии?

    qfox
    @qfox
    Ответы есть у меня
    Один из простых способов:
    1. Генерируем из исходного json по каким-то правилам bemjson c описанием структуры формы и блоков с элементами;
    2. Используем https://github.com/bem/bem-forms как базу (или пишем аналог) для создания базовой библиотеки с шаблонами и базовыми типами полей и контролов;
    3. На уровне проекта расширяем своими контролами (шаблонами, стилями, и т.д.);
    4. Собираем чем-то стандартным, типа enb.

    MVC для фронтенда не есть удачное решение, это становится очевидно, когда кол-во успешных MVC фреймворков для JS фактически равно нулю. MV* парадигма вполне работает, но без контроллеров.

    С шаблонами мусташ ситуация следующая — либо не будет возможно доопределять трансформации, описанные шаблонами: т.е. придется копировать из исходной библиотеки шаблон и изменять его, в итоге проблемы при обновлениях; либо не использовать библиотечный подход для шаблонов вообще. Почему так: потому что mustache интерполируемый и императивный шаблонизатор, его технически нельзя научить доопределению. Если все же нужен именно mustache — достаточно будет написать технологию для enb, в гитхабе точно есть примеры для jade, и, кажется, некоторых других. По сути, пара несложных функций, где пишется: возьми этот файл как шаблон для шаблонизатора такого-то и создай из него функцию для отрисовки данных.

    Если думаете про i-bem.js, то jquery у вас так и так будет (потому что i-bem использует jquery), с require.js — возможно, будет проще использовать ymodules: не сильно отличается от require.js, на нем уже основаны bem-core/bem-components и, соотв., bem-forms тоже, и взяв стандартный набор джентельмена от яндекса ничего не надо будет менять с этой точки зрения — все уже настроено.

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

    А вообще, есть форум, где на такие вопросы отвечают намного быстрее и с примерами ;-)
    Ответ написан
    Комментировать
  • Как разрабатывать при помощи bem-core и bem-tools?

    qfox
    @qfox
    Ответы есть у меня
    Самый простой способ — это склонировать https://github.com/bem/project-stub через git, удалить папку .git, установить node, зависимости (npm install), и начать работать над проектом.

    Чуть сложнее в настройке, но тоже простой — использовать yo и bem-stub, для этого нужно установить ноду, эти два пакета: npm -g install yo generator-bem-stub; и далее в новой папке можно будет запустить yo bem-stub, поотвечать на вопросы, и проект сгенерируется.

    Важно понимать, что bem server скоро начнет внутри использовать enb, так что можно уже сейчас на него переходить и использовать enb server.

    А вообще, на такие вопросы очень быстро можно получить ответ на bem.info и форуме. ;-)
    Ответ написан
    Комментировать
  • Почему не работает bem сервер?

    qfox
    @qfox
    Ответы есть у меня
    Если проблема с bem-core, bem-components (в данном случае — первое) — забыли bower install, который должен устанавливаться при npm install. Еще bem server немножко устарел и лучше использовать enb server.

    А вообще, на такие вопросы гораздо быстрее найти ответ на бем.инфо и форуме.
    Ответ написан
    Комментировать
  • Как правильнее парсить результаты ajax запроса?

    qfox
    @qfox
    Ответы есть у меня
    Если использовать https://github.com/bem/bh и https://github.com/bem/bh-php (шаблоны там почти 1-в-1, с точностью до $ в переменных), то можно выгружать шаблоны и на фронт, и на бекенде собирать нужное.

    Еще лучше использовать прослойку на nodejs чисто для сборки html для первого захода, поисковиков, людей без JS, и не думать про это в целом, а на PHP оставить всю логику и использовать как API.

    Еще, чтобы уменьшить размер передаваемых данных:
    а) gzip;
    б) raw-json;
    в) protobuf.

    Если передавать только нужное и не потеряться — нужно сделать двухпроходную шаблонизацию, т.е. в 2 шага — 1) конвертируем из сырых данных в некий промежуточный view-ориентированный json, а затем из последнего собираем html с помощью шаблонов на матчерах.

    Если любите экспериметировать, можете попробовать еще вот так:
    // Допустим, у нас есть выгруженные шаблоны на фронт
    bh.match('users-list', function ... );
    bh.match('user', function ... );
    // etc.
    // дальше мы должны получить данные с бекенда, для простоты укажем их явно
    var usersFromBackend = [{name: 'Vasya', id: 5}, {id: 42, name: 'Petya'}, ...];
    // как получили — собираем каким-то образом некую view-ориентированную структуру типа:
    var viewOriented = {
      // здесь можно использовать и что-то более умное
      block : 'users-list',
      content : fromBackend.map(function (el) {
        return {
          block : 'user',
          // привязываем к users-list по БЭМ
          // (мало ли понадобится что-то в стилях-скриптах подтюнить)
          mix : { block : 'users-list', elem : 'item' }, 
          // выводим контент в каждый div
          content : {
            block : 'link',
            mix : { block : 'user', elem : 'link' },
            url : el.url || '/users/' + el.id,
            text : el.name
          }
        };
      })
    };
    // И после получаем готовый HTML еще одной операцией, который останется куда-то вставить
    console.log(bh.apply(viewOriented));


    При том, что шаблоны у нас одинаковые (для php с точностью до $ в переменных) для фронта и бекенда — кол-во дублируемого кода падает. Появляется возможность вставлять одинаковые блоки в разные места на странице с разными данными, структурировать CSS (самое известное из BEM, даже гугл рекомендует), и т.д.
    Ответ написан
    Комментировать
  • Возврат данных cURL в виде массива?

    qfox
    @qfox
    Ответы есть у меня
    Вам нужна сериализация и десериализация данных.

    Serialize+unserialize
    json_encode+json_decode
    etc.

    Т.е., в скрипте 1 вместо `echo $out` вы делаете `json_decode($out);`.
    А в скрипте 2 вместо `var_export($arr);` делаете `echo json_encode($arr);`.

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

    Т.е., вместо:
    if (!$dbconn) {
      echo "Произошла ошибка подключения к базе.";
    }

    Нужно
    if (!$dbconn) {
      echo json_encode(["error" => "Произошла ошибка подключения к базе."]);
    }
    Ответ написан
    2 комментария
  • Книги по архитектуре веб приложений?

    qfox
    @qfox
    Ответы есть у меня
    Вопрос настолько обширный, что врядли кто-то вам сможет посоветовать актуальную литературу, т.к. нужны примеры.

    Большинство хороших архитектурных решений находится в постоянной разработке и люди, которые пишут книги, часто отстают лет на 5 от прогресса. А те, кто не отстает — находятся в творчесском процессе и им некогда писать книги.

    По теме могу посоветовать смотреть в сторону ruby/nodejs/go фреймворков для различных веб-приложений и сервисов, каждый фреймворк затачивается под определенную задачу и, если есть желание эффективно работать в этой сфере, вам так или иначе придется это делать — без чтения чужого кода и участия в разработке этих самых фреймворков сейчас никуда, и это полностью заменяет литературу по теме.

    Как пример, могу посоветовать сравнить www.sinatrarb.com (ruby), expressjs.com (nodejs) и martini.codegangsta.io (golang). Все они используют схему — создаем приложение, у приложения регистриуем обработчики для get/post/других запросов, в обработчиках получаем объекты request/response, и работаем с ними. Это считается базой для любых веб-сервисов, веб-приложений.

    Когда нужны какие-то дополнительные функции — все делается независимо от этих модулей внутри колбеков, которые в них регистрируются и там зоопарк очень большой. Если нужны контроллеры, модели — есть rails, compoundjs, beego. Если нужно сделать REST — обычно, берется синатра + доп. модули, и получается что-то вроде loopback.io

    Но, повторюсь, когда это все пишется у тебя на глазах, а цикл создания книги — год-полтора — то за это время технологии уже уходят далеко вперед и хороших книг с такой глубокой проработкой вопроса будет появлятся все меньше.
    Ответ написан
    5 комментариев
  • Как создать шаблон с помощью .tpl .php форматов?

    qfox
    @qfox
    Ответы есть у меня
    Все зависит от шаблонизатора, который вас устроит.

    twig.sensiolabs.org
    https://github.com/smarty-php/smarty/
    https://github.com/alexeyrybak/blitz (habrahabr.ru/post/18695)
    habrahabr.ru/post/128645

    Либо же, что-то типа xslt:
    https://github.com/bem/bh-php

    Если нужен более точный ответ — определитесь с вопросом ;-)
    Ответ написан
    Комментировать
  • Технологии для highload?

    qfox
    @qfox
    Ответы есть у меня
    Я бы ничего не менял. Возможно, попробовал бы еще tarantool для микрозадач или как замена редиса.

    Но как вариант — C# или Java, и RavenDB какой-нибудь тоже вполне вкатит под «технологии highload».

    Еще вместо обычного mongo можно попробовать drop-in замену в виде TokuMX: https://github.com/Tokutek/mongo
    Ответ написан
    Комментировать
  • Подсоветуйте фреймворк для node?

    qfox
    @qfox
    Ответы есть у меня
    Можно еще попробовать https://github.com/2gis/slot

    У них там специфичный БЭМ, изоморфность, и все такое.
    Ответ написан
    Комментировать
  • Javascript backend frameworks or vanilla js?

    qfox
    @qfox
    Ответы есть у меня
    В nodejs все немного подругому — нет, увы, но там совсем все иначе.

    Во-первых, ваше приложение будет висеть в памяти долго и параллельно обрабатывать несколько запросов, в то время как в PHP тред сдохнет после отправки ответа на запрос; во-вторых, в node.js широко практикуется микромодульность; в-третьих, на vanilla.js вы замучаетесь писать, потому что это просто ядро js — окружение nodejs вам все равно понадобится для работы с libuv и сокетами/дескрипторами, и это будет уже не vanillajs.

    Исходя из этих замечаний, пытливый читатель уже начнет догадываться, что ему нужны разные модули для:
    а) веб сервера (или нет);
    б) работы с хранилищами и абстракций над ними (моделей, клиентов дб с пуллом, или без, или руками все писать);
    в) записи в лог (или руками stdout перенаправлять);
    г) соль, перец по вкусу.

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

    Я бы порекоммендовал смотреть в сторону сырого https://github.com/senchalabs/connect, либо чуть более полного https://github.com/strongloop/loopback (фактически, connect с плагинами).
    Если чем-то не устраивает — можно смотреть https://www.npmjs.com/package/restify (или то, что его у себя использует: https://www.npmjs.com/browse/depended/restify).

    В качестве абстракции над моделями либо https://github.com/sequelize/sequelize (если база будет mysql/pgsql), либо https://github.com/Automattic/mongoose (если без разницы какая база) + https://github.com/Tokutek/mongo.

    Для веб логов — https://github.com/expressjs/morgan
    Для других логов — например, https://github.com/winstonjs/winston + нужные транспорты
    Для конфигов — https://github.com/flatiron/nconf, если не хватает просто require("config.json")

    И т.д.

    Главное, понять, что чем меньше модуль, тем больше вероятность, что он стабильнее работает, и что тесты написано качественно.
    Ответ написан
    Комментировать
  • Совет в изучении ООП JavaScript?

    qfox
    @qfox
    Ответы есть у меня
    Можно еще через OOP в Ruby. www.theodinproject.com/ruby-programming/object-ori...

    Берете OOP в Ruby, отсекаете Классы и Мета-классы, добавляете (вместо классов и метаклассов) — свою реализацию типа https://github.com/dfilatov/inherit или любую другую — получаете классы в JS.

    ES6 классы, насколько я знаю, это просто сахар, так что не питайте надежд — оно не далеко уйдет от того, что есть сейчас, просто появится возможность писать более коротко.
    Ответ написан
    Комментировать
  • Как отсортировать массив с добавлением разделителей групп?

    qfox
    @qfox
    Ответы есть у меня
    Толи я не понимаю, толи это ответ:
    // сортируем
    var sorted = $scope.dis.sort(function (a, b) {
      return a.name > b.name? 1 :  -1;
    });
    // собираем сам массив
    var sortedWithGroups = sorted.reduce(function (res, a) {
      // добавляем дополнительно букву перед первым словом на новую букву
      // если это первое слово на эту букву
      if (res.lastGroup !== a.name[0]) {
        res.lastGroup = a.name[0];
        res.push({name: a.name[0], group: true});
      }
      // добавляем саму ссылку
      res.push(a);
      return res;
    }, []);

    В итоге в sortedWithGroups отсортированный массив с группировкой по буквам.

    p.s. Разделил на переменные только ради комментариев. Все это можно собрать в несколько строк и вызывать reduce сразу после sort в одной конструкции.

    Ссылки:
    Array.prototype.sort: https://developer.mozilla.org/en-US/docs/Web/JavaS...
    Array.prototype.reduce: https://developer.mozilla.org/en-US/docs/Web/JavaS...
    Ответ написан
    8 комментариев