1. 52
  1. 25

    Progressive enhancement was/is always the answer in my opinion.

    1. 20

      SPAs are overrated for sure but there’s been a nice side-effect: virtual DOM and state management. Getting to declaratively, statelessly express the view according to the current state model is a much better system in a lot of cases than imperatively setting and parsing DOM nodes and attributes versus the jQuery or two-way-bound Knockout ages of yore. When you stack up a few of these components on a page it feels like maybe your whole page should just be a nesting of these models. I think that makes sense. I think the problem comes from not knowing when jQuery-like DOM manipulation works, or when a couple of React-like component on a mostly static page is enough.

      Feeling it this week, I had to wrap my head around why a “static” landing page can’t have easy CSP because the of a CSS-in-JS trend needing unsafe-inline or complecting the build with nonces instead of just writing CSS in … CSS. Or not having content Bing can actually index because “This app requires JavaScript”. Or why does a component asking for donations, inject CDN-hosted scripts at runtime instead of teaching how to add dependencies and not seeing that not only is this a security issue but didn’t even bother with with subresource integrity? The other problem may be these tools like create-react-app making it too “easy” to create an overly complicated setup (with questionable defaults)–there should be some “hard”-ness to setting up something complicated and careful consideration for your stack/tools that just goes missing allowing some other “guru” to choose for you. Obviously this example almost certainly shouldn’t have been a SPA.

      I can’t blame new programmers for not knowing what complexity budget their biting into–especially with ugh developer influencers saying these are the best and easiest way to build something. SPAs aren’t a mistake, but SPAs are overused. Static site generators have certainly been making their fair share of a comeback though.

      1. 11

        Frameworks like NextJS, Remix Run, SvelteKit, etc are solving many of the UX challenges and engineering hurdles, and very much blurring the line between SPA and static site generator.

        These frameworks all use browser history perfectly, omit JS code not needed at runtime, and let engineers choose on a route by route basis if a page should be statically generated, periodically statically generated, server rendered, or client rendered (which they discourage). The compiler/static site generator does the heavy lifting to split up code into loadable chunks, but there’s no configuration needed to get excellent performance. Things behave correctly by default (unlike create-react-app, which didn’t supply routing, history, or any semblance of server awareness last I used it).

        They’re not perfect - someone can still end up shipping 1mb of multi language syntax highlighting to every dynamic page by accident - but they do a lot to give the benefits of SPA without most of the weaknesses. There’s a huge productivity win to having all your logic expressed in a single language.

        1. 9

          I disagree conceptually with “blurring the lines” here. The level of complexity those projects bring is not really comparable to the simplicity of most traditional static site generators. Adding more complex tooling isn’t helping the situation. Suggesting we need more code generated and tools is not my idea of having cake and eating it too; it seems like good way to get a project that rots and is hard to migrate away from.

        2. 4

          SPAs are overrated for sure

          It might just be the places that I hang out, but I basically never see pro-SPA hype, and do see constant anti-SPA complaints. Where are folks seeing SPA’s being overrated?

          1. 2

            You probably won’t see people extolling the virtues of SPAs per se, but rather particular frameworks for building SPAs, like React. There are probably a lot of front-end developers who don’t know that there is anything other than SPAs.

            1. 2

              You probably won’t see people extolling the virtues of SPAs per se, but rather particular frameworks for building SPAs, like React.

              Sure, I see folks talking about how React and Svelte are cool in comparison to Angular, but that doesn’t actually have anything to do with SPAs being overrated as concept. And in the front-end world the hype that I do see is generally about server-side rendering/hybrid rendering approaches that bring things closer to web 1.0.

              There are probably a lot of front-end developers who don’t know that there is anything other than SPAs.

              As someone who has interviewed a lot of front-end developers, I don’t believe this at all. Even the most clueless have been at least aware of other ways of doing things.

        3. 16

          IMO, while I share the frustrations of the author, the series of posts is based on a false premise:

          This is, in theory, supposed to result in web apps that feel as fast and snappy as native apps.

          The explosion in SPAs may have something to do with wanting snappy UIs that feel more like native mobile apps. I think that’s a big part of the motivations of the people making the early technical tooling around SPAs. However I think a much, much bigger influence on the decision to build seemingly everything as an SPA was the decoupling of labor required to build front-end and back-end features. It let managers hire more quickly and make piecewise progress on one side without as much care for synchronizing the implementations. Often times that decoupling didn’t lead to sooner ship dates but they would lead to demos that could be used to show progress in status report meetings.

          Completely separate, I think the place SPAs shine brightest is for sites competing directly with desktop apps. e.g. draw.io, LucidChart, Photopea, Balsamiq, etc.

          1. 8

            The follow-up article, How to make MPAs that are as fast as SPAs, is interesting too.

            1. 10

              Inline everything, including CSS and JavaScript

              This will run counter to removing unsafe-inline for scripts in styles for CSP. This also will hurt caching, especially when switching pages. I’d gladly trade a teeny bit of time for security and caching. You could add nonces for the inline stuff, but you are also trading adding complexity to your system for what I view as little gain.

              Minify and gzip all the things

              2022 and not mentioning Brotli despite wide support for several years?

              1. 4

                I use ES modules to create tiny bundles of JS that I can load only on the pages that need them. Modules let me reuse shared snippets across pages without having to copy/paste/repeat, which would be an unmaintainable nightmare.

                IIRC ES modules were not around at jQuery/knockout time. Yes, you could make a tiny “calendar.js” and “header.js” etc, but then had to bite into a lot of other complexity, like onDocument load and other fun things. And imports were not inlined. I might be mistaken, but js imports are a relatively new thing (and still not supported by IE) . Also Hugo and static site generation wasn’t around back then. Same for service workers (also not fully supported by IE). Remember when you had to polyfill to use array.map ?

                I agree with OP, SPA’s are often overkill, but it seems too easy to dismiss that we got where we are today traveling trought a history of successes and mistakes. SPA’s would not have been a thing without the horrors of PHP or JSP (Java Server Pages). Little to no one would have used jquery if the browser apis had decent dom manipulation and sane apis for ajax requests. Etc etc etc.

                This to say, the best and the ugliest part of web developement is the crazy pace of change. We are pretty much living an IRL genetic algorithm.

                1. 7

                  Also Hugo and static site generation wasn’t around back then.

                  I agree with you, but static site generation as a practice it probably at least as old as dynamic site generation. Of the more modern tooling, Jekyll is just 2 years younger than jQuery itself and two years older than Knockout.js (2008 vs 2006 vs 2010)

                  1. 13

                    There was a blog tool called Movable Type which generated static pages dating back to 2001. :)

                    I strongly expect that people writing Perl scripts to output files into a “www/” directory predates cgi-bin. :)

                    1. 5

                      And the original incarnation of Blogger (1999?) did not host your blog, rather it FTPd the generated static files to your configured web host. (BlogSpot came a bit later, as a default host for people who didn’t have their own.)

                      1. 2

                        Ooh I didn’t know that.

                        My recollection is that MT had a big performance advantage at the time over a lot of competing blogging software for a while because of the static generation approach.

                      2. 2

                        I truly believe that the static nature of MT was a disadvantage at the time, and purely DB-backed blog platforms/CMS’s like Wordpress cleaned their clock because of it.

                        Now everyone who is cool sings the praises of static rendering.

                        1. 3

                          Well… it was really noticeable at the time I think that the blogs which were built on MT generally didn’t fall over when they got slashdotted. The ones which did things like making DB queries and calling sprintf() a lot in response to each HTTP request, did. :)

                      3. 6

                        My own static blog’s dependencies are Make (from 1976), m4 (from 1977), and rsync (a relative youngster from 1996).

                        1. 2

                          I would like to see this setup, in particular how you use make, if you’re willing to share.

                          1. 3

                            I am willing to share, but I’m not particularly willing to endorse or recommend my approach!

                            In particular the listing stuff gets very ugly because m4 does not have any iteration capabilities; I have to define it myself using a recursive macro.

                            1. 3

                              Ha! Thanks. I was just curious how it worked. I always love to simple lightweight solutions using untrendy tools.

                              1. 1

                                Writing it was educational; now I know what not to do in the future! But in a situation where you don’t need any iteration, well then it’s great!

                        2. 2

                          I remember using PyBlosxom, which could do either static or dynamic generation around 2005? And it was a port of Blosxom, which was in Perl, and must have been a bit older.

                          (Edit: Blosxom appears to have been started in 2002.)

                          1. 1

                            I still use Blosxom (OG Perl version) in static mode.

                            It was dead easy to implement a Gemini site with it.

                            => gemini://gerikson.com/gemlog/srs-bzns/Gemlog-with-Blosxom.gmi

                            1. 2

                              That’s awesome!

                        3. 3

                          and still not supported by IE

                          Since IE has not been developed for years and never will be again, it will never support anything new because no new releases are coming.

                          1. 1

                            We are pretty much living an IRL genetic algorithm.

                            OMG you’re right! This makes me feel simultaneously better and worse about the state of web development…

                            1. 3

                              “A world run by a bored god with one finger on the fast-forward button”, to (mis?)quote William Gibson.

                        4. 8

                          You need to build a SPA if you want your app to work offline. So if you want to compete with desktop-class software, you need a SPA. I don’t think that’s a mistake.

                          1. 12

                            I don’t have one SPA here that I can use offline. Not even the electron versions.

                            1. 7

                              There are legitimate reasons for building a SPA, some of them mentionend in the article. I would rather argue that defaulting to a SPA without further considering options is a mistake I’ve often seen.

                              1. 3

                                I agree - it shouldn’t be the default - but the article is on the glib side with “basically just a media player” as the only valid use-case.

                                1. 1

                                  As https://changelog.com/ proves this is even a bad example! It’s really offline support but even then I’m not sure it’s the deciding factor. Nothing’s stopping us from caching pre-rendered pages for offline support for (news/information sharing) consumer apps as opposed to interactive/client driven apps, e.g. editors or games.

                              2. 2

                                Maybe write a desktop app if you want it to compete in that space?

                                1. 5

                                  The economics are much better for a thick web app/SPA and a thin webview desktop app wrapper.

                                  1. 1

                                    As a Linux user, I can appreciate this. Heck, I wish Lobsters had a PWA so I could get a better experience on Android.

                              3. 6

                                In my current project I wish I had used SPAs sooner, because it has has been easier to maintain a consistent look and test JSON endpoints. This is not theoretical or generalizable, but that’s how it went around here.

                                1. 9

                                  This polemic is off-topic. From our guidelines:

                                  Will this improve the reader’s next program? Will it deepen their understanding of their last program? Will it be more interesting in five or ten years?

                                  The title and contents are both resort to over-generalizations that don’t add anything new to a very tired debate about whether the existence of SPAs can be justified. The author’s home page says everything about their agenda:

                                  Hate the complexity of modern front‑end web development? I send out a short email each weekday…

                                  1. 4

                                    Some instance of this rant is posted to this website every day.

                                    1. 3

                                      When I saw Next.js and all the SSR shenanigans, it was pretty evident to me we need very small SPAs. The moment a person navigates to a brand new URL you are better off serving a fresh page vs introducing complex routing on client side. It instantly took me back to PHP + jQuery days! I think React just got out of hands in this case.

                                      1. 3

                                        Generally speaking, though, SPAs as an industry trend or “best practice” were mistake.

                                        Generally speaking, “best practice” is a mistake.

                                        What is best practice for an advertising company the size of Alphabet will almost certainly have little overlap with best practice for a startup with a hundred users, or an established and profitable SaaS company with thousands of users. Best practice for a company making histology lab workflow software will have very little overlap with best practice for a company making mobile video games.

                                        Another aspect to consider: here in Australia, ~ 60% of startups shut down in their first three years. Finding that you’re doing things just the same as everyone else should give you pause - because the median outcome is failure (I know that is a non-unique observation, but I can’t for the life of me find the citation).

                                        Edited: ah, there we go:

                                        If you do everything the way the average startup does it, you should expect average performance. The problem here is, average performance means that you’ll go out of business.

                                        1. 2

                                          Personally I think that SPAs do serve a purpose, dynamically rendering/changing content is more efficient than loading a new page in it’s entirety since you don’t need to load the entire document again, as well as less requests to resources need to be made (such as CSS, JavaScript files, as they’re already loaded by the time content changes). While they can certainly be bulky when it comes to bundle size, in terms of request count and resource usage in some scenarios they can be more efficient.

                                          1. 2

                                            Like a lot of modern development practices, the problem SPAs solve is a problem of scale. If you want to have independent backend and frontend teams, you need them to be able to work in their own silos. Dividing a website up into the backend API and the frontend SPA does this quite neatly. In theory, the best website would be something that sends just the data you need for each click: HTML first for good first render, some means of minimal hydration, just send JSON diffs for within site navigation, don’t break the back button, do allow persistent uploads and offline use, etc. etc. New frameworks like Astro are moving in this direction, but it’s always going to be hard to create a superoptimized website, and traditional MPAs get some advantages from adding JS for client side interactivity rather than removing JS for server side rendering. Either way though it’s not simple.

                                            I will say though for a small team of full stack developers, the MPA approach is going to be easier because you don’t have go through the API bottleneck. You can just pass context to your template instead of creating an API producer on the backend and an API consumer on the frontend. It also is often going to be easier to cut client side interactivity as feature to make deadlines than to give up on rendering performance to make deadlines.

                                            1. 2

                                              Without any exaggeration, there is no platform that’s worse at building user interfaces than the default web. If you change the state of the app via a form, the entire screen re-paints. SPAs saved the web. You can’t even show a spinner without persistent process state. SPAs took the web from a platform where you just glue strings together to a platform for actual software.

                                              1. 1

                                                I don’t agree. Lots of websites are centered around showing some documents, more or less and they are not necessarily entire applications. Even then not reloading the whole page does not imply using an SPA.

                                                1. 1

                                                  But it does imply that you’re not using the default browser behavior. Turbolinks is the classic example. The second you start keeping the page around and only modifying a portion of it, you’re admitting that you want more control over your client side state and that the default browser rendering behavior doesn’t work for you.

                                                  We can talk about what the best code pattern is for making it simpler because once you get into the world of client-side state inevitably more code is required. But that’s completely different than lying to ourselves saying that we’re using default web technologies.

                                              2. 2

                                                Single Page App – is a response to failures of OS makers to recognize the need and to come up with uniform, secure, performant UI platforms, and expressive, non-vendor locked, secure methods of application distribution, deployment and updates – over the last 30 years (and before IOS/android and SPAs)

                                                If there would have been:

                                                • a decentralized ‘app store’ not just for apps but for ’suits, bundles and ‘gardens’,
                                                • a uniform UI platform + identity management platform, that worked without installing a bunch of ‘extra’ things,
                                                • without vendor lock-ins,
                                                • with commerce-friendly licensed tech

                                                then, there would not have been ‘SPAs’. Until then – SPAs are needed, it is not about ‘history’ it is about an ability to see, interact, and compose what you need – on one screen, with minimal (or no) network bandwidth requirements

                                                1. 3

                                                  This article isn’t about SPAs vs. apps, its about SPAs vs multipage apps, and how many of the contortions involved in an SPA are already handled by the browser, and are generally handled more efficiently and correctly w.r.t expected site UX and accessibility.

                                                  For your other points:

                                                  Different platforms have drastically different core UI concepts, the obsession with having single cross platform UI framework is an obsession with there being a single OS that everyone has to use. Every “cross platform” UI framework screws up a bunch of things on its non-primary platform, because different platforms are, you know, different. Changing the UX of every platform (minus one) to match one primary platform (which would out of necessity be windows) would represent a significant usability break for the majority of platforms.

                                                  what the heck are “suits and gardens”?

                                                  vendor lock in: e.g there is one OS to rule them all. Different OSs are different, and people generally like their OS of choice.

                                                  what is a “commerce friendly” license?

                                                2. 1

                                                  I really like JSX and React’s model and Redux for state. I only dabble in web development, however. Is state-management easy in server-side react? What has been people’s experience doing React server-side with state?