По мотивам предыдущего поста о необходимости сжатия составляющих частей сайта – в продолжении рассмотрим также и возможность сжать мелкие изображения. Сразу оговорюсь, что речь идет о мелких статических изображениях, не меняющихся, как правило иконок, которые встречаются почти что на каждой странице сайта.
Вы замечали иногда, что сайт загружается, сайт загрузился. Такой красивый … Но стоит навести на кнопочку – и она подсвечивается через некоторое время, а то и дергается как-то непонятно в первый раз. Или такое: Загружается сайт, а там много мелких изображений … и все постепенно заполняются. А в случае плохой связи – некоторые и не заполняются, вы обновляете страницу – грузятся одни и не грузятся теперь предыдущие … В общем – Ад. Какие есть варианты?
1 Способ. Есть такая технология – спрайты. Мы прочем все мелкие изображения в один графический файл. Один файл качается быстрее чем 10 мелких, да и грузится одинаково, а картинка выбирается сдвигом фона из этого файла. Технология вполне успешная. Она хорошо себя зарекомендовала на стандартных элементах одного размера – кнопках к примеру. И сложно –нужно каждый раз каким- то образом генерить этот спрайт из картинок. Если у какое-то изображение – нужно сделать чуть шире – нужно сдвигать все остальные изображения и прописывать это в скриптах и стилях … бяка в общем. Мы такой вариант рассматривать не будем.
2 Способ. Вы, наверное, знаете - мелкие графические файлы можно включать в CSS файл. Вы также, наверное, знаете, что это фичу поддерживают все браузеры, за исключением IE7 и ниже? По секрету сообщаю, что доля таких браузеров – на сегодняшний день – порядка 1,5% во всем мире. И эта доля стремительно падает. Да и для них можно будет выставить дополнительный файл (костыль), дополняющий оригинальный ссылками на изображения.
По этому – все мелкие и часто используемые графические файлы – будем включать в один CSS. Каким образом это ускорит работу сайта – очевидно. Вместо 10-100 точечных запросов на загрузку изображений – браузер будет тянуть один файл, да еще сжатый при помощи GZIP.
На обращение к каждому файлу тратится множество ресурсов, как у клиента, так и у сервера. Клиенту надо проверить наличие и версию файла у себя в кеше, сделать запрос на сервер. Серверу надо проверить файл у себя, считать его, передать. И так по многу раз для каждого посетителя. Также учитывайте, что у каждого браузера стоит ограничение на одновременное обращение к одному домену – 2 файла.
Функция, которая по всему файлу произведет нужную замену – умещается в 2х строках
function addimages($buffer){
return preg_replace('/url\(([\:-\w\/\.]*)/ie','"url(data:image/".((substr("\\1",-4)==".png")?"png":"gif").";base64,".base64_encode(file_get_contents("\\1"))',$buffer);
}
Она несколько доработана, чем аналогичная на хабре. В частности – работает на вложения в любых каталогах, а также при ссылках через http. Ее еще можно доработать, чтобы программа вносила и не графические части (шрифты например)
Прежде чем пользоваться данным кодом – файл нужно подготовить. Нужно убрать апострофы в адресе (скрипт пока такого не умеет)) url апостоф апостроф. Он там не нужен, а скрипт обрабатывать такое не умеет.
Еще одно действие Вам нужно будет сделать один раз. Если одно изображение используется в нескольких стилях – их нужно собрать в один через запятую и
.style_a,.style_b{
Background-image: url(../images/add.png);
}
Также Вам придется для лучшего эффекта – все конструкции с использованием тега IMG заменить простым фоном. Для семантики – это очень удобно, но не всегда приемлемо. Используйте Display: inline-block
. Если не ошибаюсь – он лучше всех заменяет имеющиеся стили.
А что про старые браузеры. Каждый 80й посетитель – не увидит мелких изображений. Для них мы можем предусмотреть в дополнение к данному файлу стилей – хвост от оригинального. Пусть клиент скушает 2 стиля вместо одного. С точки зрения разделения браузеров – отличить IE7 и ниже от других – не сложно
Условимся, что стили для IE – будут иметь хвост на конце STYLE_IE.CSSGZ
И чтобы нам не содержать у себя 2 копии файлов и вести их одновременно – давайте сделаем условный разделитель, прочитав который скрипт бы самостоятельно вычленил часть с изображениями от остальной части. Пусть это будет строка /****IMAGES****/
И если стиль содержит не только фон – нужно его описывать в секции сверху и в секции снизу.
Теперь – если мы хотим для старых браузеров дополнить изначальный стиль – пишем в HTML строку
<link href="css/style.cssgz" rel="stylesheet" type="text/css" />
<!--[if lte IE 7]><link href="css/style_ie.cssgz" rel="stylesheet" type="text/css" /><![endif]-->
Всем браузерам данная строка будет понятна, а IE7 и ниже – еще и доступна.
Помните наш код? Вот как он будет выглядеть полностью доработанным
<?php
//require 'cssmin-v3.0.1.php';
if ($handle=opendir('.')){
while(false !== ($file=readdir($handle))){
if ($file == '.' or $file == '..' or is_dir($file)) continue;
if (substr($file,-4) != '.css') continue;
$filename=substr($file,0,-4);
$css=file_get_contents($file);
$filepart=explode('/****IMAGES****/',$css);
if (isset($filepart[1]))file_put_contents($filename.'_ie.cssgz',gzencode(compress($filepart[1]),9));
$csscompress=compress($css);
//$csscompress=CssMin::minify($css);
$cssimages=addimages($csscompress);
file_put_contents($filename.'.cssgz',gzencode($cssimages,9));
}
closedir($handle);
}
function compress($buffer){
$buffer=preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!','',$buffer);
return str_replace(array("\r\n","\r","\n","\t",' ',' ',' '),'',$buffer);
}
function addimages($buffer){
return preg_replace('/url\(([\:-\w\/\.]*)/ie','"url(data:image/".((substr("\\1",-4)==".png")?"png":"gif").";base64,".base64_encode(file_get_contents("\\1"))',$buffer);
}
Берегите ресурсы хостинга. Берегите жесткие диски и скрежет головок при чтении кучи мелких файлов. Хостинг и пользователи вам скажут спасибо.
Гость
спасибо. хорошая статья!