Клиентская оптимизация
3 августа 2008

Еще немного о сжатии

В этом топике я постараюсь обобщить материал про сжатие данных. Сжиматься будет css, js, html.

Объединение файлов в модули


Первым шагом к сжатию стало объединение css и js файлов в модули. Каждый модуль содержит список css и js файлов, а также модулей, которые необходимых для собственной работы. Эту информацию я решил хранить в конфиге приложения.
<units>
   <Jquery>
      <js>
         <file>cms/js/Jquery/Core.js</file>
         <file>cms/js/Jquery/Extens.js</file>
      </js>
   </Jquery>
   <Jquery.Facebox>
      <depend>
         <unit>Jquery</unit>
      </depend>
      <js>
         <file>cms/js/Jquery/Facebox.js</file>
         <file>cms/js/Jquery/Pngfix.js</file>
      </js>
      <css>
         <file>cms/js/Jquery/Facebox.css</file>
      </css>
   </Jquery.Facebox>
   <Cms.Core>
      <js>
         <file>cms/js/Cms/Core.js</file>
         <file>cms/js/Cms/Class.js</file>
      </js>
   </Cms.Core>
</units>
* This source code was highlighted with Source Code Highlighter.

Теперь подключить необходимые файлы очень просто. Для этого я написал класс, содержащий статический метод loadUnit(). В зависимости от настроек, он может подключать исходные файлы, либо сохранять их содержимое в один монолитный и подключать его.

Сжатие и минимизация


Я выбрал 3 пакера, указанных в приложении. Для сжатия написан класс, который в зависимости от настроек системы сжимает файлы определенным образом. Сжатию также подвергается HTML. Также, если в настройках включено gzip сжатие, файлы сжимаются методом gzencode().

Кэширование


Чтобы лишний раз не сжимать файлы, можно сохранять два варианта, обычный, и сжатый методом gzip. Эти файлы отдаются напрямую web-сервером, минуя PHP. Чтобы определить, поддерживает ли клиентский браузер сжатие, используем mod_rewrite.
RewriteCond %{HTTP:Accept-Encoding} gzip [OR]
RewriteCond %{HTTP:TE} gzip
RewriteCond %{HTTP_USER_AGENT} !Safari
RewriteCond %{HTTP_USER_AGENT} !Konqueror
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^pack\/(.*)$ /pack/$1.gz [QSA,L]

Если файла нет, перенаправляем запрос скрипту, который создает его, либо устанавливаем обработчик 404 ошибки.

Еще можно добавить…


Сжатие теряет смысл, если у пользователя стоит Outpost. Он автоматически режет заголовок Accept-Encoding, поэтому мы не можем узнать, можно ли отдавать сжатый файл. Эта опция Outpost выключается в реестре, но просить пользователя это сделать не целесообразно. Если пользователь пользуется оперой, то можно использовать заголовок TE, который аналогичен заголовку Accept-Encoding. Для других браузеров я нашел только одно решение – определять возможность сжатия по версии, но из-за неточности этого метода предпочел его не использовать.

HTML на статических сайтах можно кэшировать так же, как Java Script и CSS, отдавая web-сервером браузеру напряму. При изменении данных сбрасывать кэш. Но далеко не всегда на сайтах используется статический контент. Поэтому, приходится сжимать динамически, что не приемлемо на сайтах с высокой посещаемостью. Если на таких сайтах ведется статистика посещаемости, можно использовать эти данные и в часы с низкой нагрузкой отдавать сжатый HTML.

Если не хочется все самому писать и нет необходимости подгонять сжатие под конкретную систему, можно воспользоваться готовой библиотекой Minify.

Приложение


Функция сжатия html (взята с gadelkareem.com):
function htmlCompress($html)
{
   preg_match_all('!(<(?:code|pre|script).*>[^<]+</(?:code|pre|script)>)!',$html,$pre);
   $html = preg_replace('!<(?:code|pre).*>[^<]+</(?:code|pre)>!', '#pre#', $html);
   $html = preg_replace('#<!–[^\[].+–>#', '', $html);
   $html = preg_replace('/[\r\n\t]+/', ' ', $html);
   $html = preg_replace('/>[\s]+</', '><', $html);
   $html = preg_replace('/[\s]+/', ' ', $html);
   if (!empty($pre[0])) {
      foreach ($pre[0] as $tag) {
         $html = preg_replace('!#pre#!', $tag, $html,1);
      }
   }
   return $html;
}   
* This source code was highlighted with Source Code Highlighter.

Используемые минимизаторы:
Dean Edwards JavaScript's Packer
Скрипт сжатия CSS из библиотеки Minify

Ссылки по теме:
Сжатие css и js без потери производительности сервера
CSS: все о сжатии
Практический CSS/JS: архивируем все!
+25
4k 73
Комментарии 17