Ускоряем отдачу страниц
В этой статье я покажу как сделать так, чтобы страница сайта отдавалась со скоростью статической. Всё что нужно — это использовать кэш. Реализаций может быть множество. Я предлагаю через кэширование запросов. Выглядит это так:
- Поступил запрос.
- В событии
OnHandleRequest
проверяем, есть ли для него сохранённая в кэше страница. Если есть, выдаём её пользователю и завершаем работу. Если нет, то идёт полноценная обработка. - В событии
OnWebPageComplete
сохраняем готовую страницу в кэше.
Т.е. запрос пришёл и сразу вернулся результат, значительно сократив путь. Как в магазине ИКЕА — есть специальные проходы (перемычки), позволяющие срезать путь и не проходить весь магазин целиком.
Но как вы уже, наверное, поняли, это полностью готовая страница. Все теги MODX (и кэшированные и некэшированные) распарсены. Поэтому этот приём не подойдёт для страниц с динамическим формированием контента с помощью некэшированных сниппетов и чанков. А также, если у вас логика завязана на плагины. В данном случае очередь до них не дойдёт.
Соответственно нужно исключить и страницы с личной информацией типа страниц с профилем или содержащие id и имя пользователя, токен, почту и т.д. Страница закэширует данные первого пользователя и остальные пользователи получат их вместо своих данных.
Тогда для чего же всё это нужно? А вот для всяких лендингов, справочников, документации, галерей и т.п. Т.е. страниц с минимальной логикой. В принципе, при желании, можно внедрить любые данные. Например, так
$content = str_replace("</body>", "<script> var userID=".user_id().";</script>\n</body>", $content);
Но давайте обо всём по порядку.
Наша задача как можно раньше вернуть ответ пользователю. Поэтому будем использовать событие OnHandleRequest
. Но как вы знаете, когда срабатывает это событие, ресурс ещё не определён. В нашем распоряжении есть только URL запроса. Вот к нему мы и привяжемся. Будем использовать его в качестве ключа для кэша. При первом обращении кэш у нас пустой. Поэтому запрос пройдёт полный путь. И в конце полученная страница сохранится в кэш. Все последующие запросы получат страницу уже из кэша. Дальше события OnHandleRequest
они не пройдут.
Итак, поехали. Создаём плагин. Для примера будем кэшировать все страницы с адресом site.ru/documentation
, site.ru/documentation/page1
и т.п.
switch ($modx->event->name) { case 'OnHandleRequest': if (request()->segment(1) == 'documentation') { // Формируем ключ. Заменяем слеши и тире в URL на подчёркивание $key = str_replace(['/','-'],'_',request()->path()); if ($content = cache($key,'requests')) { // Здесь можно поработать с контентом - что-то добавить или заменить. echo $content; while (ob_get_level() && @ob_end_flush()) {} flush(); exit; } } break; case 'OnWebPageComplete': $content = resource(true)->_output; $key = str_replace(['/','-'],'_',request()->path()); if (!cache($key, 'requests') && request()->match('documentation*')) { // Сохраняем кэш в отдельный раздел cache([$key => $content], 'requests'); } break; }
В папке core/cache/requests
будут появляться файлы типа documentation.cache.php
, documentation_page1.cache.php
, в которых будут лежать готовые страницы.
Если на странице есть какие-то динамические данные типа статистики просмотра и т.п., то можно сохранять кэш на 1 минуту, чтобы почаще обновлять эти данные.
Уверен, многим было бы интересно увидеть результат данной оптимизации. Тестируем страницу документации.
Показатели | Обычный режим MODX | С использование кэша |
---|---|---|
Запросы | 43 | 2 |
Время обработки запросов | 0.0604 s | 0.0004 s |
Время обработки PHP | 0.0890 s | 0.0065 s |
Общее время | 0.1494 s | 0.0069 s |
Память | 4 096 Kb | 2 048 Kb |
Результат говорит сам за себя. Я думаю, многие могут найти у себя страницы, к которым можно применить данную оптимизацию. Кстати, она будет работать и для API запросов — получили запрос, проверили, есть ли для него что в кэше, есть — отдаём, нет — работаем.
Это всё, что я хотел сказать.
П.С. Кстати, хорошая идея для компонента кэширования запросов. Дарю :) А ресурсы для кэширования можно определять через соответствующую ТВшку.
Комментарии ()
Вы должны авторизоваться, чтобы оставлять комментарии.
При сохранении в кэш регуляркой вырезать содержимое этого тега и вставить в него [[!SomeCalculations]].
А перед выводом из кэша распарсить
И таких тегов можно сделать сколько угодно — snippet_mysnippet1, chunk_statistics и т.д.
Также не забываем, что можно запустить любой плагин через $modx->invokeEvent(). Например, тот же Tickets ведёт статистику просмотров в событии OnWebPageComplete. Поэтому вызываем его перед выдачей ответа:
Пример чисто для понимания возможностей.
Очередной полезный функционал.
«О сколько нам открытий чудных....»
тут есть прогрев кэша и хранение сессий, т.к. много компонентов их использует.