Корпоративные порталы
Решение задач консолидации компании, повышение эффективности работы и исполнительской дисциплины, автоматизация Бизнес-процессов с помощью Интранет-портала.
Корпоративные сайты
Решение задач узнаваемости бренда, повышения лояльности клиентов и увеличения продаж с помощью современного корпоративного сайта.
Интернет-магазины
Организация онлайн-продаж, интеграция с учётными системами, механизмы стимулирования продаж и повышения эффективности маркетинга.

Композитный сайт: tips & tricks

24.06.2014



1. Как сделать динамическую область вне контекста шаблона компонента?

\Bitrix\Main\Page\Frame::getInstance()->startDynamicWithID("area");
   //динамический контент вне компонента
\Bitrix\Main\Page\Frame::getInstance()->finishDynamicWithID("area", "Загрузка...");
Способ с буферизацией. Удобнее в использовании, но нельзя использовать отложенные функции внутри динамической области и в заглушке.
$frame = new \Bitrix\Main\Page\FrameHelper("my_dynamic_area");
$frame->begin();
   //динамический контент
$frame->beginStub();
  //заглушка
$frame->end();
В следующем обновлении композитного сайта: компонент, находящийся в динамической области, не участвует в голосовании.


2. Как отменить композитное кеширование в любом месте страницы (проголосовать "против") ?
\Bitrix\Main\Data\StaticHtmlCache::getInstance()->markNonCacheable();


3. Страницы с расширением *.html не обрабатываются. Что делать?
На странице настроек в поле "Маска включения" добавляем "*.html".


4. Как учитывать композитные страницы в Google Analytics?
Google Analytics и Яндекс.Метрика собирают данные клиентской загрузки на основе Navigation Timing. Эта статистика показывает реальное время, с которым пользователи открывают страницы вашего сайта. Здесь важно понимать, что композит влияет только на время ожидания ответа от сервера (Server Response Time). Он не влияет на время: а) DNS lookup б) TCP-соединения в) загрузки JS, CSS и картинок.

По глобальной JS-переменной window.frameRequestStart можно определить, что страница отдалась пользователю из композитного кеша.
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-18655900-1']);
_gaq.push(['_setCustomVar', 1, 'Cache', window.frameRequestStart ? 'Composite': 'NoComposite', 3]);
Код для Google Analytics нужно располагать ниже кода, выполняющего фоновый композитный запрос.


5. В чем разница между $this->createFrame()->begin(); и $this->createFrame()->begin(""); ?
Есть несколько способов выделить в шаблоне компонента динамическую область.
Самый популярный вариант выглядит так:
$frame = $this->createFrame()->begin();
   //динамический контент
$frame->beginStub();
   //заглушка
$frame->end();
Метод beginStub может отсутствовать, т.к. в метод begin можно сразу передать текст заглушки.
$frame = $this->createFrame()->begin("Загрузка...");
   //динамический контент
$frame->end();
Пустая строка будет означать пустую заглушку.
$frame = $this->createFrame()->begin("");
   //динамический контент
$frame->end();
А вот так можно записать контент динамической области в кеш, когда контент заглушки совпадает c контентом динамической части.
$frame = $this->createFrame()->begin();
   //динамический контент = заглушка
$frame->end();

Этот способ позволяет избежать дублирования и повторного выполнения код.
С версии main 14.5.2 контент заглушки стал учитываться при подсчете хеш-суммы кеша.


6. Какие еще особенности у begin и beginStub?
Важно понимать, что код между вызовами begin-beginStub и beginStub-end выполняется всегда. И на первом хите к странице (на котором создается кеш) и на аякс-хите. Эти методы занимаются буферизацией контента и не являются аналогами конструкции if-else.


7. В теге <head> есть блок php, который проверяет специальный Cookie, и если он установлен, добавляет блок <style> с нужными стилями. Генерируется новая страничка, кеш перезаписывается. Как быть в таких случаях?
Вынести эту логику в Javascript.
<head>
<script>
if (document.cookie.indexOf("my_cookie=yes") >= 0)
{
   //Устанавливаем класс для тега <html>
   document.documentElement.className += " has-cookie";
}
</script>
</head>

<style>
.block { display: none; }
.has-cookie .block { display: block; }
</style>


8. Что является причиной перезаписи кеша?
Причин много. Вот самые популярные:
- Случайные ID в HTML и Javascript. Метод randString поможет решить эту проблему.
- Вывод данных из сессии (id, login).
- Контент страницы зависит от User Agent.
- Разный контент для анонимного и для авторизованного пользователя.
- Добавление на страницу CSS- и JS-файлов в зависимости от пользователя.


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


10. Счетчик товаров в корзине пользователя находится в динамической области. Некрасиво прыгает цифра: сначала ноль, потом один.
Давайте подобно посмотрим, из-за чего это происходит.
- В файл кеша записывается заглушка "0 товаров в корзине".
- Страница из кеша отдается пользователю и показывается.
- Даже если аяксовый хит с нужными данными приходит раньше, чем отрендерилась страница, все равно пользователь на мгновение видит заглушку.
- Это происходит из-за того, что все вставки в innerHTML (в том числе из sqlite) происходят на событии DOMContentLoaded.
- Хотя в большинстве случае виноват даже не DOMContentLoaded, а долгое выполнение аяксового запроса.

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

Как вставить до рендеринга?

а) document.write - это конструкция останавливает рендеринг страницы, для того, чтобы на лету вставить в DOM новый HTML. Разработчики браузеров не рекомендуют ее использовать, но она работает.

б) Разместить Javascript в странице так, чтобы он располагался после HTML'я, к которому обращается.
Это старый забытый способ начала 2000-x годов, когда еще jQuery'ая $.ready() не замылила всем глаза.
$.ready() или битриксовая BX.ready - это выполнение кода на событии DOMContentLoaded. Это событие гарантирует, что DOM построен и к нему можно безопасно обращаться. Минус этого события в том, что на больших страницах интерфейс уже успевает пользователю показаться, отсюда и моргание.
<!doctype html>
<html>
<body>
<div id="box" style="width: 100px; height: 100px; background: red;"></div>
<script>document.getElementById("box").style.background = "blue";</script>
<table><tr><td>some html below</td></tr></table>
</body>
</html>

Да, есть вероятность нарваться на Exception, поэтому можно подстраховаться:
function changeBox()
{
   document.getElementById("box").style.background = "blue";
}

var box = document.getElementById("box");
if (box)
{
   changeBox();
}
else
{
   BX.ready(function() { changeBox(); });
}

Откуда взять актуальные данные?

Три варианта:
- Cookies
- SQLite
- LocalStorage

Самый приемлемый вариант - это localStorage. Это key-value хранилище, которое поддерживается всеми браузерами, даже IE8.
Данные localStorage доступны мгновенно сразу во всех вкладках. Т.е. если у пользователя открыто 10 вкладок магазина и он в одной из них жмет "Добавить в корзину", то через событие localStorage'а можно мгновенно поменять во всех вкладках счетчик корзины.

Для localStorage в Битриксе есть своя обвязка под названием BX.localStorage. Она позволяет указывать время хранения данных.

Основные методы:
BX.localStorage.set(key, value, ttl)
BX.localStorage.get(key)
BX.localStorage.remove(key)

События:
BX.addCustomEvent("onLocalStorageSet", function(data) { console.log(data.key, data.value) });
BX.addCustomEvent("onLocalStorageRemove", function(data) {});
BX.addCustomEvent("onLocalStorageChange", function(data) {});

В итоге: счетчик корзины и имя пользователя можно кешировать в localStorage и использовать эти данные для борьбы с морганием.


11. Если еще какие-нибудь способы борьбы с морганием?
Все зависит от дизайна сайта и от контента динамических областей.
Старайтесь делать верстку так, чтобы вставка динамических областей не приводила к прыганию соседних элементов.
C помощью метода setAnimation(true) можно добавить эффект плавного появления контента.
Экспериментируйте с содержимым заглушек. Заглушка может быть пустой, а может повторять содержимое динамической области (см. пункт 5).


12. Динамическая область автоматически оборачивает свой контент в дополнительный div, который портит верстку сайта.
Композитному кешированию необходимы html-контейнеры для вставки в них содержимого динамических областей.
Можно использовать свои контейнеры:
echo '<div id="my_div">';
$frame = $this->createFrame("my_div", false)->begin();
   //динамический контент
$frame->beginStub();
   //заглушка
$frame->end();
echo '</div>';


Возврат к списку



Вас интересует ""?!
Напишите нам и мы с вами свяжемся!