Филатов Евгений Разработчик интерфейсов Одностраничное приложение на БЭМ Node.js Я.Субботник в Киеве, 27 апреля 2013 года
Jun 22, 2015
Филатов Евгений Разработчик интерфейсов
Одностраничное приложение на БЭМ Node.js
Я.Субботник в Киеве, 27 апреля 2013 года
Наш фронтенд
• css + js • Рендер шаблонов на сервере • Получаем данные через АПИ
Наш фронтенд
• css + js • Рендер шаблонов на сервере • Получаем данные через АПИ
Одностраничное приложение
• Скорость • Трафик • Нагрузка
Одностраничное приложение
• Прыгает верстка • Нет индексации
Что хотим?
• При прямом переходе создаем все на сервере • Потом все на клиенте
Код должен выполнятся и на клиенте и на сервере!
Node.js и браузер — не одно и то же
Помогает БЭМ
bem.info/method
На файловой системе
папки blocks ├── i-router ├── i-api-request └── i-page и файлы i-router ├── i-router.js ├── i-router.priv.js └── i-router.common.js
На файловой системе
папки blocks ├── i-router ├── i-api-request └── i-page и файлы i-router ├── i-router.js ├── i-router.priv.js └── i-router.common.js
браузер сервер
общий код
bem.info/tools/bem
bem-tools
Сборка
Сборка
Общий код
Пример
i-cookie.priv.js: function setCookie(key, val) { res.writeHead(200, { 'Set-Cookie': cookieStr(key, val) }); }
i-cookie.js: function setCookie(key, val) { document.cookie = cookieStr(key, val); }
i-cookie.common.js: function cookieStr(key, val) { return key + '=' + val; }
Общий код
bit.ly/bem-ru
i-bem
i-bem i-cookie.js: BEM.decl('i-cookie', null, { setCookie: function (key, val) { document.cookie = this.cookieStr(key, val); } }) i-cookie.common.js: BEM.decl('i-cookie', null, { queryStr: function (key, val) { return key + '=' + val; } })
BEM.blocks['i-cookie'].setCookie('my', 'test');
Страницы
Страница (сервер)
СтранСтраница (клиент) ица (сервер)
github.com/delfrrr/bem-json
Шаблонизация
Шаблонизация
• На чистом js • Шаблоны в терминах БЭМ • Асинхронная шаблонизация
{ channel: { id: 42, name: 'СТБ' } }
{ block: 'b-channel', tag: 'a', atts: { href: '/channels/42' }, content: 'СТБ' }
<a href="/channels/42" class="b-channels">СТБ</a>
Шаблоны
bemhtml
Данные
bemjson
html
{ channel: { id: 42, name: 'СТБ' } }
{ block: 'b-channel', tag: 'a', atts: { href: '/channels/42' }, content: 'СТБ' }
<a href="/channels/42" class="b-channels">СТБ</a>
Шаблоны
bemhtml
Данные
bemjson
html
data view bemjson
Шаблоны общие для клиента и сервера
Простой шаблон BEM.JSON.decl('b-channel', { onBlock: function(ctx) { var params = ctx.params(); ctx .tag('a') .attrs({ href: '/channels/' + params.id }) .content(params.name) } });
Не хватает данных BEM.JSON.decl('b-channel', { onBlock: function(ctx) { var params = ctx.params(); ctx .tag('a') .attrs({ href: '/channels/' + params.id }) .content(params.name) } });
Получаем данные в шаблонах
Асинхронность = промисы
Асинхронный шаблон! BEM.JSON.decl('b-channel'}, { onBlock: function(ctx) { var params = ctx.params(); ctx .tag('a') .attrs({ href: '/channels/' + params.id }) .defer( BEM.blocks['i-api-request'] .get('/channel-name', {params: params}) .then(function (result) { ctx.content(result.name); }) ); } });
MVC?
MVC?
Но почему не MVC?
• Логика шаблонов в шаблонах • Блоки переносимы • Все консистентно
А если блокам нужны одинаковые данные?
b-‐program
b-‐channel
i-‐api-‐request
кеш
…похожие?
b-‐channel b-‐channel b-‐channel
b-‐channel b-‐channel b-‐channel
i-‐api-‐request
групировка
Профит
54%
10%
36%
Строчек кода на проекте
common.js priv.js js
Используйте прямо сейчас
Где взять?
bem-node • github.com/wtfil/bem-node • github.com/wtfil/bem-node-test (пример)
Шаблонизатор
• github.com/delfrrr/bem-json
Комьюнити
• @bem_ru
• facebook.com/groups/bem.info/
• github.com/bem
Евгений Филатов
Разработчик интерфейсов @wtfil
github.com/wtfil