[Разработка веб-сайтов, PHP, Drupal, Программирование] #lazy_builder (не путать с lazy load) в Drupal 8/9

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
24-Дек-2020 16:30

Продолжая изучать Drupal, мы наткнулись на очень интересную технологию, которая в него встроена. И которая, на наш взгляд, используется неоправданно мало. И совершенно зря. Потому что подход, который использует эта технология, позволяет мгновенно отдать высоконагруженную (или просто долго формирующуюся) страницу пользователю, а потом «доотдать» ему данные, требующие много времени на формирование. И изучая эту технологию, мы столкнулись с тем, что нет ни одного простого объяснения, что это и как это запустить. Нет, объяснения-то есть. Простых нету. Сейчас мы попытаемся восполнить эту неприятность.
Общее описание
Итак, у нас есть страница, которая по каким-то причинам долго формирует часть данных. Причины могут быть разными — большой объём вычислений, большой объём данных, долгие запросы к какой-нибудь медленной базе данных, или вообще надо лезть на сторонний сервис, с которого получить информацию, которую потом ещё и обработать надо. Причины — неважны. Важно, что на нашей странице есть данные, которые мы может отдать сразу — заголовки, подвал, какие-то картинки, ещё кучу обрамления, текста, реклама, в конце концов. А есть данные, которые нам надо «добыть», и на это уйдёт какое-то количество времени.
Так вот. Обычно эту задачу решают через механизм «ленивой загрузки» — грузится облегчённая версия страницы, а потом срабатывает скрипт lazy loading, который с помощью JavaScript сходит на бекенд, заберёт оттуда данные и положит их в нужные места. Но у ленивой загрузки есть куча минусов. Начиная с того, что если, например, наши данные отдаются только авторизованному пользователю, то нам надо дополнительно авторизовать этот ленивый скрипт. Также нам всегда нужен включённый JavaScript. Эта «ленивая вещь» не очень хорошо дружит в поисковыми роботами. Ну и так далее.
А создатели Drupal, оказывается, молодцы. И предлагают нам ещё один механизм, который лишён почти всех минусов lazy loading'а. И называется этот механизм — «ленивый построитель» — lazy builder. Он работает, как всё гениальное — очень просто.
На то место в twig-шаблоне, где нужно вывести «тяжелые» данные, мы кладём обычную (почти) переменную, совершенно обычным способом, вот так: {{ lazy_data }}. А вот в препроцессоре, в котором мы готовим эту переменную, мы должны сказать ей волшебные слова, чтобы она стала lazy builder'ом. Выглядит это так:
$variables['lazy_data'] = [
  '#create_placeholder' => TRUE, // - это необязательно, её Drupal сам умеет включать.
  '#lazy_builder' => [ // - это те самые волшебные слова, из-за которых всё работает.
    //... чуть ниже будет подробнее
    ],
  ],
];

И теперь Drupal, когда будет рендерить страницу, на место этой переменной поставит JavaScript-плейсхолдер, а сами данные формировать в момент рендера не будет. То есть — эта страница сформируется быстро, и так же быстро будет отдана пользователю. А уже потом, когда она будет показана браузером на экране, сработает этот плейсхолдер, который полезет на бэкэнд и скажет ему — «я готов, гони данные». Бэкэнд эти данные спокойно сформирует и отдаст. И они будут вставлены на то место, где они и должны быть.
Вот и всё! И не надо никакой дополнительной авторизации — она уже была произведена на бэкэнде. И не надо подключать никаких дополнительных скриптов — Drupal сам обо всём позаботится. И не нужны никакие дополнительные API точки входа, которые надо дополнительно писать и обслуживать. Не надо никаких уточнений — что за данные вам нужны — всё это уже было сделано на бэкэнде. Мы просто кусок «строительства страницы» отложили на потом. Вот и всё, что мы сделали.
И самое гениальное здесь то, что если у пользователя не включен JavaScript — то Drupal сам это распознает и сформирует эти тяжёлые данные сразу, без использования плейсхолдера. То есть — как будто бы никакой механиз отложенного строительства и не существует. Поисковые роботы будут счастливы, что им не надо разбираться с самописными ленивыми загрузками, они получат обычную страницу. Ну а подождать несколько секунд эту страницу для них не так критично, как для человека.
А теперь немного технических подробностей, как со всем этим взлететь это сделать.
Повторимся — в twig-шаблоне мы пишем как обычно — просто кладём переменную в нужное нам место. И всё, больше никаких телодвижений предпринимать не нужно.
В препроцессоре шаблона, в котором нам надо сформировать эту переменную, мы пишем «волшебные слова», чтобы она стала «ленивой» и пишем, что она должна вызвать для ленивого рендера нашей переменной:
$variables['lazy_data'] = [
  '#create_placeholder' => TRUE, // - это необязательно, её Drupal сам умеет включать.
  '#lazy_builder' => [ // - это волшебные слова, из-за которых всё работает.
    'имя_модуля.lazy_renderer:renderBigData', [ // - это имя сервиса, который будет вызываться. Важно, что это именно сервис.
      'info' => 'Важная информация', // - это просто параметры, которые ты отдаёшь в шаблон. См. ниже
      'params' => ['foo' => 'boo'],
        'something_else' => 11
    ],
  ],
];

Теперь нам надо сделать Drupal-овский «сервис», который и будет заниматься формированием наших больших данных. Для этого в файле имя_модуля.service.yml, который лежит в корне нужного модуля (не обязательно самописного), мы должны объявить этот сервис (имя_модуля.lazy_renderer), который будет вызываться для формирования того, что надо вывести в переменную 'lazy_data', которая потом пойдёт в ту заглушку, в дом который построил Джек.
В этом сервисе делаем функцию renderBigData, которая и будет вызываться. И вот эта функция должна вернуть ссылку на шаблон, который будет отрендерен и будет вставлен в нужное место страницы, в доме который построил Джек.
Но в эту функцию хочется же передать что-нибудь, да? Вот как это делается.
Во-первых, напоминаем, что для того, чтобы продать что-нибудь ненужное, надо сначала купить что-нибудь ненужное, а для того чтобы использовать шаблон для рендера, его надо сначала объявить. То есть — в файле имя_модуля.module, в функции function promotion_theme(...) надо вернуть, вместе с остальными заготовками шаблонов, заготовку нового шаблона:
'my_template_for_lazy_building' => [
  'variables' => [
    'info' => '',
    'params' => [],
    'something_else' => 1
  ],
],

А дальше всё просто — в сервисе, в функции, подготавливается всё, что нужно, и этот свежеобъявленный шаблон возвращается на рендер, передав ему то, что тебе нужно ему передать.
А у этого шаблона, в свою очередь, есть свой препроцессор, который сработает при попытке Drupal отрендерить шаблон. В этот момент препроцессор получит те переменные, которые объявлены и переданы.
То есть, технически это выглядит так:
// Смотрим выше на вызов сервиса из нашей переменной:
// 'имя_модуля.lazy_renderer:renderBigData'
// и сопоставляем класс:
class lazy_renderer {
        public function renderBigData($info, $params, $something_else) {
        //Обрати внимание на переменные функции
    //Что-то тут делаем, готовим данные.
    return [
        '#theme' => 'my_template_for_lazy_building',
      '#info' => $info,
      '#params' => $params,
      '#something_else' => $something_else
    ];
  }
}

Сам twig-шаблон должен лежать в каталоге template модуля, само собой.
Вот и всё.
И ещё раз, чтобы подытожить «кто на ком стоял»:
  • У нас есть переменная «lazy_data». Мы её кладём в twig-шаблон какой-то страницы, как простую переменную.
  • В препроцессоре мы её формируем. И говорим ей — что она «ленивая» и что она должна вызвать сервис ('имя_модуля.lazy_renderer:renderBigData'), который вернёт шаблон (другой, 'my_template_for_lazy_building') на рендер. Этот шаблон отрендерится и вставится на место 'lazy data'.
  • Не забываем наш шаблон объявить.

Надеемся, что смогли просто, но при этом максимально подробно, рассказать про технологию Lazy Builder.
Спасибо за внимание.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_razrabotka_vebsajtov (Разработка веб-сайтов), #_php, #_drupal, #_programmirovanie (Программирование), #_lazy_builder, #_drupal, #_php, #_lazy_load, #_razrabotka_vebsajtov (
Разработка веб-сайтов
)
, #_php, #_drupal, #_programmirovanie (
Программирование
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 21:58
Часовой пояс: UTC + 5