Статьи

Перевод: Николай Мациевский aka sunnybear
Опубликована: 21 августа 2007

Оптимизируем загрузку веб-страницы

Примечание: ниже перевод статьи "Presentation Layer Performance Tuning", в которой затрагиваются основные аспекты оптимизации загрузки веб-приложений и предлагаются некоторые практические советы.

Обычный разговор про увеличение скорости работы веб-приложений сводится к обсуждению задержек при передачи информации между сервером и клиентом, оптимизации базы данных и времени, потраченного сервером для обработки и отправки HTML клиенту.

Эти процессы, однако, только частично затрагивают то время, которое клиент тратит на ожидание загрузки страницы в окне своего браузера. Большая часть времени тратится на загрузку, кеширование и отображение JavaScript, CSS и картинок (прим.: не-HTML файлов). Оптимизация производительности уровня представления (presentation layer) веб-приложений, на самом деле, сводится к двум простых условиям:

  • Меньше данных
  • Меньше запросов

Целью данной статьи является демонстрация на конкретном примере оптимизации загрузки веб-страницы на стороне клиента. Это может быть достигнуто просто за счет применения концепции «меньше запросов, меньше данных» в следующих четырех областях, каждая затрагивает различные аспекты веб-разработки клиентской части в терминах подготовки JavaScript-, CSS-файлов и картинок для размещения в сети:

  1. Сжатие (уменьшение данных).
  2. Кеширование (уменьшение запросов)
  3. Слияние (уменьшение данных и запросов)
  4. Сети доставки содержания (Content Delivery Networks) (уменьшение запросов)

Сжатие

По большому счету, для веб-приложений с большим трафиком — когда важна производительность, и каждый ненужный КБ оказывается «за бортом» — методы сжатия могут оказать большое влияние на производительность. Для JavaScript и CSS утилиты по сжатию файлов удаляют комментарии, лишние пробелы и переводы строк, заменяют все объявленные переменные меньшими по длине, уменьшая общий объем файла более, чем в 2 раза. Сжатие картинок в данном ключе менее применимо, ибо полученный результат получается несущественным (прим.: не знаю, что тут имеется в виду, но сжатие JPEG ведет к потере качества, а GIF или PNG вообще не сжимаются из изначального варианта, если сам этот вариант «с умом» сделан). Поскольку разработчики предпочитают, чтобы все их исходники были читаемыми, то сжатие, очевидно, нужно проводить уже на финальной стадии создания веб-приложения.

Cжатия ресурсных файлов можно добиться и используя серверные расширения для gzip- или deflate-сжатия. Хотя уменьшение времени передачи информации по сети является плюсом, дополнительная загрузка серверного процессора может свести на нет все преимущества. Некоторые шаги в этом направлении могут позволить добиться лучших результатов, но серьезной проблемой может стать несовместимость отдельных браузеров, и некоторые архитекторы высказываются против использования таких методов — называя их ненужной тратой ресурсов (Cal Henderson/Flickr).

Кеширование

Кеширование становится крайне важным для современных веб-сайтов, которые используют обширное подключение JavaScript и CSS. CSS- и JavaScript-файлы, в отличие от неизменных картинок, могут довольно регулярно меняться и дополняться, что создает дополнительные проблемы для владельцев сайтов, широко использующих кеширование. Методы конфигурирования веб-сервера мы рассматривать не будем, но основой является инструкция серверу для бессрочного кеширования каждого URL'а. Чтобы дать серверу понять, что файл был изменен, требуется использовать другое имя файла. На больших веб-сайтах обычно устанавливается такой процесс изменения этих файлов, что номер каждой новой версии добавляется к имени файла (например, common.v1.css становится common.v2.css). Соответственно, ссылки на эти файлы тоже должны быть программно обновлены, и это не зависит от языка программирования или системы шаблонов.

Кеширование можно оптимизировать и дальше путем настройки заголовков, которые сервер отправляет при запросе требуемых ресурсов. Вместо того, чтобы отдать его содержание, сервер может отправить заголовки, что у клиента уже имеется закешированная версия файла, для которого установлено, что срок его хранения истечет в будущем. Картинки обычно так часто не обновляют, зачем же их запрашивать снова и снова? Установка и "cache-control", и "expires" должна обеспечить поддержку протоколов HTTP 1.0 и 1.1. Типичный ответ сервера, урезанный только до заголовков с кеширующую информацией, может выглядеть следующим образом:

Date: Tue, 17 Apr 2007 18:39:57 GMT
Cache-Control: max-age=315360000
Expires: Fri, 14 Apr 2017 18:39:57 GMT
Last-Modified: Mon, 16 Apr 2007 23:39:48 GMT

Система по проверке кеширования может проанализировать данные на конкретном сайте. Она выдаст вам детальный анализ различных объектов и того, как они кешируются. Основываясь на этой информации оптимизировать параметры кеширования для различных объектов, чтобы повысить производительность (прим.: в частности, похожий анализ может делать расширение Firebug/YSlow для Firefox).

Слияние

Ограничение браузера на два параллельных запроса (прим.: подозреваю, что не касается Opera, опять-таки) к одному и тому же домену является узким местом при визуализации страницы. Уменьшая число запросов, мы можем уменьшить время отображения страницы в браузере. Объединение HTTP-ресурсов клиентской стороны может также помочь в решение данной проблемы.

Применительно к JavaScript- и CSS-файлах уменьшение HTTP-запросов будет означать общее правило для увеличения производительности, хотя стоит применять его грамотно, избегая появления больших, монолитных файлов. Если эти файлы будут часто меняться, что, на самом деле, и происходит для развивающихся веб-приложений, большим минусом будет отдавать пользователям файлы более 100 КБ каждые несколько дней. Если ваш JavaScript часто меняется, разбейте эти динамичные области кода на отдельно загружаемые части. Кроме того, если у вашего приложения присутствуют характерно различные части, например, большая часть JavaScript-библиотек используется только в определенном разделе, стоит выделить ее в отдельный файл, разделяя, таким образом, всю логику приложения на меньшие по размеру и более независимые части. По причине того, что предел HTTP-запросов жестко привязан к ограничению по умолчанию на 2 запроса на домен, веб-сайты с большим трафиком могут поддерживать несколько доменов, на которых будут расположены JavaScript и CSS, обычно на основе сетей-доставки-содержания (CDNs), которые используют различные доменные имена.

Популярным методом для уменьшения HTTP-запросов для больших наборов картинок является CSS-спрайты (CSS sprites), относительно новый подход, который позволяет таблицам стилей использовать различные области одной большой картинки, которая, фактически, содержит несколько связанных картинок (прим.: по этому адресу располагается веб-приложение для создания общей картинки из набора более мелких, которое, в том числе, создает набор стилей для отображения получившегося изображения). Спрайты были использованы на заре компьютерной эры в игровой индустрии, когда дизайнеры игр, учитывая пропускную способность (шины) соединяли всю графику, относящуюся к игре, в «спрайты», и одна большую картинка состояла из многих маленьких. Игровой движок затем отображал часть этой картинки, скрывая все остальное, при этом в память была загружена всего одна картинка.

Аналогичный подход можно применить и для CSS, где атрибуты селектора в случае необходимости могут быть использованы для отображения или сокрытия частей картинки. Этот метод оказывается способным уменьшить число HTTP-запросов для таких широко распространенных эффектов, как изменение картинки при наведении на кнопку (roll-over), и некоторых других, которым требуется предварительно загрузить несколько картинок для корректного отображения и ждать срабатывания какого-либо события.

Например, на веб-сайтах многих многонациональных компаний присутствует специальная страница с картой мира. На ней движок сайта обычно меняет картинки при наведении на различные страны — эта задача обычно решается через карты ссылок (image maps) или Flash. С использованием CSS-спрайтов эту задачу можно решить и на DHTML, обеспечив тем самым для пользователя более доступный, эффективный, семантический, удобный и оптимизированный для поисковых машин функционал. Рассмотрим недавнюю работу по изменению дизайн для Intermec — мирового лидера в производстве радио-технологий (RFID). Эта карта составляет значительную часть функционала страницы. Если пользователь наводит на текстовые ссылки языков, то соответствующая страна подсвечивается на карте. Проблема была в том, что у нас было 12 стран, которые нужно было высвечивать на этой карте. Однако, при использовании CSS-спрайтов требуется всего лишь единственный HTTP-запрос для получения всех требуемых для подсветки картинок.

Пример CSS спрайтов

Чтобы высветить США, например, пользователь вызывает событие mouseover на соответствующем объекте (в данном случае, это ссылка), которая вызывает JavaScript для анимации прозрачности фоновой картинки-спрайта для запрошенной области от 0 до 100.

Фактически, CSS отображает только часть картинки и скрывает все остальное, используя при этой комбинацию значений для атрибутов позиционирования, и скрывает все то, что выходит за объявленные границы. В случае это карты, у спрайта 456px на 705px GIF изображения три части:

  • Верхняя карта является фоновой картинкой по умолчанию при загрузке страницы.
  • Вторая и третья карты содержат закрашенные области для различных стран.

Ключевым моментом в данном случае является расположить все страны на картах так, чтобы никакие две страны не находились в одной прямоугольной области. Для Intermec используется только две дополнительные карты для достижения общего эффекта. У целевого CSS-селектора присутствует 3 набора атрибутов, которые и определяют закрашенную область.

  • Атрибуты left и top выставляют для текущей страны позицию просматриваемой области на картинке-карте по умолчанию.
  • Height и width выставляют размеры просматриваемой области.
  • Background-position перемещает фоновую картинку в нужное положение, отображая заявленную область в том прямоугольнике, который был создан с помощью первого и второго условий.
#map {
    width:456px;
    height:229px;
    background:url(images/sprite.gif) no-repeat;
    overflow:hidden;
}

#target {
    position:absolute;
    left:0;
    top:35px; 
    height:80px; 
    width:130px;
    -moz-opacity:0; opacity:0; filter:alpha(opacity=0);
    background:url(images/sprite.gif) no-repeat;
    background-position:0 -271px;
    overflow:hidden;
}

Иначе говоря, у двух HTML-элемента одинаковая картинка выставлена в качестве фоновой, первый отображает целую карту мира, а второй только показывает закрашенную область, соответствующую выбранной стране, на этой карте. Следуя этому принципу, любое количество картинок для стран, которые требуется для эффекта наведения (roll-over), могут быть запрошены с помощью единственного HTTP-запроса, выдающего одну картинку, содержащую набор всех требуемых, расположенных друг за другом.

Сети доставки содержания (CDN)

Сети доставки содержания (CDN) часто используются для уменьшения нагрузки на хостинг для веб-приложений и его канал. В этом случае увеличение производительности достигается за счет распространения всех требуемых ресурсов по сети серверов. Близость к таким веб-серверам незамедлительно оборачивается увеличение скорости загрузки компонентов.

Некоторые компании, например, Akamai, создали бизнес на основе предоставления такого рода сетей для многих крупномасштабных веб-процессов, которым необходимо предоставлять их ресурсы повсеместно. Ценовая структура Akamai основана на общем весе веб-страниц в KB и числе пользовательских загрузок. Оптимизация самих веб-страниц может очень сильно сказаться на общей цене. Например, один из наших клиентов платит приблизительно $8000 в месяц за домашнюю страницу в 320 КБ. Если бы над сайтом была проведена работа, которая бы уменьшила общий вес страницы на 25 процентов, то ежемесячная оплата для клиента сократилась бы на $2000. В этом примере речь идет всего лишь о просто домашней странице. Уже для нее затраты на разработку окупятся с лихвой!

Yahoo! недавно начала обеспечение их YUI (Yahoo! User Interface) библиотек, используя распределенную систему северов по всему миру — бесплатно! Это новый сервис обеспечивает:

  1. gzip-сжатие (уменьшает размер файлов от 60% до 90%).
  2. Контроль за кеширующими заголовками, обеспечивающий выставление header'ов, которые истекают в будущем.
  3. Распределенный хостинг файлов, основанный на географическом расположение клиента. Предоставляется на основе передовых компьютерных систем.

Сети доставки содержания задумывались как просто хостинг для картинок и больших (аудио-, видео-) файлов, но сейчас они обрабатывают и JavaScript с CSS. Использование кеширования/версионности в сочетании с распределением файлов по такой сети может привести к существенному приросту производительности.

Заключение

Как длительность HTTP-запросов может повлиять на общее время для отображения веб-страницы, так и общий размер ресурсных файлов может повлиять на производительность. Использование эффективных, семантических и грамотно спроектированных методов для программирования на стороне клиента позволит свести размер файлов к минимуму.

Например, JavaScript-библиотеки YUI, Prototype, и Dojo могут быть задействованы в создании распространенных веб-компонентов, используя изящный, разумно написанный код. Применение технологий проектирования, основанных на веб-стандартах, может уменьшить итоговое количество кода HTML, CSS, и JavaScript, которой потребует для отображения пользовательского интерфейса (например, уже не потребуется такой аттавизм, как печально известная «распорка», прозрачная GIF картинка 1x1). Используя JSON (JavaScript Object Notation) для получения данных при AJAX-запросах может ускорить общий процесс до двух раз, по причине того, что данные возвращаются в качестве JavaScript-массива, а не «чистого» XML, который еще нужно преобразовать.

Хотя многие из рассмотренных в этой статье методов позволяют сэкономить только несколько КБ от общего размера страницы, общая производительность веб-сайта в сети может сильно увеличиться. Значение рассмотренных методик особенно важно для веб-сайтов с большим трафиком, у которых возникают проблемы с использованием пропускного канала.

Читать дальше

Ссылки по теме

Все комментарии (habrahabr.ru)