Авторы InstantCMS 2 подробно описали создание виджетов в разделе документации «Виджеты» и даже наглядно показали весь процесс в видео-туториале «Создание виджета». Цель этого поста – показать работу виджетов сайта «изнутри» не вдаваясь в программистские подробности. Это будет полезно для изучения работы Двойки и для анализа купленных виджетов на тормоза или перерасход памяти.
1. Виджеты обрабатываются после окончания работы основного контроллера страницы. Это сделано для того, чтобы можно было использовать в них полученные контроллером данные.
2. Работу виджетов можно разделить на два этапа: получение/подготовка данных и рендеринг (создание html-кода). Если после первого этапа нет данных для вывода, второй этап не выполняется.
3. Виджеты вычисляются и рендерятся сразу все вместе, последовательно один за другим. Но весь полученный html-код не выводится на страницу сразу, а сохраняется в памяти и подставляется в нужные места шаблона позже во время рендеринга всей страницы.
4. Виджеты могут быть как частью какого-то компонента, так и отдельными (общими). По сути и принципу работы они практически одинаковы, основное отличие в расположении файлов виджета: или в папке компонента, или в отдельной папке widgets. Мы это увидим дальше.
Посмотрим на первый виджет странницы. Им оказалось «Нижнее меню».
Файлы виджета лежат вне папок какого-либо компонента, что ещё раз подтверждает, что это общий виджет. Например, класс виджета /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’. Например, класс виджета /system/controllers/content/widgets/categories/widget.php, а его шаблон в /templates/default/controllers/content/widgets/categories/categories.tpl.php
Так же наблюдаем внутри виджета ошибку подключения языкового файла. Всё правильно, виджет простой и ему достаточно нескольких констант из языковго файла его контроллера, которые были загружены ранее, на этапе проверки авторизации пользователя.
Получается, что это очень тяжёлый, не оптимизированный виджет с точки зрения памяти? Нет, виджет оптимизирован. Просто хук ‘menu_admin’ должен возвращать пункты меню администратора сайта, если они доступны пользователю. А для этого нужно загрузить и запустить некоторые «тяжёлые» файлы Админки: фронтенд, модель и языковой файл. Что мы и видим в самом начале скрина (Include 74-75, Autoload 38). Так что понимаем это и успокаиваемся — всё в порядке, так и должно быть.
Это был просто ещё один пример анализа кода для разработчиков.
Теперь вы знаете, как в общих чертах посмотреть работу новых виджетов и убедиться, что они не будут тормозить ваши сайты.
Введение
Нужно помнить несколько моментов про виджеты.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). Так что понимаем это и успокаиваемся — всё в порядке, так и должно быть.
Это был просто ещё один пример анализа кода для разработчиков.
Теперь вы знаете, как в общих чертах посмотреть работу новых виджетов и убедиться, что они не будут тормозить ваши сайты.