This. Set aside the performance of the initial load for a moment. When I interact with the SPAs we’ve built in recent years, I am still shocked how snappy they are as I perform actions throughout the site. Every “pageview” requires the download of a tiny REST API response and comparably tiny HTML fragment. As a user - that experience is a pure delight compared to a full blown page re-load, re-download and re-render with every action.
As a user it infuriates me when I fill out a long form, hit submit and find out I forgot to select the proper “Mr. Mrs. Ms” title and my password, credit card number and PIN have all be blown away.
As a user I’m willing to pay a few more seconds upfront for snappy and seamless interactions as I use the app.
I think the mistake that is more often committed (and where I myself as a user have less patience) is treating everything that can be accessed via URL as an “app”. If the user is coming to just download bytes, don’t build an app. An app is only justified when a user is coming to manipulate data.
I don't agree with this logic one bit. What you seem to be experiencing is SPA's that can use improvement. There is no reason why a SPA is required to load the entire app at once. There are many ways to split out the code so that each page only loads the bare minimum of what it needs. It is totally possible to provide a better user experience on mobile devices when the app only has to download the JSON required to render the next page. There are many tricks that can be done to take advantage of this. The SPA can load the bare minimum to render the page requested and then start pre loading the rest of the app or leave it on demand.
While I agree that there are many situations where a straight port of a static site to a SPA doesn't give too much benefit, it sets them up to move to more advanced interactions moving forward.
The web, although maybe not originally intended, has become the most powerful software platform we have. Things are getting dramatically better and the rate of innovation isn't showing any signs of this slowing down. It is already amazing and it's going to get better.
We owe it to our users to provide all of them with a good experience. We also owe it to ourselves to write good, clean, maintainable applications. The wonder of it is that very, very often if we write RESTful apps then progressive enhancement just falls out naturally: a GET request with some JSON Accept header will return data; with text/html it'll return data, and possibly a form to update it; a POST with some JSON Content-Type will DTRT, and so will one with application/x-www-form-urlencoded or multipart/form-data.
Why wouldn't one do that?
Of course, the user experience of such an app isn't as great as a singing, dancing single-page app (SPA). But a user experience is better than no user experience, which is what offering only an SPA provides.
It's just sloppy to require JavaScript and CSS to use a web site. It's particularly sloppy when that web site is composed of documents.
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.
I certainly agree. There are almost always ways to avoid "loading a good bit of data on the user's first use". But for your traditional SPA, it's quite common that you need to make a few AJAX calls to your backend API in order to fetch some data to show to the user. This was built for mostly that case, not for the "let's block the user's screen for 5+ seconds while we do unnecessary data fetches" case.
Edit: I misspoke when I said "a good bit of data" in my original response. I simply meant any API calls to your backend.
The problem a lot of developers have with SPA is that they literally shove the entire app into 1 page load. Which is where most of their problems come from. If you use a hybrid approach. Have the data you need to show the page right away cached in the html and then load any other data after while that page is being used. And you break the app up into multiple pages. It works perfectly fine. It actually makes it super easy to hand out work to a team of devs and minimizes stepping on each other.
An SPA, if properly designed, can help interactive use significantly though, compared to full page reloads. You may pay for the reduction in interactive latency with an upfront loading cost, but when comparing to desktop applications that is often not too bad anyway (Excel doesn't load immediately on most PCs, games of any modern design generally don't either). People are more willing to wait a second or few initially than they are to wait half a second when getting more data from an app that they consider to already be loaded.
The problem is that many are not properly designed. In fact often the patten is often used when it is not really appropriate and a fairly static site would (again with that caveat: if properly designed) be much more efficient and just as user-friendly.
True, but for apps which are meant to be interactive you also need to take into account SPAs that might make very small requests for a good while once the main bundle has been downloaded.
So, for a world-normal device which one is better? A site that downloads 1MB of Javascript and then makes data requests of a few KBs or a site that makes a 300KB request with a page reload every time you interact with it?
My general rule is that if the application is interactive, meant to be used for long periods of time and SEO is not an issue, well-written SPAs result in better UX.
That's not the case of Reddit for example. Most users spend the most time reading comments, and that requires very little interactivity. So old Reddit is miles ahead of the new slow and bloated one.
Server push gets you closer with a traditional app, but it doesn't really solve the problem (or rather - yes, you get to reinvent it yourself, but you can do it better, with the specific context of your app)
Basically - My argument is that developers tend to treat SPAs the same as "the website" but with a bigger js framework. And that's the wrong mindset.
Instead, you should think of the first load as an install of a native application. You want to push absolutely everything, not just the next couple of resources you might need (like imgs/css). Ideally you push the current page first, and do the rest in the background while the user can interact with the current page, since you're almost never CPU bound on terrible connections anyways.
You'll get one additional load at login (because now I'm pushing all relevant user data), but after that... basically everything is rendered from cache (including optimistic cache updates based on what the user might be adding/updating).
After that... unless you log out or have cache evicted, you're going to see immediate response times, even while offline.
---
This isn't easy, and most teams don't bother, so if the comment is "If you're treating an SPA like a traditional page - don't bother" then I tend to agree.
but an SPA genuinely opens up options for bad connections that otherwise just don't exist (or are so bad people won't use them)
Doesn't it ever backfire though? I've used plenty of SPAs that shouldn't have been, forcing me to wait for the page to load twice and increasing frustration. If they'd just stuck some AJAX where appropriate the experience would be so much better.
Sure, but what about responsiveness and other metrics? Reducing the absolute amount of data sent over the wire may be what you are optimizing for, but it's not by any means the absolute metric of performance. Personally, as a user, for many web apps I would rather see a longer initial page load but have all subsequent actions appear instantaneous (a la Gmail), than spread the load times out across every action.
My point isn't that SPAs are better than traditional web apps or anything like that, just that these decisions depend entirely on what you are optimizing for and what your priorities are. If initial page load time is your priority, then an SPA may not be the way to go; however, if your goal is to maximize responsiveness or interactivity, then the extra 2MB of JS will likely pay off.
Yep. In SPAs with good architecture, you only need to load the page once, which is obviously weighed down by the libraries, but largely is as heavy or light as you make it. Everything else should be super minimal API calls. It's especially useful in data-focused apps that require a lot of small interactions. Imagine implementing something like spreadsheet functionality using forms and requests and no JavaScript, as others are suggesting all sites should be: productivity would be terrible not only because you'd need to reload the page for trivial actions that should trade a but of json back and forth, but also because users would throw their devices out the window before they got any work done. You can also queue and batch changes in a situation like that so the requests are not only comparatively tiny, you can use fewer requests. That said, most sites definitely should not be SPAs. Use the right tool for the job
In theory. In practice most SPAs are slow at first load and slow when changing pages then crash when too much data is requested.
Beyond that, unless your users are a captive audience (have to use your software for their job) you should probably be optimizing for a positive first impression.
Worse yet, with a traditional web app, you are in control of loading the page - or stopping the load, for that matter. With an SPA, it does all those requests in the background. Many apps fail silently (as in, don't refresh) if request to the backend fails.
The allure of the SPA. In theory it reduces load times (except for the inital page load) by preventing users from re-loading the same set of base resources for each subsequent page. In practice, it results in a bloated initial page request and requires devs to re-implement a ton of functionality normally handled by the browser (and they inevitably overlook things). I've worked on a couple projects where team members insisted we implement the web interface as a SPA and it has always resulted in an inferior user experience IMO.
I think of good applications as a collection of SPAs. There is no benefit to forcing every single feature of an app into only one page. Ajax means we can implement more functionality without a page reload, which is good to a degree, but at a cost of slower initial load, losing URL state, and difficulty tracing UI behavior to underlying code.
I am working on a legacy SPA now and it's horrible. (Our users have learned to refresh frequently due to uncertainty of state.) I am not sure how much to blame on poor implementation as opposed to inherent weaknesses of SPA architecture.
Your application seems to be a magical unicorn (not being sarcastic!). Most SPA websites I use on a regular basis end up having to reload all of their page components every visit, and frequently on every 'back'.
I've purposefully reduced my website to a minimal amount of HTML so that even on connections with high latency and low bandwidth, it loads quickly into the browser.
A lot of webapps I've seen lately could have just as easily been a lightweight, single PHP script with minimal styling and scripting.
That saves battery and bandwidth. SPAs only save bandwidth.
I completely agree with the author. A few months back I examined the number of network requests required to populate the data for a page I was trying to improve performance on.
Let's just say it did not go well. Despite best intentions of being API-first with a SPA front-end, when you have a data-heavy and query-heavy application, it is absolutely the wrong choice ten times out of ten.
It leads to (not so) hilarious situations where the older, server-side rendered version of your app that uses jQuery absolutely demolishes your new hotness in performance. Try explaining that one with a straight face.
As a user it infuriates me when I fill out a long form, hit submit and find out I forgot to select the proper “Mr. Mrs. Ms” title and my password, credit card number and PIN have all be blown away.
As a user I’m willing to pay a few more seconds upfront for snappy and seamless interactions as I use the app.
I think the mistake that is more often committed (and where I myself as a user have less patience) is treating everything that can be accessed via URL as an “app”. If the user is coming to just download bytes, don’t build an app. An app is only justified when a user is coming to manipulate data.
reply