Как сжимать CSS
07 Apr, 2005Иногда на больших сайтах размер CSS файла вырастает до 20 килобайт и больше. Несмотря на то что он кэшируется, есть способ все же сжать сам файл. Этот пост практически перевод статьи "The Definitive Post on Gzipping your CSS" написанной Mike Papageorge.
Здесь я опишу методы сжатия CSS файла на 70-80% с помощью PHP. Вообще говоря это можно сделать и без PHP, лишь используя модули апача: mod_gzip или mod_deflate. То как это можно сделать описано тут. Если же доступа к конфигурации у вас нет (как часто бывает на хостингах), то можно воспользоваться одним из нижеследующих методов.
Собственно сжатие
Для сжатия понадобится вот такой кусочек кода<?php ob_start ("ob_gzhandler"); header("Content-type: text/css; charset=UTF-8"); header("Cache-Control: must-revalidate"); $offset = 60 * 60 ; $ExpStr = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT"; header($ExpStr); ?>Этот код делает следующее:
- Использует PHPшный ob_gzhandler для посылки сжатых данных. Эта функция сначала проверит может ли броузер принимать контент типа 'gzip,deflate' encoding;при отрицательном ответе посылает несжатые данные.
- Посылает header с content type и кодировкой файла - здесь это text/css и UTF-8.
- Далее проверяет надо ли уже обновлять кэш для этого файла
- Посылает информацию о том, сколько хранить файл в кэше до следующей загрузки.
Метод первый
Первый метод заключается в переименовании вашего CSS файла в.php
. При этом прикрепление к страничке будет выглядеть так:
@import url(mycss.php);Ну и в начало файла нужно добавить кусочек кода указанный выше.
Метод второй
Второй метод чуть более универсальный. Тут не надо будет ничего менять в CSS файлах. Однако он требует правки .htaccess файла. Во-первых нужно сохранить код указанный выше, например в файл "gzip-css.php". А затем добавить в .htaccess файл следующие строки:AddHandler application/x-httpd-php .css php_value auto_prepend_file gzip-css.php php_flag zlib.output_compression On
Пример
Я применил первый метод на зеркале ukr.net по адоесу http://alegol.ukr.net/. Результат себя полностью оправдал. Поскольку доступа к логам у меня нет, то я воспользовался сервисом websiteoptimisation. Результаты можно увидеть по адресам: alegol, ukr.net В результате размер CSS файла упал с 18Кб до 4.5Кб. Жаль нельзя логи посмотреть и узнать как оно на самом деле работает при массовых нагрузках.Заключение
100% очень полезная штука особенно когда нет контроля над веб-сервером.Однако есть несколько недочетов. Ходят слухи что есть какой то глюк в одной из версий ИЕ6, якобы он посылает инфу что может читать gzip, но на самом деле не раскодирует контент такого типа. Если кто то заметит подобный глюк или что то слышал об этих случаях просьба откликнуться в комменты.
Надо только еще перепроверить как оно нагружает сервер, ну а малым и средним сайтам 100% мастду.
Мну удалось найти такую инфу.
Unfortunately, IE6 (and perhaps earlier versions?) appears to have a bug with gzip over SSL where the first 2048 characters are not included in the HTML rendering of the page when refresh is pressed. It only seems to happen on longish pages, and not when the page is first loaded. In fact, sometimes it doesn't happen at all. The only current solution is to put a 2048 character comment at the start of your longish pages of all spaces (which compresses pretty well, fortunately).
Однако тут имелись ввиду ХТМЛ файлы и апачевское сжатие, поэтому не знаю имеет ли это отношение к нашему случаю.
*/ // assume that REQUEST_URI contains short URI from document root $file = $_SERVER['DOCUMENT_ROOT'].$_SERVER['REQUEST_URI']; // we don't have to warn about file existing because rewrite rule guarantees that. if (($content = file_get_contents($file)) !== false) { // handle HTTP request header If-Modified-Since (simulating static content) $lastmod = filemtime($file); if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { $modsince = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']); if ($modsince != -1 && $modsince == $lastmod) { header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); header('Content-Type: text/css'); exit(); } } $maxAge = 3600 * 24; header('Expires: '.gmdate("D, d M Y H:i:s", time() + $maxAge) . " GMT"); header('Cache-Control: public; max-age='.$maxAge); header('Last-Modified: '.gmdate("D, d M Y H:i:s", $lastmod) . " GMT"); header('Content-Type: text/css'); // output CSS file ob_start('gz_handler'); echo $content; ob_end_flush(); } else // we should never reach this condition (only if some hardware error) echo "Read file error"; ?>