Композитный сайт битрикс. Часть 2 — Подводные камни

slowpoke

Да уж … прошло уже более 2х месяцев со дня последнего поста. Честно признаться — времени не хватает, и работы много, и семья, и хобби.

Как и обещал, пишу пост про те тонкости и подводные камни. Если у вас стандартный сайт, сделанный на стандартном шаблоне, то скорее всего вы с ними не столкнетесь. Проблемы начинаются там, где кончается «зона комфорта», а, как говорится, не выйдешь из зоны комфорта — не будет никакого движения вперед. Поэтому давайте не будем останавливаться, а дадим немного газу и ускорим ваш сайт!

Проблема №1. Рандом

Рандом в битриксе существует в разных проявлениях. Одну из рандомных проблем разработчики битрикса решили — это рандомные строки. Часто разработчики используют рандомные строки в своих компонентах и шаблонах для того, чтобы создавать какие-то уникальные идентификаторы для каких-то элементов. Например, нужно вывести на странице несколько блоков с изображениями или видео, а в последствии обратиться к ним через  js по идентификатору. Сгенерировать случайную строку можно разными способами в php, в битриксе есть специальная функция для генерации случайных строк и величин.

Тут и кроется первая проблема. Если компонент на каждом вызове будет генерировать какую-то случайную строку и будет выводить ее в шаблон, то этот шаблон в композитном режиме работать не будет, просто потому, что он меняется каждый хит.

Решение достаточно простое, оно описано в официальном курсе битрикса по композитному сайту. Для CBitrixComponent написали метод randString(), который генерирует псевдо-случайную величину, которая будет зависеть строго от композитного кеша.

Проблема №2. Снова рандом

Простая и очень частая ситуация — часто на главной странице интернет-магазина выводится какой-то блок (Спецпредложения, Новинки, Самые продаваемые товары), который содержит в себе какой-то набор товаров. Часто товары в таких блоках выводятся в случайном порядке. Ясно дело — раз товары меняются на каждом хите, то и композитный кеш для страницы нормально работать не будет.

Тут уже придется немного поломать голову над решением. Первое что приходит в голову — подгружать данный блок на страницу с помощью ajax уже после загрузки. Ну и спрашивается — зачем тогда композит? Кого устраивает — можно сделать и так, но тогда кто-то может не увидеть этот контент (например злобный SEO-шник, который думает, что поисковики до сих пор анализируют сайты по загруженному контенту без учета отработки ajax запросов после загрузки страницы). Мне такой вариант не подошел.

Идем дальше. Можно рендерить с помощью js! Для меня это тоже не вариант в большинстве случаев. Загружать на страницу каждый раз придется больше данных, чем требуется. Дополнительно придется писать рендер на js с помощью какого-нибудь очередного новомодного фреймворка типа angularjs, ну или на коленках. Как-то все это не унифицированно …

Следующий шаг, который является вроде-бы правильным с точки зрения битрикса — выделение всего компонента и его шаблона в динамическую область. Т.е. что я должен сделать — отключить полностью автокеширование компонента, обозначить шаблон как «динамический» и опрашивать базу на каждом хите к главной странице. А что если у меня там 100500 запросов к базе, которые ну никак нельзя оптимизировать? Нет уж, извините, вариант опять не для меня.

Ну и наконец путь, которым пошел я, как обычно, через  ж… Пришлось опять лезть в ядро. Оказывается, можно научить сайт использовать композит не только в компонентах, но и в любом другом месте. Для этого можно использовать класс \Bitrix\Main\Page\FrameStatic. Простой пример:

В примере показан упрощенный вариант. Немного поясню как правильно использовать:
Компонент с рандомным набором товаров может быть подключен с абсолютно любыми параметрами, в т.ч. и с кешем (можно использовать многовариантный кеш, запуская компонент с разными параметрами, чтобы добиться более менее видимой «рандомности» при включенном кеше).
В качестве заглушки можно использовать не только какую-то надпись, но и любой другой html. В моем случае используется специальная функция, которая внутри себя подключает точно такой же компонент с точно теми же параметрами (только без вариативного кеша, но с рандомом).

В результате работы этого кода посетитель, пришедший на сайт, увидит на мгновение сначала один набор товаров (условно рандомный), и мгновенно тут же этот html будет подменен на реально рандомный html со списком товаров. На эту смену контента можно еще наложить и какой-то эффект, чтобы обновление контента смотрелось гладко.

Прошу, напишите в комментах, если у вас есть более оригинальное, продуманное и взвешенное решение. Мне, увы, в голову больше ничего не пришло

Проблема №3. События

Было дело — подключал композит на сайте, на котором использовались региональные поддомены (которые сам и реализовывал). Так получилось, что функционал, связанный с региональностью, был завязан на обработчике события OnPageStart (определение региона, редирект на нужный поддомен и т.д.)
Как только подключили композит, начались странные глюки. Редирект, который должен был срабатывать при наличии определенной куки у пользователя, не срабатывал. Опытным путем было выяснено, что он таки срабатывает, но только лишь на втором композитном хите, а первый хит не доходит до редиректа.

Дело оказалось в том, что разработчики битрикса решили полностью обойти работу ядра при отдаче композитного контента, и дело до проверки события OnPageStart банально не доходит.

К сожалению, решить данную проблему без вмешательства в ядро мне так и не удалось. Сделал просто — добавил подключение своего скрипта до подключения непосредственно композита, например в файле /bitrix/header.php

А уже в подключенном файле — вся необходимая мне логика.
Кстати, на эту тему создал идею для разработчиков битрикса, поддержите плиз 🙂

Заключение

В общем-то битрикс не придумал ничего нового — просто сделали еще одну оболочку поверх существующего кеша. Подобный кеш уже давно имеется и в других системах управления сайтами, подобие подобного кеша есть даже в phpbb.

Но при подключении композита у разработчика сразу появляется больше работы, нужно постоянно следить за развитием сайта и учитывать, что каждый компонент должен работать в режиме композита, что несомненно будет сказываться на трудоемкости последующих задач.

  • Азат Фаттахов

    по п3. до этого ещё идёт отдача nginx даже не доходя до указанного header.php
    описал свое решение в созданной вами идее битрикса

    • Если она корректно настроена — то да. Но в связи с необходимостью делать определенную работу пришлось от этого отказаться

  • Максим Лавриненко

    По п2. иногда может подойти ротация нескольких случайных вариантов. Т.е. компонент внутри себя кешируется в зависимости от случайного числа, например от 1 до 100. В итоге через какое-то время имеем 100 вариаций и для обычного пользователя будет казаться что при обновлении страницы он видит случайны блок

    • В общем-то, когда я говорил о многовариантном кеше, я именно это и имел ввиду 🙂 большинство стандартных компонентов для формирования идентификатора кеша используют массив всех входящих в него параметров. Для создания разных рандомных вариантов кеша я обычно добавляю к вызову компонента один лишний параметр, в качестве значения которому передаю нечто вроде rand(1,10).