Клиентская оптимизация — это оптимизация процесса загрузки клиентским приложением содержимого веб-страниц. Основная цель такой оптимизации — достижение максимальной скорости загрузки страниц сайта браузером клиента, ведь даже незначительные изменения времени загрузки могут иметь серьезные последствия для задачи, возложенной на сайт.
При построении высокопроизводительных сайтов должен присутствовать и клиентский, и серверный подход, они во многом дополняют друг друга. Главное отличие клиентского подхода состоит в том, что в качестве объекта оптимизации рассматриваются страницы сайта, получаемые браузером клиента, состоящие из HTML-документа, содержащего вызовы внешних объектов, а также сами внешние объекты (чаще всего это файлы CSS, файлы JavaScript и изображения).
Может показаться, что клиентская оптимизация является лишь составляющей частью серверной оптимизации, однако это не так. Различные технологические решения клиентской области сайта при одинаковой нагрузке на сервер могут обеспечивать совершенно разные характеристики клиентского быстродействия.
При исключении из рассмотрения всех факторов, относящихся к серверному программному обеспечению и каналу передачи данных, можно заключить, что увеличение скорости загрузки страницы на различных стадиях загрузки принципиально возможно за счет ограниченного количества методов. Об этих методах и пойдет речь далее.
Большинство приведенных в курсе методов оптимизации являются универсальными и могут быть применены практически в любом случае, на любом сайте. Но только выбор наиболее подходящего плана оптимизации может привести к наилучшему результату при решении каждой конкретной задачи.
Перед оптимизацией сайта необходим тщательный анализ его клиентской производительности, а также четко сформулированная цель оптимизации, ведь в подобном усовершенствовании важен только результат, а не процесс.
Процедуру анализа веб-сайта можно разделить на несколько основных стадий: анализ веб-страниц и их компонентов, анализ стадий загрузки веб-страниц и анализ характеристик браузеров, при помощи которых веб-страницы обычно загружаются.
Целью клиентской оптимизации может быть решение подобных задач:
Это далеко не полный перечень возможных целей. Иногда и вовсе требуется достигать компромисса и выбирать между несколькими взаимо-исключающими вариантами оптимизации. В таких ситуациях лучше иметь максимум возможной информации о ваших веб-сайтах и их посетителях.
Определить список "критических" страниц, на которых необходим максимальный эффект оптимизации, можно при помощи систем сбора и анализа статистики. Необходимо также учитывать назначение и специфику оптимизируемого сайта или сервиса.
Как правило, оптимизация требуется на главной странице сайта и других страницах с высокой посещаемостью, но это не всегда так. В качестве примера можно привести страницы оформления заказа на коммерческом сайте. На них может приходить лишь 5% от общего числа посетителей сайта, однако если они будут загружаться слишком медленно, посетители могут так и не стать клиентами.
(рис 1.1) Внешний вид сервиса Google AnalyticsСервис работает по тому же принципу, что и большинство Интернет-счетчиков: специальный код устанавливается на всех страницах сайта и регистрирует каждое посещение, собирая все данные о нем.
Относительно молодой, но активно развивающийся русскоязычный сервис для оценки посещаемости сайтов и анализа поведения пользователей на нем. Позволяет получить детальную информацию об источниках перехода на сайт, числе возвратов, просматриваемом содержимом, географии и демографии посещений, программных и аппаратных характери-тиках компьютеров пользователей.
Для сбора всей упомянутой выше информации достаточно лишь установить определенный код на всех страницах анализируемого сайта.
Одним из наиболее популярных среди веб-разработчиков средств для анализа и разработки веб-страниц является дополнение
Панель Net в дополнении
(рис 1.2) Внешний вид панели Net дополнения Firebug для FirefoxСтоит заметить, что аналогичные
функциональностью обладает надстройка Web Inspector, в Opera Dragonfly, в Internet Explorer — Developer Toolbar.
(рис 1.3) Информация о заголовках открытой страницы на панели Net дополнения Firebug для Firefox
Дополнение LiveHTTPHeaders для Firefox позволяет в режиме реального времени получать исчерпывающую информацию о пересылаемых между браузером и сервером заголовках. Кроме того, в этом дополнении существует режим Replay, позволяющий отправлять на сервер произвольные запросы GET или POST, что часто бывает удобно при разработке.
(рис 1.4) Режим ручной отправки запроса в дополнении LiveHTTPHeaders
Дополнение YSlow для Firefox позволяет легко определить общее количество объектов, из которых состоит веб-страница, а также понять соотношения между объектами различного типа. В списке, содержащем перечень всех загруженных на странице объектов, предоставляется детальная информация по каждому такому объекту: размер, наличие сжатия, размер cookie, заголовки, время отклика и др.
(рис 1.5) Панель статистической информации о странице дополнения YSlow для Firefox
Более мощным средством для получения информации о составе и ходе загрузки веб-страниц является приложение HTTPWatch. Это приложение устанавливается в виде дополнений к браузерам Firefox и Internet Explorer и предоставляет более полную и более точную информацию, чем
(рис 1.6) Внешний вид дополнения HTTPWatch для Firefox
Небольшое дополнение к браузеру Firefox под названием Hammerhead позволяет имитировать многократную последовательную загрузку набора заданных страниц. Число попыток может быть установлено пользователем. Как результат работы дополнение отображает среднее время полной загрузки каждой испытуемой страницы. Дополнение позволяет очищать кэш после каждой загрузки для имитации обоих случаев: когда пользователь загружает страницу впервые или загружает ее повторно.
Дополнения YSLow и PageSpeed для Firefox позволяют получить интегральную оценку клиентской производительности любой загруженной браузером страницы, а также дают некоторые советы, следуя которым, можно улучшить производительность.
Разумеется, приведенные советы не могут покрыть всех возможных ситуаций, и иногда их выполнение может оказать даже отрицательное влияние на какой-либо из других параметров быстродействия вашего сайта. Однако более высокая интегральная оценка, которую дадут эти дополнения, будет в большинстве случаев соответствовать более оптимизированному сайту.
(рис 1.7) Панель анализа страницы дополнения YSlow для Firefox
Существует целый ряд веб-сервисов, позволяющих получить комплексную оценку клиентской производительности тестируемого сайта.
http://webo.in/ — По результату проверки предоставляется детальный план возможных действий по оптимизации со ссылками на тематические статьи, строятся
http://webpagetest.org/ — Сайт вычисляет время всех стадий загрузки и строит подробные диаграммы загрузки, позволяя при этом проводить серии из заданного количества тестов с определяемыми пользователем параметрами. История тестирования сохраняется.
http://site-perf.com/ — Этот сервис позволяет эмулировать большое число параметров загрузки: количество соединений на хост, пропускную способность канала и многие другие, включая даже процент потерянных пакетов. Отображается детальная статистика по всем серверам, с которых производилась загрузка.
Клиентская оптимизация во многом основывается на некотором наборе известных свойств распространенных браузеров. К этим свойствам относится порядок загрузки браузером объектов, вызываемых на странице, возможность параллельной загрузки этих объектов, максимальное число соединений, поддержка различных алгоритмов сжатия и пр. Для того чтобы узнать значения этих свойств в конкретном браузере, существует несколько приведенных ниже веб-сервисов.
Этот сервис при помощи специально разработанных тестов позволяет определить все наиболее важные, с точки зрения клиентской оптимизации, характеристики вашего браузера. Кроме того, на веб-сайте сохраняются результаты всех ранее предпринятых пользователями тестов, благодаря чему можно найти информацию о поддержке тех или иных характеристик почти для любой версии любого браузера.
(рис 1.8) Отчет о характеристиках наиболее распространенных браузеров сервиса Browserscope
Этот сервис позволяет сконструировать, а затем загрузить в вашем браузере модель веб-страницы с произвольным количеством встроенных и внешних объектов, расположенных в выбранном вами порядке. В завершение каждой предпринятой попытки Cuzillion отображает время, затраченное на загрузку созданной страницы. Благодаря этому сервису легко можно оценить влияние изменений в структуре веб-страниц на скорость их загрузки в каждом конкретном браузере.
(рис 1.9) Пример веб-страницы, созданной сервисом Cuzillion
Очевидный способ увеличения скорости загрузки страницы — уменьшение размера загружаемых объектов. В ряде ситуаций можно без потерь содержания изменить состав HTML-документа, файлов CSS и JavaScript и тем самым уменьшить суммарный размер загружаемых пользователями страниц.
На высоконагруженных страницах, какими являются, например, главные страницы поисковых систем GoogLe, Yahoo, Яндекс, возникают ситуации, когда каждый лишний байт страницы критичен для быстродействия.
Минимизация применима к коду HTML, CSS и JS и в зависимости от размера и содержимого кода позволяет достичь результатов, близких к gzip-сжатию, уменьшать файлы до 30% от исходного размера, а иногда и более. При использовании же еще и gzip-сжатия предварительная минимизация позволяет увеличить итоговую степень сжатия в среднем на 3-5%.
В ситуациях, когда gzip-сжатие применить невозможно, например, когда CSS- и JS-код встроены в веб-страницу, минимизация — один из немногих оставшихся способов существенно уменьшить размер такой веб-страницы.
Стоит заметить, что после проведения минимизации результирующий код по-прежнему будет полностью совместим со всеми браузерами, т. к. он останется тем же корректным HTML-, CSS- или JS-кодом, в то время как gzip-сжатие до сих пор поддерживается не всеми пользовательскими браузерами. Кроме того, минимизированный код всегда распознается и обрабатывается браузером быстрее.
Так называется процесс, при котором JavaScript-код специальным образом запутывается для того, чтобы затруднить процесс его разбора и модификации. Обфускация может включать в себя те же операции, что и минимизация, а также:
Ниже приведен фрагмент JS-кода до обфускации:
var Prototype = {
Version: '1.6.1_rc3',
Browser: (function(){
var ua = navigator.userAgent;
var isOpera = Object.prototype.toString.call(window.opera)== '[object Opera]';
return {
IE: !!window.attachEvent !isOpera,
Opera: isOpera,
WebKit: ua.indexOf('AppleWebKit/') > -1,
Gecko: ua.indexOf('Gecko') > -1 ua.indexOf('KHTML') === -1,
MobileSafari: /Apple.*Mobile.*Safari/.test(ua)
}
})(),
BrowserFeatures: {
XPath: !!document.evaluate,
SelectorsAPI: !!document.querySelector,
ElementExtensions: (function() {
var constructor = window.Element || window.HTMLElement;
return !!(constructor constructor.prototype);
})(),
SpecificElementExtensions: (function() {
if (typeof window.HTMLDivElement !== 'undefined')
return true;
var div = document.createElement('div');
var form = document.createElement('form');
var isSupported = false;
if (div['__proto__'] (div['__proto__'] !==
form['__proto__'])) {
isSupported = true;
}
div = form = null;
return isSupported;
})()
},
ScriptFragment: '<script[^>]*<([\\S\\s]*?)<\/script>',
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
emptyFunction: function() { },
K: function(x) { return x }
};
А так этот же код выглядит после обфускации:
eval((function(x)
{
var d="";
var p=0;
while(p<x.length)
{
if(x.charAt(p)! ="`")d+=x.charAt(p++);
else{var l=x.charCodeAt(p+3)-28;
if(l>4)d+=d.substr(d.lengthx.charCodeAt(p+1)*96-x.charCodeAt(p+2)+3104-l,l);
else d+="`";p+=4}}return d})("var Prototype={Version:\"1.6.0.3\",
Browser:{IE:!!(window.attachEventnavigator.userAgent.indexOf(\"Opera\")===-1),` )!:` -@>
-1,WebKit` 1:Apple` C\"/`P\"Gecko` 7:` >!` I!`!_;KHTML`!w#,MobileSafari:!!`E0match(/`!P!.*` K\".*`M\"/)}
`#F$Features:{XPath:!!document.evaluate,SelectorsAPI` 5(query` 5$,ElementExtensions:
!!`$=#HTML`8#,Specific` =.` o%create` :#(\"div\").__proto__`\"C!==`24form` ?(},
ScriptFragment:\"<s` ,![^>]*>([\\\\S\\\\s]*?)</` 4\">
\",JSONFilter:/^\\/\\*-secure-([\\s\\S]*)\\*\\/\\s*$/,emptyFunction:f` \"#(){},K` %x){return x;}};"))
Несмотря на подобный вид, такой код работает точно так же, как исходный, из которого он был получен.
В редких ситуациях при помощи обфускации можно достичь более эффективного сжатия, чем при помощи минимизации, но это отнюдь не является основной целью операции. В ситуации, когда в код добавляется большое количество избыточного кода, объем кода может значительно увеличиваться.
О наиболее популярных приложениях для минимизации и обфуска-ции было рассказано в книге "Разгони свой сайт", во второй главе. Также часть подобных приложений рассматривается в начале седьмой главы.
Наиболее простым способом уменьшения размера загружаемых объектов с точки зрения внедрения является сжатие текстовых файлов при помощи технологии gzip. Эта технология, основанная на широко известном алгоритме
Со времен появления поддержки протокола HTTP/1.1 браузеры указывают в HTTP-запросах поддерживаемые типы сжатия, устанавливая заголовок Accept-Encoding:
Accept-Encoding: gzip, deflate
Если веб-сервер получает такой заголовок в запросе, он может применить сжатие ответа одним из методов, перечисленных клиентом. Отправляя ответ, сервер уведомляет клиента о том, каким методом сжимался ответ, при помощи заголовка Content-Encoding.
Content-Encoding: gzip
Для использования технологии gzip-сжатия обычно достаточно прописать несколько строк в конфигурационном файле сервера, и общая скорость загрузки может возрасти на десятки и даже сотни процентов — размер сжатых файлов обычно не превышает 20% от исходного размера.
С использованием gzip-сжатия нагрузка на браузеры пользователей практически не возрастает, поскольку восстановление сжатого файла малого размера (а на веб-страницах размеры текстовых файлов измеряются в килобайтах) происходит почти мгновенно. Временные затраты возможны на стороне сервера, но только в случае динамического сжатия, т. е. сжатия в реальном времени. В ситуации, когда динамическое сжатие оказывает недопустимо большую нагрузку на веб-сервер, следует применять статическое сжатие, т. е. сжатие и кэширование всех необходимых файлов только при их изменении.
Используя gzip-сжатие, важно убедиться в том, что оно отключено для изображений и других двоичных файлов. Поскольку эти файлы уже сжаты, а их размер обычно существенно превышает размеры типичных текстовых файлов, применение gzip-сжатия не принесет никакого выигрыша в клиентском быстродействии веб-страниц, а лишь увеличит нагрузку на сервер. Следует также обратить внимание на то, что сжатие эффективно только для файлов размером порядка одного килобайта и более. Сжатие файлов меньшего размера ощутимого результата, скорее всего, не принесет.
Достичь дополнительного выигрыша при сжатии файлов HTML и CSS можно также за счет применения стандартов верстки, при которых везде, где это возможно, используется один и тот же регистр, а все HTML-атрибуты, CSS-свойства и другие подобные
Сжатие текстовых файлов подробно рассмотрено во второй лекции.
За счет использования подходящих графических форматов и эффективного сжатия без потерь суммарный размер страницы может быть уменьшен иногда на 50% и более.
Изображения, полученные с фотоаппаратов или сохраненные в некоторых графических редакторах, могут содержать много килобайт дополнительной информации, комментариев (т. н. метаданных), а также избыточную цветовую палитру.
Существует несколько графических форматов, поддерживаемых всеми современными браузерами: PNG-8, PNG-24, JPEG, GIF, ICO. Каждый из этих форматов позволяет в определенных ситуациях получить значительный выигрыш в размере по сравнению с другими форматами. Основные рекомендации для различных типов изображений приведены ниже.
Для полноцветных изображений с богатой цветовой палитрой (фотографий, сложных градиентов и т. п.) следует использовать формат JPEG высокой степени качества. Необходимо помнить о том, что JPEG — формат сжатия с потерями, и чем выше степень сжатия, тем большее число артефактов появится на итоговом изображении.
В случаях, когда для верстки требуются полупрозрачные изображения, следует использовать формат PNG-24, поддерживающий альфа-каналы. Нельзя однако забывать о том, что браузер Internet Explorer 6 не поддерживает полупрозрачность в таких изображениях и для их корректного вывода следует применять фильтр ALphalmageLoader.
Для изображений с ограниченной палитрой следует применять формат PNG-8. Этот формат, как и формат GIF, позволяет использовать прозрачность (не альфа-каналы), но в большинстве случаев превосходит GIF по качеству сжатия итогового файла. Достигается это за счет более совершенной методики сжатия (фильтрации), которая охватывает и горизонтальные, и вертикальные повторения, а также хорошо работает с градиентами.
Единственным кроссбраузерным форматом, позволяющим отображать анимацию в изображениях, является формат GIF. Однако уже в ближайшем будущем ему может составить конкуренцию развивающийся формат APNG. Подробнее об этом формате можно узнать в разделе 3.3.
Для иконок веб-сайта существует специальный формат ICO, однако большинство современных браузеров могут использовать в качестве иконки изображение любого поддерживаемого ими формата. Более подробно о применении
Наибольшего эффекта от оптимизации можно достичь, только используя наиболее подходящий формат для каждого случая. Нередко разделение сложных изображений (содержащих, например, полноцветное изображение с некоторым количеством мелкого текста и полупрозрачную рамку) на несколько отдельных изображений, накладывающихся одно на другое, может существенно уменьшить размер веб-страницы.
Удобной программой для ручной оптимизации статических изображений в Windows и Mac OS является программа Adobe Photoshop, для ани-мированных изображений — Adobe Fireworks. В операционных системах семейства Linux одним из наиболее подходящих приложений является Gimp.
О том, как можно автоматизировать оптимизацию изображений, рассказано в третьей лекции.
Для уменьшения размера кода следует использовать такие способы верстки, которые требуют минимум тегов HTML и правил CSS. Так, семантическая верстка с применением независимых блоков более предпочтительна, чем верстка
Не стоит использовать в верстке атрибуты HTML и свойства CSS, значения которых подразумеваются по умолчанию, такие, например, как target="_self".
Избыточного кода в CSS можно также избежать, приняв стандарт отображения типовых элементов на веб-страницах, таких как заголовки, параграфы, списки, ссылки и т. д. Один раз определив стиль оформления ссылки и параграфа, больше не придется описывать его для каждого нового блока.
Суммарный объем кода можно также сократить за счет устранения встроенного на веб-странице CSS- и JS-кода. Множество одинаковых атрибутов style="" в HTML-тегах за счет использования классов в большинстве случаев можно заменить единственным, общим для всех элементов CSS-селектором, а множество JavaScript-обработчиков (например, обработчиков onclick="", onmouseover="" и др.) — одним-единственным обработчиком. Изменить верстку и JavaScript-логику в подобных ситуациях, как правило, достаточно несложно.
Нередко на веб-страницах можно найти некоторое количество неиспользуемого кода, находящегося как в самом HTML-документе, так и во внешних файлах.
Время загрузки этих страниц увеличивается на время загрузки неиспользуемых внешних файлов из сети или из кэша браузера и на время, необходимое для разбора всех элементов DOM-дерева и CSS-правил, которые могут быть к ним применены. В случаях, когда размер веб-страницы и файлов ресурсов измеряется в сотнях килобайт, задержка может быть существенной.
Если в файлах CSS и JS, подключаемых на веб-странице, большой объем кода относится исключительно к другим страницам, следует перераспределить такой код по нескольким файлам, подключая их на страницах по необходимости. Для обнаружения неиспользуемого на странице CSS-кода можно воспользоваться дополнением Dust-Me
Сохраняя в файлах cookie лишь идентификаторы данных, хранящихся на сервере, можно существенно уменьшить их размер. В идеальной ситуации, чтобы для передачи cookie потребовался лишь один пакет, его размер должен быть не больше одного килобайта.
Сократить размер cookie также можно, гибко определяя содержащиеся в них поля. Если какие-то поля нужны лишь для ограниченного диапазона веб-страниц, нужно определять их только для этого диапазона, а не для всех страниц сайта.
Для статического контента (например, изображений, файлов CSS и JS) можно использовать отдельные домены, не передающие cookie вовсе.
Размер HTML-документа обычно составляет порядка 10% от общего размера страницы. Остальные 90% занимают вызываемые со страницы внешние объекты (чаще всего это изображения, файлы CSS и JS).
Помимо непосредственной загрузки каждого внешнего объекта браузеру необходимо совершить целый ряд дополнительных действий:
Таким образом, из-за отсутствия этих временных издержек один внешний объект всегда загружается быстрее, чем несколько объектов того же суммарного размера, загружающихся последовательно, а поскольку многие браузеры загружают внешние файлы JS строго последовательно, количество этих объектов способно существенно повлиять на скорость загрузки веб-страницы.
Наибольший эффект от уменьшения количества запросов к серверу ощутят пользователи с низкой пропускной способностью канала и большим временем отклика от сервера — обычно это пользователи мобильных устройств и коммутируемых соединений.
(рис 1.10) Влияние количества внешних объектов на скорость загрузки веб-страницыНа веб-страницах не следует использовать фреймы. При необходимости применения их число должно быть минимальным.
Среди минусов фреймов: избыточные запросы к серверу, блокирование события onload, а также затруднения при поисковой индексации и сохранении адресов и состояний веб-страниц. Следует также заметить, что тег iframe исключен из стандартов XHTML 1.0 Strict и XHTML 1.1.
Использование фреймов, как правило, оправданно только тогда, когда требуется безопасно вставить блок какого-либо стороннего содержимого, например, рекламный блок. В большинстве же случаев можно избежать применения фреймов за счет разумного использования серверных скриптов и техник AJAX.
Уменьшить количество запросов к серверу можно за счет минимизации количества вызовов CSS-файлов. Оптимальное количество таких вызовов — не более двух на страницу.
Не следует подключать на каждой веб-странице все использующиеся на сайте CSS-файлы, пусть тот код, который нужен на ограниченном числе страниц, вызывается только на них.
Разработчики, заботящиеся о доступности своих веб-страниц, часто предусматривают несколько файлов стилей для различных типов устройств просмотра веб-страниц. В этой ситуации в секции <head> может оказаться похожий набор вызовов:
<link type="text/css" rel="stylesheet" href="screen.css" media=" screen" /> <link type="text/css" rel="stylesheet" href="handheld.css" media="handheld" /> <link type="text/css" rel="stylesheet" href="print.css" media="print" />
Уменьшить количество запросов в этой ситуации можно, объединив содержимое всех трех файлов в одном и используя для каждого типа устройств отдельное правило @media.
На этапе разработки, чтобы легче сопровождать код и исключить его избыточность, часто бывает удобно применять CSS-правило @import или вызывать в HTML-документе больше число CSS-файлов. В такой ситуации перед публикацией на сервере можно использовать инструменты для автоматического объединения CSS-файлов и подстановки кода, вызываемого свойством @import, чтобы уменьшить число запросов к серверу.
К сожалению, иногда для корректного отображения веб-страниц в старых версиях браузера Internet Explorer требуется отдельный набор CSS-правил. В таких ситуациях часто прибегают к использованию условных комментариев. Лучшим примером их применения является следующая конструкция, когда любой браузер запросит лишь один файл, предназначенный для него:
<!—[if gt IE 7]><!—> <link rel="stylesheet" href="css/style.css"/> <!—<![endif]—> <!—[if lt IE 8]> <link rel=stylesheet href="css/style.ie.css"> <![endif]—>
Как и в рассмотренной выше ситуации с файлами CSS, на странице часто подключается несколько файлов JavaScript. Уменьшив их количество, можно значительно увеличить итоговую скорость загрузки страницы.
Весь код JS можно объединить в одном файле, загружаемом и кэши-руемом единожды. Это лучшее решение в том случае, когда кода JavaScript на сайте относительно немного (порядка 50-100 килобайт в сжатом виде).
В ситуации, когда сайт представляет собой сложное веб-приложение и объем кода превышает 100-150 килобайт в сжатом виде, у объединения всего кода в одном файле имеется отрицательная сторона: при запросе первой страницы пользователь неизбежно будет загружать часть кода, которую мог бы не загружать вовсе. Кроме того, в крупных веб-приложениях бывает не просто уследить за зависимостями модулей, — часто нужный код повторяется и, разумеется, загружается пользователем несколько раз.
Допустим, на сайте существует определенная последовательность страниц, посещаемых каждым новым пользователем, причем для каждой отдельной страницы требуются разные модули JS. Для страницы P1 — модули F1, F2 и F3, для страницы P2 — модули F1, F3 и F4, а для страницы P3 — модули F1, F3, F5 и F6. Возможны три ситуации.
Выходом из положения может стать продуманное объединение модулей и выделение их ядра, т. е. набора модулей, используемых на большинстве часто загружаемых пользователями страниц. В приведенном примере таким ядром будут объекты F1 и F3.
В сложных ситуациях задача разбиения может быть легко формализована и решена, однако на практике это почти никогда не требуется и для нахождения лучшего варианта объединения достаточно рассмотреть описанные выше варианты.
Более подробно о методах автоматического объединения текстовых файлов рассказано в четвертой лекции.
Технология объединения изображений для уменьшения числа запросов к серверу достаточно проста. Файл с несколькими объединенными в определенном порядке изображениями (спрайт) загружается единожды, после чего в разных частях страницы отображаются те или иные его области. Возможно даже создание эффектов анимации при помощи объединенных изображений.
(рис 1.11) Примеры объединения изображений в одном файлеХорошим примером может послужить метод использования единственного изображения для анимированной двухпозиционной кнопки. Верстка такой кнопки представляет собой обыкновенную ссылку с текстом:
<a class="button" href="#">Текст кнопки</a>
В стилях же, при помощи свойства background и :hover,задано положение фона для различных состояний кнопки:
a.button {
background: url(/img/button.png) 0 0 no-repeat;
display: inline-block;
width: 100px;
height: 20px;
}
a.button:hover {
background-position: -100px 0;
}
Перед объединением изображений следует разбить их на следующие группы:
(repeat) ;(repeat-x) ;(repeat-y) ;(norepeat).Эти группы нужны для того, чтобы исключить возможность появления остальных изображений из группы в области другого изображения. Так, изображение с фиксированной высотой, повторяющееся на странице по горизонтали (например, градиентная заливка фона), может находиться в группе аналогичных изображений, выше или ниже их, но никак не слева и не справа.
Если изображение всегда фиксированного размера и не повторяется по какому-либо направлению, его можно размещать в любом месте итогового файла.
Если же изображение, к примеру, использовано в списках, в роли маркера, находящегося в фоне элементов списка, необходимо обеспечить пустое пространство в объединенном изображении правее и ниже изображения маркера. В противном случае под текстом списка может оказаться другая часть спрайта.
Анимированные изображения лучше объединять отдельно, в зависимости от их размера и палитры.
Минусом применения
Не стоит забывать и про достаточно старый способ оптимизации, когда несколько расположенных рядом изображений объединяются в одно и при помощи тега <map> на этом изображении размечаются доступные для взаимодействия области.
В ряде случаев фрагменты CSS- и JS-кода, а также изображения можно подставлять напрямую в HTML-документ.
Плюсы такой подстановки очевидны: количество запросов внешних объектов при загрузке страницы уменьшается до минимального количества. Минусом при использовании такого подхода на всех страницах сайта будет то, что пользователь лишится возможности кэшировать какие-либо объекты, вновь и вновь будет загружать их при просмотре страниц сайта.
Из этого очевидно, что подстановку внешних объектов в HTML-документ следует производить в следующих случаях:
<style>, расположенного в секции <head> страницы, а JavaScript-код — в теги <script> в конце документа, перед закрывающим тегом <body> либо также внутри секции <head>.Следуя приведенным выше рекомендациям, необходимо избегать встраивания CSS- и JS-кода непосредственно в теги веб-страницы (т. е. в атрибуты style, onclick и т. д.). Это исключит дублирование кода на странице, а также упростит его сопровождение.
Встраивать изображения прямо в HTML-документ можно, используя схему data:URI. По стандарту RFC 2397 такие URI предназначены для вставки небольших объектов как "непосредственных данных". Синтаксис должен быть следующим:
data:[<тип данных>][;base64],<данные>
В случае изображений необходимо указание mime-типа для них (например, image/gif). После него должно располагаться
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQA QMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDr Az3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkS uQmCC" width="16" height="14" alt="Встроенное изображение" />
Такие изображения, внедренные в HTML-страницы, разумеется, кэ-шируются только вместе с самим HTML-документом, содержащим их. Однако учитывая то, что изображения могут быть встроены и в файлы каскадных стилей, можно добиться кэширования этих изображений путем объединения их в одном внешнем CSS-файле.
У данного подхода есть следующие минусы:
Решение первой проблемы возможно за счет использования gzip-сжатия файлов CSS, в которых располагаются встроенные изображения. Вторая и третья проблемы легко решаются автоматическим преобразованием изображений в
Описание способа автоматического встраивания изображений в код по схеме data:URI можно найти в четвертой лекции.
Перед тем как браузер сможет установить соединение с вебсервером, он должен разрешить доменное имя, т. е., зная его, вычислить IP-адрес сервера. Результат может быть закэширован в браузере и операционной системе пользователя, и задержки при повторном открытии веб-страницы не возникнет.
Если же такой записи в кэше не существует, задержка на время поиска IP-адреса может оказаться значительной и будет зависеть от доступности DNS-сервера, содержащего требуемую информацию (а иногда и от доступности цепочки таких серверов).
Наилучший способ уменьшить временные издержки, связанные с разрешением доменного имени — использовать наименьшее количество различных хостов для размещения внешних объектов веб-страниц, в особенности для тех объектов, которые требуются для первоначального отображения страницы.
Идеальным с точки зрения минимизации времени разрешения адреса DNS-сервера считается вариант, когда все объекты расположены на том же хосте, откуда была загружена веб-страница. Чем меньше используется хостов, тем больше вероятность того, что браузер сможет повторно использовать уже установленное соединение.
На практике же почти у всех браузеров существуют ограничения на количество одновременных соединений с одним хостом. Принимая во внимание это ограничение, наибольший выигрыш в скорости загрузки страниц можно получить, распределив загружаемые объекты по нескольким (4-6) хостам. Подробнее об особенностях параллельной загрузки объектов можно прочитать в пятой главе книги "Разгони свой сайт".
Иногда возникает необходимость перенаправить браузер с одного адреса на другой. Причины чаще всего следующие:
Какой бы ни была причина, каждый редирект порождает дополнительный HTTP-запрос, занимающий определенное время. Поэтому для страниц, для которых скорость загрузки наиболее критична, число реди-ректов должно быть сведено к минимуму. Для этого необходимо:
<meta> или JavaScript-обработчика. Редиректы, отправляющие браузеру код состояния 300, 301 или 302 и заголовок Location, обрабатываются браузером моментально, а при выполнении клиентских редиректов браузеру требуется дополнительное время на разбор полученной веб-страницы. Кроме того, некоторые браузеры могут кэшировать информацию о ре-директах, тем самым ускоряя повторную загрузку ранее открытых веб-страниц.Браузеры и прокси-серверы обычно стремятся сохранить максимум информации в своих хранилищах, для того чтобы ускорить повторную загрузку ранее загруженных объектов. Важно помнить, что при этом возможна потеря актуальности представляемых данных, поэтому политика кэширования должна быть организована с учетом всех возможных ситуаций.
Кэширование — это один из наиболее мощных механизмов для уменьшения объема передаваемых по сети данных, притом внедряется этот механизм очень просто. Ниже приведено краткое описание наиболее значимых для кэширования заголовков.
Когда HTTP-сервер отправляет объект (например, HTML-документ или изображение) браузеру, он может дополнительно с ответом отправить заголовок Expires с меткой времени. Браузеры обычно хранят ресурс вместе с информацией об истечении его срока действия в
день недели(сокр.), число(2 цифры) месяц(сокр.) год часы:минуты:секунды GMT
Заголовок Expires устанавливает время актуальности информации. Для ресурсов, которые не должны кэшироваться, его нужно выставлять в текущие время и дату (документ устаревает сразу же после получения), для форсирования кэширования его можно определять на достаточно далекую дату в будущем, например:
Expires: Mon, 27 Dec 2027 00:00:00 GMT
Заголовок Cache-Control определяет набор директив, относящихся непосредственно ко времени и специфике кэширования документа. Для запрета кэширования можно выставить его в следующее значение:
Cache-Control: no-store, no-cache, must-revalidate
Если же, наоборот, требуется сохранить ресурс в кэш браузера на продолжительный период времени, например, на год (60 * 60 * 24 * 365 секунд), нужно отправлять следующий заголовок:
Cache-Control: max-age=31536000
Заголовок Last-Modified может отправляться сервером для того, чтобы передать браузеру информацию о дате последнего изменения документа. Дата должна задаваться в том же формате, что и в случае с заголовком Expires:
Last-Modified: Tue, 4 Aug 1995 04:58:08 GMT
При наличии такой информации в If-Modified-Since:
If-Modified-Since: Tue, 29 Oct 1994 19:43:31 GMT
В случае если дата последнего изменения осталась прежней, сервер ответит кодом состояния 304 Not Modified и данные не будут отправлены повторно. В противном случае сервер передаст новую версию файла.
Данная схема позволяет экономить время, затрачиваемое на передачу данных, однако при ее использовании браузер все равно будет устанавливать соединение с сервером, чтобы узнать, имеется ли более новая версия.
Заголовок ETag является почти полной аналогией заголовка Last-Modified за тем исключением, что в качестве передаваемого значения может выступать произвольная строка. Заголовок отправляется сервером в следующем формате:
ETag: "any-type-of-tag-or-hash"
Впоследствии, для того чтобы сервер мог определить, является ли объект, находящийся в кэше браузера, точно таким же, как соответствующий объект на сервере, браузер может отправить следующий заголовок:
If-None-Match: "any-type-of-tag-or-hash"
И аналогично, если теги совпадают, сервер отвечает кодом состояния 304 Not Modified и данные не передаются повторно. В противном случае сервер передаст новую версию файла.
Если время кэширования при помощи заголовков Expires и Cache-Control установлено на несколько лет вперед и требуется сообщить клиентскомубраузеру, что исходный объект изменился, можно воспользоваться двумя способами.
Можно обновить GET-строку запроса, например, используя номер версии или дату последнего изменения:
http://testdomain.com/global.css?v1
http://testdomain.com/global.css?20080901
А можно добавить номер версии или дату последнего изменения в само имя файла:
http://testdomain.com/global.v1.css
Во втором случае, для того чтобы исключить проблемы с локальными прокси-серверами, которые могут кэшировать файлы с GET-параметрами, и чтобы не создавать множество физических файлов, достаточно указать в конфигурации сервера правило: при запросах такого вида отдается каждый раз один и тот же файл.
В спецификации RFC-2616 HTTP-кэшированию посвящена целая глава. В ней подробно рассматривается, как работают все приведенные выше заголовки. Также о многих тонкостях использования кэширования более подробно рассказано в четвертой лекции.
Даже когда веб-страница и все внешние объекты загружены на компьютер пользователя, браузеру по-прежнему требуется время для того, чтобы разобрать страницу, интерпретировать код HTML и CSS, выполнить код JavaScript. Принимая во внимание особенности работы браузеров на этом этапе, можно достичь существенно более высокой скорости загрузки страницы.
Разбирая полученный HTML-код, браузер строит
Если на веб-странице присутствует большое количество элементов или объем CSS-кода достаточно велик, страница может прорисовываться с ощутимой задержкой. Когда объем кода уменьшить уже невозможно, более высокой скорости загрузки можно достичь за счет эффективной верстки. Основные рекомендации к верстке следующие.
#header .menu li a будет применяться дольше, чем аналогичный ему селектор #header .menu-item. В первом случае браузеру необходимо будет найти все ссылки на странице, проверить, находятся ли они в контексте элемента списка, элемента с классом menu и, наконец, элемента с идентификатором header. Второй вариант более предпочтителен, поскольку поиск элементов по классу и идентификатору выполнится существенно быстрее.При изменении ряда свойств элементов веб-страницы, а также в некоторых других ситуациях браузеры производят перерасчет геометрии и положения элементов, находящихся в потоке веб-страницы, после чего заново перерисовывают страницу или ее часть. Если веб-страница достаточно сложна, ее обновление будет заметно для пользователя и неизбежно вызовет задержку в его работе со страницей.
Вот неполный список действий, вызывающих в большинстве браузеров перерисовку страниц или их частей:
class, font, display, visible, margin, padding, width, height;:hover.Учитывая эти особенности, можно свести к минимуму число перерисовок страниц, а для того чтобы скорость перерисовок была наивысшей, необходимо:
position: absolute и position: fixed ;
От структуры HTML-документа во многом зависит скорость загрузки страницы пользователем. Даже при одинаковом суммарном размере страниц и равном количестве внешних объектов две различные страницы могут загружаться за совершенно разное время. Причина в том, что отображение элементов частично загруженной страницы в большинстве браузеров осуществляется только после выполнения следующих шагов:
<head> ;<body>, расположенных в потоке выше выводящегося элемента.В большинстве браузеров отображение страницы будет приостановлено до тех пор, пока все внешние CSS-файлы не будут загружены. Кроме того, теги <style>, встречающиеся на странице, будут порождать частичную или полную перерисовку страницы, иногда изменяя уже отобразившийся макет, с которым пользователь мог начать взаимодействовать.
Таким образом, более высокой скорости отображения страницы можно добиться, располагая в самом начале веб-страницы, в разделе <head>, все элементы <link>, содержащие вызовы файлов CSS-стилей, а также все встроенные стили, содержащиеся в тегах <style>.
Из-за того, что код JavaScript может изменять содержимое и макет веб-страницы, браузеры приостанавливают отображение элементов, следующих за JS-кодом, до тех пор, пока код не будет загружен и исполнен. Большинство браузеров при этом приостанавливают даже загрузку внешних объектов,следующих за таким JS-кодом. Однако если на момент начала загрузки JS-файла загрузка внешних объектов уже была начата, они будут загружены параллельно.
В приведенном ниже примере на веб-странице загружаются два внешних файла CSS и JS.
<head> <script type="text/javascript" src="script-1.js"></script> <link rel="stylesheet" type="text/css" href="style-1.css" /> <script type="text/javascript" src="script-2.js"></script> <link rel="stylesheet" type="text/css" href="style-2.css" /> </head>
При таком порядке следования в документе и при пустом кэше большинство браузеров будет вынуждено дождаться загрузки первого файла JavaScript, только потом начать загрузку следующих двух файлов CSS и JS и лишь по завершении загрузки второго файла JS загрузить последний файл стилей.
Всего лишь изменив порядок следования вызовов внешних объектов так, чтобы впереди были вызовы файлов CSS, можно получить ощутимый выигрыш в скорости загрузки.
<head> <link rel="stylesheet" type="text/css" href="style-1.css" /> <link rel="stylesheet" type="text/css" href="style-2.css" /> <script type="text/javascript" src="script-1.js"></script> <script type="text/javascript" src="script-2.js"></script> </head>
В этой ситуации браузер может инициировать параллельную загрузку сразу трех внешних объектов — двух файлов стилей и первого файла JS. По окончанию их загрузки браузеру остается загрузить лишь один файл JavaScript, и итоговое время загрузки будет ощутимо ниже.
Как видно на приведенной ниже диаграмме, в первой ситуации загрузка каждого файла JavaScript блокирует получение остальных внешних объектов, создавая дополнительные задержки. Во второй же ситуации вместе с загрузкой первого файла JS происходит параллельная загрузка максимально возможного количества внешних объектов.
(рис 1.12) Диаграмма загрузки внешних объектов при различном порядке их вызововРазумеется, экономия времени в каждом отдельном случае будет зависеть от размеров загружаемых объектов и их количества, однако пренебрегать этой особенностью не стоит.
Следует помнить, что данная особенность неактуальна в браузерах, поддерживающих параллельную неблокирующую загрузку внешних объектов. Перечень таких браузеров можно получить при помощи инструментов, описанных чуть ранее в этой лекции.
Во всех браузерах можно выделить несколько основных стадий загрузки страницы. Рассмотрим эти стадии.
Чтобы ускорить наступление предварительной загрузки, следует снизить число вызываемых в заголовке страницы файлов до минимума, применить к ним динамическое сжатие, или, для еще большего быстродействия — статическое сжатие. При использовании статического сжатия серверу не придется тратить дополнительное время на сжатие, он будет сразу готов отдать сжатый файл.
Загрузку файлов, не требующихся на стадии предварительной загрузки, имеет смысл перенести в стадию пост-загрузки.
Итогом первой стадии загрузки является доставленный и оформленный HTML-документ, с которым пользователь уже может взаимодействовать. Издержки на доставку всех файлов JavaScript должны быть сведены к минимуму, так как на этом этапе они только помешают, замедлив отображение основного содержимого страницы.
При правильной группировке загружаемых внешних объектов и за счет использования закэшированных браузером объектов эта стадия может наступать значительно быстрее.
Необходимо сконфигурировать веб-сервер так, чтобы при запросе любой другой страницы пришлось запрашивать минимум дополнительных объектов. Должен быть также продуман вопрос форсированного сброса кэша в ситуациях, когда это будет необходимо.
Также при запросе большого количества изображений браузер неизбежно столкнется с ограничением максимального количества соединений на хост, и для обхода этого ограничения необходимо настроить дополнительные серверы для выдачи статического содержимого. Число дополнительных хостов следует напрямую из числа статических файлов, поэтому надо определиться с ними на этапе автоматизации процесса публикации.
На этой же стадии можно использовать прием объединения изображений.
К началу этой стадии у пользователя уже должна быть в распоряжении оформленная HTML-страница, на которой все ссылки и формы должны работать без JavaScript.
На этой стадии могут загружаться любые объекты, которые необходимые для этой или каких-либо других страниц.
При помощи специального обработчика JavaScript, который начинает работать на этой стадии, возможно к уже существующей функциональности страницы добавить расширенные возможности в виде подсказок,дополнительных данных с сервера, какой-либо анимации и т. д.
Этот обработчик может производить следующие операции:
В случае применения технологии data:URI для уменьшения количества вызываемых объектов на этой стадии необходимо загружать файл CSS, содержащий все используемые на странице изображения в формате base-64.
Об отложенной загрузке ресурсов, не требующихся на момент первого отображения страницы, можно прочитать в пятой главе, а также в седьмой главе книги "Разгони свой сайт".
Во многих современных браузерах, в частности, в последних версиях браузера Safari, активно внедряется прогрессивная логика отображения страницы.
С одной стороны, браузер не ждет последовательной и полной загрузки всех блокирующих вывод страницы внешних объектов, а с другой — не отображает неформатированную веб-страницу. Сочетая преимущества сразу нескольких подходов, браузер определяет, в какой момент какую часть страницы можно отобразить, чтобы опыт пользователя был наилучшим.
Загрузка всех внешних объектов производится параллельно, и разбор содержимого не останавливается. При этом, если производится обращение к свойству стиля или макета, модуль JavaScript приостанавливает свою работу и ожидает загрузку всех незагруженных файлов CSS. Как только все стили загружены, выполнение сценария продолжается с того места, где оно было приостановлено.
У всех браузеров существует ограничение на количество соединений на один хост, находящееся в интервале от 2 до 8 соединений на хост. Для увеличения скорости загрузки внешних объектов можно применять распределенную систему хранения и доставки контента (CDN), организовав или арендовав систему хостов, находящихся на одном или нескольких физических серверах (географически распределенных, если это требуется). Часть хостов должны принимать и обрабатывать запросы пользователей, создавать и передавать результирующие HTML-документы. Остальные хосты должны использоваться только для передачи клиентом статических ресурсов. Благодаря такой схеме скорость доставки контента пользователям будет максимальной, в то же время нагрузка на хостинг веб-сайта может значительно снизиться.
Необходимо заметить, что разделять по нескольким хостам имеет смысл только изображения и файлы CSS, так как файлы JavaScript почти во всех браузерах загружаются строго последовательно.
Создать подобную систему распределенного хранения можно либо при помощи автоматического балансировщика, либо установив альтернативные пути к внешним объектам вручную.
Большое число дополнительных хостов может увеличить временные затраты браузера на установление соединений, поэтому в наибольшем количестве ситуаций предпочтительно использование не более 5 дополнительных хостов (1 основной хост и 4 для параллельной загрузки кэширу-емых объектов) без учета не контролируемых вами хостов, например рекламных. Это позволяет ускорить загрузку приблизительно на 60% в случае большого количества файлов.
Подробнее о системах распределенного хранения контента (CDN) рассказано в пятой лекции.
Клиентская оптимизация — это оптимизация процесса загрузки клиентским приложением содержимого веб-страниц. Основная цель такой оптимизации — достижение максимальной скорости загрузки страниц сайта браузером клиента, ведь даже незначительные изменения времени загрузки могут иметь серьезные последствия для задачи, возложенной на сайт.
При построении высокопроизводительных сайтов должен присутствовать и клиентский, и серверный подход, они во многом дополняют друг друга. Главное отличие клиентского подхода состоит в том, что в качестве объекта оптимизации рассматриваются страницы сайта, получаемые браузером клиента, состоящие из HTML-документа, содержащего вызовы внешних объектов, а также сами внешние объекты (чаще всего это файлы CSS, файлы JavaScript и изображения).
Может показаться, что клиентская оптимизация является лишь составляющей частью серверной оптимизации, однако это не так. Различные технологические решения клиентской области сайта при одинаковой нагрузке на сервер могут обеспечивать совершенно разные характеристики клиентского быстродействия.
При исключении из рассмотрения всех факторов, относящихся к серверному программному обеспечению и каналу передачи данных, можно заключить, что увеличение скорости загрузки страницы на различных стадиях загрузки принципиально возможно за счет ограниченного количества методов. Об этих методах и пойдет речь далее.
Большинство приведенных в курсе методов оптимизации являются универсальными и могут быть применены практически в любом случае, на любом сайте. Но только выбор наиболее подходящего плана оптимизации может привести к наилучшему результату при решении каждой конкретной задачи.
Перед оптимизацией сайта необходим тщательный анализ его клиентской производительности, а также четко сформулированная цель оптимизации, ведь в подобном усовершенствовании важен только результат, а не процесс.
Процедуру анализа веб-сайта можно разделить на несколько основных стадий: анализ веб-страниц и их компонентов, анализ стадий загрузки веб-страниц и анализ характеристик браузеров, при помощи которых веб-страницы обычно загружаются.
Целью клиентской оптимизации может быть решение подобных задач:
Это далеко не полный перечень возможных целей. Иногда и вовсе требуется достигать компромисса и выбирать между несколькими взаимо-исключающими вариантами оптимизации. В таких ситуациях лучше иметь максимум возможной информации о ваших веб-сайтах и их посетителях.
Определить список "критических" страниц, на которых необходим максимальный эффект оптимизации, можно при помощи систем сбора и анализа статистики. Необходимо также учитывать назначение и специфику оптимизируемого сайта или сервиса.
Как правило, оптимизация требуется на главной странице сайта и других страницах с высокой посещаемостью, но это не всегда так. В качестве примера можно привести страницы оформления заказа на коммерческом сайте. На них может приходить лишь 5% от общего числа посетителей сайта, однако если они будут загружаться слишком медленно, посетители могут так и не стать клиентами.
(рис 1.1) Внешний вид сервиса Google AnalyticsСервис работает по тому же принципу, что и большинство Интернет-счетчиков: специальный код устанавливается на всех страницах сайта и регистрирует каждое посещение, собирая все данные о нем.
Относительно молодой, но активно развивающийся русскоязычный сервис для оценки посещаемости сайтов и анализа поведения пользователей на нем. Позволяет получить детальную информацию об источниках перехода на сайт, числе возвратов, просматриваемом содержимом, географии и демографии посещений, программных и аппаратных характери-тиках компьютеров пользователей.
Для сбора всей упомянутой выше информации достаточно лишь установить определенный код на всех страницах анализируемого сайта.
Одним из наиболее популярных среди веб-разработчиков средств для анализа и разработки веб-страниц является дополнение
Панель Net в дополнении
(рис 1.2) Внешний вид панели Net дополнения Firebug для FirefoxСтоит заметить, что аналогичные
функциональностью обладает надстройка Web Inspector, в Opera Dragonfly, в Internet Explorer — Developer Toolbar.
(рис 1.3) Информация о заголовках открытой страницы на панели Net дополнения Firebug для Firefox
Дополнение LiveHTTPHeaders для Firefox позволяет в режиме реального времени получать исчерпывающую информацию о пересылаемых между браузером и сервером заголовках. Кроме того, в этом дополнении существует режим Replay, позволяющий отправлять на сервер произвольные запросы GET или POST, что часто бывает удобно при разработке.
(рис 1.4) Режим ручной отправки запроса в дополнении LiveHTTPHeaders
Дополнение YSlow для Firefox позволяет легко определить общее количество объектов, из которых состоит веб-страница, а также понять соотношения между объектами различного типа. В списке, содержащем перечень всех загруженных на странице объектов, предоставляется детальная информация по каждому такому объекту: размер, наличие сжатия, размер cookie, заголовки, время отклика и др.
(рис 1.5) Панель статистической информации о странице дополнения YSlow для Firefox
Более мощным средством для получения информации о составе и ходе загрузки веб-страниц является приложение HTTPWatch. Это приложение устанавливается в виде дополнений к браузерам Firefox и Internet Explorer и предоставляет более полную и более точную информацию, чем
(рис 1.6) Внешний вид дополнения HTTPWatch для Firefox
Небольшое дополнение к браузеру Firefox под названием Hammerhead позволяет имитировать многократную последовательную загрузку набора заданных страниц. Число попыток может быть установлено пользователем. Как результат работы дополнение отображает среднее время полной загрузки каждой испытуемой страницы. Дополнение позволяет очищать кэш после каждой загрузки для имитации обоих случаев: когда пользователь загружает страницу впервые или загружает ее повторно.
Дополнения YSLow и PageSpeed для Firefox позволяют получить интегральную оценку клиентской производительности любой загруженной браузером страницы, а также дают некоторые советы, следуя которым, можно улучшить производительность.
Разумеется, приведенные советы не могут покрыть всех возможных ситуаций, и иногда их выполнение может оказать даже отрицательное влияние на какой-либо из других параметров быстродействия вашего сайта. Однако более высокая интегральная оценка, которую дадут эти дополнения, будет в большинстве случаев соответствовать более оптимизированному сайту.
(рис 1.7) Панель анализа страницы дополнения YSlow для Firefox
Существует целый ряд веб-сервисов, позволяющих получить комплексную оценку клиентской производительности тестируемого сайта.
http://webo.in/ — По результату проверки предоставляется детальный план возможных действий по оптимизации со ссылками на тематические статьи, строятся
http://webpagetest.org/ — Сайт вычисляет время всех стадий загрузки и строит подробные диаграммы загрузки, позволяя при этом проводить серии из заданного количества тестов с определяемыми пользователем параметрами. История тестирования сохраняется.
http://site-perf.com/ — Этот сервис позволяет эмулировать большое число параметров загрузки: количество соединений на хост, пропускную способность канала и многие другие, включая даже процент потерянных пакетов. Отображается детальная статистика по всем серверам, с которых производилась загрузка.
Клиентская оптимизация во многом основывается на некотором наборе известных свойств распространенных браузеров. К этим свойствам относится порядок загрузки браузером объектов, вызываемых на странице, возможность параллельной загрузки этих объектов, максимальное число соединений, поддержка различных алгоритмов сжатия и пр. Для того чтобы узнать значения этих свойств в конкретном браузере, существует несколько приведенных ниже веб-сервисов.
Этот сервис при помощи специально разработанных тестов позволяет определить все наиболее важные, с точки зрения клиентской оптимизации, характеристики вашего браузера. Кроме того, на веб-сайте сохраняются результаты всех ранее предпринятых пользователями тестов, благодаря чему можно найти информацию о поддержке тех или иных характеристик почти для любой версии любого браузера.
(рис 1.8) Отчет о характеристиках наиболее распространенных браузеров сервиса Browserscope
Этот сервис позволяет сконструировать, а затем загрузить в вашем браузере модель веб-страницы с произвольным количеством встроенных и внешних объектов, расположенных в выбранном вами порядке. В завершение каждой предпринятой попытки Cuzillion отображает время, затраченное на загрузку созданной страницы. Благодаря этому сервису легко можно оценить влияние изменений в структуре веб-страниц на скорость их загрузки в каждом конкретном браузере.
(рис 1.9) Пример веб-страницы, созданной сервисом Cuzillion
Очевидный способ увеличения скорости загрузки страницы — уменьшение размера загружаемых объектов. В ряде ситуаций можно без потерь содержания изменить состав HTML-документа, файлов CSS и JavaScript и тем самым уменьшить суммарный размер загружаемых пользователями страниц.
На высоконагруженных страницах, какими являются, например, главные страницы поисковых систем GoogLe, Yahoo, Яндекс, возникают ситуации, когда каждый лишний байт страницы критичен для быстродействия.
Минимизация применима к коду HTML, CSS и JS и в зависимости от размера и содержимого кода позволяет достичь результатов, близких к gzip-сжатию, уменьшать файлы до 30% от исходного размера, а иногда и более. При использовании же еще и gzip-сжатия предварительная минимизация позволяет увеличить итоговую степень сжатия в среднем на 3-5%.
В ситуациях, когда gzip-сжатие применить невозможно, например, когда CSS- и JS-код встроены в веб-страницу, минимизация — один из немногих оставшихся способов существенно уменьшить размер такой веб-страницы.
Стоит заметить, что после проведения минимизации результирующий код по-прежнему будет полностью совместим со всеми браузерами, т. к. он останется тем же корректным HTML-, CSS- или JS-кодом, в то время как gzip-сжатие до сих пор поддерживается не всеми пользовательскими браузерами. Кроме того, минимизированный код всегда распознается и обрабатывается браузером быстрее.
Так называется процесс, при котором JavaScript-код специальным образом запутывается для того, чтобы затруднить процесс его разбора и модификации. Обфускация может включать в себя те же операции, что и минимизация, а также:
Ниже приведен фрагмент JS-кода до обфускации:
var Prototype = {
Version: '1.6.1_rc3',
Browser: (function(){
var ua = navigator.userAgent;
var isOpera = Object.prototype.toString.call(window.opera)== '[object Opera]';
return {
IE: !!window.attachEvent !isOpera,
Opera: isOpera,
WebKit: ua.indexOf('AppleWebKit/') > -1,
Gecko: ua.indexOf('Gecko') > -1 ua.indexOf('KHTML') === -1,
MobileSafari: /Apple.*Mobile.*Safari/.test(ua)
}
})(),
BrowserFeatures: {
XPath: !!document.evaluate,
SelectorsAPI: !!document.querySelector,
ElementExtensions: (function() {
var constructor = window.Element || window.HTMLElement;
return !!(constructor constructor.prototype);
})(),
SpecificElementExtensions: (function() {
if (typeof window.HTMLDivElement !== 'undefined')
return true;
var div = document.createElement('div');
var form = document.createElement('form');
var isSupported = false;
if (div['__proto__'] (div['__proto__'] !==
form['__proto__'])) {
isSupported = true;
}
div = form = null;
return isSupported;
})()
},
ScriptFragment: '<script[^>]*<([\\S\\s]*?)<\/script>',
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
emptyFunction: function() { },
K: function(x) { return x }
};
А так этот же код выглядит после обфускации:
eval((function(x)
{
var d="";
var p=0;
while(p<x.length)
{
if(x.charAt(p)! ="`")d+=x.charAt(p++);
else{var l=x.charCodeAt(p+3)-28;
if(l>4)d+=d.substr(d.lengthx.charCodeAt(p+1)*96-x.charCodeAt(p+2)+3104-l,l);
else d+="`";p+=4}}return d})("var Prototype={Version:\"1.6.0.3\",
Browser:{IE:!!(window.attachEventnavigator.userAgent.indexOf(\"Opera\")===-1),` )!:` -@>
-1,WebKit` 1:Apple` C\"/`P\"Gecko` 7:` >!` I!`!_;KHTML`!w#,MobileSafari:!!`E0match(/`!P!.*` K\".*`M\"/)}
`#F$Features:{XPath:!!document.evaluate,SelectorsAPI` 5(query` 5$,ElementExtensions:
!!`$=#HTML`8#,Specific` =.` o%create` :#(\"div\").__proto__`\"C!==`24form` ?(},
ScriptFragment:\"<s` ,![^>]*>([\\\\S\\\\s]*?)</` 4\">
\",JSONFilter:/^\\/\\*-secure-([\\s\\S]*)\\*\\/\\s*$/,emptyFunction:f` \"#(){},K` %x){return x;}};"))
Несмотря на подобный вид, такой код работает точно так же, как исходный, из которого он был получен.
В редких ситуациях при помощи обфускации можно достичь более эффективного сжатия, чем при помощи минимизации, но это отнюдь не является основной целью операции. В ситуации, когда в код добавляется большое количество избыточного кода, объем кода может значительно увеличиваться.
О наиболее популярных приложениях для минимизации и обфуска-ции было рассказано в книге "Разгони свой сайт", во второй главе. Также часть подобных приложений рассматривается в начале седьмой главы.
Наиболее простым способом уменьшения размера загружаемых объектов с точки зрения внедрения является сжатие текстовых файлов при помощи технологии gzip. Эта технология, основанная на широко известном алгоритме
Со времен появления поддержки протокола HTTP/1.1 браузеры указывают в HTTP-запросах поддерживаемые типы сжатия, устанавливая заголовок Accept-Encoding:
Accept-Encoding: gzip, deflate
Если веб-сервер получает такой заголовок в запросе, он может применить сжатие ответа одним из методов, перечисленных клиентом. Отправляя ответ, сервер уведомляет клиента о том, каким методом сжимался ответ, при помощи заголовка Content-Encoding.
Content-Encoding: gzip
Для использования технологии gzip-сжатия обычно достаточно прописать несколько строк в конфигурационном файле сервера, и общая скорость загрузки может возрасти на десятки и даже сотни процентов — размер сжатых файлов обычно не превышает 20% от исходного размера.
С использованием gzip-сжатия нагрузка на браузеры пользователей практически не возрастает, поскольку восстановление сжатого файла малого размера (а на веб-страницах размеры текстовых файлов измеряются в килобайтах) происходит почти мгновенно. Временные затраты возможны на стороне сервера, но только в случае динамического сжатия, т. е. сжатия в реальном времени. В ситуации, когда динамическое сжатие оказывает недопустимо большую нагрузку на веб-сервер, следует применять статическое сжатие, т. е. сжатие и кэширование всех необходимых файлов только при их изменении.
Используя gzip-сжатие, важно убедиться в том, что оно отключено для изображений и других двоичных файлов. Поскольку эти файлы уже сжаты, а их размер обычно существенно превышает размеры типичных текстовых файлов, применение gzip-сжатия не принесет никакого выигрыша в клиентском быстродействии веб-страниц, а лишь увеличит нагрузку на сервер. Следует также обратить внимание на то, что сжатие эффективно только для файлов размером порядка одного килобайта и более. Сжатие файлов меньшего размера ощутимого результата, скорее всего, не принесет.
Достичь дополнительного выигрыша при сжатии файлов HTML и CSS можно также за счет применения стандартов верстки, при которых везде, где это возможно, используется один и тот же регистр, а все HTML-атрибуты, CSS-свойства и другие подобные
Сжатие текстовых файлов подробно рассмотрено во второй лекции.
За счет использования подходящих графических форматов и эффективного сжатия без потерь суммарный размер страницы может быть уменьшен иногда на 50% и более.
Изображения, полученные с фотоаппаратов или сохраненные в некоторых графических редакторах, могут содержать много килобайт дополнительной информации, комментариев (т. н. метаданных), а также избыточную цветовую палитру.
Существует несколько графических форматов, поддерживаемых всеми современными браузерами: PNG-8, PNG-24, JPEG, GIF, ICO. Каждый из этих форматов позволяет в определенных ситуациях получить значительный выигрыш в размере по сравнению с другими форматами. Основные рекомендации для различных типов изображений приведены ниже.
Для полноцветных изображений с богатой цветовой палитрой (фотографий, сложных градиентов и т. п.) следует использовать формат JPEG высокой степени качества. Необходимо помнить о том, что JPEG — формат сжатия с потерями, и чем выше степень сжатия, тем большее число артефактов появится на итоговом изображении.
В случаях, когда для верстки требуются полупрозрачные изображения, следует использовать формат PNG-24, поддерживающий альфа-каналы. Нельзя однако забывать о том, что браузер Internet Explorer 6 не поддерживает полупрозрачность в таких изображениях и для их корректного вывода следует применять фильтр ALphalmageLoader.
Для изображений с ограниченной палитрой следует применять формат PNG-8. Этот формат, как и формат GIF, позволяет использовать прозрачность (не альфа-каналы), но в большинстве случаев превосходит GIF по качеству сжатия итогового файла. Достигается это за счет более совершенной методики сжатия (фильтрации), которая охватывает и горизонтальные, и вертикальные повторения, а также хорошо работает с градиентами.
Единственным кроссбраузерным форматом, позволяющим отображать анимацию в изображениях, является формат GIF. Однако уже в ближайшем будущем ему может составить конкуренцию развивающийся формат APNG. Подробнее об этом формате можно узнать в разделе 3.3.
Для иконок веб-сайта существует специальный формат ICO, однако большинство современных браузеров могут использовать в качестве иконки изображение любого поддерживаемого ими формата. Более подробно о применении
Наибольшего эффекта от оптимизации можно достичь, только используя наиболее подходящий формат для каждого случая. Нередко разделение сложных изображений (содержащих, например, полноцветное изображение с некоторым количеством мелкого текста и полупрозрачную рамку) на несколько отдельных изображений, накладывающихся одно на другое, может существенно уменьшить размер веб-страницы.
Удобной программой для ручной оптимизации статических изображений в Windows и Mac OS является программа Adobe Photoshop, для ани-мированных изображений — Adobe Fireworks. В операционных системах семейства Linux одним из наиболее подходящих приложений является Gimp.
О том, как можно автоматизировать оптимизацию изображений, рассказано в третьей лекции.
Для уменьшения размера кода следует использовать такие способы верстки, которые требуют минимум тегов HTML и правил CSS. Так, семантическая верстка с применением независимых блоков более предпочтительна, чем верстка
Не стоит использовать в верстке атрибуты HTML и свойства CSS, значения которых подразумеваются по умолчанию, такие, например, как target="_self".
Избыточного кода в CSS можно также избежать, приняв стандарт отображения типовых элементов на веб-страницах, таких как заголовки, параграфы, списки, ссылки и т. д. Один раз определив стиль оформления ссылки и параграфа, больше не придется описывать его для каждого нового блока.
Суммарный объем кода можно также сократить за счет устранения встроенного на веб-странице CSS- и JS-кода. Множество одинаковых атрибутов style="" в HTML-тегах за счет использования классов в большинстве случаев можно заменить единственным, общим для всех элементов CSS-селектором, а множество JavaScript-обработчиков (например, обработчиков onclick="", onmouseover="" и др.) — одним-единственным обработчиком. Изменить верстку и JavaScript-логику в подобных ситуациях, как правило, достаточно несложно.
Нередко на веб-страницах можно найти некоторое количество неиспользуемого кода, находящегося как в самом HTML-документе, так и во внешних файлах.
Время загрузки этих страниц увеличивается на время загрузки неиспользуемых внешних файлов из сети или из кэша браузера и на время, необходимое для разбора всех элементов DOM-дерева и CSS-правил, которые могут быть к ним применены. В случаях, когда размер веб-страницы и файлов ресурсов измеряется в сотнях килобайт, задержка может быть существенной.
Если в файлах CSS и JS, подключаемых на веб-странице, большой объем кода относится исключительно к другим страницам, следует перераспределить такой код по нескольким файлам, подключая их на страницах по необходимости. Для обнаружения неиспользуемого на странице CSS-кода можно воспользоваться дополнением Dust-Me
Сохраняя в файлах cookie лишь идентификаторы данных, хранящихся на сервере, можно существенно уменьшить их размер. В идеальной ситуации, чтобы для передачи cookie потребовался лишь один пакет, его размер должен быть не больше одного килобайта.
Сократить размер cookie также можно, гибко определяя содержащиеся в них поля. Если какие-то поля нужны лишь для ограниченного диапазона веб-страниц, нужно определять их только для этого диапазона, а не для всех страниц сайта.
Для статического контента (например, изображений, файлов CSS и JS) можно использовать отдельные домены, не передающие cookie вовсе.
Размер HTML-документа обычно составляет порядка 10% от общего размера страницы. Остальные 90% занимают вызываемые со страницы внешние объекты (чаще всего это изображения, файлы CSS и JS).
Помимо непосредственной загрузки каждого внешнего объекта браузеру необходимо совершить целый ряд дополнительных действий:
Таким образом, из-за отсутствия этих временных издержек один внешний объект всегда загружается быстрее, чем несколько объектов того же суммарного размера, загружающихся последовательно, а поскольку многие браузеры загружают внешние файлы JS строго последовательно, количество этих объектов способно существенно повлиять на скорость загрузки веб-страницы.
Наибольший эффект от уменьшения количества запросов к серверу ощутят пользователи с низкой пропускной способностью канала и большим временем отклика от сервера — обычно это пользователи мобильных устройств и коммутируемых соединений.
(рис 1.10) Влияние количества внешних объектов на скорость загрузки веб-страницыНа веб-страницах не следует использовать фреймы. При необходимости применения их число должно быть минимальным.
Среди минусов фреймов: избыточные запросы к серверу, блокирование события onload, а также затруднения при поисковой индексации и сохранении адресов и состояний веб-страниц. Следует также заметить, что тег iframe исключен из стандартов XHTML 1.0 Strict и XHTML 1.1.
Использование фреймов, как правило, оправданно только тогда, когда требуется безопасно вставить блок какого-либо стороннего содержимого, например, рекламный блок. В большинстве же случаев можно избежать применения фреймов за счет разумного использования серверных скриптов и техник AJAX.
Уменьшить количество запросов к серверу можно за счет минимизации количества вызовов CSS-файлов. Оптимальное количество таких вызовов — не более двух на страницу.
Не следует подключать на каждой веб-странице все использующиеся на сайте CSS-файлы, пусть тот код, который нужен на ограниченном числе страниц, вызывается только на них.
Разработчики, заботящиеся о доступности своих веб-страниц, часто предусматривают несколько файлов стилей для различных типов устройств просмотра веб-страниц. В этой ситуации в секции <head> может оказаться похожий набор вызовов:
<link type="text/css" rel="stylesheet" href="screen.css" media=" screen" /> <link type="text/css" rel="stylesheet" href="handheld.css" media="handheld" /> <link type="text/css" rel="stylesheet" href="print.css" media="print" />
Уменьшить количество запросов в этой ситуации можно, объединив содержимое всех трех файлов в одном и используя для каждого типа устройств отдельное правило @media.
На этапе разработки, чтобы легче сопровождать код и исключить его избыточность, часто бывает удобно применять CSS-правило @import или вызывать в HTML-документе больше число CSS-файлов. В такой ситуации перед публикацией на сервере можно использовать инструменты для автоматического объединения CSS-файлов и подстановки кода, вызываемого свойством @import, чтобы уменьшить число запросов к серверу.
К сожалению, иногда для корректного отображения веб-страниц в старых версиях браузера Internet Explorer требуется отдельный набор CSS-правил. В таких ситуациях часто прибегают к использованию условных комментариев. Лучшим примером их применения является следующая конструкция, когда любой браузер запросит лишь один файл, предназначенный для него:
<!—[if gt IE 7]><!—> <link rel="stylesheet" href="css/style.css"/> <!—<![endif]—> <!—[if lt IE 8]> <link rel=stylesheet href="css/style.ie.css"> <![endif]—>
Как и в рассмотренной выше ситуации с файлами CSS, на странице часто подключается несколько файлов JavaScript. Уменьшив их количество, можно значительно увеличить итоговую скорость загрузки страницы.
Весь код JS можно объединить в одном файле, загружаемом и кэши-руемом единожды. Это лучшее решение в том случае, когда кода JavaScript на сайте относительно немного (порядка 50-100 килобайт в сжатом виде).
В ситуации, когда сайт представляет собой сложное веб-приложение и объем кода превышает 100-150 килобайт в сжатом виде, у объединения всего кода в одном файле имеется отрицательная сторона: при запросе первой страницы пользователь неизбежно будет загружать часть кода, которую мог бы не загружать вовсе. Кроме того, в крупных веб-приложениях бывает не просто уследить за зависимостями модулей, — часто нужный код повторяется и, разумеется, загружается пользователем несколько раз.
Допустим, на сайте существует определенная последовательность страниц, посещаемых каждым новым пользователем, причем для каждой отдельной страницы требуются разные модули JS. Для страницы P1 — модули F1, F2 и F3, для страницы P2 — модули F1, F3 и F4, а для страницы P3 — модули F1, F3, F5 и F6. Возможны три ситуации.
Выходом из положения может стать продуманное объединение модулей и выделение их ядра, т. е. набора модулей, используемых на большинстве часто загружаемых пользователями страниц. В приведенном примере таким ядром будут объекты F1 и F3.
В сложных ситуациях задача разбиения может быть легко формализована и решена, однако на практике это почти никогда не требуется и для нахождения лучшего варианта объединения достаточно рассмотреть описанные выше варианты.
Более подробно о методах автоматического объединения текстовых файлов рассказано в четвертой лекции.
Технология объединения изображений для уменьшения числа запросов к серверу достаточно проста. Файл с несколькими объединенными в определенном порядке изображениями (спрайт) загружается единожды, после чего в разных частях страницы отображаются те или иные его области. Возможно даже создание эффектов анимации при помощи объединенных изображений.
(рис 1.11) Примеры объединения изображений в одном файлеХорошим примером может послужить метод использования единственного изображения для анимированной двухпозиционной кнопки. Верстка такой кнопки представляет собой обыкновенную ссылку с текстом:
<a class="button" href="#">Текст кнопки</a>
В стилях же, при помощи свойства background и :hover,задано положение фона для различных состояний кнопки:
a.button {
background: url(/img/button.png) 0 0 no-repeat;
display: inline-block;
width: 100px;
height: 20px;
}
a.button:hover {
background-position: -100px 0;
}
Перед объединением изображений следует разбить их на следующие группы:
(repeat) ;(repeat-x) ;(repeat-y) ;(norepeat).Эти группы нужны для того, чтобы исключить возможность появления остальных изображений из группы в области другого изображения. Так, изображение с фиксированной высотой, повторяющееся на странице по горизонтали (например, градиентная заливка фона), может находиться в группе аналогичных изображений, выше или ниже их, но никак не слева и не справа.
Если изображение всегда фиксированного размера и не повторяется по какому-либо направлению, его можно размещать в любом месте итогового файла.
Если же изображение, к примеру, использовано в списках, в роли маркера, находящегося в фоне элементов списка, необходимо обеспечить пустое пространство в объединенном изображении правее и ниже изображения маркера. В противном случае под текстом списка может оказаться другая часть спрайта.
Анимированные изображения лучше объединять отдельно, в зависимости от их размера и палитры.
Минусом применения
Не стоит забывать и про достаточно старый способ оптимизации, когда несколько расположенных рядом изображений объединяются в одно и при помощи тега <map> на этом изображении размечаются доступные для взаимодействия области.
В ряде случаев фрагменты CSS- и JS-кода, а также изображения можно подставлять напрямую в HTML-документ.
Плюсы такой подстановки очевидны: количество запросов внешних объектов при загрузке страницы уменьшается до минимального количества. Минусом при использовании такого подхода на всех страницах сайта будет то, что пользователь лишится возможности кэшировать какие-либо объекты, вновь и вновь будет загружать их при просмотре страниц сайта.
Из этого очевидно, что подстановку внешних объектов в HTML-документ следует производить в следующих случаях:
<style>, расположенного в секции <head> страницы, а JavaScript-код — в теги <script> в конце документа, перед закрывающим тегом <body> либо также внутри секции <head>.Следуя приведенным выше рекомендациям, необходимо избегать встраивания CSS- и JS-кода непосредственно в теги веб-страницы (т. е. в атрибуты style, onclick и т. д.). Это исключит дублирование кода на странице, а также упростит его сопровождение.
Встраивать изображения прямо в HTML-документ можно, используя схему data:URI. По стандарту RFC 2397 такие URI предназначены для вставки небольших объектов как "непосредственных данных". Синтаксис должен быть следующим:
data:[<тип данных>][;base64],<данные>
В случае изображений необходимо указание mime-типа для них (например, image/gif). После него должно располагаться
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQA QMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDr Az3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkS uQmCC" width="16" height="14" alt="Встроенное изображение" />
Такие изображения, внедренные в HTML-страницы, разумеется, кэ-шируются только вместе с самим HTML-документом, содержащим их. Однако учитывая то, что изображения могут быть встроены и в файлы каскадных стилей, можно добиться кэширования этих изображений путем объединения их в одном внешнем CSS-файле.
У данного подхода есть следующие минусы:
Решение первой проблемы возможно за счет использования gzip-сжатия файлов CSS, в которых располагаются встроенные изображения. Вторая и третья проблемы легко решаются автоматическим преобразованием изображений в
Описание способа автоматического встраивания изображений в код по схеме data:URI можно найти в четвертой лекции.
Перед тем как браузер сможет установить соединение с вебсервером, он должен разрешить доменное имя, т. е., зная его, вычислить IP-адрес сервера. Результат может быть закэширован в браузере и операционной системе пользователя, и задержки при повторном открытии веб-страницы не возникнет.
Если же такой записи в кэше не существует, задержка на время поиска IP-адреса может оказаться значительной и будет зависеть от доступности DNS-сервера, содержащего требуемую информацию (а иногда и от доступности цепочки таких серверов).
Наилучший способ уменьшить временные издержки, связанные с разрешением доменного имени — использовать наименьшее количество различных хостов для размещения внешних объектов веб-страниц, в особенности для тех объектов, которые требуются для первоначального отображения страницы.
Идеальным с точки зрения минимизации времени разрешения адреса DNS-сервера считается вариант, когда все объекты расположены на том же хосте, откуда была загружена веб-страница. Чем меньше используется хостов, тем больше вероятность того, что браузер сможет повторно использовать уже установленное соединение.
На практике же почти у всех браузеров существуют ограничения на количество одновременных соединений с одним хостом. Принимая во внимание это ограничение, наибольший выигрыш в скорости загрузки страниц можно получить, распределив загружаемые объекты по нескольким (4-6) хостам. Подробнее об особенностях параллельной загрузки объектов можно прочитать в пятой главе книги "Разгони свой сайт".
Иногда возникает необходимость перенаправить браузер с одного адреса на другой. Причины чаще всего следующие:
Какой бы ни была причина, каждый редирект порождает дополнительный HTTP-запрос, занимающий определенное время. Поэтому для страниц, для которых скорость загрузки наиболее критична, число реди-ректов должно быть сведено к минимуму. Для этого необходимо:
<meta> или JavaScript-обработчика. Редиректы, отправляющие браузеру код состояния 300, 301 или 302 и заголовок Location, обрабатываются браузером моментально, а при выполнении клиентских редиректов браузеру требуется дополнительное время на разбор полученной веб-страницы. Кроме того, некоторые браузеры могут кэшировать информацию о ре-директах, тем самым ускоряя повторную загрузку ранее открытых веб-страниц.Браузеры и прокси-серверы обычно стремятся сохранить максимум информации в своих хранилищах, для того чтобы ускорить повторную загрузку ранее загруженных объектов. Важно помнить, что при этом возможна потеря актуальности представляемых данных, поэтому политика кэширования должна быть организована с учетом всех возможных ситуаций.
Кэширование — это один из наиболее мощных механизмов для уменьшения объема передаваемых по сети данных, притом внедряется этот механизм очень просто. Ниже приведено краткое описание наиболее значимых для кэширования заголовков.
Когда HTTP-сервер отправляет объект (например, HTML-документ или изображение) браузеру, он может дополнительно с ответом отправить заголовок Expires с меткой времени. Браузеры обычно хранят ресурс вместе с информацией об истечении его срока действия в
день недели(сокр.), число(2 цифры) месяц(сокр.) год часы:минуты:секунды GMT
Заголовок Expires устанавливает время актуальности информации. Для ресурсов, которые не должны кэшироваться, его нужно выставлять в текущие время и дату (документ устаревает сразу же после получения), для форсирования кэширования его можно определять на достаточно далекую дату в будущем, например:
Expires: Mon, 27 Dec 2027 00:00:00 GMT
Заголовок Cache-Control определяет набор директив, относящихся непосредственно ко времени и специфике кэширования документа. Для запрета кэширования можно выставить его в следующее значение:
Cache-Control: no-store, no-cache, must-revalidate
Если же, наоборот, требуется сохранить ресурс в кэш браузера на продолжительный период времени, например, на год (60 * 60 * 24 * 365 секунд), нужно отправлять следующий заголовок:
Cache-Control: max-age=31536000
Заголовок Last-Modified может отправляться сервером для того, чтобы передать браузеру информацию о дате последнего изменения документа. Дата должна задаваться в том же формате, что и в случае с заголовком Expires:
Last-Modified: Tue, 4 Aug 1995 04:58:08 GMT
При наличии такой информации в If-Modified-Since:
If-Modified-Since: Tue, 29 Oct 1994 19:43:31 GMT
В случае если дата последнего изменения осталась прежней, сервер ответит кодом состояния 304 Not Modified и данные не будут отправлены повторно. В противном случае сервер передаст новую версию файла.
Данная схема позволяет экономить время, затрачиваемое на передачу данных, однако при ее использовании браузер все равно будет устанавливать соединение с сервером, чтобы узнать, имеется ли более новая версия.
Заголовок ETag является почти полной аналогией заголовка Last-Modified за тем исключением, что в качестве передаваемого значения может выступать произвольная строка. Заголовок отправляется сервером в следующем формате:
ETag: "any-type-of-tag-or-hash"
Впоследствии, для того чтобы сервер мог определить, является ли объект, находящийся в кэше браузера, точно таким же, как соответствующий объект на сервере, браузер может отправить следующий заголовок:
If-None-Match: "any-type-of-tag-or-hash"
И аналогично, если теги совпадают, сервер отвечает кодом состояния 304 Not Modified и данные не передаются повторно. В противном случае сервер передаст новую версию файла.
Если время кэширования при помощи заголовков Expires и Cache-Control установлено на несколько лет вперед и требуется сообщить клиентскомубраузеру, что исходный объект изменился, можно воспользоваться двумя способами.
Можно обновить GET-строку запроса, например, используя номер версии или дату последнего изменения:
http://testdomain.com/global.css?v1
http://testdomain.com/global.css?20080901
А можно добавить номер версии или дату последнего изменения в само имя файла:
http://testdomain.com/global.v1.css
Во втором случае, для того чтобы исключить проблемы с локальными прокси-серверами, которые могут кэшировать файлы с GET-параметрами, и чтобы не создавать множество физических файлов, достаточно указать в конфигурации сервера правило: при запросах такого вида отдается каждый раз один и тот же файл.
В спецификации RFC-2616 HTTP-кэшированию посвящена целая глава. В ней подробно рассматривается, как работают все приведенные выше заголовки. Также о многих тонкостях использования кэширования более подробно рассказано в четвертой лекции.
Даже когда веб-страница и все внешние объекты загружены на компьютер пользователя, браузеру по-прежнему требуется время для того, чтобы разобрать страницу, интерпретировать код HTML и CSS, выполнить код JavaScript. Принимая во внимание особенности работы браузеров на этом этапе, можно достичь существенно более высокой скорости загрузки страницы.
Разбирая полученный HTML-код, браузер строит
Если на веб-странице присутствует большое количество элементов или объем CSS-кода достаточно велик, страница может прорисовываться с ощутимой задержкой. Когда объем кода уменьшить уже невозможно, более высокой скорости загрузки можно достичь за счет эффективной верстки. Основные рекомендации к верстке следующие.
#header .menu li a будет применяться дольше, чем аналогичный ему селектор #header .menu-item. В первом случае браузеру необходимо будет найти все ссылки на странице, проверить, находятся ли они в контексте элемента списка, элемента с классом menu и, наконец, элемента с идентификатором header. Второй вариант более предпочтителен, поскольку поиск элементов по классу и идентификатору выполнится существенно быстрее.При изменении ряда свойств элементов веб-страницы, а также в некоторых других ситуациях браузеры производят перерасчет геометрии и положения элементов, находящихся в потоке веб-страницы, после чего заново перерисовывают страницу или ее часть. Если веб-страница достаточно сложна, ее обновление будет заметно для пользователя и неизбежно вызовет задержку в его работе со страницей.
Вот неполный список действий, вызывающих в большинстве браузеров перерисовку страниц или их частей:
class, font, display, visible, margin, padding, width, height;:hover.Учитывая эти особенности, можно свести к минимуму число перерисовок страниц, а для того чтобы скорость перерисовок была наивысшей, необходимо:
position: absolute и position: fixed ;
От структуры HTML-документа во многом зависит скорость загрузки страницы пользователем. Даже при одинаковом суммарном размере страниц и равном количестве внешних объектов две различные страницы могут загружаться за совершенно разное время. Причина в том, что отображение элементов частично загруженной страницы в большинстве браузеров осуществляется только после выполнения следующих шагов:
<head> ;<body>, расположенных в потоке выше выводящегося элемента.В большинстве браузеров отображение страницы будет приостановлено до тех пор, пока все внешние CSS-файлы не будут загружены. Кроме того, теги <style>, встречающиеся на странице, будут порождать частичную или полную перерисовку страницы, иногда изменяя уже отобразившийся макет, с которым пользователь мог начать взаимодействовать.
Таким образом, более высокой скорости отображения страницы можно добиться, располагая в самом начале веб-страницы, в разделе <head>, все элементы <link>, содержащие вызовы файлов CSS-стилей, а также все встроенные стили, содержащиеся в тегах <style>.
Из-за того, что код JavaScript может изменять содержимое и макет веб-страницы, браузеры приостанавливают отображение элементов, следующих за JS-кодом, до тех пор, пока код не будет загружен и исполнен. Большинство браузеров при этом приостанавливают даже загрузку внешних объектов,следующих за таким JS-кодом. Однако если на момент начала загрузки JS-файла загрузка внешних объектов уже была начата, они будут загружены параллельно.
В приведенном ниже примере на веб-странице загружаются два внешних файла CSS и JS.
<head> <script type="text/javascript" src="script-1.js"></script> <link rel="stylesheet" type="text/css" href="style-1.css" /> <script type="text/javascript" src="script-2.js"></script> <link rel="stylesheet" type="text/css" href="style-2.css" /> </head>
При таком порядке следования в документе и при пустом кэше большинство браузеров будет вынуждено дождаться загрузки первого файла JavaScript, только потом начать загрузку следующих двух файлов CSS и JS и лишь по завершении загрузки второго файла JS загрузить последний файл стилей.
Всего лишь изменив порядок следования вызовов внешних объектов так, чтобы впереди были вызовы файлов CSS, можно получить ощутимый выигрыш в скорости загрузки.
<head> <link rel="stylesheet" type="text/css" href="style-1.css" /> <link rel="stylesheet" type="text/css" href="style-2.css" /> <script type="text/javascript" src="script-1.js"></script> <script type="text/javascript" src="script-2.js"></script> </head>
В этой ситуации браузер может инициировать параллельную загрузку сразу трех внешних объектов — двух файлов стилей и первого файла JS. По окончанию их загрузки браузеру остается загрузить лишь один файл JavaScript, и итоговое время загрузки будет ощутимо ниже.
Как видно на приведенной ниже диаграмме, в первой ситуации загрузка каждого файла JavaScript блокирует получение остальных внешних объектов, создавая дополнительные задержки. Во второй же ситуации вместе с загрузкой первого файла JS происходит параллельная загрузка максимально возможного количества внешних объектов.
(рис 1.12) Диаграмма загрузки внешних объектов при различном порядке их вызововРазумеется, экономия времени в каждом отдельном случае будет зависеть от размеров загружаемых объектов и их количества, однако пренебрегать этой особенностью не стоит.
Следует помнить, что данная особенность неактуальна в браузерах, поддерживающих параллельную неблокирующую загрузку внешних объектов. Перечень таких браузеров можно получить при помощи инструментов, описанных чуть ранее в этой лекции.
Во всех браузерах можно выделить несколько основных стадий загрузки страницы. Рассмотрим эти стадии.
Чтобы ускорить наступление предварительной загрузки, следует снизить число вызываемых в заголовке страницы файлов до минимума, применить к ним динамическое сжатие, или, для еще большего быстродействия — статическое сжатие. При использовании статического сжатия серверу не придется тратить дополнительное время на сжатие, он будет сразу готов отдать сжатый файл.
Загрузку файлов, не требующихся на стадии предварительной загрузки, имеет смысл перенести в стадию пост-загрузки.
Итогом первой стадии загрузки является доставленный и оформленный HTML-документ, с которым пользователь уже может взаимодействовать. Издержки на доставку всех файлов JavaScript должны быть сведены к минимуму, так как на этом этапе они только помешают, замедлив отображение основного содержимого страницы.
При правильной группировке загружаемых внешних объектов и за счет использования закэшированных браузером объектов эта стадия может наступать значительно быстрее.
Необходимо сконфигурировать веб-сервер так, чтобы при запросе любой другой страницы пришлось запрашивать минимум дополнительных объектов. Должен быть также продуман вопрос форсированного сброса кэша в ситуациях, когда это будет необходимо.
Также при запросе большого количества изображений браузер неизбежно столкнется с ограничением максимального количества соединений на хост, и для обхода этого ограничения необходимо настроить дополнительные серверы для выдачи статического содержимого. Число дополнительных хостов следует напрямую из числа статических файлов, поэтому надо определиться с ними на этапе автоматизации процесса публикации.
На этой же стадии можно использовать прием объединения изображений.
К началу этой стадии у пользователя уже должна быть в распоряжении оформленная HTML-страница, на которой все ссылки и формы должны работать без JavaScript.
На этой стадии могут загружаться любые объекты, которые необходимые для этой или каких-либо других страниц.
При помощи специального обработчика JavaScript, который начинает работать на этой стадии, возможно к уже существующей функциональности страницы добавить расширенные возможности в виде подсказок,дополнительных данных с сервера, какой-либо анимации и т. д.
Этот обработчик может производить следующие операции:
В случае применения технологии data:URI для уменьшения количества вызываемых объектов на этой стадии необходимо загружать файл CSS, содержащий все используемые на странице изображения в формате base-64.
Об отложенной загрузке ресурсов, не требующихся на момент первого отображения страницы, можно прочитать в пятой главе, а также в седьмой главе книги "Разгони свой сайт".
Во многих современных браузерах, в частности, в последних версиях браузера Safari, активно внедряется прогрессивная логика отображения страницы.
С одной стороны, браузер не ждет последовательной и полной загрузки всех блокирующих вывод страницы внешних объектов, а с другой — не отображает неформатированную веб-страницу. Сочетая преимущества сразу нескольких подходов, браузер определяет, в какой момент какую часть страницы можно отобразить, чтобы опыт пользователя был наилучшим.
Загрузка всех внешних объектов производится параллельно, и разбор содержимого не останавливается. При этом, если производится обращение к свойству стиля или макета, модуль JavaScript приостанавливает свою работу и ожидает загрузку всех незагруженных файлов CSS. Как только все стили загружены, выполнение сценария продолжается с того места, где оно было приостановлено.
У всех браузеров существует ограничение на количество соединений на один хост, находящееся в интервале от 2 до 8 соединений на хост. Для увеличения скорости загрузки внешних объектов можно применять распределенную систему хранения и доставки контента (CDN), организовав или арендовав систему хостов, находящихся на одном или нескольких физических серверах (географически распределенных, если это требуется). Часть хостов должны принимать и обрабатывать запросы пользователей, создавать и передавать результирующие HTML-документы. Остальные хосты должны использоваться только для передачи клиентом статических ресурсов. Благодаря такой схеме скорость доставки контента пользователям будет максимальной, в то же время нагрузка на хостинг веб-сайта может значительно снизиться.
Необходимо заметить, что разделять по нескольким хостам имеет смысл только изображения и файлы CSS, так как файлы JavaScript почти во всех браузерах загружаются строго последовательно.
Создать подобную систему распределенного хранения можно либо при помощи автоматического балансировщика, либо установив альтернативные пути к внешним объектам вручную.
Большое число дополнительных хостов может увеличить временные затраты браузера на установление соединений, поэтому в наибольшем количестве ситуаций предпочтительно использование не более 5 дополнительных хостов (1 основной хост и 4 для параллельной загрузки кэширу-емых объектов) без учета не контролируемых вами хостов, например рекламных. Это позволяет ускорить загрузку приблизительно на 60% в случае большого количества файлов.
Подробнее о системах распределенного хранения контента (CDN) рассказано в пятой лекции.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.