Как работают виджеты (без PHP и с картинками)

+11
1.1K
Авторы InstantCMS 2 подробно описали создание виджетов в разделе документации «Виджеты» и даже наглядно показали весь процесс в видео-туториале «Создание виджета». Цель этого поста – показать работу виджетов сайта «изнутри» не вдаваясь в программистские подробности. Это будет полезно для изучения работы Двойки и для анализа купленных виджетов на тормоза или перерасход памяти.

Введение

Нужно помнить несколько моментов про виджеты.

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

2. Работу виджетов можно разделить на два этапа: получение/подготовка данных и рендеринг (создание html-кода). Если после первого этапа нет данных для вывода, второй этап не выполняется.

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

4. Виджеты могут быть как частью какого-то компонента, так и отдельными (общими). По сути и принципу работы они практически одинаковы, основное отличие в расположении файлов виджета: или в папке компонента, или в отдельной папке widgets. Мы это увидим дальше.

Начало

В «Расширенной отладке» включим показ контроллера, виджетов (с фильтром по заголовку «Войти на сайт» — чтобы не показывать все виджеты) и шаблонов (с фильтром по имени шаблона ‘main’ – это основной шаблон страниц сайта).
Откроем, например, страницу списка статей демо-сайта site/articles. Видим, что виджеты обрабатываются после окончания работы контроллера, но до рендеринга основного шаблона страницы ‘main’, как и было сказано выше.

Первый виджет на странице — «Нижнее меню»

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

Посмотрим на первый виджет странницы. Им оказалось «Нижнее меню».
Зелёным фоном выделены начало и окончание обработки виджета. В первой строке видно название виджета «Нижнее меню» и его имя ‘menu’. Если в реальном логе подвести к ним мышку, то появятся подсказки о том, что это за значение. Видим, что имени контроллера нет, значит это общий виджет.

Файлы виджета лежат вне папок какого-либо компонента, что ещё раз подтверждает, что это общий виджет. Например, класс виджета /system/widgets/menu/widget.php, а его шаблон в /templates/default/widgets/menu/menu.tpl.php

Поскольку это первый виджет на странице, то сначала автоматически загружается класс для работы с виджетами cmsWidget (Autoload 35), потом подключаются класс виджета ‘menu’ (Include 63) и его языковой файл (Include 63). Пока всё логично.

А дальше – открытие для программистов. Оказывается, в Двойке есть компонент «Меню» (Autoload 36), которого не видно в списке компонентов. На самом деле всё просто: у него есть только модель для более удобной работы с меню, но нет ни фронтенда, ни опций. Поэтому нет смысла регистрировать этот компонент и показывать в списке.

Потом одним SQL-запросом загружаются (Database_SQL 18) и сохраняются в памяти все включённые пункты всех меню. Это сделано для увеличения скорости движка, чтобы не лазить в БД для каждого меню отдельно.

После получения списка пунктов текущего меню происходит событие ‘menu_before_list’ (Event 31), позволяющее добавить, удалить или изменить эти пункты.

И последний этап – рендеринг меню (Template 13-14). Видно, какие файлы шаблонов при этом используются.
В это время возникает ещё пара событий (Event 32-33), которые позволяют откорректировать html-код меню. Таким образом, благодаря событиям можно не изменяя файлы движка или чужих компонентов изменять любое меню по своему желанию.
Если интересно, можете отдельно почитать «Что такое события и хуки».

В итоге статус виджета в строке его окончания (Widget 1 end): «Выведен на страницу». Всё в порядке!

На что ещё можно обратить внимание. В строке окончания виджета видно время его работы – 10.96 мс (это на моём компе, на вашем будет другое). То есть, сразу видно, насколько данный виджет «утяжеляет» страницу.
При этом время составляющих его частей (подключение файлов, рендеринг и т.п.) вполовину меньше. На что ушло остальное время? В данном случае больше 6 мс ушло на кеширование полученных из БД пунктов всех меню и обработку пунктов этого меню. На скрине таймкоды начала и окончания этого процесса выделены оранжевыми рамками. Таким образом разработчики смогут увидеть «тяжёлые» места своих виджетов (и других продуктов).

Виджет использовал 206 Кбайт памяти. Подпись ‘end’ возле этих цифр говорит о том, что превышения пика памяти предыдущих этапов не было, поэтому память считалась как разница между значениями в начале и в конце виджета. Если бы во время работы виджета был достигнут новый пик памяти, то подпись была бы ‘peak’ и использованная память вычислялась бы как разница между этим пиком и значением памяти при старте виджета.

Виджет «Категории контента»

Давайте посмотрим на виджет «Категории контента». Его работа выглядит так же, как и виджета «Нижнее меню», только отсутствует загрузка класса работы с виджетами. Всё идет по плану 😊
У этого виджета в строке лога присутствуют не только заголовок и имя, а и имя компонента, к которому относится виджет – ‘content’ (оно выделено розовым цветом, как и везде в отладке). Это не общий виджет.

Его файлы находятся в папках компонента ‘content’. Например, класс виджета /system/controllers/content/widgets/categories/widget.php, а его шаблон в /templates/default/controllers/content/widgets/categories/categories.tpl.php

Виджет «Войти на сайт» — не выведен

А вот у виджета «Войти на сайт», очевидно, что-то пошло не так. Во-первых, слишком мало строк в логе, а во-вторых, его статус в строке окончания – «Не выведен». Что произошло?
Включим показ данных и результатов для виджетов. Данные виджету переданы. Но поскольку я открываю страницу, войдя на сайт как администратор, класс виджета возвращает результат FALSE, а это значит, что рендерить и выводить виджет на страницу не нужно. Всё просто.

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

Виджет «Меню пользователя» — много памяти

И рассмотрим ещё один виджет «Меню пользователя». Весь его лог длинный, поэтому посмотрим только на окончание.
На нижней строке лога (окончание виджета) видим большое потребление памяти – 898 Кбайт по пику. Чуть выше я выделил зелёным фоном хук ‘menu_admin’, который съел половину памяти виджета – 449 КБайт. Оба значения я на скрине выделил оранжевыми рамками.

Получается, что это очень тяжёлый, не оптимизированный виджет с точки зрения памяти? Нет, виджет оптимизирован. Просто хук ‘menu_admin’ должен возвращать пункты меню администратора сайта, если они доступны пользователю. А для этого нужно загрузить и запустить некоторые «тяжёлые» файлы Админки: фронтенд, модель и языковой файл. Что мы и видим в самом начале скрина (Include 74-75, Autoload 38). Так что понимаем это и успокаиваемся — всё в порядке, так и должно быть.
Это был просто ещё один пример анализа кода для разработчиков.


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

Еще от автора

Хуки-хухуки: Исключаем неактивных пользователей из списков
Как иногда начинают свой монолог неопытные стендаперы: «У всех в жизни было такое …
«Расширенная отладка» для InstantCMS 2.14.1 (v.14.1.2) – большое обновление для разработчиков
Новые возможности и удобства, облегчающие разработчикам отладку компонентов и шаблонов.
Использование расширенной отладки. Часть 11. Анализ ошибок 403/404 и редиректов
Одной из неудобных задач при отладке для меня является поиск причины ошибки 403/404.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.