Многие современные приложения обмениваются данными в режиме реального времени с последующей частичной или полной перезагрузкой страницы.
Цель документа — показать, как разрабатывать БЭМ-проекты, ориентированные на динамические данные.
В документе рассматривается процесс создания двух приложений:
- Hello, World — быстрый старт по созданию динамических приложений.
- Social Services Search Robot — приложение для поиска твитов и видео по ключевому слову.
Для работы потребуется установить:
- Node.js 4+.
- Git.
- Git Bash (пользователям ОС Windows).
Примечание. В документе не рассматриваются вопросы верстки и клиентского JS.
Представляет собой динамическое приложение, которое выводит слова «Hello, World!» в выходной поток, демонстрируя тем самым, что оно запускается и может выполнять операции ввода/вывода.
Давайте создадим это приложение, а затем расширим его до Social Services Search Robot.
Чтобы создать приложение Hello, World:
-
Склонируйте шаблонный репозиторий bem-express.
git clone https://github.com/bem/bem-express.git bem-project
Примечание. В данном примере используется
bem-express
версии 2.00. -
Перейдите в директорию проекта.
cd bem-project
-
Удалите историю версионирования исходного репозитория.
rm -rf .git
-
Инициализируйте собственный Git-репозиторий.
git init
-
Установите зависимости.
npm install
-
Соберите проект и запустите сервер.
npm run dev
Примечание. За сборку проекта отвечает ENB.
При запуске приложения в терминале выведется сообщение о том, что сервер выполняется на порту 3000:
Server is listening on 3000
.Примечание. Если порт 3000 занят, его можно переназначить (например, на 8000):
PORT=8000 npm run dev
На компьютере запустился:
- Cервер — отвечает за обработку динамических данных.
- Nodemon — следит за изменениями на файловой структуре и перезапускает сервер.
- Chokidar — следит за изменениями в директориях *.blocks/ и перестраивает структуру проекта.
- Livereload — обновляет страницу в браузере.
-
Откройте браузер и введите адрес localhost:3000.
Должна открыться страница со следующим содержимым:
Index page content footer content
-
Откройте файл server/index.js и внесите следующие изменения в код, начинающегося строкой
app.get('/', function(req, res)
:// ... app.get('/', function(req, res) { + var hello = 'Hello'; + var world = 'World'; render(req, res, { view: 'page-index', title: 'Main page', meta: { description: 'Page description', og: { url: 'https://site.com', siteName: 'Site name' } }, + hello: hello, + world: world }) }); // ...
-
Откройте файл common.blocks/page-index/page-index.bemtree.js и замените его содержимое на следующее:
block('page-index').content()(function() { // Получаем данные из глобального объекта `this` var data = this.data; // Возвращаем полученные данные: `data.hello: 'Hello'`, `data.world: 'World'` return data.hello + ', ' + data.world + '!'; });
После сохранения, сервер автоматически перезапустится, и содержимое страницы изменится на:
Hello, World! footer content
Приложение Hello, World готово.
Примечание. Если при создании приложения возникли сложности, поищите решение на форуме. Если готового ответа не нашлось, задайте вопрос экспертам.
Представляет собой динамическое приложение, которое выводит последние твиты и видео по ключевому слову.
Цель разработки данного приложения — показать взаимосвязь:
- технологий БЭМ;
- данных и интерфейса в БЭМ-проекте.
Работу приложения можно представить следующей схемой:
- Пользователь отправляет запрос на сервер.
- Приложение получает данные от Twitter Search API и YouTube Data API в соответствии с запросом пользователя.
- Приложение передает полученные данные BEMTREE-шаблонизатору, который преобразует данные в BEMJSON.
- Приложение передает BEMJSON BEMHTML-шаблонизатору, который преобразует BEMJSON в HTML.
- Приложение возвращает HTML-страницу пользователю.
В работе будем использовать следующие технологии:
- BEMDECL — технология для описания деклараций в БЭМ.
- DEPS — технология для описания зависимостей в БЭМ.
- BEMTREE — шаблонизатор преобразующий данные в BEMJSON.
- BEMHTML — шаблонизатор преобразующий BEMJSON в HTML.
- i-bem.js — JavaScript-фреймворк для БЭМ.
Определяет список БЭМ-сущностей, используемых на странице.
Такой список в БЭМ называется декларацией. Задача декларации — определить, что и в каком порядке подключать в сборку.
Декларации описываются в файлах с расширением .bemdecl.js
.
Пример декларации из приложения Hello, World:
// Файл `desktop.bundles/index/index.bemdecl.js`
exports.blocks = [
{ name: 'root' }
];
Как видно из примера, в файле index.bemdecl.js определен только блок root
. Это не означает, что на странице нет других блоков. Блок root
следует рассматривать как центральную «точку входа» для сборщика. Все остальные БЭМ-сущности попадают в сборку по зависимостям. При использовании технологии DEPS, в декларации определяют блок, с которого начинается сборка проекта.
Пример сборки проекта по зависимостям (из приложения Hello, World):
root(DECL) # Сборщик ищет файл index.bemdecl.js
|
└──> root(DEPS) # Сборщик ищет файл root.deps.js
|
└──> page(DEPS) # Сборщик ищет файл page.deps.js
|
├──> header(DEPS) # Сборщик ищет файл header.deps.js
| |
| └──> ...
|
├──> body(DEPS) # Сборщик ищет файл body.deps.js
| |
| └──> ...
|
└──> footer(DEPS) # Сборщик ищет файл footer.deps.js
|
└──> ...
Подробнее о технологии BEMDECL.
Определяет зависимости между БЭМ-сущностями, которые разнесены по файловой структуре проекта и не отражены в декларации.
Зависимости описываются в виде JavaScript-объекта в файлах с расширением .deps.js
.
Пример зависимостей для блока root
из приложения Hello, World:
// Файл `common.blocks/root/root.deps.js`
({
shouldDeps: 'page'
})
Подробнее о технологии DEPS.
Является частью шаблонизатора bem-xjst и преобразует данные в BEMJSON.
Шаблоны описываются в BEMJSON-формате в файлах с расширением .bemtree.js
.
Вход и выход шаблонизатора:
Подробнее о технологии BEMTREE.
Является частью шаблонизатора bem-xjst и преобразует BEMJSON-описание страницы в HTML.
Шаблоны описываются в файлах с расширением .bemhtml.js
.
Вход и выход шаблонизатора:
Подробнее о технологии BEMHTML.
Клиентский JavaScript-фреймворк для веб-разработки в рамках БЭМ-методологии.
JavaScript-код описывается в файлах с расширением .js
.
Позволяет:
- Разрабатывать веб-интерфейс в терминах блоков, элементов, модификаторов.
- Описывать логику работы блока в декларативном стиле — как набор состояний.
- Легко интегрировать код JavaScript с BEMHTML-шаблонами и CSS.
- Гибко переопределять поведение библиотечных блоков.
Подробнее о технологии i-bem.js.
Имеет следующий вид:
bem-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 # Текстовое описание проекта
- Изменение файловой структуры проекта
- Установка дополнительных модулей
- Получение OAuth-токена для Twitter
- Получение OAuth-токена для Google
- Конфигурация приложения
- Работа с Twitter Search API
- Работа с YouTube Data API
- Верстка
Прежде чем перейти к работе с Twitter Search API и YouTube Data API, давайте изменим структуру взятого за основу приложения Hello, World.
-
Создайте в директории server следующие поддиректории и файлы:
server/ + controllers/ # Контроллеры + index.js # Контроллер обработки запросов и рендеринга HTML + helpers/ # Хелперы + index.js # Входная точка для модулей-хелперов (E) + twitter.js # Модуль-хелпер для работы с Twitter Search API (E) + youtube.js # Модуль-хелпер для работы с YouTube Data API (E) + middleware/ # Модули промежуточного звена + auth.js # Модуль проверки прохождения аутентификации на YouTube (E) + app.js # Модуль монтирования промежуточных модулей + auth.js # Модуль аутентификации на YouTube (E) config.js index.js rebuild.js render.js + routes.js # Модуль маршрутизации запросов
Примечание. Файлы помеченные флагом E (Empty) потребуются позже.
-
Добавьте следующий код в файл controllers/index.js.
-
Добавьте следующий код в файл app.js.
-
Добавьте следующий код в файл routes.js.
-
Замените содержимое файла index.js на следующее.
Примечание. В
index.js
остается только функциональность, отвечающая за запуск приложения и прослушивание запросов на порте.
После выполненных действий, по адресу localhost:3000 по-прежнему должна открываться страница со следующим содержимым:
Hello, World!
footer content
Примечание. Если ваш код не работает — ищите опечатки.
Для работы приложения необходимо установить следующие модули:
- express — предоставляет функциональность для построения веб-приложения.
- passport — предоставляет стратегии аутентификации в приложениях на Node.js.
- passport-youtube-v3 — предоставляет стратегию аутентификации на Youtube посредством аккаунта Youtube и токенов OAuth 2.0.
- twitter — клиентская библиотека для работы с Twitter REST API.
- googleapis — клиентская библиотека для работы с Google REST API.
- moment — JavaScript библиотека для синтаксического анализа, валидации и форматирования дат.
Установить модули можно командой:
$ npm install express passport passport-youtube-v3 twitter googleapis@^20.0.1 moment --save
Twitter предлагает приложениям возможность выдавать аутентифицированные запросы от имени самого приложения. Для доступа к API используется открытый протокол авторизации OAuth 2.0.
Чтобы получить OAuth-токен:
- Изучите документацию.
- Зарегистрируйте приложение.
- Получите ключи: Consumer Key, Consumer Secret.
- Закодируйте строку вида:
<Consumer Key>:<Consumer Secret>
методом Base64. - Получите OAuth-токен.
Используйте полученные токен и ключи в запросах к Twitter Search API. Подробнее см. Работа с Twitter Search API.
Важно! Сохраните полученные токен и ключи (Consumer Key и Consumer Secret). Они необходимы для конфигурационного файла приложения.
Google предлагает приложениям возможность выдавать аутентифицированные запросы от имени самого приложения. Для доступа к API используется открытый протокол авторизации OAuth 2.0.
Примечание. За получение и обновление OAuth-токена с помощью POST-запроса в обмен на код авторизации отвечает модуль passport-youtube-v3.
Чтобы получить OAuth-токен:
- Изучите документацию.
- Зарегистрируйте приложение и получите Client ID и Client Secret.
- Укажите callback URL (в нашем случае это
http://localhost:3000
) в учетной записи вашего приложения.
Используйте полученные Client ID и Client Secret в запросах к YouTube Data API. Подробнее см. Работа с YouTube Data API.
Важно! Сохраните полученные ключи (Client ID и Client Secret). Они необходимы для конфигурационного файла приложения.
-
Добавьте в файл server/config.js поле
services
.module.exports = { staticFolder: 'static', defaultPort: 3000, cacheTTL: 30000, sessionSecret: 'REPLACE_ME_WITH_RANDOM_STRING', + services: { + twitter: { + consumer_key: '*****', + consumer_secret: '*****', + bearer_token: '*****' + }, + youtube: { + client_id: '*****', + client_secret: '*****', + redirect_url: 'http://localhost:3000' + } + } };
-
Замените звездочки полученными ключами и токенами.
-
Скройте файл server/config.json от системы контроля версий Git, чтобы случайно не отправить личные ключи в репозиторий.
# файл .gitignore server/config.js
Twitter Search API позволяет найти твиты, опубликованные за последние 7 дней.
Чтобы настроить приложение на взаимодействие с API:
-
Откройте файл controllers/index.js и замените его содержимое на следующее.
-
Добавьте следующий код в файл helpers/index.js:
module.exports = { twitter: require('./twitter') };
-
Добавьте следующий код в файл helpers/twitter.js.
YouTube Data API позволяет искать видео по ключевому слову.
Чтобы настроить приложение на взаимодействие с API:
-
Добавьте следующий код в файл server/auth.js.
-
Отредактируйте файл server/routes.js:
var router = require('express').Router(), controllers = require('./controllers'), + passportYouTube = require('./auth'), + middleware = require('./middleware/auth'), + isAuthenticated = middleware.isAuthenticated; router - .get('/ping/', function(req, res) { - res.send('ok'); - }) - .get('/', controllers.getContent); + .get('/auth/youtube', passportYouTube.authenticate('youtube')) + .get('/auth/youtube/callback', passportYouTube.authenticate('youtube', + {failureRedirect: '/error', failureFlash: true }), (req, res) => { + res.redirect('/'); + }) + .get('/', isAuthenticated, controllers.getContent); module.exports = router;
-
Замените содержимое файла controllers/index.js на следующее.
-
Отредактируйте файл helpers/index.js:
module.exports = { twitter: require('./twitter'), + youtube: require('./youtube') };
-
Добавьте следующий код в файл helpers/youtube.js.
-
Добавьте следующий контент в файл middleware/auth.js:
module.exports = { isAuthenticated: function(req, res, next) { if (req.isAuthenticated()) return next(); return res.redirect('/auth/youtube'); } };
Данный документ не содержит описания верстки и клиентского JavaScript, которое привело бы к большему объему, а, значит, и к меньшей практической ценности документа.
Процесс верстки сведен к следующим шагам:
- Удалите все блоки из директории common.blocks.
- Склонируйте следующие блоки в директорию common.blocks.
- Добавьте logo.svg в директорию static.
- Перезапустите сервер:
npm run dev
.
Приложение Social Services Search Robot готово.
Примечание. Если при создании приложения возникли сложности, поищите решение на форуме. Если готового ответа не нашлось, задайте вопрос экспертам.
Чтобы закодировать строку:
-
Сформируйте строку вида:
<Consumer Key>:<Consumer Secret>
.Пример
xvz1evFS4wEEPTGEFPHBog:L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg
Примечание. Получить ключи Consumer Key и Consumer Secret можно, перейдя на вкладку Keys and Access Tokens вашего приложения.
-
Запустите терминал или Git Bash (пользователям ОС Windows).
-
Выполните команду
echo -n "xvz1evFS4wEEPTGEFPHBog:L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg" | base64
. -
Скопируйте полученный код.
Пример
eHZ6MWV2RlM0d0VFUFRHRUZQSEdFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==
Примечание. Если возникли сложности, воспользуйтесь онлайн-ресурсом base64encode.org.
Чтобы получить токен:
-
Установите и запустите Postman.
-
Выберите тип запроса POST.
-
Введите адрес сервера (для Twitter —
https://api.twitter.com/oauth2/token
). -
Перейдите на вкладку Headers.
-
Добавьте заголовки:
Authorization
иContent-Type
с соответствующими значениями.Key Value Authorization Basic закодированная строка Consumer Key:Consumer Secret
Content-Type application/x-www-form-urlencoded;charset=UTF-8 Примечание. Basic указывает на базовый метод авторизации.
-
Перейдите на вкладку Body → Выберите опцию
x-www-form-urlencoded
. -
Введите в поле Key тело запроса
grant_type
со значениемclient_credentials
. -
Нажмите кнопку Send.
OAuth-сервер вернет токен в JSON-формате:
{
"token_type": "bearer",
"access_token": "AAAAAAAAAAAAAAAAAAAAAA%2FAAAAAAAAAA%3DAAAAAAAAAAAAAAAAAA"
}
Важно! Сохраните полученный токен для конфигурационного файла приложения.