1. 12

    1. 14

      Something a lot of people may have missed is that good old fashioned, separate-page-load-per-click sites got a LOT visibly faster over the past decade thanks to a feature called paint holding: https://developer.chrome.com/blog/paint-holding/

      Short version: browsers used to load new pages when you click a link by showing a blank screen and then loading the page. These days they behave differently: they start loading the new page in the background, then swap in the new page once enough of it has loaded (provided it loads within a short time limit).

      So if your pages load fast enough, users won’t get that flash-of-white that was one of the reasons people got excited about SPAs in the first place.

      1. 2


        If I get caching+bundling right for all the static assets: the first pageview will download 1 HTML file + all the static assets required, and then the second pageview wiill also download 1 HTML file and reuse the cached static assets (*). That’s the same number of requests and the same load time, achieved within a lower complexity budget than anything involving dynamic templating.

        (* Except for assets like images that differ from one page to another, but that’s about the same either way.)

        1. 1

          In addition, browsers these days do a lot more caching of work like Javascript parsing and compilation, on top of a cache of the raw sources, which again significantly reduces the disadvantages of MPAs https://stackoverflow.com/questions/1096907/do-browsers-parse-javascript-on-every-page-load https://blog.mozilla.org/javascript/2017/12/12/javascript-startup-bytecode-cache/

          1. 1

            Oh sweet. I knew this was split out into multiple threads so they could do stuff like parse the HTML, JS and CSS in parallel, but I didn’t know the parsing was cached.

    2. 2

      The only way I can think some sort of complicated client-side “app” would need to exist in some documentation is if it’s supposed to have interactive examples you type and run in the browser. But even for that, it’s probably better and safer to just defer to something which specializes in that exact task rather than rolling your own gigantic thing in React or whatever.

      And Sphinx + hosting on RTD does just fine. I just did a quick check with network inspector, and pulling up the docs for one of my libraries had a response time of 50ms.

    3. 1

      Also, a simplistic implementation of client-side navigation is bad for accessibility, particularly for screen reader users.

    4. 1
      var script = document.createElement('script');
      script.src = "https://unpkg.com/htmx.org@1.9.5"
      script.integrity = "sha384-xcuj3WpfgjlKF+FXhSQFQ0ZNr39ln+hwjN3npfM9VBnUskLolQAcN80McRIVOPuO";
      script.crossOrigin = 'anonymous';
      script.onload = function() {
          var body = document.querySelector("body");
          body.setAttribute('hx-boost', "true");

      Useless use of var. This is the same as writing window.script = document.createElement('script');. 😕

      1. 1

        My JS skills are lacking, what would be the “correct” thing to do instead?

        1. 2

          script = document.createElement…

          Would be equivalent to what you wrote.

          If you want the name to be invisible to other scripts then you could use an “IIFE” or a module.

          Edit: or you could maybe just wrap the script in braces and use let. I can’t remember what version of JS you need for that to work (non-strict, strict or module mode).

        2. 2

          There are a variety of choices. The quickest is to write an IIFE:

          (function() {
            var script = document.createElement('script');

          Another choice is to run the script in modern mode by linking to it with <script type="module" src="/whatever.js"></script>, but that sometimes has unwanted side effects (if a script expected to write to the window, for example). I’m not sure Sphinx has a mode for that.

          Another thing Sphinx probably doesn’t have a mode for is just writing the script tag directly, since all this JS does is add another script tag that you can just write yourself.

            onload="document.body.setAttribute('hx-boost', 'true'); htmx.process(document.body);"