Статьи

Введение в Resource Timing API

Недавно SitePoint опубликовал несколько хороших статей о производительности. В частности, Крэйг Баклер написал статью под названием « Увеличение среднего веса страниц в 2013 году на 32%», а также в другой статье обсуждались некоторые простые способы снижения веса веб-сайта .

Но повышение скорости работы наших веб-сайтов и приложений не сводится к минимизации файлов JavaScript и использованию компрессора изображений. Во многих случаях нам приходится иметь дело с внешними ресурсами (библиотеками из CDN, видео с YouTube, изображениями из Flickr и т. Д.) Или внутренними ресурсами, которые необходимо точно измерить, чтобы определить, что замедляет загрузку наших страниц.

Ранее я рассмотрел некоторые API, которые могут помочь в тестировании производительности веб-сайта. Например, API High Resolution Time и User Timing API . В этой статье я познакомлю вас с другим API в этой категории: Resource Timing API .

Что такое API синхронизации ресурсов?

Resource Timing API позволяет собирать полную информацию о времени, связанную с ресурсами в документе. Это позволяет измерять задержку пользователя, что крайне важно для оценки веб-страниц. Этот API является Рекомендацией кандидата W3C, поэтому мы можем быть уверены, что важные функции в основном заблокированы, но в будущем в спецификации могут быть небольшие изменения.

Использование Resource Timing API позволяет нам получать и анализировать подробный профиль всех данных синхронизации сети для каждого ресурса на странице. Мы рассмотрим эти данные в следующем разделе. На данный момент важно, чтобы вы понимали, как этот API может помочь нам отслеживать эффективность ресурсов нашей страницы, и определяете, сколько и какие ресурсы мы должны оптимизировать.

Теперь, когда мы знаем, что это за API, давайте углубимся в его возможности.

Методы, свойства и события

Resource Timing API предоставляется через свойство performancewindow Мы можем получить информацию, собранную для каждого ресурса, используя метод getEntriesByType() Если это звучит знакомо вам, это потому, что это тот же метод, который используется API User Timing. Разница в том, что для получения информации об этих ресурсах мы должны передать строковый resourcegetEntriesByType()

Метод getEntriesByType()PerformanceResourceTimingPerformanceEntry Из-за этого каждый из этих объектов предоставляет следующие унаследованные свойства:

  • name
  • entryTyperesource
  • startTime
  • durationresponseEndstartTime

В дополнение к этим свойствам API Resource Timing предоставляет другое свойство initiatorType Если запрос был инициализирован элементом на странице, его значение равно имени тега (например, img<img>script<script> Другими возможными значениями являются cssurl()background: url(...)xmlhttprequestXMLHttpRequest

Каждый объект PerformanceResourceTiming

  • initiatorType
  • redirectStart
  • redirectEnd
  • fetchStart
  • domainLookupStart
  • domainLookupEnd
  • connectStart
  • connectEnd
  • secureConnectionStart
  • requestStart
  • responseStart
  • responseEnd

Следующее изображение предлагает графическое представление этих атрибутов. Те, которые подчеркнуты, могут быть недоступны при получении ресурсов из разных источников:

Иллюстрирование атрибутов синхронизации, определенных интерфейсом PerformanceResourceTiming

Ресурсы, получаемые от сторонних производителей, должны предоставлять дополнительный заголовок HTTP ( Timing-Allow-Origin: * Если заголовок отсутствует, единственными доступными данными является общая продолжительность запроса. Это может показаться важным ограничением использования этого API. Однако, как писал Илья Григорик в своем посте « Измерение производительности сети с помощью Resource Timing API» , некоторые веб-сайты, такие как Google, Facebook и Disqus, внедрили заголовок для предоставления этой информации.

Как мы уже видели, API Resource Timing предоставляет множество атрибутов, которые мы можем прочитать, чтобы понять, на что тратится время для каждого ресурса. Однако он также предоставляет два метода: clearResourceTimings()setResourceTimingBufferSize() Первый очищает буфер, используемый для хранения текущего списка ресурсов PerformanceResourceTiming

Последний устанавливает максимальное количество объектов, хранящихся в буфере. Он принимает целое число, чтобы указать предел. Если метод не вызывается явно, в спецификации говорится, что пользовательский агент должен хранить не менее 150 ресурсов PerformanceResourceTiming Когда лимит ресурсов для хранения достигнут, API запускает событие onresourcetimingbufferfull

Теперь, когда мы узнали об атрибутах, методах и событиях, давайте посмотрим, сколько браузеров поддерживают этот API.

Совместимость браузера

Браузерная поддержка этого API вполне приемлема для настольных компьютеров, поскольку она реализована в Chrome 25+, Internet Explorer 10+ и Opera 15+. На мобильных устройствах ситуация очень похожа с добавлением последних версий браузера Android.

Проверить, поддерживает ли браузер этот API, немного сложно, потому что мы должны протестировать несколько условий. Сначала мы должны проверить наличие свойства performancewindow Затем мы должны проверить наличие метода getEntriesByType() Это последнее условие можно проверить, проверив, что вызов getEntriesByType('resource')

Превращение этого описания в код приводит к следующему фрагменту:

 if ( !('performance' in window) ||
    !('getEntriesByType' in window.performance) ||
    !(window.performance.getEntriesByType('resource') instanceof Array)
  ) {
  // API not supported
} else {
   // API supported. Hurray!
}

Создание демо

В этом разделе мы создадим простую демонстрацию, которая позволит нам увидеть этот API в действии и информацию, которую он предоставляет. Демонстрация загружает два ресурса: изображение с SitePoint.com, включенное через <img><script>

Хотя оба являются внешними ресурсами, последний позволяет нам собирать информацию о времени благодаря заголовку Timing-Allow-Origin: * Это означает, что даже если это внешний ресурс, мы получим всю информацию, предоставляемую API.

При наличии разметки первое, что нам нужно сделать, — это проверить, поддерживает ли браузер Resource Timing API. Если API не поддерживается, мы отображаем сообщение «API не поддерживается». Если браузер реализует API, мы присоединяем слушателя к событию loadwindow Таким образом, мы обязательно выполним любое действие после загрузки всех ресурсов. Внутри обработчика мы создаем список на лету, чтобы показать показатели, полученные через API.

Наша демонстрационная страница будет использовать следующий HTML:

 <span id="rt-unsupported" class="hidden">API not supported</span>

  <div>
     <h2>Test 1 - jQuery</h2>

     <ul id="script-list">
     </ul>
  </div>
  <div>
     <h2>Test 2 - Image</h2>

     <img src="http://www.sitepoint.com/wp-content/themes/sitepoint/assets/svg/sitepoint.svg" />
     <ul id="img-list">
     </ul>
  </div>

  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

А вот JavaScript, который будет отображать некоторые данные, которые мы можем исследовать, что покажет нам, на что способен API:

 if ( !('performance' in window) ||
       !('getEntriesByType' in window.performance) ||
       !(window.performance.getEntriesByType('resource') instanceof Array)
     ) {
     document.getElementById('rt-unsupported').classList.remove('hidden');
  } else {
     window.addEventListener('load', function() {
        var resources = window.performance.getEntriesByType('resource');
        for(var obj in resources) {
           var list = '';
           for(var properties in resources[obj]) {
              list += '<li>' + properties + ': <span class="value">' + resources[obj][properties] + '</span></li>';
           }
           document.getElementById(resources[obj].initiatorType + '-list').innerHTML = list;
        }
     });
  }

Вы можете посмотреть код в прямом эфире здесь .

Вывод

Как мы уже видели, использование этого API не должно быть слишком сложным для использования его в будущем проекте. К сожалению, поддержка среди браузеров не идеальна, но тот факт, что три основных браузера (Chrome, Opera и Internet Explorer) поддерживают ее, все еще является хорошей новостью.

Больше нет оправданий неспособности улучшить производительность вашего сайта, и этот новый API сделает это намного проще.