6 ms·
I think the DX is significantly better as well with fast reload… As a user, the typical SPA offers a worse experience. Frequent empty pages with progress bars
by 0cf8612b2e1e 2y ago
I think the DX is significantly better as well with fast reload…
As a user, the typical SPA offers a worse experience. Frequent empty pages with progress bars spinning before some small amount of text is rendered.
- zozbot234 2y ago> As a user, the typical SPA offers a worse experience. Your typical SPA has loads of pointless roundtrips. SSR has no excess roundtrips by definition, but there's probably ways to build a 'SPA' experience that avoids these too. (E.g. the "HTML swap" approach others mentioned ITT tends to work quite well for that.) The high compute overhead of typical 'vDOM diffing' approaches is also an issue of course, but at least you can pick something like Svelte/Solid JS to do away with that.
- eastbound 2y agoRequires additional engineering.
- boomskats 2y ago> Your typical SPA has loads of pointless roundtrips This is an implementation choice/issue, not an SPA characteristic. > there's probably ways to build a 'SPA' experience that avoids these too PWAs/service workers with properly configured caching strategies can offer a better experience than SSR (again, when implemented properly). > The high compute overhead... I prefer to do state management/reconciliation on the client whenever it makes sense. It makes apps cheaper to host and can provide a better UX, especially on mobile.
- apothegm 2y agoExcept for a user on a lower specced device that can’t performantly handle filtering and joining on that mass of data in JS code, or perhaps can’t even hold the data in memory.
- lelanthran 2y ago> Except for a user on a lower specced device that can’t performantly handle filtering and joining on that mass of data in JS code, or perhaps can’t even hold the data in memory. Just how low-spec and/or how much state-data are we talking about here? I ask only because I am downloading an entire dataset and doing all the logic on the client, and my PC is ancient. I'm on a computer from 2011 (i7 870 @ 2.9GHz with 16MB of RAM), and the client-side filtering I do, even on a few dozens of thousand of records retrieved from the server, still takes under a second. On my private app, my prospect list containing maybe 4k records, each pretty substantial (as they include history of engagements/interactions with that client) is faster to sort and filter on the client than it is to download the entire list. I am usually waiting for 10s while the hefty dataset downloads, but the sorting and filtering happens in under a second. I do not consider that a poor UX.
- apothegm 2y ago10s is painful. A server-rendered app should be able to deliver that data, already rendered, in closer to a fifth of a second. Fast enough that the user doesn’t even notice any wait.
- lelanthran 2y ago> 10s is painful. A server-rendered app should be able to deliver that data, already rendered, in closer to a fifth of a second. How do you know how large the dataset is? All you know from my post is that a dataset that takes 10s to download (I'm indicating the size of it here!) takes under a second to filter and sort. My point is that if your client-code is taking long to filter and sort, then your dataset is already so large that the user has been waiting a long time for it already; they already know that this dataset takes time. FWIW, the data is coming in as CSV, compressed, so it's as small as possible. It's not limited by the server. Having it rendered by the server will increase the payload substantially.
- apothegm 1y agoThe JS processing and rendering time on an underpowered CPU is the issue, not the payload size. It’s difficult to describe how excruciatingly slow some seemingly simple e-commerce and content sites are to render on my 2019 laptop or how slowly they react to something as simple as a mouseover or how they peg the CPU - while absolutely massively complex and large server-rendered HTML loads and renders in an eyeblink.
- smileysteve 2y agoAs an issue, yes, often ignored by QA, Product and engineers
- int_19h 2y agoMy biggest annoyance with SPAs is that they usually break forward/back/history in various subtle (or not so subtle) ways. Yes, I know that this can be made to work properly, in principle. The problem is that it requires effort that most web devs are apparently unwilling to spend. So in practice things are just broken.
- jefozabuss 2y agoI still have some ptsd from payment gateway integrations via iframes about 6-7 years ago. If you thought SPAs are bad by themselves for history tracking imagine those banking iframes randomly adding more entries via inside navigation/redirection that you have to track manually.
- hirvi74 2y agoA lot can be said for just putting a "back" button a page. I still do it occasionally for this very reason. Then again, my user base for the apps I write are the most non-technical folks imaginable, so many of them have no concept of a browser back button to begin with. I am not being hyperbolic either.
- int_19h 2y agoThing is, the browser back button is still there, though. So now you have two identical buttons that do different things. And that's really bad UX.
- creakingstairs 2y agoI’m split on this. I used to agree with you but when I talked to internal users and customers, they really liked having a back button in the app. I would tell them the browser back button is there and we haven’t broken history so it should work to which they just often shrug and say they “just” prefer it. My hypothesis is that they’ve had to deal with so many random web apps breaking the back button so that behaviour is no longer intuitive for them. So I don’t push back against in-app back buttons any more.
- WuxiFingerHold 2y agoYes, pure old school SPAs have at least one additional roundtrip on the first visit of the site: 1. Fetch index.html 2. Fetch js, css and other assets 3. Load personalized data (json) But usually step 1 and 2 are served from a cdn, so very fast. On subsequent requests, 1 and 2 are usually served from the browser cache, so extremely fast. SSR is usually not faster. Most often slower. You can check yourself in your browser dev tools (network tab): SPA: https://www.solidjs.com/ https://www.solidjs.com/ vs. Poster child SSR: https://nextjs.org/ https://nextjs.org/ So much complexity and effort in the nextjs app, but so much slower.
- yawaramin 1y ago> Poster child SSR That's not really SSR though, it's partial SSR but then hydrated into a client-side React app, so a SPA. If you really want to compare try an htmx page.
- hombre_fatal 2y ago> Your typical SPA has loads of pointless roundtrips. SSR has no excess roundtrips by definition SSR also has excess round trips by nature. Without Javascript, posting a form or clicking a like button refreshes the whole page even though a single <span> changed from a "12 likes" to "13 likes".
- ai-christianson 1y agoI think most of the thread is talking about SSR with partial HTML replacement.
- brandensilva 2y agoWe have been moving to localized cache stores and there aren't any client side loaders anymore outside of the initial cache generation. Think like Linear, Figma, etc It just depends on what you are after. You can completely drop the backend, apis, and have a real time web socketed sync layer that goes direct to the database. There is a row based permissions layer still here for security but you get the idea. The client experience is important in our app and a backend just slows us down we have found.
- veqq 2y ago> We have been moving to localized cache stores and there aren't any client side loaders anymore outside of the initial cache generation. Think like Linear, Figma, etc. That's never the case.
- dingnuts 2y ago>and have a real time web socketed sync layer that goes direct to the database you might be able to drop a web router but pretending this is "completely drop[ping] the backend" is silly. Something is going to have to manage connections to the DB and you're not -- I seriously hope -- literally going to expose your DB socket to the wider Internet. Presumably you will have load balancing, DB replicas, and that sort of thing, as your scale increases. This is setting aside just how complex managing a DB is. "completely drop the backend" except the most complicated part of it, sure. Minor details.
- threetonesun 2y agoI assumed they meant a client side DB and then a wrapper that syncs it to some other storage, which wouldn't be terribly different than say a native application the relies on a cloud backed storage system. Which is fine and cool for an app, but if you do something like this for say, a form for a doctor's office, I wish bad things upon you.
- WD-42 2y agoThis exactly. It seems like the last 10 years of JavaScript framework progress has been driven by DX, not UX. Like at some point everyone forgot this crap just needs to work at the end of the day, no user benefits from 3 rewrites over 5 years because the developer community decided functions are better than classes.
- ryantownsend 2y agoIn my view, DX should be renamed "Developer Convenience" as we all know that convenience is often a trade-off. Please forgive the self-promotion but this was exactly the premise of a conference talk I gave ~18 months ago at performance.now() in Amsterdam: https://www.youtube.com/watch?v=f5felHJiACE https://www.youtube.com/watch?v=f5felHJiACE
- tomjuggler 1y agoThat was super annoying when I was just picking up react.
- WuxiFingerHold 2y agoThere's no way around waiting for the data to arrive. Being it JSON for SPA or another page for MPA / SSR. For MPA the browser provides the loading spinner. Some SPA router implementations stay on the current page and route to the new one only after all the data has arrived (e.g. Sveltekit).
- qudat 2y agoIf you employ a "preload then rehydrate" data sync paradigm then you should never see a blank page -- except on initial JS load. This is just an improper data sync strat and has nothing to do with SPA. I built a lib specifically designed for this strat: https://starfx.bower.sh/learn#data-strategy-preload-then-refresh https://starfx.bower.sh/learn#data-strategy-preload-then-ref...