Websites are no longer websites. More precisely, a website is no longer a “site,” a single, static location. Instead, the race to build more immersive digital experiences is making websites more dynamic and interactive, with content and logic updated in real time. Websites are now often called “web applications,” whether they comprise e-commerce shopping carts, media/content galleries, software portals, or other functions.
This evolution has allowed developers to create more engaging experiences for users, but some of the foundational thinking about how we measure website performance hasn’t kept up with these changes. For example, while page load time remains a key metric for how web apps are measured, the term’s definition no longer completely matches how web apps are designed and used. That’s particularly true with the shift towards “Single Page Apps,” such as with React or Angular. The result can dramatically over- or under- measure your page load times, or miss certain page loads completely. And that can skew a key metric that development, business, marketing, and IT stakeholders all use to make important decisions about their websites.
Reviewing the definition of a page load
So, how should we think about this new world of page loads?
The web performance community took a major step forward in 2010 when Chrome, Firefox, and Internet Explorer began to implement the W3C spec that would become the Navigation Timing API standard. Increased visibility into page load timing was a recognized need, and while it was possible to manually build timing instrumentation into a website, this new browser API provided a less-intrusive, standard way to capture this information from the web browser itself. The Navigation Timing spec continues to be actively used and updated, with expanded support and improvements to timing granularity.
The API describes a series of milestones that occur during a page load, culminating with the
window.load event. When the
window.load event fires, it demarks the end of the document-loading process, when all of the objects in the document are in the DOM, and all the images, scripts, stylesheets, and sub-frames have finished loading. For a static website, when the window.load event is fired, the page is fully loaded into the browser window, completely rendered and ready to be used.
Page Load Process for Traditional Websites
A new world of dynamic content
We can see this in number of use cases:
- Dynamic content loading: Pulling customized content dynamically based on user consumption
Examples: Customized news/video content based on user viewing patterns, customized product recommendations for a shopping cart, customized user-account information
- Lazy loading: Downloading content only after the user scrolls it into the window viewport, in order to speed the initial page load by reducing the amount of content involved
Example: Scrolling through a photo-album carousel, dashboard, or content widgets
- Third-party widgets: Pulling components and content from external services
Examples: Social media widgets from Twitter or Facebook, feedback widgets, discussion widgets, display advertisements
- Real-time content: Continuous polling of a backend system to pull refreshed data
Examples: Live game trackers, election results, live blogs, event broadcasts
- Pre-loaded content: Loading content invisibly behind the scenes for a more seamless user experience
Examples: Infinite scrolling news sites that automatically load the next article as the user scrolls through the first, autoplaying video content
These more sophisticated experiences drive increased architectural complexity for web applications, and the
window.load event no longer captures a complete representation of the users’ experiences.
Page Load Process for Modern Web Applications
Dynamic views with Single-Page Apps
Single-Page Apps (SPAs)—often built with frameworks or libraries like React, Angular, Ember, Backbone, and others—take these ideas around dynamic user experiences to the next level. More than just dynamic content or widgets, SPAs render completely new views for a user as part of a route change. After clicking on a link, users may think that they’ve navigated to another page, but they may have actually just had dynamically pulled content re-rendered client-side, without a full page refresh.
Visibility to track these route changes has become important, since users experience them as a new “soft” page load. However, the
window.load event is unable to track these route changes, and would see these subsequent user interactions and route change activities as still part of the original page load.
Understanding the “true” customer experience of your page load
Between dynamic content and SPAs, the gap between the
window.load event and when a user can actually use the page becomes increasingly significant. A page may take only 200 ms for the onload event to fire, but by the time all the AJAX calls have finished and the DOM has settled, it may be 1000 ms (or even double that) before the page is fully rendered and usable. This later time is a more accurate representation of the customer experience.
And this is just a simplified example. Many modern web experiences employ several of these design use cases at once, which can further slow the “true” customer experience of the page. For companies that care about their digital customer experience, getting a true view of the customer experience of a page load can be an enlightening experience, uncovering how long it really takes for a user to start engaging with web content, not to mention the impact this can have on key metrics like conversions, engagement, and digital revenue.
Measuring page loads in a new world of dynamic web pages
window.load event remains an important metric, but it increasingly tells only a partial story of the customer’s page load experience. Let’s take a look at New Relic Browser’s SPA monitoring to see what happens after that initial page load event for a Angular application:
For a given page load in an application, we can see breakdowns across backend time, frontend time, and when the window.onload event occurred. This is far more complete information than the
window.load event, when it actually took close to 10 seconds in frontend time for the page to be finished.
This deeper visibility into page loads is valuable, though in a Single-Page Application, it may be the case that route changes make up a greater part of your user experience than page loads. In this same Angular application, we can see that there’s actually more throughput traffic with route changes than for page loads.
The same way we can look into page load timings, we can also drill into route change timings with New Relic Browser’s framework-agnostic SPA instrumentation. No matter what framework is being used, or even if something is custom-built based on SPA principles, we can get this deep visibility into this frontend performance.
Once you have visibility into what customers are actually experiencing during page loads and route changes, the next question is how to improve it.