gzip, статика и graceful degradation*
Придумал мазу. Если что, она из области «создать себе проблему и героически её забороть».
Кратко: для приближения к нирване достаточно рядом с js|css контентом класть его .gz-копии и этот .htaccess
RewriteEngine on
RewriteRule ^(.*\.gz)$ $1 [L]
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteRule ^(.*)$ $1.gz
AddEncoding x-gzip .gz
AddType application/x-javascript .js
AddType text/css .css
Длинно:
Если вебмастер хочет экономить трафик свой и клиента, обычно он включает в своём апаче сжатие. То есть, берет mod_deflate или mod_gzip, и они сами всё за него делают: смотрят, умеет ли клиент gzip, если умеет, то сжимают данные и подставляют нужные заголовки. Все довольны, все смеются.
Но у такого подхода есть парочка минусов. Первый: сжатие производится динамически. То есть, каждый раз, когда сервер отдает, например, prototype.js, сжималка заново выполняет свою работу. Не то, чтобы это чрезмерно грузит сервер, но неаккуратненько как-то ©
Второй минус заключается в том, что в mod_deflate нельзя отключить режим передачи chunked (disclaimer: точнее, я пока что не нашел, как это сделать). Mod_gzip это как будто умеет, но он не так проверен временем. Чем грозен режим chunked? Да особенно ничем, кроме того, что всенародно нелюбимый браузер™ не всегда его понимает. Если протокол https, данные сжаты, а режим передачи chunked, IE может попытаться использовать файл, не разжимая его (подробности тут).
Первый вариант, который приходит в голову для решения проблемы — при отдаче грамотно сжимать данные скриптом так, чтобы аццкий режим не включался. Собственно, первые полчаса я именно так и бился. Однако, каюсь, ниасилил. При запросе самого файла он прекрасно открывается, но если он подключен к документу — фиг! Даже в опере. Скорее всего, я где-то неоднократно слажал, но это неважно, потому что я придумал способ получше.
Натолкнула меня на идею вот эта статейка. Именно там я увидел фразу "Here since the Javascript is static, which is true for most AJAX applications these days, we can pre-compress which will reduce latency and CPU overhead." То есть, мы радостно отдаём браузеру уже готовый .gz файл и идём готовить что-то изысканное из двух зайцев.
Но как быть с теми клиентами, которые не понимают сжатия? Естественно, для них нужен свой, несжатый файл, который нужно отдавать убогим. Только непонятно, когда который из двух файлов подключать. Смотреть в шаблоне на заголовки HTTP? Не, так мешать уровень протокола и уровень отображения я не согласен : )
Разбираться с заголовками — это работа скорее апача. Конкретнее, mod_rewrite. Он, правда, не слышал о HTTP_ACCEPT_ENCODING, зато спокойно скушает такую конструкцию: %{HTTP:Accept-Encoding}. Немного мучений, и имеем на выходе такую конструкцию для .htaccess:
RewriteEngine on
RewriteRule ^(.*\.gz)$ $1 [L]
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteRule ^(.*)$ $1.gz
Человеческим языком говоря: при запросе не .gz файла приписывать к имени запрашиваемого .gz, если клиент понимает gzip.
Тут встает другая проблема: апач честно говорит клиенту, что отдает не яваскрипт и даже не css, а гзип. IE, конечно, заголовки Content-Type игнорирует, но это не повод расслабляться. Кроме того, откуда браузеру знать, что отправленные ему байты перед употреблением нужно разжать? («Сжатый файл» и «сжато при передаче» — разные вещи все-таки.) Тут нас выручит mod_mime:
AddEncoding x-gzip .gz
AddType application/x-javascript .js
AddType text/css .css
Небольшое пояснение: если вы не знали, в представлении апача у файла может быть несколько расширений. Например, у prototype.js.gz их два: js и gz. Этим мы и пользуемся: если у файла есть расширение gz, то отправляем заголовок Content-Encoding: gzip. А две другие строчки нужны для того, чтобы перекрыть апачевское умолчание «отдавать для .gz файлов Content-Type: application/x-gzip». Мы укажем верный Content-Type.
Естественно, удобнее всего будет, если вы автоматизируете процесс создания .gz-копий. Заодно очень полезно склеивать все однотипные файлы в один (значительно уменьшается число запросов к серверу), и вырезать оттуда всё лишнее: пробелы, комментарии и т.п. Это несложно, jsmin и Vitamin вам в руки.
В результате всех мучений имеем в пять раз меньший объём css+js.
ps: если на полезный контент нет ссылок, его никто никогда не найдёт; иными словами: пеарьте меня, пеарьте! : )
*graceful degradation ~ нормальная работа в том случае, если клиент туп; например, не видит он картинок, но сайтом пользоваться может, или нет у него яваскрипта, но это ему почти не мешает.
комментарии
ex_digital_4:
Может, Prototype разрешат? :)
_arty:
ну уже почти : )
я еще под шумок и scriptaculous пропихну ; )
ex_digital_4:
Злой ты, Арти. Кова-а-арный.
_arty:
и не говори ; )
собсно, я это уже почти сделал
все равно в два раза уменьшился размер скриптов по сравнению с тем, что было. Но мог и в 4 уменьшиться : )
anonym:
во блин арти
эка тебя расплющило
_arty:
ну это лучше, чем когда ничего не хочется делать : )
xabk:
Факт:)
tragati:
Прикольно. Мне понравилось то что ты это все разрюхал. Я сам давно хотел из темы сжатия сделать что-нибудт полезное и пользоваться.
xabk:
Интересно. Спасибо)
xabk:
Сорри, забыл в первом комменте добавить пост в utx)
othamelamed:
(Впечатления переводчика) > > Очень интересно, спасибо. .
_arty:
переводчика?
texhapb: А как быть с IE?
Ведь там были какие-то глобальные проблемы с пожатым контентом, хоть он и типа "Accept-Encoding gzip" (см. здесь и здесь)...
_arty: Re: А как быть с IE?
texhapb: Re: А как быть с IE?
Из 1-й статьи:
Но не все так просто. Текущие версии Netscape 4 (точнее, 4.06–4.08) в заголовке утверждают, что понимают содержимое, сжатое с помощью gzip, однако, на самом деле, не умеют распаковывать эти архивы. Прочие версии Netscape 4 тоже испытывают разнообразные трудности с загрузкой сжатых скриптов и стилей. А значит, мы должны отсекать этих агентов на стороне сервера и подставлять им неупакованный контент. Это довольно просто. Куда интереснее проблемы, возникающие у Internet Explorer (версии с 4 по 6).
Загружая сжатый с помощью gzip JavaScript, Internet Explorer порой некорректно распаковывает его или прерывает распаковку в процессе, отдавая клиенту половину файла. Если для вас критична работоспособность JavaScript, вы должны избегать отсылки сжатых скриптов по запросу IE. Даже в тех случаях, когда IE способен загрузить сжатый JavaScript, он зачастую не кэширует его, независимо от указаний, записанных в тегах (актуально для некоторых версий IE 5.x).
Как быть?
_arty: Re: А как быть с IE?
на мамонта я положил с прибором : )
а про ie рекомендую все-таки почитать приведенную мной ссылку. По крайней мере, для меня в проблемах эксплорера авторитетнее msdn, чем компьютерра и particletree.com, с которого она перевела статью : )
texhapb: Re: А как быть с IE?
Я буду посмотреть.
А чего я за осла держусь - я с позиции "как сделать нормально и продать клиенту". А эти гады даже про IE ни сном ни духом, и на стандарты им ложить. А с позиции науки твой подход лучше.
_arty: Re: А как быть с IE?
хм
кому на стандарты ложить? микрософту да, но кому еще?
texhapb: Re: А как быть с IE?
Боссам - заказчикам. Им главное, чтоб в Интернете (=осле) все работало. А что это "некрасиво", порождает проблемы при разработке, тяжело (=неудобно клиенту) - не особо важно. Большинству.
P.S. Появись в ICQ, plz...
_arty: Re: А как быть с IE?
а, это да, боссам положить
ты джаббер себе когда заведешь? : )
texhapb: Re: А как быть с IE?
А где мне зарегаться? На jabber.ru не нашел. Кидай в ICQ.
_arty: Re: А как быть с IE?
вообще регаться нужно через сам клиент
а самый простой способ - завести себе google talk, ибо он тоже джаббер. Завести его проще простого - talk.google.com
caitlynanope:
История биржевого игрока» (HavardAR) Начало смотри в статье «Плавный трейдинг.