RU
Форум

Методология

Инструментарий

Платформа

Создаем динамический БЭМ-проект

Введение

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

Цель документа — показать, как разрабатывать динамические проекты по БЭМ, используя полный стек технологий.

В документе рассмотрен процесс создания динамического приложения Social Services Search Robot (SSSR). Оно позволяет искать последние твиты и видео по ключевому слову.

При разработке проекта используется:

После прочтения вы сможете разрабатывать собственные БЭМ-проекты, ориентированные на динамические данные.

Обратите внимание, что для работы с примерами, описанными в документе, необходимо иметь базовые навыки:

Важно! В документе не рассматриваются вопросы верстки и клиентского JS.

Для работы потребуется установить:

Важно! Пользователям операционной системы Windows необходимо дополнительно установить Git Bash.

Все примеры программного кода, описанные в документе, проверены в версиях:

Примечание. npm — менеджер пакетов, входящий в состав Node.js.

Используемые обозначения

В документе приняты следующие условные обозначения:

Используемые технологии

Полный стек технологий БЭМ состоит из:

Подробнее о BEMJSON-формате входных данных.

BEMDECL

Определяет список БЭМ-сущностей, используемых на странице.

Такой список в БЭМ называется декларацией. Задача декларации — определить, что и в каком порядке подключать в сборку.

Декларации описываются в файлах с расширением .bemdecl.js.

Пример декларации из приложения Hello, World:

// Файл `desktop.bundles/index/index.bemdecl.js`
exports.blocks = [
    { name: 'root' }
];  

Как видно из примера, в файле index.bemdecl.js определен только блок root.

При использовании технологии DEPS, в декларации определяют БЭМ-сущность, с которой будет начинаться сборка проекта.

Блок root следует рассматривать как центральную «точку входа» при работе над проектом. Все остальные БЭМ-сущности попадают в сборку по зависимостям.

Пример сборки проекта по зависимостям:

root(DECL)
|
└──> root(DEPS)
     |
     └──> page(DEPS)
          |
          ├──> header(DEPS)
          |    |
          |    └──> ...
          |
          ├──> body(DEPS)
          |    |
          |    └──> ...
          |
          └──> footer(DEPS)
               |
               └──> ...

Подробнее о технологии BEMDECL.

DEPS

Определяет зависимости между БЭМ-сущностями, которые разнесены по файловой структуре проекта и не отражены в декларации.

Зависимости описываются в виде JavaScript-объекта в файлах с расширением .deps.js.

Пример зависимостей для блока root из приложения Hello, World:

// Файл `common.blocks/root/root.deps.js`
({
    shouldDeps: 'page'
})

Подробнее о технологии DEPS.

BEMTREE

Является частью шаблонизатора bem-xjst и преобразует данные в BEMJSON.

Шаблоны описываются в BEMJSON-формате в файлах с расширением .bemtree.js.

Вход и выход шаблонизатора:

BEMTREE

Подробнее о технологии BEMTREE.

BEMHTML

Является частью шаблонизатора bem-xjst и преобразует BEMJSON-описание страницы в HTML.

Шаблоны описываются в файлах с расширением .bemhtml.js.

Вход и выход шаблонизатора:

BEMHTML

Подробнее о технологии BEMHTML.

i-bem.js

Клиентский JavaScript-фреймворк для веб-разработки в рамках БЭМ-методологии.

JavaScript-код описывается в файлах с расширением .js.

Позволяет:

Подробнее о технологии i-bem.js.

Приложение Hello, World

У программистов есть традиция: начинать программирование на новом языке или фреймворке с приложения Hello, World. Приложение обычно выводит слова «Hello, World» в выходной поток, демонстрируя тем самым, что оно запускается и может выполнять операции ввода/вывода.

Давайте создадим это приложение, а затем расширим его до желаемого SSSR.

Для этого понадобится локальная копия шаблонного репозитория bem-express. Копию можно сделать с помощью Git.

Примечание. Для пользователей OS X или Linux все команды выполняются в терминале. Пользователям Windows потребуется Git Bash. Убедитесь, что Git Bash запущен от имени администратора.

Шаблонный репозиторий

При решении задач по разработке динамических приложений в рамках БЭМ создан шаблонный репозиторий bem-express. Он содержит необходимый минимум конфигурационных файлов и решает целый класс задач, таких как сборка проекта, настройка линтеров, подключение библиотек и др.

В bem-express по умолчанию подключены основные БЭМ-библиотеки:

Быстрый старт

Чтобы создать приложение Hello, World, выполните следующие действия:

Приложение Hello, World готово.

Не получилось?

Если при создании приложения возникли сложности, поищите решение на форуме. Если готового ответа не нашлось, задайте вопрос экспертам.

Файловая структура

После установки всех зависимостей файловая структура приложения Hello, World должна иметь следующий вид:

sssr-project/
    .enb/                 # Конфигурационные файлы для сборщика ENB
    common.blocks/        # Базовые реализации блоков
    desktop.bundles/      # Директории бандлов проекта
    development.blocks/   # Блоки, подключаемые в процессе разработки
    node_modules/         # Установленные модули Node (пакеты)
    server/               # Директория с серверным кодом
    static/               # Корневая директория для раздачи статических файлов
    .bemhint.js           # Конфигурация линтера Bemhint
    .borschik             # Конфигурация сборщика файлов Borschik
    .eslintignore         # Исключение файлов и директорий в ESLint
    .eslintrc             # Конфигурация ESLint
    .gitignore            # Исключение файлов и директорий в Git
    .stylelintrc          # Конфигурация Stylelint
    .travis.yml           # Автоматический запуск линтеров в Continuous Integration
    nodemon.json          # Конфигурация для пакета Nodemon
    package.json          # Описание проекта для npm
    README.md             # Текстовое описание проекта

Рассмотрим подробнее некоторые основные директории:

.enb

Содержит конфигурацию сборщика ENB.

Сборка решает следующие задачи:

Алгоритм сборки описывается в файле .enb/make.js.

Подробнее о сборке БЭМ-проектов.

common.blocks

Содержит реализации всех БЭМ-сущностей проекта.

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

common.blocks/
    body/                 # Директория блока body
    footer/               # Директория блока footer
    header/               # Директория блока header
    page/                 # Директория блока page
        _view/            # Поддиректория модификатора page_view
        page.bemtree.js   # Реализация блока page в технологии BEMTREE  
        page.deps.js      # Реализация блока page в технологии DEPS
    page-index/           # Директория блока page-index
    root/                 # Директория блока root

Перед отправкой в браузер файлы собираются и оптимизируются.

desktop.bundles

Содержит файлы полученные в результате сборки. Такие файлы в БЭМ-методологии называются бандлами.

Одной директории бандла соответствует одна страница проекта:

desktop.bundles/
    index/                # Бандлы для страницы index
        index.bemdecl.js  # Декларация для страницы index
        index.bemhtml.js  # Бандл страницы index в технологии реализации BEMHTML
        index.bemtree.js  # Бандл страницы index в технологии реализации BEMTREE
        index.css         # Бандл страницы index в технологии реализации CSS
        index.deps.js     # Бандл страницы index в технологии реализации DEPS
        index.js          # Бандл страницы index в технологии реализации JS
        ...

Примечание. Единственным не автоматически сгенерированным файлом в директории index является файл index.bemdecl.js. Подробнее технология BEMDECL рассматривается ниже.

server

Содержит модули Node, которые прослушивают веб-запросы и генерируют страницу.

Файловая структрура директории:

server/
    config.js             # Конфигурация приложения
    index.js              # Точка входа приложения
    rebuild.js            # Пересборка приложения
    render.js             # Рендеринг HTML

Модули и их назначение:

static

Содержит статические файлы, предназначенные для внешнего доступа:

static/
    favicon.ico           # Фавиконка
    index.min.css         # Символическая ссылка на desktop.bundles/index/index.min.css
    index.min.js          # Символическая ссылка на desktop.bundles/index/index.min.js

Подробнее о символических ссылках.

Приложение Social Services Search Robot

Demo

SSSR — это сервис для поиска твитов и видео, отвечающих заданному набору параметров. Параметры поиска передаются в Twitter Search API и YouTube Data API в виде HTTP-запроса методом GET. Программные интерфейсы формируют ответ в виде JSON-документа.

Цель разработки данного приложения — показать:

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

Примечание. Для разработки приложения необходимо установить некоторые модули Node.

Схема работы приложения

Схематично работу приложения можно представить следующим образом:

Chart of Social Services Search Robot

Шаг 1. Запрос

Пользователь отправляет запрос на сервер.

Шаг 2. Получение данных

Приложение обращается за данными к Twitter Search API и YouTube Data API в соответствии с полученным от пользователя запросом.

Примечание. Генерация запроса и подготовка полученных данных для дальнейшей шаблонизации подробно рассматриваются ниже.

Шаг 3. BEMTREE-шаблонизация

Приложение передает полученные данные BEMTREE-шаблонизатору, который преобразует данные в BEMJSON.

Шаг 4. BEMHTML-шаблонизация

Приложение передает BEMJSON BEMHTML-шаблонизатору, который преобразует BEMJSON в HTML.

Шаг 5. Отправка результата пользователю

Приложение возвращает результат (HTML-страницу) пользователю.

Примечание. Обновлять можно как всю страницу целиком, так и контент нужного блока.

Используемые модули Node

Давайте ближе познакомимся с концепцией модуля Node и рассмотрим основные из них, необходимые для работы приложения.

Важно! В разделе не рассматриваются все используемые модули. Подробно с необходимым модулем можно ознакомиться на сайте npm. Здесь можно найти каталог всех модулей Node с поддержкой поиска.

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

Система модулей Node построена по образцу системы CommonJS, механизма создания взаимодействующих модулей. Центральное место в системе занимает контракт, который должен выполняться разработчиками, чтобы их модули нормально взаимодействовали с другими.

Все пакеты установленные с помощью менеджера пакетов npm находятся в директории node_modules.

Подключение модулей происходит при помощи команды require. Если пакет установлен с использованием npm, указывать путь не нужно. Достаточно указать имя:

var express = require('express');

При подключении собственного локального модуля, необходимо указать к нему путь:

var someModule = require('./somefolder/somemodule');

Важной особенностью любого модуля является то, что он должен быть рассчитан на взаимодействие с Node. Для этого модуль нужно экспортировать с помощью module.exports:

module.exports = {
    // some module
};

Для работы приложения потребуются следующие модули:

Примечание. Установить необходимые модули можно одной командой:

npm install express passport passport-youtube-v3 twitter googleapis moment --save

express

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

Установка:

npm install express --save

В документации Express представлено минимальное приложение «Hello World Express». Оно демонстрирует основную последовательность действий:

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!')
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!')
});

passport

Предоставляет различные стратегии аутентификации в приложениях на Node.js.

Установка:

npm install passport --save

Пример авторизации по протоколу OAuth 2.0:

var passport = require('passport'),
    OAuth2Strategy = require('passport-oauth').OAuth2Strategy;

/**
 * Функция монтирует необходимую стратегию авторизации
 * @function
 * @param {string} provider — Например, facebook, twitter, google, ...
 * @param {object} strategy — Стратегия авторизации
 */
passport.use('provider', new OAuth2Strategy({
    authorizationURL: 'https://www.provider.com/oauth2/authorize',
    tokenURL: 'https://www.provider.com/oauth2/token',
    clientID: SERVICE_APP_ID,
    clientSecret: SERVICE_APP_SECRET,
    callbackURL: 'https://www.example.com/auth/provider/callback'
}));

Примечание. OAuth 2.0 — открытый протокол авторизации, который позволяет предоставить третьей стороне ограниченный доступ к защищенным ресурсам пользователя без необходимости передавать ей (третьей стороне) логин и пароль.

passport-youtube-v3

Предоставляет механизм аутентификации на Youtube посредством аккаунта Youtube и токенов OAuth 2.0.

Установка:

npm install passport-youtube-v3 --save

Пример

var passport = require('passport'),
    YoutubeV3Strategy = require('passport-youtube-v3').Strategy;
/**
 * Функция монтирует стратегию YoutubeV3Strategy
 * @function
 * @param {object} strategy — Стратегия
 */
passport.use(new YoutubeV3Strategy({
    clientID: YOUTUBE_APP_ID,
    clientSecret: YOUTUBE_APP_SECRET,
    callbackURL: '/auth/youtube/callback',
    scope: ['https://www.googleapis.com/auth/youtube.readonly']
}, verify));

Подробнее о том как получить OAuth-токены.

twitter

Клиентская библиотека для работы с Twitter REST API.

Установка:

npm install twitter --save

Пример

var Twitter = require('twitter');
// Создаем экземпляр объекта Twitter
var client = new Twitter({
  consumer_key: '',
  consumer_secret: '',
  bearer_token: ''
});

var params = {q: 'bem'};
/**
 * Функция поиска. Ищет твиты по заданным параметрам.
 * @function
 * @param {object} params - Параметры поиска.
 * @param {function} callback - Получает найденные твиты.
 */
client.get('search/tweets', params, function(error, tweets, response) {
  if (!error) {
    console.log(tweets);
  }
});

googleapis

Клиентская библиотека для работы с Google REST API.

Установка:

npm install googleapis --save

Пример

var google = require('googleapis'),
    OAuth2 = google.auth.OAuth2;
// Создаем экземпляр объекта OAuth2
var oauth2Client = new OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);
// Устанавливаем учетные данные для исходящих вызовов
oauth2Client.setCredentials({
  access_token: 'ACCESS TOKEN HERE',
  refresh_token: 'REFRESH TOKEN HERE'
});
// Логинимся
var youtube = google.youtube({
    version: 'v3',
    auth: this.oauth2Client
});

var params = {q: 'bem'};
/**
 * Функция поиска. Ищет видео по заданным параметрам.
 * @function
 * @param {object} params - Параметры поиска.
 * @param {function} callback - Получает найденные видеоролики.
 */
youtube.search.list(params, function(error, video, response) {
  if (!error) {
    console.log(video);
  }
});

moment

JavaScript библиотека для синтаксического анализа, валидации и форматирования дат.

Установка:

npm install moment --save

Пример

var moment = require('moment');

moment().startOf('day').fromNow();             // 17 часов назад

Подготовка структуры проекта

Прежде чем начать писать код, необходимо немного изменить структуру взятого за основу приложения Hello, World.

Изменения для:

Изменения для статических файлов

static

Директория static

Директория common.blocks

Директория server

В результате выполненных действий файловая структура директории static должна иметь следующий вид:

static/
    images/
        favicon.ico
index.min.css
index.min.js

Изменения для серверного кода

server-changes

Директория server

Директория controllers

Директория helpers

Директория middleware

В результате выполненных действий файловая структура директории server должна иметь следующий вид:

server/
    controllers/
        index.js          # Контроллер обработки запросов и рендеринга HTML
    helpers/
        index.js          # Входная точка для модулей-хелперов (пустой)
        twitter.js        # Модуль-хелпер для работы с Twitter Search API (пустой)
        youtube.js        # Модуль-хелпер для работы с YouTube Data API (пустой)
    middleware/
        auth.js           # Модуль проверки прохождения аутентификации на YouTube (пустой)
    app.js                # Модуль монтирования промежуточных модулей
    auth.js               # Модуль аутентификации на YouTube (пустой)
    config.json           # Конфигурация приложения
    index.js              # Запуск приложения и прослушивание запросов на порте
    rebuild.js            # Модуль отслеживания изменений и перезапуска сервера
    render.js             # Рендеринг HTML
    routes.js             # Маршрутизатор

Получение OAuth-токенов

Сервисы Twitter и Google хранят различные данные пользователей — твиты, видео на Youtube, письма в Почте, фотографии и так далее. Чтобы обеспечить удобный доступ к этим данным из других приложений или сторонних сервисов, они используют открытый протокол авторизации OAuth 2.0.

Согласно протоколу, разработчик регистрирует приложение на OAuth-сервере и запрашивает доступ к определенным данным. Авторизованный пользователь разрешает или запрещает его.

Получение OAuth-токена для Twitter

Twitter предлагает приложениям возможность выдавать аутентифицированные запросы от имени самого приложения.

С чего начать?

Примечание. Postman необходим для получения OAuth-токена с помощью POST-запроса в обмен на код, полученный методом Base64.

Как закодировать строку?

Чтобы закодировать строку методом Base64:

Примечание. Если возникли сложности, воспользуйтесь онлайн-ресурсом base64encode.org.

Как получить OAuth-токен в обмен на код?

Чтобы получить токен в обмен на код:

Получение OAuth-токена для Google

Google предлагает приложениям возможность выдавать аутентифицированные запросы от имени самого приложения.

Примечание. За получение и обновление OAuth-токена с помощью POST-запроса в обмен на код авторизации отвечает модуль passport-youtube-v3.

С чего начать?

Важно! Сохраните полученные ключи (Client ID и Client Secret). Они необходимы для конфигурационного файла приложения.

Конфигурация приложения

После того как все ключи и токены получены, их необходимо добавить в конфигурационный файл приложения:

Работа с Twitter Search API

Twitter Search API позволяет найти последние или популярные твиты, опубликованные на сайте Twitter.com за последние 7 дней.

Подробнее:

Доступ к API

Для успешного вызова API необходимы:

Вызов API

Изменения для работы с Twitter Search API:

twitter-changes

Директория controllers

Директория helpers

Работа с YouTube Data API

YouTube Data API позволяет найти видеоролики, опубликованные на сайте Youtube.com. По умолчанию в набор результата поиска включены следующие ресурсы: видео, каналы, списки воспроизведения.

Подробнее:

Доступ к API

Для успешного вызова API необходимы:

Вызов API

Изменения для работы с YouTube Data API:

youtube-changes

Директория server

Директория controllers

Директория helpers

Директория middleware

Верстка

В данном документе первоочередное внимание уделено вопросу взаимодействия технологий БЭМ. Поэтому он не содержит описания верстки и клиентского JavaScript. Описание верстки привело бы к большему объему, а, значит, и к меньшей практической ценности этого документа.

Процесс верстки сведен к следующим шагам:

Приложение Social Services Search Robot готово.

Не получилось?

Если при создании приложения возникли сложности, поищите решение на форуме. Если готового ответа не нашлось, задайте вопрос экспертам.

Оцените статью
Сообщить об ошибке на Гитхабе или исправить в prose.io.