Напишу-ка я ещё разок про packer. phing, нормы бухгалтерского учёта и ещё про чё-то.
В предыдущей своей чудовищной заметке про компрессию javascript-ов я упоминал perl-версию packer-а Дэна Эдвардса.
Её приходилось запускать через exec (и соответственно нужен perl). А вот совсем недавно нашёл реализацию этого мега-алгоритма на php и даже не одну.
Соответственно первая реализация была “впендюрена” в phing.task.ext.JsPacker.Task, а вторая напомнила о том что давно собирался изложить.
А именно – про gzip-сжатие js-файлов:
Собственно проблем ровно никаких – mod_gzip в apache, gzip on; в nginx и можно тему закрывать. Но как обычно “есть нюансы”: не всегда эти модули установлены на сервере, не всегда их получается установить, ну и главный “нюанс”: файлы статические, закономерно возникает мысль – зачем их упаковывать при каждом запросе? Вот об этом я и хотел рассказать, но не буду ;o)
Собственно решение прямо в лоб – упаковать файлы один раз и “задеплоить” на сервер. Я это(сжатие) делаю с помощью всё того же phing-а, а решение о том какой файл (сжатый или нет) отдать клиенту принимает mod_rewrite:
RewriteEngine on
RewriteRule ^(.*\.js\.gz)$ – [L]
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*)$ $1.gz
Это содержимое .htaccess который лежит в директории с js (или httpd.conf в секции Directory/Location отвечающей за эту же директорию).
Смысл вроде прозрачен, но я поясню – если рядом с файлом moi-super-bolshoy-javascript.js будет находиться его сжатая копия moi-super-bolshoy-javascript.js.gz и в запросе будет явно указано, что клиент поддерживает gzip-encoding, то ему(клиенту) выдадут именно сжатую копию. В противном случае (сжатие не поддерживается или сжатого файла нет) в ответ вернётся оригинальный файл.
В итоге уменьшили трафик сервера(и естественно клиентов) и снизили нагрузку на сервер.
Естественно этот фокус можно (и даже наверное нужно) проделать с css.
P.S.
Далеко не все файлы стоит упаковывать зипом . И не каждый файл стоит упаковывать packer-ом – стоит проверить результат на jsl(int)-ом – не редки случаи “поломки” скриптов. Ну а как упаковать оптимальнее – решать индивидуально с каждым файлом предстоит вам.
Update
А вот нашёлся способ отдачи gzip-ованного контента даже лучший, чем описал я.
А вот эта директива:
%{HTTP:Accept-Encoding}
правильная? Не поделишься ссылкой, откуда ты ее взял?
Из мануала: RewriteCond – чуть ниже под заголовком “Special Notes”
Спасибо – буду знать. А вот Accept-Encoding может содержать только gzip? У меня например браузер отправляет gzip,deflate – второе deflate не помешает совпадению условия? И еще в других скриптах я встречал поддержку MIME-Type x-gzip – что ты думаешь об этом?
GET /jsgz/test.js HTTP/1.1
Accept-Encoding: gzip,deflate
HTTP/1.x 200 OK
Content-Type: application/x-javascript
Content-Encoding: gzip
Про поддержку не понял, поэтому ничего об этом не думаю ;o)
Имелось ввиду, что браузер может отправить заголовок Accept-Encoding: x-gzip, а не Accept-Encoding: gzip,deflate. Наверное, под *nix-ом такое возможно.
GET /jsgz/test.js HTTP/1.1
Host: devserver.lan
Accept-Encoding: x-gzip
HTTP/1.1 200 OK
Content-Type: application/x-javascript
Content-Encoding: x-gzip
Любое вхождение строки gzip в accept-encoding сработает – в мануале недвусмысленно написано, что CondPattern (в данном случае строка gzip) – это регулярное выражение:
is the condition pattern, i.e., a regular expression which is applied to the current instance of the TestString, i.e., TestString is evaluated and then matched against CondPattern.
Т.е. по-другому его можно записать как ^.*gzip.*$
о, спасибо, за подробный explanation, надеюсь мои ламерские вопросы были не очень annoying.
да нет не очень 🙂
даже полезные – узнал новое аглицкое слово “annoying” ;o)
http://csstidy.sourceforge.net/
м? 🙂
привет коллегам
Pingback:Пакуем скрипты автоматически
Похоже на то что нужно – будем смотреть.
В закладках ещё есть Icey’s CSS Compressor – говорят до половины ужимает…
И ещё одна интересная “штучка”.
Привет-привет (мир тесен) ;o)