\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 и Яндекс.Метрика собирают данные клиентской загрузки на основе
По глобальной JS-переменной window.frameRequestStart можно определить, что страница отдалась пользователю из композитного кеша.
var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-18655900-1']); _gaq.push(['_setCustomVar', 1, 'Cache', window.frameRequestStart ? 'Composite': 'NoComposite', 3]); |
5. В чем разница между $this->createFrame()->begin(); и $this->createFrame()->begin(""); ?
Есть несколько способов выделить в шаблоне компонента динамическую область.
Самый популярный вариант выглядит так:
$frame = $this->createFrame()->begin(); //динамический контент $frame->beginStub(); //заглушка $frame->end(); |
$frame = $this->createFrame()->begin("Загрузка..."); //динамический контент $frame->end(); |
$frame = $this->createFrame()->begin(""); //динамический контент $frame->end(); |
$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>'; |
Т.е. я вижу, что для соответсвующей страницы нет композитной копии, вижу, что страница выполняется динамически, вижу ссылку на файл (например, /bitrix/components/bitrix/catalog.store.amount/templates/.default/template.php)
Этот файл-то я вижу, что не содержит намёков на композит, но хз откуда он вообще взялся.
И при чём тут кеш.
=)
До версии main 14.5.2 закешированный шаблон всегда голосовал "за".
Проверьте свои страницы, в отладочном логе будет присутствовать специальная пометка "(from component cache)".
А вот битриксоидам не спасибо.
Всё работало, всё было хорошо, а с обновлением сдох композит.
И ведь шаблон /bitrix/templates/eshop_adapt_blue/components/bitrix/system.pagenavigation/arrows/template.php - он слегка системный (из демо магаза). Собственно, добавление в него $this->setFrameMode(true); как-то не особо помогает...
Блин, не было печали, внедрили композит ))))
Это старый забытый способ начала 2000-x годов, когда еще jQuery'ая $.ready() не замылила всем глаза.
Зашёл в демо-лабораторию, там точная копия моего. А на него ругается, что он видите ли Reason: (from component cache)
Можно использовать свои контейнеры:
echo '<div id="my_div">';
$frame = $this->createFrame("my_div"->begin();
//динамический контент
$frame->beginStub();
//заглушка
$frame->end();
echo '</div>';
На странице настроек в поле "Маска включения" добавляем "*.html".
Обращение в разработку 49660, 18.04.14, до сих пор не закрытое.
Такая беда.
На других страницах композит работает?
В логе есть что-нибудь?
Если кнопка не выводится - либо композит не работает, либо вы заплатили 300к, чтобы она не выводилась, либо разработчики ее скрыли, нарушив соглашение ее использования.
Динамика в отображении, пример с баннером
не получается повторить.
Где можно увидеть работающий пример или полностью работающий код со всеми js?
Проблема моделируется только на мобильном safari и только с включеннным композитом, было протестированно на 3х айфонах и на 5 сайтах с включенным композитом(
Когда на сайте включен композит мы можем перемещатся по сайту стрелочками "вперед" и "назад", и если мы после этих переходов нажмем обновить страницу то мы получим пустую страницу и обновление уже не поможет, до тех пор пока не сбросится кеш браузера контента не будет видно.
Данный код вреравно обновляет кэш композита
данный код лежит в ШАБЛОНЕ САЙТА
суть кода - количество товаров в корзине , у каждого пользователя оно разное
<?$frame = new \Bitrix\Main\Page\FrameHelper("ajax_basket");
$frame->begin();?>
<?if(count($GLOBALS['BX_MASTER_TOVAR_IN_BASKET']) > 0){echo '<span class="count">'.count($GLOBALS['BX_MASTER_TOVAR_IN_BASKET']).'</span>';}?>
<?$frame->end();?>
завел тему на форум там подробнее описал проблему -
Спасибо огромное
Или например такое решение как ПОХОЖИЕ ТОВАРЫ - у меня они каждый раз выводятся в случайном порядке и тем самым создается новая html страница.
Установите глобальный класс через JS, а в CSS - .firefox .myclass {}
Если сайт на Битриксе, то такие классы уже проставляет стандартная библиотека BX. Если открыть эту страницу в Dev Tools мы увидим:
Также можно воспользоваться библиотекой modernizr.com
У меня в log.txt все время выдает два сообщения. Я изменял эти два файла, но сообщения все так же выводятся. В чем может быть ошибка?
Все другие отредактированные файлы изменения приняли, кроме этих двух:
Host: 192.168.2.102:80
Date: 2015-10-20 09:19:35
Module: Composite was rejected
Reason: (from component cache) /bitrix/templates/shop707_/components/bitrix/catalog.section/new/template.php
----------
Host: 192.168.2.102:80
Date: 2015-10-20 09:19:35
Module: Composite was rejected
Reason: (from component cache) /bitrix/templates/shop707_/components/bitrix/catalog.section/sale/template.php
В начале я просто поставил для них $this->setFrameMode(true),
а после поставил $this->setFrameMode(true) {код ...} $frame->end(). Ничего не изменилось.
Что в данном случае нужно подправлять?
Заранее спасибо.
p.s. Прошелся по ссылке с ответа к посту Федорова Ивана. Но там просто список изменении и не указаны способы исправления.
Bitrix\Main\Page\Frame::getInstance()->finishDynamicWithID("area", "Загрузка...", "третий параметр");
можно узнать подробности про третий параметр тут?
- решает ли композит проблемы когда надо вставлять любые динамические области в кешируемые области?