Rishikesh Borkotoky

Using Navigation Timing APIs to understand your webpage

Blog Post created by Rishikesh Borkotoky Employee on Aug 25, 2016

Any webpage can be made slick and beautiful today (I mean just look at this page which was made almost a year back!) but to really understand the beauty of your webpage you should not just look at the different CSS , designs/templates or third party tools that can be used but also the inner working of your page and how fast users can work with it. To go about understanding this performance aspect of your page you can use a vast majority of RUM solutions and synthetic testing platforms such as webpagetest.org (everyone’s 2nd free app after WINRAR) or you can also use the Navigation Timing APIs that are already available in your browser.

 

The navigation timing APIs were released in 2011 and are built in-to most modern browsers such as Chrome, Mozilla, IE/Edge and solved many problems for a lot of people who wanted to capture page performance metrics from within real browsers. This inbuilt JavaScript API marks the EPOCH timestamps of most browser events related to performance and navigation and we can use these timestamps to look at certain KPIs for a webpage by just collecting these timings via a simple script. It’s of course easier said than done as there are many factors that need to be taken into account here. For example, you will need someone to analyze all that data, understand how to use it to improve the performance/make the numbers better, consider outliers etc. However, that should not stop anyone from trying it all out so below is a simple summary of these Navigation timings and how some of those attributes can be used to understand where your webpage is slowing down.

 

 

The Navigation Timing API and its attributes

 

We will not delve into the definition of popular metrics or KPIs individually but instead try to understand them in conjunction with the W3C Navigation Timing API [1]

 

                   navigation-timing                                    Overview of the different Navigation Timings involved as per the W3C spec [2]

 

  • Navigation Start: This is where it all begins or in some cases begins again. The attribute navigationStart will mark the time when the previous document/page has terminated. If there is no previous document this value will be equal to the value of performancetiming.fetchStart which is the time at which the browser is ready to fetch the requested document using a HTTP request.

 

  • Unload Events: An unload even is thrown when user navigates away from the page. For example, the user could have clicked on a link to leave the page, typed in a new URL in the address bar, used the forward or back buttons on the browser or closed the current browser window. Even a page reload will first create an unload event. We can can the values of both the start and end of these events from the attributes unloadEventStart and PerformanceTiming.unloadEventEnd.

 

  • Redirection: Any overhead that is added by HTTP redirects can be looked at from the attributes redirectStart and PerformanceTiming.redirectEnd.

 

  • Domain Lookup: The time when domain lookup starts and ends is marked by the attributes domainLookupStart and PerformanceTiming.domainLookupEnd respectively. If there was a persistent connection involved or the content was stored in local resources such as cache the value will be same as PerformanceTiming.fetchStart.

 

  • Connection Times: The value for the moment when the request was made to open a connection to the network is measured by the attribute connectStart and the moment when the connection is opened is measured by PerformanceTiming.connectEnd. Note that if there is an issue in the transport layer the connection establishment is restarted again so these attributes alone won’t give us an insight if there was an issue in the transport layer. For HTTPS connections the attribute that measures the start of the secure handshake is PerformanceTiming.secureConnectionStart.

 

  • Request/Response Times: The time when the browser sent the request to obtain the document is stored in the attribute requestStart. The time when the browser received the first byte and the last byte of response is present in the attributes PerformanceTiming.responseStart and PerformanceTiming.responseEnd. The response to the requests can be from any source such as a server or from cache and that is independent of the timings.

 

  • DOM Events: There are various events that occur until a page has fully loaded and some critical components of the same process can be separated by the various DOM events and Onload events.
    • The start time of the entire process can be retrieved from the attribute domLoading. This signifies the time that the browser is going to start parsing of the bytes of HTML that have been received.
    • domInteractive marks the time at which browser has completed parsing the entire HTML and constructed the DOM i.e. the DOM is now ready.
    • Once the CSSOM is ready and no stylesheets that are blocking/waiting for some JS execution are left, the browser can begin creating the render tree. This start and end time of this process is marked by the domContentLoadedEventStart and domContentLoadedEventEnd and allows us to track how long this execution took. Many webpages have logic/application frameworks that wait for the onload event to fired.                          Simple Process of Render Tree construction when we have Synchronous JS involved [3]
    • Once all the the processing is complete and all the page resources have been loaded (the loading spinner on the browser has stopped) the time is marked by domComplete i.e. the page and all it’s sub resources are ready.

 

 

  • Load Events: As a final step in every page load, the browser will fire an onload event which can trigger any additional functions or logic waiting for this event. The start time of this is marked by Timing.loadEventStart and the moment the load event is complete is marked by PerformanceTiming.loadEventEnd.

 

 

Using the attributes to measure KPIs

 

Now that we have a slight understanding to what the API and its attributes are we can combine them together to measure the different events that have occurred on your page and see where exactly its slowing down. Here are some examples of metrics that can be calculated:

 

  • Total First byte Time = responseStart - navigationStart
  • Latency = responseStart – fetchStart
  • DNS / Domain Lookup Time = domainLookupEnd - domainLookupStart
  • Server connect Time = connectEnd - connectStart
  • Server Response Time = responseStart - requestStart
  • Page Load time = loadEventStart - navigationStart
  • Transfer/Page Download Time = responseEnd - responseStart
  • DOM Interactive Time = domInteractive - navigationStart
  • DOM Content Load Time = domContentLoadedEventEnd - navigationStart
  • DOM Processing to Interactive =domInteractive - domLoading
    How long the browser spends loading the webpage until the user can starting interacting with it.
  • DOM Interactive to Complete = domComplete - domInteractive
    How long it takes for the browser to load images/videos and execute any JavaScript code waiting for the domContentLoaded event.
  • Onload = loadEventEnd - loadEventStart
    How long it takes the browser to execute Javascript code waiting for the window.load event.

 

 

If you would like to try the same on your own webpage you can use the below code snippet and give it a shot.

var a = window.performance.timing,

interactive = a.domInteractive - a.domLoading, dcl = a.domContentLoadedEventStart -   a.domLoading, complete =  a.domComplete - a.domLoading ,  dns = a.domainLookupEnd - a.domainLookupStart , tcp = a.connectEnd -  a.connectStart , ttfb = a.responseStart - a.navigationStart ;       

textContent ='ttfb :'+ttfb+ 'ms , interactive: ' + interactive + 'ms, ' + 'DOM content loaded: ' + dcl + 'ms, DOM complete: ' + complete + 'ms , dns :'+dns + 'ms , tcp: '+ tcp+ 'ms';

 

If you want to have a look at these timings without adding any scripts or editing the code on your page, as I previously mentioned modern browsers will also capture the timings on every run. You can access the same by following any of the below methods

  • Open up the console from the Tools Menu of your browser (press Ctrl-Shift-J on Windows and Linux, or Command-Option-J on a Mac).
    • Just type in ‘performance.timing’ which will bring in the values and on expanding you can see the EPOCH values collected. Then its just a matter of doing the required calculations or you can also calculate the same within the console.
  • If you are running google chrome, you can store the above snippet as well and run it to give you the required metrics.
    • Head over to the sources tab on the DEV tools. Switch to the Snippets view and save the script as a new snippet. We can run this at anytime to directly get the required metrics in the console. 

          

That’s all folks

 

I hope you were able to get a better understanding and end up using the Navigation Timing APIs to breakdown your page performance. The entire explanation to the Navigation Timing API is of course available at the official W3 Spec where you can find more details on each of the Navigation Timing API attributes and look for more ways of using these APIs on your website.

 

 

Bibliography:

[1] https://www.w3.org/TR/navigation-timing/

[2] https://www.w3.org/TR/navigation-timing/timing-overview.png

[3] http://www.igvita.com/posts/12/doc-render-js.png

Outcomes