Network latency in web applications is not a new performance culprit. Developers and operations teams have known for years that sending and receiving data over networks can be slow. Yet as web pages carry consistently increasing amounts of CSS, JavaScript, and HTML, optimizing for better network performance—from reducing the number of connections to caching to bundling AJAX requests—still doesn’t get the attention it deserves.

To change that, let’s look at some common network-related performance problems developers experience when using single-page app (SPA) frameworks, and discuss how to address them as browser vendors encourage developers to use secure connections and new protocols like HTTP/2 gain wider acceptance.

Revisiting the client-server model for SPA

Building a modern JavaScript web application requires a substantial amount of technical knowledge. SPAs introduce an even more complicated development model than the designers of the World Wide Web had in mind in the early 1990s. The original design of the Web—still visible in the navigation bar of nearly every browser—assumed a set of pages joined by hyperlinks that can be navigated backwards and forwards or reloaded.

In this model, comparing the load time of two simple HTML pages on the same domain is straightforward because they have different URLs, server-side processing time, and static dependencies such as CSS, images, and JavaScript.

Understanding performance in SPA apps is more challenging. It still relies on some combination of JavaScript, HTML, and CSS to render the page, but a SPA app makes additional requests (usually via AJAX) for additional content—including entirely new views—without completely reloading the originally requested page.

Performance questions like “How long did the page take to render?” and “How much time was spent doing server-side processing?” become complicated because a single view is often rendered using multiple HTTP requests triggered by JavaScript code that exists outside the classic browser page lifecycle.

Assume the network is slow and unreliable

Every smartphone user is familiar with pages that load slowly (or not at all) due to a flaky cellular data connection. As web apps capture an increasingly global, mobile audience, fast, reliable, and affordable internet connections can no longer be assumed.

Page size is closely related to how quickly a page loads, so measuring the overall size of the page is a good place to start the optimization process. Tools like New Relic Synthetics that give developers a breakdown of content sizes is a good starting point when deciding what can be removed or compressed.

This testing needs to be continuous and iterative, because web page sizes can vary over time. For example, when we analyzed presidential-candidate sites during the primary campaign in February 2016, the total response size and load time fluctuated wildly on some sites as images and videos were rapidly updated in response to current events.

Methods to reduce page transfer size vary. Simply removing unneeded JavaScript libraries and code and enabling image and gzip compression techniques on the server-side can help enormously. More advanced tools like Webpack or Rollup allow advanced dynamic loading and bundling techniques designed specifically for apps using SPA frameworks.

The best network request is one you don’t have to make

Correctly caching static and dynamic resources, a feature built into the HTTP protocol and every browser, is important for apps that depend on repeat visitors. Google has an excellent primer on HTTP caching that is required reading for understanding how and why to cache using the Cache-Control and ETag headers.

Content-delivery networks (CDNs) are especially powerful when used in conjunction with well-defined public caching strategies. By caching content at edge locations all over the globe on servers located physically closer to users, CDNs can significantly reduce network latency. With secure connections using the Transport Layer Security (TLS) protocol quickly becoming standard for mobile and web content, there are potential performance benefits to performing the handshake needed to establish a secure connection as geographically close to users as possible.

Most important, however, auditing and investing time on HTTP caching and CDN strategy benefits all browser and mobile browser clients regardless of SPA framework, device, location, or operating system.

Implementing web performance optimizations using microservices

Performance best practices like caching, bundling requests, leveraging CDNs, and the emergence of new protocols like HTTP/2 and TLS put pressure on the systems and infrastructure that power SPAs. For many teams, implementing these strategies is limited by difficult-to-change legacy systems and APIs. A software architecture pattern—what SoundCloud calls backends-for-frontends (BFFs)—is emerging that encourages teams to build small, specialized services that optimize the delivery of content to specific clients.

In this model, instead of a large REST API monolith shared by external clients like web, mobile, and third-party partners, a small service is built that optimizes delivery for a specific downstream consumer. A web browser BFF could support features like HTTP/2, implement caching methods, or bundle API requests from downstream services to reduce the number of AJAX requests. A native mobile BFF, in contrast, could leverage cutting-edge data transfer protocols like gRPC that aren’t supported by browsers.

A major downside to this pattern is the need to manage the increased operational complexity of managing new services. A BFF must be very stable and always available—otherwise external requests will fail and users will notice. Ideally, however, a BFF service bridges the knowledge gap between backend and frontend teams. Technical expertise on how the frontend is designed and performs is directly integrated into the design of the service that supports it, allowing client-specific design decisions to be quickly implemented and deployed.

A checklist for finding and optimizing slow AJAX requests

Before designing a new backend system or implementing a caching strategy, it’s a good idea to start by investigating pages that are most impacted by slow AJAX requests. Let’s check out the page load timings and route change timings in this Angular application using New Relic Browser’s SPA monitoring. We’ll sort pages by their average response time, so we can focus our energy on the slowest parts of the application, and drill into the associated AJAX timing information so we can see the most time-consuming calls:

When going through the list of AJAX requests with the slowest response times, it’s possible to perform a basic performance audit. As discussed above, this could include such questions as:

Can any AJAX requests be eliminated?

For pages with multiple AJAX requests to the same host, can they be combined?

Is caching configured using the ETag or Cache-Control header? Has it been tested?

Is gzip compression enabled?

Is a CDN being used? How does page responsiveness vary for international users?

Networking performance is required knowledge for frontend developers

Users of web apps don’t care what framework was used to build it, they just want the web app to be fast and functional. While SPA frameworks can make creating desktop-like customer experiences easier for developers, a key bottleneck of web app performance, network request latency, is here to stay despite promising new innovations in protocol design.

Focusing on usability, design, and performance has long been the domain of frontend developers. However, with modern frameworks and app design, SPAs can no longer be thought of in relative isolation from backend systems. As SPAs directly and indirectly depend on dozens of upstream services—from internal apps, APIs, and CDNs to third-party products—understanding and getting network performance right is critical to the overall user experience.

Additional Resources