Сайт Романа ПарпалакаЗаметкиТехнологииВеб-разработкаКлиентская оптимизация

Клиентская оптимизация

3 августа 2013 года

Клиентская оптимизация — это набор методов для ускорения загрузки, отображения и работы сайтов в браузерах.

Теория

Начинающий специалист найдет понятное изложение основ клиентской оптимизации в книгах «Реактивные веб-сайты» и «Разгони свой сайт».

Недавно досмотрел трехчасовой доклад Ильи Григорика, специалиста Гугла, о технических особенностях работы сетей и браузеров и о следствиях для клиентской оптимизации (первая часть и вторая часть). Многое было знакомым. Тем не менее, послушал не без интереса.

Среди прочего речь шла о том, что на скорость загрузки и отображения сайтов влияет не только ширина канала, но и задержки времени (latency; измеряется утилитой ping). При этом ситуация в мобильном и десктопном вебе существенно различается. Хотя с развитием мобильных сетей ширина каналов растет, с задержками по-прежнему всё плохо.

Действительно новым для меня был совет о вреде буферизации. Желательно как можно быстрее отдать браузеру хотя бы часть страницы, а потом уже производить какие-то действия и генерировать оставшуюся часть. Смысл этого совета заключается в том, что отправить можно неизменяемое содержимое служебной секции <head> и шапку страницы. Браузер распознает обращение ко внешним стилям и начнет загружать css-файлы, не дожидаясь загрузки остального html-кода.

В своем движке S2 я делал ровно противоположную вещь: специально перехватывал содержимое страницы для вычисления размера ответа (заголовок Content-length), для вычисления хеша ETag и, наконец, для gzip-сжатия ответа (включается в админке).

Ранняя отправка части ответа лишает нас этих плюшек. И если вы задумываетесь о такой оптимизации, то легко пожертвуете условными GET-запросами и сжатием (которое на больших нагрузках скорее всего окажется вредным). Что касается Content-length, то без этого заголовка в HTTP 1.0 не работал механизм keep-alive. В HTTP 1.1 с этим всё в порядке: в этой версии поддерживается передача ответа порциями в одном соединении.

Напомню, что keep-alive подразумевает повторное использование подключения к веб-серверу для передачи нескольких файлов. Без keep-alive на каждый файл (будь то стиль, скрипт или картинка) открывается новое соединение, и о производительности можно забыть.

Отсутствие буферизации лишает еще одной полезной возможности отправлять заголовки в процессе обработки запроса. Например, если в базе данных не нашлось содержимого, соответствующего запрошенному URL, то уже нельзя отправить заголовок о 404-й ошибке. Или сделать перенаправление 301/302.

В общем, следовать совету о ранней отправке непросто. И дело не только в настройке программного обеспечения, которое с радостью буферизирует всё подряд. Дело в том, что не всегда можно выделить неизменную часть страницы со ссылками на стили, не выполняя остальной работы по построению страницы. Я решил, что в S2 такой оптимизации не будет. Она сильно ограничила бы гибкость. Да и выигрыш получается небольшим при времени сборки страницы в несколько десятков миллисекунд.

Практика

После просмотра теоретического материала я, как любитель оптимизировать, должен был посмотреть свежим взглядом на свои сайты. Каково же было мое удивление, когда я обнаружил на сайте движка обращение к Google Analytics, хотя никогда ее не устанавливал! Причина оказалась неожиданной.

Как известно, браузеры еще не научились показывать видео так же легко и просто, как картинки. Когда я размещал на сайте движка видеоинструкции, выяснилось, что видеохостинги пережимают файлы и изменяют размер кадра, чем портят записанную с экрана картинку. Тогда я воспользовался библиотекой video.js. Она показывает ролики через HTML 5 в современных браузерах и во флеш-плеере в устаревших.

Для простоты я не стал загружать файлы на свой сервер и подключил библиотеку из CDN. Это было разумно и с точки зрения оптимизации: CDN отдавал сжатую версию, а на моем сервере gzip-сжатие статических файлов не было настроено. Как говорится, сделал и забыл. Но бесплатный сыр бывает только в мышеловке. И в качестве «платы» авторы video.js со временем включили в CDN-версию вызов Google Analytics. Вот еще одна причина не доверять свои сайты чужим сервисам.

Загрузил библиотеку на сервер и начал решать вопрос с gzip-сжатием. Как и любой нормальный веб-сервер, nginx способен сжимать файлы на лету. Но это создает дополнительную нагрузку на сервер, ведь ему приходится делать одну и ту же работу при каждом запросе к файлам. Другую интересную возможность предоставляет модуль gzip static. Этот модуль отдает вместо запрашиваемых файлов заранее подготовленные сжатые версии этих файлов с расширением .gz. Их удобно создавать во время развертывания сайта или по расписанию. Например, команда gzip -cn6 script.js > script.js.gz рядом с файлом script.js создаст файл script.js.gz.

Когда-то давно nginx в стандартных пакетах Debian был скомпилирован без модуля gzip static. В текущей же версии, Debian 7, ситуация изменилась, и мне оставалось добавить несколько строк к конфигурации nginx. В результате 50-килобайтный скрипт video.js сжимается до 16 килобайт.

В заключение обсудим вопрос об этих 50 килобайтах ради отображения видео. 50 килобайт — много это или мало? Сегодня многие скажут «мало», обвешивая сайт библиотеками и фреймворками на сотни килобайт. Я противник такого подхода. Моя правота подтверждается каждый раз, когда кто-то пытается открывать сайты на медленном интернете. Другое дело — сжатая в три раза версия. Загрузка 16 килобайт скриптов для кроссбраузерного отображения видео вполне допустима.

Поделиться

Читайте также

Debian 8
Обновил Debian на виртуальном сервере до недавно вышедшей 8 версии (jessie).
2015
AMP
Статья на хабре про AMP. Вообще, эта «технология» всегда казалась мне странной.
2017
Система управления шаблонами
Эта статья написана для начинающих веб-мастеров.
2006
Правильная организация RSS
В пользе RSS уже давно никто не сомневается.
2007

Оставьте свой комментарий


Формулы на латехе: $$f(x) = x^2-\sqrt{x}$$ превратится в $$f(x) = x^2-\sqrt{x}$$.
Выделение текста: [i]курсивом[/i] или [b]жирным[/b].
Цитату оформляйте так: [q = имя автора]цитата[/q] или [q]еще цитата[/q].
Других команд или HTML-тегов здесь нет.