Оптимизация. Загружаем важный CSS инлайном
Запись от 07.06.2014
Сервис PageSpeed от Google дает рекомендацию удалять из верхней части страницы блокирующий код, в том числе и подключение CSS файлов - их загрузка блокирует отображение HTML.
Проблема в том, что если мы перенесем подключение CSS к </body>, то сначала посетитель увидит страницу с дефолтными стилями браузера, затем страница моргнет и применятся стили от сайта.
Что бы этого избежать необходимо в отдельный файл CSS выписать все правила, которые нужны для отображения первого экрана, затем из файла загрузить их инлайново в области HEAD, таким образом парсинг страницы браузером будет последовательным и быстрым.
Естественно, что будет лучше, если файл будет сжат в одну строку, удалены все лишние пробелы и знаки табуляции.
Для решения этих задач я делаю следующее:
1. Выделяю в отдельный файл все необходимые стили для первого экрана;
2. Добавляю в /bitrix/php_interface/page_speed.php следующий код:
Здесь includeCSS проверяет, есть ли сжатая версия CSS, если нет, то создает её и выводит с помощью echo. А compressCSS удаляет много лишнего из CSS (но не всё, т.к. функция требует дополнительной отладки и проверки на множестве реальных проектах).
В области head страницы меняю $APPLICATION->SetAdditionalCSS на includeCSS. Все. Profit!
UPD1: Вариант использовать в готовых решениях по-быстрому: в папку с шаблоном кидаем functions.php с вышеописанным кодом, а в header.php пишем:
UPD2: Обратите внимание: редактор битрикса порезал код, в своем файле замените "st yle" на "style"
UPD3: Обновил код. Теперь, при обновлении исходного CSS файла обновляется и кеш, удаляя старые версии кеша.
UPD4: Подумал тут... надо бы сампоальное кеширование заменить штатным от битрикса. Так будет только лучше и надежнее. Не пойму, почему сразу так не сделал :)
Проблема в том, что если мы перенесем подключение CSS к </body>, то сначала посетитель увидит страницу с дефолтными стилями браузера, затем страница моргнет и применятся стили от сайта.
Что бы этого избежать необходимо в отдельный файл CSS выписать все правила, которые нужны для отображения первого экрана, затем из файла загрузить их инлайново в области HEAD, таким образом парсинг страницы браузером будет последовательным и быстрым.
Естественно, что будет лучше, если файл будет сжат в одну строку, удалены все лишние пробелы и знаки табуляции.
Для решения этих задач я делаю следующее:
1. Выделяю в отдельный файл все необходимые стили для первого экрана;
2. Добавляю в /bitrix/php_interface/page_speed.php следующий код:
function includeCSS($path) {
$sCacheFileName = str_replace(Array("/"), "__", $path)."_".filemtime($_SERVER["DOCUMENT_ROOT"].$path).".css";
$sCacheFilePathDir = "bitrix/cache/include-css/".SITE_ID."/".SITE_TEMPLATE_ID;
$sCacheFilePathUrl = "/".$sCacheFilePathDir."/".$sCacheFileName;
$sCacheFilePathServer = $_SERVER["DOCUMENT_ROOT"].$sCacheFilePathUrl;
if(file_exists($sCacheFilePathServer)) {
$sCacheFileContent = file_get_contents($sCacheFilePathServer);
echo '<st yle type="text/css">'.$sCacheFileContent.'</style>';
} else {
/* del old cache */
$sFullPathCache = $_SERVER["DOCUMENT_ROOT"]."/".$sCacheFilePathDir."/";
if($handle = opendir($sFullPathCache)) {
while(false !== ($file = readdir($handle))) {
if($file != "." && $file != "..") unlink($sFullPathCache.$file);
}
closedir($handle);
}
$sContentCSS = file_get_contents($_SERVER["DOCUMENT_ROOT"].$path);
$sContentCSS_compressed = compressCSS($sContentCSS);
if(is_dir($sCacheFilePathDir)) {
file_put_contents($sCacheFilePathServer, $sContentCSS_compressed);
echo '<st yle type="text/css">'.$sContentCSS_compressed.'</style>';
} else {
if(mkdir($sCacheFilePathDir, 0777, true)) {
file_put_contents($sCacheFilePathServer, $sContentCSS_compressed);
echo '<st yle type="text/css">'.$sContentCSS_compressed.'</style>';
}
}
}
}
function compressCSS($css) {
$sResult = preg_replace("/\/\*[^*]+\*\//", "", $css); // comments
$sResult = preg_replace("/\s*(:|,|;|{|}|\t)\s*/", "$1", $sResult); // whitespaces
$sResult = preg_replace("/(\t+|\s{2,})/", "", $sResult); // tabs and double whitespace
return $sResult;
}
Здесь includeCSS проверяет, есть ли сжатая версия CSS, если нет, то создает её и выводит с помощью echo. А compressCSS удаляет много лишнего из CSS (но не всё, т.к. функция требует дополнительной отладки и проверки на множестве реальных проектах).
В области head страницы меняю $APPLICATION->SetAdditionalCSS на includeCSS. Все. Profit!
UPD1: Вариант использовать в готовых решениях по-быстрому: в папку с шаблоном кидаем functions.php с вышеописанным кодом, а в header.php пишем:
require $_SERVER["DOCUMENT_ROOT"]."/bitrix/php_interface/page_speed.php";
includeCSS(SITE_DIR."/css/style.css");
UPD2: Обратите внимание: редактор битрикса порезал код, в своем файле замените "st yle" на "style"
UPD3: Обновил код. Теперь, при обновлении исходного CSS файла обновляется и кеш, удаляя старые версии кеша.
UPD4: Подумал тут... надо бы сампоальное кеширование заменить штатным от битрикса. Так будет только лучше и надежнее. Не пойму, почему сразу так не сделал :)