Member-only story
Static SPAs: Exploration of Leptos, Dioxus, and Next.js
Not a Medium member? Read the post here for free.
One of my absolute favorite methods of deploying Frontends is to pre-generate all routes statically, and then let each route load the dependencies they need for interactivity.
- Load times are fast
- The user only downloads what they need (great for slower or mobile networks)
- SEO is great in many cases, and okay in others[¹]
- It can all still be deployed in the most optimal way which is CDN + Static Assets[²]
I particularly care a lot about infrastructure scalability, maintainability, robustness, and cost. SSR typically makes each of these significantly worse compared to simply serving static files. I also don’t believe mixing your API into your Frontend code (i.e. Server Actions) will do you any favors when you start scaling up your teams, but that’s a topic for another day.
In this post we’ll explore how this can be setup and compare a couple of different frameworks. Let’s start with the overall results before we dive into the details:

*: Support for chunking in WASM is generally poor, although recent strides have been made towards it (see wasm-bindgen#3939)
**: Dioxus support is in a state of flux, changing and improving how Static Generation is supported, leading to the docs and examples currently being broken (tracked in dioxus#2587)
💡 You can see all the examples in the https://github.com/Tehnix/comparison-ssg-rust-js repository.
In case it’s still not clear exactly what I mean with a “Static SPA”, let’s set up an example with Next.js, which supports this out of the box. The term for this is a bit messy, and you’ll find that React believes that this can still be called SSR where your rendering is just happening in compile time. Next.js will be calling this SSG in their Pages Router, and has confusingly changed the name of this in their newer App Router to be called Static Exports.
Let’s dive into the comparisons of how to achieve this across frameworks: