Introduction to the Resource Timing API

Share this article

SitePoint has published some good articles on performance recently. In particular, Craig Buckler wrote an article entitled Average Page Weights Increase by 32% in 2013 along with another one discussing some easy wins to reduce the weight of a website.

But improving the speed of our websites and apps isn’t just a matter of minifying JavaScript files and employing an image compressor. In many cases we have to deal with external resources (libraries from a CDN, videos from YouTube, images from Flickr, and so on) or internal resources that need to be accurately measured to establish what’s slowing down the loading of our pages.

I’ve previously covered some APIs that can help in testing the performance of a website. For example, the High Resolution Time API and the User Timing API. In this article, I’ll introduce you to another API in this category: The Resource Timing API.

What’s the Resource Timing API?

The Resource Timing API allows you to collect complete timing information related to resources in a document. It enables you to measure user latency, which is crucial to benchmark web pages. This API is a W3C Candidate Recommendation so we can be sure that significant features are mostly locked, but there could be minor changes to the spec in the future.

Using the Resource Timing API allows us to retrieve and analyze a detailed profile of all the network timing data for every resource on the page. We’ll cover what these data are in the next section. For the moment, it’s important that you understand how this API can help us in tracking the performance of the resources of our page, and determine how many and what resources we have to optimize.

Now that we know what this API is, let’s delve into its features.

Methods, Properties, and Events

The Resource Timing API is exposed through the performance property of the window object. We can retrieve the information collected for each resource using the getEntriesByType() method. If this sounds familiar to you, this is because it’s the same method used by the User Timing API. The difference is that to retrieve information about these resources we have to pass the string resource to getEntriesByType().

The getEntriesByType() method returns a list of PerformanceResourceTiming objects, which extend the PerformanceEntry interface. Because of this, each of these objects expose the following inherited properties:

  • name – The resolved URL of the requested resource
  • entryType – The value is always equal to resource
  • startTime – The time immediately before the user agent starts to queue the resource for fetching
  • duration – The difference between responseEnd and startTime

In addition to these properties, the Resource Timing API exposes another property called initiatorType. If the request has been initialized by an element on the page, its value is equal to the name of the tag (e.g. img for <img>, script for <script>, and so on). Other possible values are css (for CSS resources downloaded using the url() syntax — e.g. background: url(...)) and xmlhttprequest (for XMLHttpRequest objects).

Each PerformanceResourceTiming object provides the following specific and read-only attributes:

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

The following image offers a graphical representation of these attributes. Those that are underlined may not be available when fetching resources from different origins:

Illustrating the timing attributes defined by the PerformanceResourceTiming interface

Resources fetched from a third-party must provide an additional HTTP header (Timing-Allow-Origin: *) to allow the site to gather detailed network timing data. If the header is absent, the only available data is the total duration of the request. This may seem like an important limit to the use of this API. However, as Ilya Grigorik wrote in his post Measuring network performance with Resource Timing API, several websites like Google, Facebook, and Disqus, have implemented the header to offer this information.

As we’ve seen, the Resource Timing API provides a lot of attributes that we can read to understand where the time is spent for each resource. However, it also provides two methods: clearResourceTimings() and setResourceTimingBufferSize(). The former clears the buffer used to store the current list of PerformanceResourceTiming resources.

The latter sets the maximum number of objects stored in the buffer. It accepts an integer to specify the limit. If the method isn’t called explicitly, the specification states that the user agent should store at least 150 PerformanceResourceTiming resources. When the limit of the resources to store is reached, the API fires an event called onresourcetimingbufferfull.

Now that we’ve learned the attributes, methods, and events exposed, let’s see how many browsers support this API.

Browser Compatibility

Browser support for this API is decent on desktop as it has been implemented in Chrome 25+, Internet Explorer 10+, and Opera 15+. On mobile, the situation is very similar with the addition of the latest versions of the Android browser.

Testing if a browser supports this API is a bit tricky because we have to test for several conditions. First we have to test for the presence of the performance property of the window object. Then, we have to test for the presence of the getEntriesByType() method and that it’s able to collect resources. This last condition can be verified by checking that the call to getEntriesByType('resource') returns an array.

Turning this description into code results in the following snippet:

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

Building a Demo

In this section we’ll build a simple demo that allows us to see this API in action and the information it provides. The demo loads two resources: an image from SitePoint.com included via an <img> tag, and the jQuery library from the Google CDN via a <script> tag.

While both are external resources, the latter allows us to gather timing information thanks to the Timing-Allow-Origin: * header. This means that even if it’s an external resource, we’ll obtain all the information exposed by the API.

With the markup in place, the first thing we have to do is to test if the browser supports the Resource Timing API. If the API isn’t supported, we display the message “API not supported”. In case the browser implements the API, we attach a listener to the load event of the window object. In this way we’re sure to execute any action after all the resources are loaded. Inside the handler, we create a list on-the-fly to show the measures obtained through the API.

Our demo page will use the following 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="https://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>

And here’s the JavaScript that will display some data that we can examine, which will show us what the API can do:

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;
        }
     });
  }

You can view the code live here.

Conclusion

As we’ve seen, using this API shouldn’t be too difficult for you to employ it in a future project. Unfortunately, the support among browsers is not ideal, but the fact that three of the major browsers (Chrome, Opera, and Internet Explorer) supports it is still good news.

There are no more excuses for failing to improve the performance of your website, and this new API will make it that much easier.

Frequently Asked Questions (FAQs) about Resource Timing API

What is the main purpose of the Resource Timing API?

The Resource Timing API is a powerful tool that provides detailed network timing data for all resources loaded by a web application. This includes images, CSS, JavaScript, and any other resources referenced by the application. The API allows developers to accurately measure the performance of their web applications, identify bottlenecks, and optimize resource loading for better user experience.

How does the Resource Timing API differ from other performance measurement tools?

Unlike other performance measurement tools that only provide high-level timing data, the Resource Timing API provides granular timing information for each individual resource. This includes the time taken for DNS lookup, TCP handshake, request and response times, and more. This level of detail allows developers to pinpoint exactly where performance issues are occurring.

How can I access the data provided by the Resource Timing API?

The Resource Timing API exposes a JavaScript interface that developers can use to access the timing data. This interface is accessible through the window.performance object. The getEntriesByType("resource") method can be used to retrieve an array of PerformanceResourceTiming objects, each representing a resource loaded by the application.

What information is included in a PerformanceResourceTiming object?

A PerformanceResourceTiming object includes a wealth of information about the loading of a resource. This includes the URL of the resource, the type of the resource (e.g., “img”, “script”), and detailed timing data such as startTime, responseEnd, and duration. It also includes more specific timings like fetchStart, domainLookupStart, domainLookupEnd, connectStart, connectEnd, requestStart, responseStart, and responseEnd.

Can I use the Resource Timing API to measure the performance of third-party resources?

Yes, the Resource Timing API can be used to measure the performance of both first-party and third-party resources. However, due to privacy concerns, some timing data for third-party resources may be restricted or unavailable.

Is the Resource Timing API supported by all browsers?

The Resource Timing API is widely supported by modern browsers, including Chrome, Firefox, Safari, and Edge. However, it may not be supported by older browsers or some mobile browsers. You can check the current level of support on websites like Can I Use.

Can the Resource Timing API impact the performance of my web application?

The Resource Timing API is designed to have minimal impact on the performance of your web application. It operates asynchronously and does not block the loading of resources. However, like any API, it should be used judiciously to avoid unnecessary overhead.

How can I use the Resource Timing API to improve the performance of my web application?

By providing detailed timing data for each resource, the Resource Timing API allows you to identify bottlenecks and optimize resource loading. For example, you might discover that a particular image is taking a long time to load, and decide to optimize it or load it asynchronously. Or you might find that a third-party script is slowing down your page load, and decide to defer it or load it in a different way.

Can I use the Resource Timing API in conjunction with other performance APIs?

Yes, the Resource Timing API can be used in conjunction with other performance APIs, such as the Navigation Timing API and the User Timing API, to provide a comprehensive view of your web application’s performance.

Are there any limitations or caveats I should be aware of when using the Resource Timing API?

One limitation of the Resource Timing API is that it only provides timing data for resources that are loaded by the current page. It does not provide timing data for resources that are loaded by iframes or other embedded content. Additionally, as mentioned earlier, some timing data for third-party resources may be restricted or unavailable due to privacy concerns.

Aurelio De RosaAurelio De Rosa
View Author

I'm a (full-stack) web and app developer with more than 5 years' experience programming for the web using HTML, CSS, Sass, JavaScript, and PHP. I'm an expert of JavaScript and HTML5 APIs but my interests include web security, accessibility, performance, and SEO. I'm also a regular writer for several networks, speaker, and author of the books jQuery in Action, third edition and Instant jQuery Selectors.

html5 apiLouisLnetwork latencyperformance timingperformance-toolsresource timingresource timing apitiming api
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week