In the year since SOASTA announced support for monitoring the performance of single page applications (SPAs), we've been continually improving how we help our customers measure their apps.
We've learned a lot from our customers from how they are building their single page apps. Many of our monitoring improvements are being driven by the variety of websites that our customers are building, using everything from do-it-yourself templating engines to full-blown frameworks such as Angular, Backbone.js, Ember.js, or React.
There are two key things we've learned, which have driven the development of our SPA monitoring and measurement capabilities:
- Every SPA looks and behaves differently. The great thing is that the methodology we're using for measuring SPAs can be applied to nearly every single page app out there. While the details of how to instrument each SPA may vary by framework, as long as we know when to start monitoring important user interactions, measuring these SPA navigations has given our customers better visibility into the performance of their applications beyond the "onload" metric the performance community had focused on for years.
- We've also been able to learn a lot about how our customers want to monitor, diagnose, and fix the performance of their apps. While tracking the overall SPA load time is important, developers may need additional data to improve it. For example, it's important to understand whether it's a hard or soft navigation, as each will have different performance characteristics. (More on this later in this post.) Being able to know whether the majority of the time is being spent in back-end or front-end can help determine where developers will focus their energy.
This post will highlight some of the changes we've been rolling into Boomerang (an open-source library used to capture performance metrics) to better monitor single page applications.
Support for Every SPA Framework
When we originally announced support for monitoring the performance of single page applications, we focused on supporting AngularJS. Since then, as more SPA frameworks have become popular, we've extended support to nearly every framework out there:
While we have full-fledged support for the most popular SPA frameworks, the last item in the list is important because it means we support essentially every SPA framework out there, as long as it updates the URL or hash (#) when the view changes.
For example, all of the major frameworks listed above also use window.history to change the URL (without the browser actually navigating) as the user is clicking around. Most SPA frameworks have the concept of a "route", which is often tied to a unique view. When the route changes, we know a SPA navigation has started, and we can begin monitoring.
In addition, we've also added support for Angular's ui-router module, which is an alternative to ng-router.
Understanding hard versus soft navigations
In the world of single page apps, there are two distinct types of "navigations":
- Hard navigation: The first time a visitor loads your app
- Soft navigation: Every route change after the hard navigation
These two types of SPA navigations have drastically different performance characteristics, and it's important to be able to analyze them separately. For most SPAs, every URL on your site could be loaded either via a hard navigation or a soft navigation, depending on whether the user started from another site (e.g. search results) or from an internal page.
A hard navigation is the first navigation to your site. During this navigation the browser is doing a full navigation by tearing down any page it was on previously, fetching the new page's HTML and downloading all of its resources. Remember that with single page applications, during a hard navigation the onload event is no longer relevant and is just one milestone on the way to getting all of the page's resources. After the SPA framework is downloaded (i.e. the angular.js file), it will begin to fetch any templates, script, images or XHRs necessary to render the current view. All of this may happen after the onload event.
How we updated Boomerang: Because of these factors, a soft navigation will always be faster than the initial hard navigation. Boomerang now logs whether each SPA navigation is a hard or a soft navigation, so you can track the experience for each.
Understanding Backend vs. Frontend Time
In a traditional website, a page load's performance is often split between back-end and front-end times. Here's how our community defines the two for a traditional (non-SPA) website:
- Back-end: From the beginning of the navigation to the first bytes of the root HTML.
- Front-end: From the first bytes of the root HTML to the page's onload event.
Splitting the time up in this way is important because it helps you determine which components are contributing to the overall page load experience. It's useful to have this breakdown so you can know where to focus your investigations. For example, if your back-end time comprises 80% of the overall page load time, you may want to look into speeding up your web servers. But typically, front-end dominates overall load time, as in this graph, which shows front-end and back-end times over a one-month period:
With single page apps, we can't use these same definitions. For one thing, the onload event doesn't matter. And second, hard navigations and soft navigations behave differently and require unique definitions of what back-end time means.
At SOASTA, we've decided to define back-end and front-end for SPAs differently than with traditional apps:
- Hard navigations:
- Back-end: From the beginning of the navigation to the first bytes of the root HTML
- Front-end: From the first bytes of the root HTML to the end of the last resource fetched for the view (route)
- Soft navigations:
- Front-end: The total time of the soft navigation minus the back-end time
How we updated Boomerang: Boomerang has been updated to measure the back-end and front-end for SPAs time according to these definitions.
In addition to the monitoring features above, we've found that each customer site is built a little differently than the next. To help our customers measure the exact metrics that are important to them, we've made Boomerang a bit more flexible for single page apps.
For example, we've added the following features:
- Some "routes" (views) aren't as important as others. For example, depending on how you've built your app, the URL may change when a minor widget on the page is clicked, even though the entire view doesn't change. We've given our customers the ability to filter out specific route changes so they can focus on the ones that matter most.
- The way we've defined the end of a SPA navigation may not work in every circumstance, so we've added a feature to Boomerang so the customer can let us know when the navigation is complete.
- In addition to monitoring single page apps, we also support monitoring individual XMLHttpRequests (XHRs). We've expanded XHR support to be able to monitor XHRs before boomerang.js has even loaded.
How we updated Boomerang: You can see these new features (and more) in the open-source Boomerang project.