Reflecting on Single-Page Applications

Although I was an early adopter of client-side web applications, it’s hard to fully divorce yourself from all the tradeoffs that go into a system you’ve built when analyzing a single aspect. Recently, I’ve been noticing that some of the websites and services that I rely on in my day-to-day life have been rewritten into SPAs, so I’ve taken the opportunity to step back and reflect on the effects that are visible to end users.

Why SPAs, Anyway?

As a software developer, client-side frameworks have a pretty big advantage: the promise of only having to implement my UI logic and rendering in one place. I still vividly remember some software I’ve worked on where doing anything dynamically required writing stateful and messy code in both JavaScript and server. SPA frameworks are amazing for the developer because they free you from the tedious work and reduce the opportunity for an entire class of bugs.

Even better, because all rendering happens in the client’s web browser, any sort of dynamic interaction with the page becomes much faster for the end user. It’s not necessary to reload a whole page when submitting a form. Navigating to a different page altogether also becomes much faster because the client has already loaded the code to render the shape and structure of that next page, if not the data itself.

From this perspective, it appears to be a win for everyone. Users get a better experience. The people developing the system itself are also rewarded with a nicer development experience and better code. The reduced hassle for developers (hypothetically) saves development cost.

Issues with SPAs in Practice

As a software consultant, all of the software that I create has one thing in common (with rare exception). It’s not necessarily how the software is architected internally, or the tools that are used to make it, or even whether it’s meant to run on a phone, a server, or a desktop computer. It’s just that I don’t personally use the software. The software I make is for other people.

In a way, I’m actually happy about this, as my work is focused on helping other people. Unfortunately, it does deny me complete understanding of how the software I create fits holistically into daily life.

Reflecting on how I use the single-page applications that others have created, I’ve been surprised at a couple of revelations.

First, the cost of initially loading the app in the browser is actually perceptible. In fact, it bothers me quite a bit. One of the greatest strengths of the web as a platform is how easily and quickly you can transition between different sources of information and content, regardless of whether (or how often) you’ve visited a source before. It’s easy to underestimate what a small penalty in loading time can feel like for a user. Even a half a second is painful and introduces friction.

I’d expected that the increased snappiness of interacting with a client-side app would outweigh the cost of the initial page load, but this turns out not to be the case. There are two reasons for this. First is simply that, more often than not, I don’t tend to keep the page open for very long. I usually have a task or two to accomplish, and then I’m done.

Second, it turns out that although the client can render all on its own, it still ends up awaiting data from the server. The common case of navigating through different “pages” can be just as slow as loading a new HTML document. It frequently is.

Another surprise was that a number of the applications failed at providing good feedback about when they were busy or communicating with the server. The browser naturally provides valuable feedback about when it’s busy talking to the server, but that’s not something a single-page app gets for free.

It can be confusing. It’s not a fun experience to click a button, wonder if anything’s happening at all, and then eventually see it take effect. In scenarios like that, it’s honestly better to just load a new page than to show no feedback at all.

Conclusion

I was surprised to see that single-page frameworks didn’t always result in a clear win for the user. I’m not saying SPAs are bad, or that any of these issues can’t be solved with more engineering.

When I work on greenfield web applications in the future, I’m going to pay closer attention to the decision of whether or not to use a client-side framework. Should I find myself working in, e.g., Ember or React again in the future, I’ll pay more attention to these aspects of the user experience and how I can improve them.