1С-Битрикс

Last-Modified и If-Modified-Since в 1С-Битрикс

Важно: Пример с Cache-Control: public относится только к публичным страницам, которые действительно разрешено кэшировать. Для авторизованных, персонализированных, корзинных и других пользовательских страниц политику кэширования нужно выбирать отдельно.

Среди заголовков, передаваемых сервером, есть Last-Modified — он сообщает дату последнего изменения страницы и используется прежде всего для HTTP-кэширования и условных запросов. Поисковые роботы могут учитывать дату изменения как один из технических сигналов, но сам заголовок не гарантирует и не ускоряет индексацию. HTTP-заголовок Last-Modified указывает последнее изменение страницы. Это необходимо, чтобы браузер или робот понимал, когда страница была изменена. Наряду с этим, клиент(робот или браузер) отправляет серверу заголовок If-Modified-Since с датой последнего изменения страницы(что хранится у клиента), таким образом спрашивая, есть ли изменения или нет. Если дата совпадает, то сервер должен вернуть 304 Not Modified, говоря клиенту, что изменений не было и можно отдавать закешированную страницу. Если же на сайте не настроены эти заголовки или дата не совпадает, то сервер отдает заголовок 200 OK и загружает текущую страницу. Таким образом получается, что если правильно настроить заголовки Last-Modified и If-Modified-Since, то страница не будет загружена сервером, а клиент отдаст из кеша последнюю страницу. Что обоюдно выгодно всем, так как клиент экономит трафик, а сервер свои ресурсы.

Теперь давайте попробуем применить это в битриксе. В 1С-Битрикс такой сценарий обычно требует настройки в коде: одной штатной опции недостаточно, чтобы одинаково обработать статические и динамические страницы. Чтобы все корректно настроить, придется немного покопаться в коде битрикса и прописать все вручную.

Для начала изменим файл init.php. Он находится либо в /bitrix/php_interface/init.php, либо по адресу /local/php_interface/init.php. Если его нигде нет, то создайте его тут /local/php_interface/. В нем надо прописать самое главное - вывод этих заголовков. На других страницах сайта мы объявим глобальную переменную $lastModified, а здесь мы ее будем проверять:

AddEventHandler('main', 'OnEpilog', array('CNetsenseFunction', 'SetLastModified'));
class CNetsenseFunction
{
	public function SetLastModified()
	{
		GLOBAL $lastModified;

		if (!$lastModified) return;

		if ($lastModified)
		{
			header("Cache-Control: public");
			header('Last-Modified: '.gmdate('D, d M Y H:i:s', $lastModified).' GMT');

			if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified) {
				header('HTTP/1.1 304 Not Modified'); exit();
			}
		}
	}
}

Условие if (!$lastModified) return; завершает обработчик, если значение $lastModified не задано. Поэтому он выводит заголовки Last-Modified и Cache-Control только для страниц, где эта переменная установлена заранее. Ниже показано, как задать время изменения для статических страниц и содержимого компонентов.

Теперь нам нужно проставить эту глобальную переменную $lastModified для статических страниц и для динамических.

Для статики, можно прописать в шаблоне сайта код:

GLOBAL $lastModified;
if (!$lastModified){
    $lastModified = strtotime(date("D, d M Y H:i:s", filemtime($_SERVER['SCRIPT_FILENAME'])));
}

Таким образом, если еще не установлена глобальная переменная $lastModified, мы, используя функцию PHP filemtime(), получим дату последнего изменения текущего файла и установим ее в нашу глобальную переменную.

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

Для страниц со списком элементов:

В result_modifier.php

if(!empty($arResult["ITEMS"])){
    $thisTime = strtotime("-5 years", time());
    $thisDate = date("Y-m-d", $thisTime);
	
    foreach ($arResult["ITEMS"] as $key => $arItem){
        if($arItem["DATE_CREATE"] && strtotime($thisDate) < strtotime($arItem["DATE_CREATE"])){
            $thisDate = $arItem["DATE_CREATE"];
        }

        if($arItem["TIMESTAMP_X"] && strtotime($thisDate) < strtotime($arItem["TIMESTAMP_X"])){
            $thisDate = $arItem['TIMESTAMP_X'];
        }
    }

    $this->__component->arResult["LAST_MODIFY"] = $thisDate;
    $this->__component->SetResultCacheKeys(array("LAST_MODIFY"));
}

В component_epilog.php

GLOBAL $lastModified;
$lastModified = strtotime($arResult['LAST_MODIFY']);

Для детальных страниц:

В component_epilog.php

GLOBAL $lastModified;
$thisDate = $arResult["TIMESTAMP_X"] ? $arResult["TIMESTAMP_X"] : $arResult["DATE_CREATE"];

if ($thisDate){
    $lastModified = MakeTimeStamp($thisDate);
}

Чтобы код правильно работал, надо в компонентах указать вывод "Дата создания" и "Дата изменения" элементов. Так же следует полностью сбросить кеш, если он включен. Проверять ответы страницы стоит на сайте last-modified.com

Нужна проверка технического SEO?
SEO-аудит · Техническая SEO-оптимизация

Комментарии

0 комментариев

Комментариев пока нет.

Оставить комментарий

Есть проект или задача?

Расскажите, что нужно разработать, доработать или интегрировать. Разберём задачу и предложим следующий шаг.

Обсудить проект