Лучший способ сжать HTML, CSS & JS с mod_deflate и отключенным mod_gzip

8
задан Charles Roper 7 September 2008 в 16:23
поделиться

5 ответов

Извините за задержку - это - напряженная неделя для меня.

Предположения:

  • .htaccess находится в том же файле как compress.php
  • статические файлы, которые будут сжаты, находятся в static подкаталог

Я запустил свое решение с установки следующих директив в .htaccess:

RewriteEngine on
RewriteRule ^static/.+\.(js|ico|gif|jpg|jpeg|png|css|swf)$ compress.php [NC]

Требуется, что Ваш поставщик позволяет Вам переопределять mod_rewrite опции в .htaccess файлы. Затем сам compress.php файл может быть похожим на это:

<?php

$basedir = realpath( dirname($_SERVER['SCRIPT_FILENAME']) );
$file = realpath( $basedir . $_SERVER["REQUEST_URI"] );

if( !file_exists($file) && strpos($file, $basedir) === 0 ) {
    header("HTTP/1.0 404 Not Found");
    print "File does not exist.";
    exit();
}

$components = split('\.', basename($file));
$extension = strtolower( array_pop($components) );

switch($extension)
{
    case 'css':
        $mime = "text/css";
        break;
    default:
        $mime = "text/plain";
}

header( "Content-Type: " . $mime );
readfile($file);

Необходимо, конечно, добавить больше типов пантомимы к оператору переключения. Я не хотел делать иждивенца решения на pecl fileinfo расширение или любые другие волшебные библиотеки обнаружения типа пантомимы - это - самый простой подход.

Что касается обеспечения сценария - я делаю перевод в реальный путь в файловой системе, таким образом, не взломанной '../../../etc/passwd' или другие пути к файлам сценария оболочки, не проходит.

Это

$basedir = realpath( dirname($_SERVER['SCRIPT_FILENAME']) );
$file = realpath( $basedir . $_SERVER["REQUEST_URI"] );

отрывок. Хотя я вполне уверен большинство путей, которые находятся в другой иерархии, чем $basedir будет обработан Apache, прежде чем они даже достигнут сценария.

Также я проверяю, ли получающийся путь в дереве каталогов сценария. Добавьте заголовки для управления кэшем как pilif предложенный, и у Вас должно быть рабочее решение Вашей проблемы.

7
ответ дан 5 December 2019 в 12:15
поделиться

Что я делаю:

  • Я помещаю сценарии в a js и таблицы стилей в a css dir, соответственно.
  • В конфигурации Apache я добавляю директивы как так:

    <Directory /data/www/path/to/some/site/js/>
        AddHandler application/x-httpd-php .js
        php_value auto_prepend_file gzip-js.php
        php_flag zlib.output_compression On
    </Directory>
    <Directory /data/www/path/to/some/site/css/>
        AddHandler application/x-httpd-php .css
        php_value auto_prepend_file gzip-css.php
        php_flag zlib.output_compression On
    </Directory>
    
  • gzip-js.php в js каталог похож на это:

    <?php
        header("Content-type: text/javascript; charset: UTF-8");
    ?>
    
  • … и gzip-cs.php в css каталог похож на это:

    <?php
        header("Content-type: text/css; charset: UTF-8");
    ?>
    

Это не может быть самым изящным решением, но это несомненно - простое, которое требует немногих изменений и работ хорошо.

4
ответ дан 5 December 2019 в 12:15
поделиться

что когда-либо Вы делаете, быть осторожными относительно кэширования на стороне клиента:

Браузеры действительно все сортируют приемов, чтобы попытаться минимизировать bandwith и существует много путей в протоколе HTTP, чтобы сделать это, со всеми из которых имеет дело апач - если Вы просто служите локальному файлу.

Если Вы не, то это - Ваша ответственность.

Взгляните, по крайней мере, на Завершающий тег и механику If-Modified-Since, которые поддерживаются всеми текущими браузерами и, кажется, самый устойчивый способ запросить сервер для обновленного содержания.

Возможный способ служить файлу CSS браузерам с помощью If-Modified-Since-Header является чем-то вроде этого (пустые заголовки для выключения любых заголовков некэширования, которые PHP отправляет на значение по умолчанию):

$p = 'path/to/css/file'
$i = stat($p);
if ($_SERVER['HTTP_IF_MODIFIED_SINCE']){
    $imd = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
    if ( ($imd > 0) && ($imd >= $i['mtime'])){
        header('HTTP/1.0 304 Not Modified');
        header('Expires:');
        header('Cache-Control:');
        header('Last-Modified: '.date('r', $i['mtime']));
        exit;
    }
}
header('Last-Modified: '.date('r', $i['mtime']));
header('Content-Type: text/css');
header('Content-Length: '.filesize($p));
header('Cache-Control:');
header('Pragma:');
header('Expires:');
readfile($p);

Код будет использовать if-modified-since-header, который браузер отправляет в проверку, если фактический файл на сервере изменился начиная с даты браузер дал. Если так, файл отправляется, иначе, 304, Не Измененные, возвращается, и браузер не должен повторно загружать целое содержание (и если это достаточно интеллектуально, это имеет в наличии проанализированный CSS в памяти также).

Существует другой механик, включающий сервер, отправляющий уникальный Заголовок завершающего тега за каждой частью содержания. Клиент отправит ту спину с помощью заголовка If-None-Match, позволяющего сервер решить не только в день последнего изменения, но также и на самом содержании.

Это просто делает код более сложным, хотя, таким образом, я пропустил его. FF, IE и Opera (вероятно, Safari также) все отправляют заголовок If-Modified-Since, когда они получают содержание с Измененным в последний раз присоединенным заголовком, таким образом, это хорошо работает.

Также имейте в виду, что определенные версии IE (или Время выполнения JScript он использует) все еще имеют проблемы с GZIP-переданным содержанием.

О. И я знаю, что это не часть вопроса, но также - Acrobat в некоторых версиях. У меня были случаи и случаи белых экранов при обслуживании PDFs с кодированием передачи gzip.

1
ответ дан 5 December 2019 в 12:15
поделиться

Можно попытать счастья с mod_rewrite.

Создайте сценарий, который берет локальное статическое имя файла, как введено, через например. $_SERVER['QUERY_STRING'] и выводы это в сжатой форме. Многие поставщики не позволяют настраивать mod_rewrite с .htaccess файлам или отключили его полностью все же.

Если Вы не использовали, переписывают прежде, я рекомендую руководству хорошего новичка, как, вероятно, этот. Таким образом, можно сделать апачское перенаправление всеми запросами на статический файл к сценарию PHP. style.css будет перенаправлен к compress.php? style.css, например.

Как всегда быть чрезвычайно осторожными относительно входа Вы принимаете, или Вы имеете XSS используйте на руках!

1
ответ дан 5 December 2019 в 12:15
поделиться

Вместо gzipping на лету, когда пользователи запрашивают CSS и JavaScript файлы, вы можете gzip их заранее. Пока Apache обслуживает их с правильными заголовками, вы золотой.

Например, в Mac OS X, gzipping файла в командной строке так же просто, как:

gzip -c styles.css > styles-gzip.css

Может быть, это не тот тип рабочего процесса, который работает на вас.

.
1
ответ дан 5 December 2019 в 12:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: