Оптимизация сайта для PageSpeed

Оптимизация сайта для PageSpeed

Задача

Провести оптимизацию выдачи контента Битрикс, контроль качества оптимизации провести при помощи PageSpeed Insights.

Решение

Инструменты для проверки скорости

Сервисы оптимизации изображений

Общие рекомендации

  • 1) Привести в соответствие изображения, таким образом, что бы браузеру не приходилось их масштабировать
  • 2) Включить сжатие файлов в nginx
  • 3) При помощи настроек битрикс перенести js и css в конец страницы
  • 4) Минифицировать js и css при помощи gulp или иными средствами
  • 5) Исключить служебные скрипты и стили битрикс из формирования пользовательских страниц сайта
  • 6) Минифицировать html

Перенос js и css в конец страницы

JS

Для корректной работы битрикс с файлами стилей и скриптов их нужно подключать при помощи функций Битрикс:

<?php
$asset = \Bitrix\Main\Page\Asset::getInstance();

// подключение стилей 
$asset->addCss(SITE_TEMPLATE_PATH.'/some.css');

// подключение скриптов
$asset->addJs(SITE_TEMPLATE_PATH.'/some.js');

// подключение произвольных кусков кода
$asset->addString('<link rel="canonical" href="https://'.$_SERVER['HTTP_HOST'].$APPLICATION->GetCurPage(false).'"/>');

Для объединения всех стилей и скриптов в единый файл нужно в настройках Битрикс Настройки -> Настройки продукта -> Настройки модулей -> Главный модуль активировать галки Объединять CSS файлы и Объединять JS файлы

Так же можно проставить галки Создавать сжатую копию объединенных CSS и JS файлов и Переместить весь Javascript в конец страницы

Программно опцию “Переместить весь Javascript в конец страницы” можно активировать так:

$asset->setJsToBody(true);

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

Не все скрипты нужно помещать в футер. например tagManager от гугла должен быть вверху. Для исключения скрипта из переносимых нужно добавить атрибут data-skip-moving=true в тег script. Пример:

<script data-skip-moving="true">
  // your script code
</script>

CSS

Для переноса CSS в конец страницы у Битрикса нет стандартных средств, но т.к. за вывод css отвечает отдельный метод, то мы можем вывести его в footer.php самостоятельно.

Для этого нужно вместо:

<?php
$APPLICATION->ShowHead();
?>

В файле header.php добавить:

<?php
// вместо $APPLICATION->ShowHead();
$bXhtmlStyle = true;
echo '<meta http-equiv="Content-Type" content="text/html; charset='.LANG_CHARSET.'"'.($bXhtmlStyle? ' /':'').'>'."\n";
$APPLICATION->ShowMeta('robots', false, $bXhtmlStyle);
$APPLICATION->ShowMeta('keywords', false, $bXhtmlStyle);
$APPLICATION->ShowMeta('description', false, $bXhtmlStyle);
$APPLICATION->ShowLink('canonical', null, $bXhtmlStyle);
$APPLICATION->ShowHeadStrings();
$APPLICATION->ShowHeadScripts();
?>

В файле footer.php добавить:

<?php
$APPLICATION->ShowCSS(true, $bXhtmlStyle);
?>

Исключить служебные скрипты и стили битрикс из формирования пользовательских страниц сайта

Для этого нужно добавить обработку контента страницы перед выдачей его из буфера браузеру.

В init.php должно быть добавлено подключение файлов констант, обработчиков и функций, т.к. все действия уже будем совершать с ними.

Пример подключения файлов в init.php:

<?php
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();

// Подключение констант
if(file_exists($_SERVER['DOCUMENT_ROOT'].
'/local/php_interface/include/constants.php'))
{
require_once($_SERVER['DOCUMENT_ROOT'].
'/local/php_interface/include/constants.php');
}

// Подключение обработчиков событий
if(file_exists($_SERVER['DOCUMENT_ROOT'].
'/local/php_interface/include/handlers.php'))
{
require_once($_SERVER['DOCUMENT_ROOT'].
'/local/php_interface/include/handlers.php');
}

// Подключение глобальных функций (чаще всего используется для переноса кода сторонних разработчиков
// при получении проекта на доработку)
if(file_exists($_SERVER['DOCUMENT_ROOT'].
'/local/php_interface/include/functions.php'))
{
require_once($_SERVER['DOCUMENT_ROOT'].
'/local/php_interface/include/functions.php');
}

В файл functions.php добавим функции обработчиков событий:

<?php
// удаляем скрипты ядра при отдаче сайта пользователям
function deleteKernelJs(&$content) {
    global $USER, $APPLICATION;
    if((is_object($USER) && $USER->IsAuthorized()) || strpos($APPLICATION->GetCurDir(), '/bitrix/')!==false) return;
    if($APPLICATION->GetProperty('save_kernel') == 'Y') return;

    $arPatternsToRemove = Array(
        '/<script.+?src=".+?kernel_main\/kernel_main\.js\?\d+"><\/script\>/',
        '/<script.+?src=".+?bitrix\/js\/main\/core\/core[^"]+"><\/script\>/',
        '/<script.+?>BX\.(setCSSList|setJSList)\(\[.+?\]\).*?<\/script>/',
        '/<script.+?>if\(\!window\.BX\)window\.BX.+?<\/script>/',
        '/<script[^>]+?>\(window\.BX\|\|top\.BX\)\.message[^<]+<\/script>/',
    );

    $content = preg_replace($arPatternsToRemove, '', $content);
    $content = preg_replace("/\n{2,}/", "\n\n", $content);
}

// удяляем css ядра при отдаче сайта пользователям
function deleteKernelCss(&$content) {
    global $USER, $APPLICATION;
    if((is_object($USER) && $USER->IsAuthorized()) || strpos($APPLICATION->GetCurDir(), "/bitrix/")!==false) return;
    if($APPLICATION->GetProperty('save_kernel') == 'Y') return;

    $arPatternsToRemove = Array(
        '/<link.+?href=".+?kernel_main\/kernel_main\.css\?\d+"[^>]+>/',
        '/<link.+?href=".+?bitrix\/js\/main\/core\/css\/core[^"]+"[^>]+>/',
        '/<link.+?href=".+?bitrix\/templates\/[\w\d_-]+\/styles.css[^"]+"[^>]+>/',
        '/<link.+?href=".+?bitrix\/templates\/[\w\d_-]+\/template_styles.css[^"]+"[^>]+>/',
    );

    $content = preg_replace($arPatternsToRemove, '', $content);
    $content = preg_replace("/\n{2,}/", "\n\n", $content);
}

В файл handlers.php добавим обработку событий:

<?php
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();

$eventManager = \Bitrix\Main\EventManager::getInstance();

// удяляем скрипты ядра при отдаче сайта пользователям
$eventManager->addEventHandler('main', 'OnEndBufferContent', 'deleteKernelJs');

// удяляем css ядра при отдаче сайта пользователям
$eventManager->addEventHandler('main', 'OnEndBufferContent', 'deleteKernelCss');