Генератор форм

Для веб-мастера

Реклама

Разгони свой сайт. Статическое сжатие css- и js- файлов на лету!

Рейтинг:
Дата: 11 апреля 2011 Просмотры 46346 Комментарии 19

В сегодняшней статье я расскажу Вам об одном из способ ускорения загрузки Ваших сайтов, а именно мы будем сжимать css и js файлы. Хочу обратить Ваше внимание, что все это будете происходить автоматически, без Вашего участия, а оригинал файла всегда будет не изменным!

Алгоритм работы скрипта будет следующий:

  1. Объединяем все css- или js-файлы в один
  2. Создаем сжатую версию этого файла (причем только тогда, когда в оригинале были произведены какие-либо изменения)
  3. Реализовываем автоматическую отдачу сервером актуальной версии файла (в сжатом виде, если это поддерживает браузер)
  4. Если браузер  закэшировал этот файл, то берем из кэша браузера

Итак, с целями и задачами разобрались. Теперь переходим непосредственно к созданию скрипта, который будет выполнять все эти действия. Для этого в корне сайта, создадим новый php-файл и назовем его mini.php.

Так как один скрипт должен обрабатывать и js- и css-файлы, то ему нужно передавать помимо самих файлов еще и тип этих файлов. Выглядеть это будет примерно так:

<link href="mini.php?type=css&files=reset,standart,style" rel="stylesheet" type="text/css">

 

или так:

<script type="text/javascript" src="mini.php?type=javascript&files=script,ajax"></script>

 

Теперь в нашем скрипте будут доступны такие переменные:

$_GET['type'] — будет содержать тип файлов
$_GET['files'] — через запятую, список файлов, которые нужно объединить и сжать

Следующим шагом необходимо задать директории для хранения кэша, js- и css-файлов:

// Папка для хранения кэша
$cachedir = dirname(__FILE__) . '/cache';
// Папка где расположены css-файлы
$cssdir   = dirname(__FILE__) . '/styles';
// Папка где расположены js-файлы
$jsdir    = dirname(__FILE__) . '/js';

 

Относительно этих директорий и необходимо указывать путь к файлам при подключении.

Далее проверим были ли переданы файлы скрипту:

//Если файлы не переданы выводим 404 ошибку
if (!isset($_GET['files']) or strlen($_GET['files']) == 0)
{
    header('Status: 404 Not Found');
    exit();
}

 

Теперь проверим существует ли директория для хранения кэша и если её нет, то создаем её:

if (!file_exists($cachedir))
{
    mkdir($cachedir);
}

 

Следующим шагом определяем абсолютный путь к папке с файлами в зависимости от типа файлов:

$type = $_GET['type'];

switch ($type) {
    case 'css':
        $base = realpath($cssdir);
        break;
    case 'javascript':
        $base = realpath($jsdir)
        break;
    default:
        header ("HTTP/1.0 503 Not Implemented");
        exit;
}

 

Так как мы передаем файлы без расширения, то необходимо написать функцию, которая будет автоматически добавлять к каждому файлу расширение в зависимости от его типа:

function addExtension($file,$type)
{
    if ($type == 'javascript' && substr($file, -3) !== '.js'){
        $file .= '.js';
    } 
    elseif($type == 'css' && substr($path, -4) !== '.css') {
        $file .= '.css';
    }

    return $file;
}

 

Используя эту функцию, сформируем массив файлов:

//Получаем массив файлов
$files = explode(',', $_GET['files']);
$types = array_fill(0,sizeof($files),$type);

// Добавляем разширение для переданных файлов
$files = array_map('addExtension',$files,$types);

 

Далее проверяем существуют ли переданные файлы на сервере и получаем время последнего редактирования

$lastmodified = 0;

foreach ($files as $file){
    $path = realpath($base.'/'.$file);

    if (!file_exists($path)) {
        header ("HTTP/1.0 404 Not Found");
        exit;
    }

    $lastmodified = max($lastmodified, filemtime($path));   
}

 

Создаем хэш файлов и отправляем браузеру Etag заголовок:

$md5 = md5($_GET['files']);
$hash = $lastmodified . '-'.$md5;

header ("Etag: \"" . $hash . "\"");

if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == '"' . $hash . '"')
{
    header ("HTTP/1.0 304 Not Modified");
    header ('Content-Length: 0');
    exit;
}

 

Теперь мы подошли к самому интересному. Нам необходимо объединить все файлы в один, вырезать из него все комментарии, переносы строк, табуляцию. Если браузер пользователя поддерживает GJIP-сжатие, то сжать его и автоматически отдать его в браузер.

Итак, определяем метод сжатия:

$gzip = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
$deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate');

$encoding = $gzip ? 'gzip' : ($deflate ? 'deflate' : 'none');

if (!strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') && preg_match('/^Mozilla\/4\.0 \(compatible; MSIE ([0-9]\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches)) {
    $version = floatval($matches[1]);

    if ($version < 6)
        $encoding = 'none';

    if ($version == 6 && !strstr($_SERVER['HTTP_USER_AGENT'], 'EV1'))
        $encoding = 'none';
}

 

Если браузер поддерживает сжатие и существует сжатый файл на сервере, то берем файл из кэша:

$cachefile = 'cache-' .$md5. '.' .(($type === 'css') ? 'css': 'js') . (($encoding != 'none')? '.' . $encoding : '');

if (file_exists($cachedir.'/'.$cachefile) && $lastmodified < filemtime($cachedir.'/'.$cachefile)) {

    if ($encoding != 'none') {
        header ("Content-Encoding: " . $encoding);
    }

    header ("Content-Type: text/".$type);
    header ("Content-Length: " . filesize($cachedir.'/'.$cachefile));

    readfile($cachedir.'/'.$cachefile);
    exit;
}

 

Если сжатый файл не существует на сервере, то формируем его, сжимаем, записываем на сервер и отдаем браузеру:

$contents = '';

foreach ($files as $file){
    $path = realpath($base.'/'.$file);
    $contents .= file_get_contents($path);
}

// Удаляем комментарии, переносы строк, табуляцию, тройные пробелы
if($type === 'css'){

    $contents = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $contents);
    $contents = str_replace(array("\r", "\n", "\t", '   '), '', $contents);
}
else{
    require('jsmin.php');
    $contents = JSMin::minify($contents);
}

// выводим Content-Type файла
header ("Content-Type: text/".$type);

if (isset($encoding) && $encoding != 'none')
{
    // Выводим сжатый файл
    $contents = gzencode($contents, 9, $gzip ? FORCE_GZIP : FORCE_DEFLATE);
    header ("Content-Encoding: " . $encoding);
    header ('Content-Length: ' . strlen($contents));
    echo $contents;
} 
else
{
    // Выводим объединенный файл
    header ('Content-Length: ' . strlen($contents));
    echo $contents;
}

// Записываем в кэш
file_put_contents($cachedir.'/'.$cachefile, $contents);


 

Ну вот собственно и все! Скачать исходники можно здесь!

Оцените эту статью:



Похожие статьи
Интересно почитать

    Получать новые материалы этого сайта на свой email адрес?

    Отправлять мне комментарии по эл. почте?

Простая CRM

Нашли ошибку в тексте

Система Orphus
https://biznesguide.ru/coding/130.html
3,86 из 5 на основе 47 оценок.