Many people in the web community believe that SPAs (single page applications) give users a superior user experience.

But most of the time, SPAs give users an unfamiliar, slow and fragile experience. Furthermore SPAs are much harder make.

In this article, I’ll explain why that is. But before I do let’s make sure we’re on the same page about what SPAs actually are.

You might think about MVC, data flow and client-side templating when you think of SPAs. But they‘re not the defining characteristics of SPAs.

In actual fact, you can use all those things to create rich, but more traditional ROCA-style sites.

SPAs can be defined as applications that handle routing or navigation using client-side JavaScript.

In other words, instead of letting browsers handle the browsing, the application code hijacks it in order to change the URL, make requests and render responses itself using JavaScript.

Using JavaScript to do the very thing that browsers are made for and already do for free is the cause of all the problems.

# 1. Going back and forward quickly and reliably

Browsers store history so that pages load quickly when the user clicks back. Daniel Puplus explains in Building Single Page Applications that:

“When a user presses the browser’s back button they expect the change to happen quickly and for the page to be in a similar state to how it was last time they saw it.



“In the traditional web model the browser will typically be able [to] use a cached version of the page and linked resources.



“In a naive implementation of a SPA hitting back will do the same thing as clicking a link, resulting in a server request, additional latency, and possibly visual data changes.”

To give users the expected, fast experience, we need to emulate the same native browser behaviour using JavaScript. This means:

storing pages in memory, local storage, client-side databases or cookies. working out when to retrieve the cached pages and when to invalidate them.

For (2) there needs to be logic to work out whether the user is changing the URL manually — by clicking a link or typing a URL directly in the location bar.

Or by pressing the browser back or forward buttons which is not achievable as far as I know.

# 2. Scroll position

Browsers remember the scroll position of pages you’ve visited. Daniel Puplus again explains how SPAs cause trouble here:

“Lots of sites get this wrong and it’s really annoying. When the user navigates using the browser’s forward or back button the scroll position should be the same as it was last time they were on the page. This sometimes works correctly on Facebook but sometimes doesn’t. Google+ always seems to lose your scroll position.”

To fix this, our code needs to store, retrieve and apply the correct scroll position when the user navigates back and forth.

# 3. Cancelling navigation

When a user clicks cancel or a link, the browser will stop any in-flight requests.

SPAs retreive entire (data for) pages using AJAX. So there could be several requests in-flight. The first request could finish last. Or a user could click (and request) the same link twice.

This is problematic because its inefficient, will use up people’s data unnecessarily and cause visual glitches as subsequent requests finish that should have been cancelled.

The code needs to handle all of these cases.

To let users cancel requests, we need to put a custom cancel button in the UI – which isn’t desirable.

# 4. Handling unsaved changes

In a traditional web application, we can warn users of unsaved changes using the beforeunload event. But SPAs don’t navigate, which means this event won’t fire. So this needs reimplimenting from scratch.

# 5. Search engine ranking

Search engine optimisation is usually an afterthough when building SPAs. But retrofitting this is difficult and costly.

Creating a separate dedicated server-rendered site for search engines is wasteful and means having to maintain a lot of extra code.

With a traditional ROCA style site we get this for free.

# 6. Loading CSS and JS

As SPAs grow in size, loading all of the assets will get really slow. This typically leads to conditionally loading CSS and JavaScript.

But script loaders contain hacks, slow down development and reduce reliability.

Analytics tools track page views by default — you just add the analytics code to the page.

But SPA pages aren’t real pages which means additional logic needs to be written to make analytics can track pseudo pages when they get rendered.

# 8. Automated functional testing

Like the previous point, automation tools like Selenium know when a page has loaded.

But automation tools don’t automatically know a page has been loaded with AJAX.

THis makes tests more challenging to write to handle timeouts and they’ll be slower to execute.

# 9. Memory leaks

As SPAs don’t load pages, the page may stay open for a long time.

This increases the chance of memory leaks which can cause the browser to crash, and battery powered devices to drain quickly.

# 10. Loading indicators

The browser’s loading indicator provides an accurate, predictable and familiar experience to users across all sites the user visits in their browser.

As SPAs use AJAX to render pages, we need to create a custom loading indicator from scratch. Besides the extra work, custom loading indicators tend to be inaccurate and unfamiliar.

This can cause users to click the link again which slows users down further.

# 11. JavaScript will fail

JavaScript can fail for many reasons. And most SPAs aren’t written using progressive enhancement.

The result of which is a blank screen and leaving users to refresh the page or give up.

# 12. They’re probably slower

SPAs are very likely to be slower than server-side rendering because:

“Fun fact: it takes a Moto G4 about 15.66 times longer to evaluate 2.1MB of (decompressed) JS than it does to decode a 10MP image.”—Harry Roberts

# 13. They’re not accessible by default

Read One-page-applications are not accessible by Craig Abbott.

# 14. They just don’t feel right

Read Why I hate your Single Page App by Stefan Tilkov.

Many people think SPAs provide faster and better experiences but in reality they create a slower, unfamiliar and inaccessible experience.

Worse is that they’re harder to make in the first place.

And it‘s not just me – Twitter, Lifehacker and Delicious went back to more traditional architectures for these reasons.

You can read more below:

JavaScript is not better at browsing than browsers.

Instead let the browser handle that and focus on creating rich, robust and accessible experiences by following the rule of least power and following the principles of ROCA.