Настройка компонентов для композитного сайта
Если страницы еще нет в кеше, система формирует страницу так, как если бы сайт работал без поддержки композита. И в
таком виде отдает страницу браузеру. После чего подготавливает страницу к сохранению в кеше. По меткам в html-коде,
расставленным программистом, вырезает из страницы динамические блоки и вставляет вместо них статические заглушки.
Эти заглушки могут быть просто текстом «Загрузка...», анимированной картинкой loader.gif
или каким-либо
html-кодом. Кроме того, система добавляет к странице javascript-код, который: во-первых, выполнит фоновый
ajax-запрос на получение динамического контента, а во-вторых, вставит полученные динамические блоки на место
заглушек. Теперь страница содержит только статику и у нее есть ajax-загрузчик. В этом виде страница сохраняется в
кеш.
Если страница есть в кеше, она будет отдана практически мгновенно, без выполнения php-кода и запросов к базе данных. Браузер, получив страницу из кеша, выполнит фоновый ajax-запрос, получит от сервера актуальные данные в формате json и вставит на место заглушек динамические блоки.
При фоновом ajax-запросе Битрикс формирует страницу полностью. Из полученного html-кода страницы вырезаются динамические данные и отправляются браузеру в формате json. На место вырезанных динамических блоков вставляются заглушки, на страницу добавляется ajax-загрузчик. После замены всей динамики на статику и добавления ajax-загрузчика, вычисляется контрольная сумма получившейся страницы. Если эта сумма не совпадает с контрольной суммой страницы в кеше — кеш перезаписывается.
Адаптация шаблона компонента
Перевод сайта на использование композита подразумевает настройку всех используемых компонентов и их шаблонов на корректную работу в композитном режиме. По умолчанию логика работы следующая: все компоненты «голосуют» за включение технологии, а шаблоны — «голосуют» против. Поведение по умолчанию можно изменить: шаблоны компонентов при ручной настройке композита должны быть определены как:
Статичный шаблон, его можно записывать в кеш:
$this->setFrameMode(true);
Динамичный шаблон, его нельзя записывать в кеш:
$this->setFrameMode(false);
Статичный шаблон с динамичными зонами:
$this->createFrame()->begin('Загрузка...');
Со статичным и динамичным шаблоном все понятно, а вот статичный шаблон с динамичными зонами рассмотрим подробнее. Самый простой вариант — когда весь шаблон компонента включается в динамическую зону:
<?
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true) die();
// весь шаблон компонента включается в динамическую зону
$this->createFrame()->begin('Загрузка...');
?>
<h1><?= $arResult['NAME']; ?></h1>
<article id="iblock-element">
<img src="<?= $arResult['DETAIL_PICTURE']['SRC']; ?>" alt="<?= $arResult['DETAIL_PICTURE']['ALT']; ?>" title="<?= $arResult['DETAIL_PICTURE']['TITLE']; ?>" />
<p>Количество просмотров: <?= $arResult['SHOW_COUNTER'] ? $arResult['SHOW_COUNTER'] : 0; ?></p>
<div><?= $arResult['DETAIL_TEXT'] ?></div>
<p><a href="<?= $arResult['SECTION']['SECTION_PAGE_URL']; ?>">Назад в раздел</a></p>
</article>
Если код $this->createFrame()->begin('Загрузка...');
стоит в начале компонента и нигде не
завершается (зона в этом случае завершается автоматически), то реально это означает, что весь компонент —
динамичный. В кеш будет записана заглушка, пользователь увидит на мгновение текст «Загрузка...», а после
ajax-запроса — на место заглушки будет вставлен html-код шаблона компонента.
Временная заглушка до получения данных ajax-запросом:
<div id="bxdynamic_vpV9RD_start" style="display:none"></div>
Загрузка...
<div id="bxdynamic_vpV9RD_end" style="display:none"></div>
После ajax-запроса, на место заглушки будет вставлен html код:
<div id="bxdynamic_vpV9RD_start" style="display:none"></div>
<h1>Абиссинская кошка</h1>
<article id="iblock-element">
<img src="/upload/iblock/b59/b598753f287a05c04ca3079764033bca.jpg" alt="Абиссинская кошка. Породы кошек. Статьи о домашних животных" title="Абиссинская кошка. Породы кошек. Статьи о домашних животных" />
<p>Количество просмотров: 5</p>
<div>
<p>
Абиссинская кошка — одна из самых древних пород кошек. Изображение кошек на
древних египетских росписях, а также указание их цвета в описаниях «солнечный
кот», «лазуритовая кошка горизонта» наводят на мысли о том, что речь шла именно
об абиссинских кошках.
</p>
</div>
<p><a href="/test/category/id/16/">Назад в раздел</a></p>
</article>
<div id="bxdynamic_vpV9RD_end" style="display:none"></div>
Виды вставок
В разметке сначала указывается собственно динамичная часть, которая будет различной для каждого пользователя, а
затем, через вызов beginStub()
— та часть, которая будет записана в кеш и которая будет показана
пользователю, пока не получены данные из первой части.
В качестве заглушки будет показана надпись «Загрузка...», которую мы передаем параметром методу begin()
:
$frame = $this->createFrame()->begin('Загрузка...');
// динамический контент
$frame->end();
Если вместо текста «Загрузка...» нужна пустая заглушка, то методу begin()
надо передать пустую строку:
$frame = $this->createFrame()->begin('');
// динамический контент
$frame->end();
Если необходимо, чтобы в заглушке отображались данные компонента, полученные на предыдущем хите, то метод
begin()
необходимо вызвать без параметров:
$frame = $this->createFrame()->begin();
// динамический контент = заглушка
$frame->end();
Еще один вариант формирования заглушки и динамического контента:
$frame = $this->createFrame()->begin();
// динамический контент
$frame->beginStub();
// html-код заглушки
$frame->end();
В качестве параметра методу begin()
можно передать анимированное изображение:
$this->createFrame()->begin('<img src="/images/loader.gif" alt="" />');
Код между вызовами begin()…beginStub()
и beginStub()…end()
выполняется всегда. И на первом
хите к странице (на котором создается кеш) и на ajax-хите. Эти методы занимаются буферизацией контента и не являются
аналогами конструкции if…else
. Вызов $frame->end()
завершает разметку динамичной части
в шаблоне компонента.
Контейнер для динамической вставки
Вставка динамического контента после ajax-запроса создает неприятный эффект — элементы страницы резко смещаются
вниз, освобождая место под динамический контент. Давайте создадим свой контейнер с уникальным идентификатором для
динамического контента и стилизуем его — установим min-height
, чтобы место под динамический контент
было зарезервировано сразу. Кроме того, используем метод setAnimation()
, который плавно изменяет
opacity
контейнера от нуля до единицы:
<p id="iblock-element">
<?
// показываем надпись во время загрузки контента
$frame = $this->createFrame()->begin('Загрузка элемента');
// задаем свой идентификатор динамического контента, вместо сгенерированного системой
$frame->setContainerID('iblock-element');
// добавляем анимацию динамического контента после ajax-запроса, opacity плавно изменяется от 0 до 1
$frame->setAnimation(true);
echo date('H:i:s d.m.Y');
$frame->end();
?>
</p>
Использование Web SQL браузера
Можно использовать локальную базу данных браузера, чтобы сохранять в ней динамические блоки страниц. Когда браузер получает страницу из кеша, он выполняет фоновый ajax-запрос на получение динамичных блоков, чтобы заменить заглушки. Получение актуальных данных с сервера может занять какое-то время. Если последние актуальные данные с сервера сохранять в локальной базе данных браузера, мы можем показать их практически сразу.
<p id="iblock-element">
<?
$frame = $this->createFrame()->begin();
// задаем свой идентификатор динамического контента, вместо сгенерированного системой
$frame->setContainerID('iblock-element');
echo date('H:i:s d.m.Y');
// код заглушки
$frame->beginStub();
// запись в LocalStorage
$frame->setBrowserStorage(true);
$frame->end();
?>
</p>
Этот пример показывает, как можно сохранить в локальную SQL-базу динамический контент, но делать так не следует.
Пример правильного использования — корзина интернет-магазина, которая показывается на всех страницах сайта.
Это совсем маленький динамический блок и у него
всегда один идентификатор, например bxdynamic_VTD1tH
. Запись в локальной базе для этого блока будет
только одна и в ней — последние актуальные данные корзины.