I've found that SSR is generally quite slow. If you're using it, you'd want a CDN or some other caching layer in front of your server so you don't need to render each page server-side.
What about stuff like Phoenix LiveView, which can push dozens of updates per second per client to hundreds of clients simultaneously?
The obvious downside to Liveview is that all of the UI state resides on the server. Every UI update therefore requires a full roundtrip request to the server, and so reducing latency is of paramount importance. That's why fly.io is so heavily invested in the Phoneix ecosystem, because their service is predicated on the idea of distributing your app globally to reduce latency. A React/Angular/Vue spa on the other hand can make decisions about how to update the UI without contacting the server. In fact, many PWAs these days are actually designed to work completely offline.
> Every UI update therefore requires a full roundtrip request to the server,
while this is certainly the easiest path, you don't HAVE to put all your ui states on the server. its trivially easy to plugin alpinejs for small ui state stuff that is all client side.
Another huge benefit, the js escape hatch lets you create a bidirectional bridge between your custom js and your user's liveview instance.
Yeah you can definitely pull in Alpine for UI updates that don't require any server side interaction, but then your app's logic is fragmented between different frameworks (Alpine and LiveView).
It's definitely doable, and I know the PETAL stack (Phoenix Elixir Tailwind Alpine) is super popular, but it's nice (and perhaps less error prone) to have all of your UI logic handled by a single framework. This consolidation of UI code under a single framework was one of the killer features of SPAs initially. Prior to that lots of sites were built with a server side templating framework with jquery sprinkled in for client side UI updates.
I agree heavily with this assessment.
I think there is room for a framework similar to Phoenix LiveView but also allows compiling certain interactivity to the client. Next.js and Remix are kind-of fulfilling this but they have downsides.
In the BEAM ecosystem, I think there is room for [Gleam](https://gleam.run) to be used to compile to both Javascript and the BEAM.
There was actually a developer working on a subset of Elixir that compiles to JS called Elixirscript[1], but development seems to have stalled. Another functional statically typed compile-to-js language which targets the BEAM vm is Purescript through the Purerl project [2].
If you're going to compile to JS though, there's an argument to be made that you might not want to target the BEAM at all. You could potentially run your entire backend on something like Cloudflare Workers, which has over 200 points of presence around the world, so latency is about as low as possible. The other CDNs have their own competing worker runtimes as well (e.g. Cloudfront functions, Netlify functions, etc.). These edge worker runtimes also have the benefit of not charging for each individual region in which you operate. You can also run any language which compiles to WASM like Rust, Assemblyscript, or Grain [3] on these edge runtimes. The only missing piece for me is a distributed database, but it looks like Cloudflare at least is working on that [4].
[1] https://github.com/elixirscript/elixirscript
[2] https://github.com/purerl/purerl