back
▲ 81 points

Ask HN: Are there any solid arguments against SPAs in 2017?

by pier25·9y ago·144 comments·view on hn ↗
144 comments
The high level answer is "absolutely" and the more detailed answer is "it depends how you build them".

If built without server-side rendering, they're often obscenely slow. Browse the Modern Web™ on 2G and it's rage-inducing. A comment I made when this same question came up recently: https://news.ycombinator.com/item?id=13212789

If built poorly, all of the browser features you've come to rely on break. Like the back button. And links. And scrolling.

Does your website need to be accessible? Better remember to build that in too.

How about SEO? AMP? Browser history?

Most of this stuff works out of the box with traditional HTML and server-side rendered pages. So even though it's 2017, I think the question you should still ask yourself is, do you plan to re-implement all of this functionality? If not, 10MB of the hottest new JS framework may not be for you...

(And this is coming from someone who builds SPAs for clients for a living.)

The SPA frameworks and web APIs available to us now are pretty good - browserHistory as you mention, is available via `window.history.pushstate` and abstracted away for you in most SPA frameworks.

> If built poorly, all of the browser features you've come to rely on break

Alternatively phrased: "you may have to learn some new APIs"

But the SEO can be an issue (Google is not consistently executing AJAX) and render performance is definitely an issue.

I made https://www.prerender.cloud/ to address the SEO and rendering performance but that still doesn't make SPA the obvious choice.

Do you need a rich client experience? ( a UI that continuously updates to reflect the state of a data store, or more generally, a complicated UI that doesn't do a hard page refresh ) If yes, then SPA is the better solution.

If you just need a non-interactive set of pages (a blog), then a SPA probably isn't the answer.

> If not, 10MB of the hottest new JS framework may not be for you...

What hot new JS framework is 10MB? React is ~60kb gzipped

The auth frameworks (auth0.com or AWS Cognito) are large though, ~150KB gzipped. But with code splitting you can eliminate that from your main page. Or you can move the auth part of your app to a subdomain (app.example.com) and keep example.com lightweight w/out auth0/cognito)

I would add to your detailed answer... for what reason you're building a browser based app.

There are use cases where a browser delivered application is desirable, but you really aren't targeting "the public" meaning arbitrary consumers or business customers via a website. For example, there are good reasons to build browser based interfaces to certain enterprisy business apps for internal corporate user consumption. In these cases, you may be able to reduce the cost of maintaining full applications by relying on more simple and ubiquitous browsers while trying to keep some of the richer GUI functionality of a full fat client by building an SPA.

Nonetheless, your other points do apply (except for SEO and perhaps some of the mobile concerns, context mattering here). How you build them still matters; you just typically have greater control over much of the footprint and whether or not it's the right approach still needs to considered (SPA is not a default).

I appreciate that this isn't the typical area of interest for those coming to Hacker News, but it still exists and can be good to think of from time to time.

I think SPAs make sense for a very limited set of applications. I worked on Grooveshark, which was an SPA by necessity - you don't want page refreshes breaking music playback. We had to do an insane amount of work to get initial load times down, and it was never as fast as we wanted it to be. Some things about an SPA were nice, your server side code can be very fast and very simple and scalable when you can rely on the client side to maintain state for example, but with that comes a lot of fragility and ultimately, a lot more work.

Working on a SPA can be lots of fun, so I'd consider it for a hobby project, but I wouldn't go the SPA route for a production app unless there were some very compelling reasons to do so.

I think Grooveshark helped me create more code than coffee did for the few years it was active.

Just wanted to take a moment to thank you, and all the others who worked on it for making that possible. I know I wasn't alone to feel very, very lost and sad when it closed up.

So, free beer in case we ever meet IRL.

Your bad experiences are not because SPA is a bad idea, but because you did it wrong. Once an app is loaded there's simply no reason to every throw it out and start over. Do native apps have to throw any data away every time they open a dialog, or change an aspect of the gui? No, because that is silly and stupid. The only reason page refreshes even exist is because the original design of the internet was for viewing documents. However that's not was the web is used for any longer, for the most part. The web is not simply for viewing documents. It's at least as much for running apps now. A good webapp loads ONCE and then simply makes ajax calls to get JSON from the server when it needs to re-render part of the screen or even most of the screen, but if you are still doing entire page refreshes in 2017, then i'm just sorry but you are clueless. That's just not the way to do it. Web development is complicated, and I admit just reloading the entire page every time something happens is easier, but that doesn't make it better. Like the old expression "anything worth doing is worth doing right". It applies here.
SPAs don't bring major benefits but they certainly make the implementation complex.

Github is a good example of it. Server side renders are generally faster than when done using front-end framework.

I will just post this tweet from a google employee here : In my tests, a client-rendered SPA, + caching, + service worker, is still slower than an uncached server render

https://twitter.com/jaffathecake/status/799199764558401536

They pass the rendering to the clients allowing the server to serve more clients.
Here'a couple for starters.

1. They don't work well in multiple browser tabs. Specifically if you're storing a lot of data in memory it gets duplicated between tabs. Perhaps shared workers might be a solution in the future, but not now.

2. They allow designers to "enhance" the UI in new and wonderful ways, which isn't always good for user experience. It's like being tele-ported back to the windows native apps days. Plain old web apps forced simplicity and consistency in how things worked across the web. With spa's not so much.

3. Harder to test/re-create error conditions because often state of an application isn't represented in the url. (though it can, with good app state storage/structure, actually be better I think)

4. Harder to deploy new versions to apps sitting in users browser. So a user loads your wonderful spa app and leaves it open all day in their browser. You deploy an updated version mid day... how exactly does that user know to load the new version? In traditional web apps, updated versions are loaded on next page load.

5. You have to do something for page loading indication, since the browser no longer gives any indication it's waiting on the server for new data.

Very interesting! I'm trying the demos on http://intercoolerjs.org/docs.html and noticed its a little slow to update the form (after the mouse enter demo).

Do you update only after the post succeeds?

SPAs = Single Page Apps (not that everyone here wouldn't know that definition...but acronyms seriously suck ;). They create miscommunication and people who haven't been initiated yet are afraid to ask what it means. This one in particular has a lot of meanings: http://www.acronymfinder.com/Information-Technology/SPA.html (it likely means something completely different to a security person vs a network admin vs a front end dev.)
SPA is just an architecture. The argument "against" SPAs is the same as any other tech - don't use the wrong tool for the job.

The right tool really depends on your specific use-case, and business situation...

I make things so here's my perspective: SPAs are more complex which means more work and more problems.

One of the apps I'm building has one page that needs complex interactivity. So that's the only page which will have a vuejs/vuex-driven UI.

For the rest, Turbolinks gives me high performance for (almost) free.

So for someone like me who doesn't like typing more, spending more time and fixing more issues than absolutely necessary, SPAs are a no go for 2017.

A poorly written SPA has worse usability than a poorly written Rails CRUD app, because your potential screw-up surface area is larger.

If you have a lot of experience writing SPAs and a team that's eager to learn, maybe you'll get everything right: server-side rendering, graceful error handling when the app plumbing fails, appropriate separation of server-side and client-side workloads, good performance on shitty connections, consistent behavior across browsers...

Personally, I enjoy using well-made SPAs, but often find myself fighting against many of them because there are so many considerations that go into making them right.

What is your favorite spa app?
I see, breaking back button and links is one problem with that is mentioned a lot with SPAs. However, with a good routing library can easily solve both of these, especially when targeting modern browsers, IE11+, Android 4+ and iOS 8+.

Even for older browsers, in "no-framework" setting, I have used https://github.com/mtrpcic/pathjs with a lot of success.

Getting scroll position to stay where you left is tricky, though. Has anybody posted some tricks on getting this right?

Most routers have a "onBeforeNavigate" hook that you can use to cache the scroll position. In that regard, it's not difficult... but where to cache it is a whole 'nother question!
Yes there are and I am a fan and built some - currently working at a bank as dev for rent - and they are doing it poorly ( I don't want to name the stack, because it's not responsible for a 4mb first page load + 1mb CSS - uncompressed ), it's their first big Js project and their cool 'kids' fresh from university... No server-side rendering and no-js fallback, concept copied from another bank... so glad I am out soon - it really makes my head hurt. I didn't think you can hurt an app so much by moving it do Spa, just for the sake of Spa. Most surprising, for me personally - UX issues, because they have no 'refresh'/change indicator and people don't expect things to change instantly - without page reload...
Most SPAs I visit break swipe-right-to-go-back functionality on my iPad – and it's infuriating. GitHub and mobile Reddit are huge offenders of that one.
Man I spent ages trying to get swipe right to work in my web/cordova app (in particular dealing with both url routing and animated back/forward transitions), and I was confused why I could find so few articles or discussions about it. Perhaps many SPA's just don't bother?

Maybe I should dust off my blog and do something about this missing bit of arcane SPA lore.

Lots of arguments here against an SPA are along the lines of "it probably is the wrong answer to your requirement most of the time". Related question. When is it best to use an SPA? My hunch is that it's not purely about aesthetics but something functional like Grooveshark/soundcloud not stopping a song that's playing when changing the page. Just not sure what qualifies as needing an SPA.
For me, perfect example why not move to SPA in 2017 is Freshbooks, I'm their active user and found that their new version(introduced recently) is slow, initial load slow (very), transitions between tabs is slow etc. Personally I dont see the reason they moved to SPA (they using Ember framework which I heard very optimized in compare other frameworks(not libraries as React))
There's a ton of sites that have moved to SPAs that shouldn't be. Three come to mind as I use them quite a bit: Walmart.ca, Fido.ca and Rogers.ca

Hell even Google cannot get SPAs right using their own framework [1]

[1] - https://pbs.twimg.com/media/C0n-bqwWEAEV6eg.jpg:large

The latest version of Ember has improved performance considerably although generally it's considered slow compared to modern alternatives like Angular 2, React, Cycle, etc.
I really like them - when they are done well, ie not obscenely slow.

Like most people, I hate it when something like an article or a wiki turns itself into an SPA for no reason. But I do find myself thinking that the space between "should be an SPA" and "should be a static site" is not very big.

Don't use a SPA if you intend to get a lot of mobile traffic and/or all your site does is render articles or other text-based content.
If you intend to get single pageview mobile visits, sure. But if your mobile users are expected to interact at length with the page, then you get the benefits of an SPA.
Traditional applications are simpler implementation-wise and impose fewer demands on the client (in terms of performance, using the latest browser, etc).
Twice as much code to write. Ok, maybe not twice as much, but it does seem like a lot more stuff needs done in the front end compared to just writing a fairly standard app in Django.
1) It's too hard. And I think this argument gets way less attention than it deserves. Most businesses these days win or lose based on agility and time to market. The more energy you spend innovating your tech stack, the less energy you have available to innovate your business model.

2) Javascript bloat. This is increasingly important as mobile gradually overtakes desktop, and cheap Android phones proliferate. The more client-side code, the more your performance is limited by your users' own crappy devices.

3) It's not trendy anymore. There was only one truly exemplary, popular SPA, and that was Gmail. Isomorphic/universal is the new hotness, and that requires server-side rendering.

4) The Stack Overflow Effect[1] didn't take. Every client-side framework is so painful that people can't wait to migrate their production apps to something different. So now there are dozens, probably hundreds of frameworks in production, and each community lacks the stability and size to allow newcomers to bootstrap quickly.

5) It's just bad UX. People still manage to get SPAs wrong in 2017. My bank just rolled out a new SPA interface to their suite of consumer budgeting tools, and didn't bother with the History API. Every time I navigate back, it takes me out of the suite entirely and I have to find my way back manually to where I was. I think this problem is a consequence of #1 and #4, though.

-------------------------

[1]: http://svdictionary.com/words/stack-overflow-effect

Extra complexity. If you're building something simple, it's often quicker or easier to reason about if you just put it together with a basic web framework.

But if you're doing anything reasonably advanced or specifically need the "application-like" feel of an SPA, I don't think there are really any compelling arguments against it. Maaaaaybe the size of the initial payload, but there are strategies to mitigate against that anyway.

Just to provide a counter point, I find it much simpler to work with SPAs. You can build a clean API which only deals with JSON, and ship a separate frontend which is deployed reliably to a CDN. I can see why 'one thing' would seem simpler than 'two things', but like functions and modules, often having more makes things simpler to grok.
I mean, I was able to build my own single page app in a few hundred lines of javascript front-end code, and a few hundred more lines of javascript for some interface elements.

See: https://www.futureclaw.com

This also includes server-side rendering of the initial page.

I didn't use Angular or React or Ember or any other framework.. I just went ahead and made my own with ES6. The latest Javascript ES6 makes all of this easier.

If you're worried about complexity, just ignore the existing frameworks and do it from scratch.

Even if all your code resides on the backend, there's no reason why you can't maintain a similar separation between front end/display logic, and backend logic where data can be passed between the two layers but neither makes assumptions about the other.
It's certainly quicker to build something simple without it, but if the site needs to be maintained, things are much easier if your data is separate from your view.
That's only really true if you're building your first SPA.

Since I build so many SPAs, at this point I can spin up and work on a new one much faster than I could for a non-SPA.

HTML is easy and fun ...

  <h1 class="big"><% =topic %></h1>
vs

  function createTopic(strTopic) {
    var heading = document.createElement("h1");
    var topicText = document.createTextNode(strTopic);
    heading.appendchild(topicText);
    heading.setAttribute("class", "big");
    return heading;
  }
Great question. Recently I decided against splitting my application into two different apps: backend and frontend. I landed on a simple Rails app with an internal API with webpack included for ES6/React/Mobx stuff.

https://sergiotapia.me/using-webpack-and-react-in-a-rails-ap...

Best of both worlds.

The engineer in me loves the idea of them being separate. For performance, for technical reasons and for scalability.

The 9-to-5'er in me doesn't agree. I would spend too much time orchestrating. For example, saving user JWT tokens and having to handle requesting one for each api query. Too much time spent on things other than my core business problem.

With a simple Rails app, I can sign in my users with Devise, no brainer. And build out React stuff on HAML templates as needed.

SPA is very broad. Static content work best when delivering only the minimal assets needed to render. Googles AMP does a very good job at this. Dynamic apps have a very different set of concerns. All SPAs aren't the same. Only the stateless, pure renders, like React and Vue, offer a compelling potential to unify the concerns of static content and apps that need to run across multiple platforms and network conditions. It comes at increased complexity and cost to maintain a multi-platform structure. If there's no business or consumer benefit there's not need to over engineer a solution to use a SPA.
I'm surprised nobody has mentioned a big selling point of a well-built SPA: cross platform portability. The architecture of an SPA forces you to clearly separate backend and frontend, so that frontend web is effectively an independent client querying a backend API, just like a mobile app. With frameworks like react native, you can build your web app at the same time you build your mobile apps, realistically achieving 80%+ code reuse across platforms. When you're a small team trying to launch quickly and broadly, cross platform portability is very valuable.
They can be overkill. But usually aren't, even for a static site, if the site will be maintained or updated, or has a modicum of reused views, such as a gallery.
Yes, basically it's much easier to work with and the tools/development experience are much better - which correlates to being able to deliver faster, sometimes much faster.

Time to market is often a very important metric for a web app.

However SPAs make for a smoother experience. Most client facing apps live or die based on the user experience, and there are very few Product Managers who'd agree to a full old-style multi-page app.

As far as I'm concerned there are only two scenarios where I'll prefer an old-style app over an SPA:

1. when building internal apps for employees

2. when time to production is extremely important.

Many, the first of which is whether it needs to be a web app at all or a desktop one.
https://github.com/Clay-Ferguson/meta64 --> is still a work in progress, but if you want to see a great example of modern architecture in a web app, check it out. Yes it's mine. It's running Google Polymer, JQuery, TypeScript, SpringBoot (with embedded Tomcat), Apache Oak JCR, and is a SPA that only updates the portion of the screen that changes. It never reloads the page. Full page reloads as a part of webapp architure has been totally obsolete and bad desing for at least 7 years now. SPAs are the best architecture for a lot of different reasons.

There is one part of it that is mildly interesting (on the site itself) which is the RSS reader capability here:

http://meta64.com/?id=/rss/feeds

Because obfuscation of absolutely everything, so that the end user doesn't know what we're doing to them, is extremely lucrative!
Not really. Swimming, bathing relaxing and spending nude time in saunas with other people will still be an important part of our daily life. :-P