There was a time that I would have never imagined the need to write an article like this. If you were to ask someone how a website worked, even 10 ...
For further actions, you may consider blocking this person and/or reporting abuse
I think in nearly all the applications I developed in my experience there was no need for SPA. We were doing it because front-end frameworks went this direction. I think MPA built with a framework which allows for writing JS declaratively is the actual way forward. And we've been seeing this realization quite recently. But still, it's unbelievable seeing fresh start-ups deciding to build SPA for their web-based businesses without thinking about SSR or at least static prerendering.
Yeah my experience was opposite. I worked almost exclusively in scenarios where SPAs are beneficial. Administration and internal web applications, private social media, education apps behind logins. It's why I created Solid since I wanted to improve that, but I also recognize I have to be in the minority.
But I just keep seeing React powered Isomorphic Frameworks (and I don't mean Astro, which is clearly unique) that claim they are somehow improving performance or changing the game. And sadly maybe not so much. I've already explored the limits to performance a long this vector, and I suspect these frameworks won't even be taking things that far. For many use cases it really is not the optimal approach. And this isn't specific to React, but applying SPA patterns where they aren't needed.
The issue is, people want to write apps one way. Many people don't want to know how to write web apps 3 or 4 different ways and have to pick each time; that is a big decrease in developer experience. These systems are so complex, many people don't want to know all the specific implementation details of all of them, let alone even one in many cases. Many people aren't even front end devs, and they need to pick something and roll with it (React is that at the moment).
Yeah I'd contend though if I were looking at realworld cases. MPAs would probably be the better default for the vast majority of sites. This was a difficult perspective for me to come around to being such a big proponent of SPAs. But let's face it. Just writing some HTML with sprinklings of JavaScript probably still covers the vast majority. We need better tools here for sure, but we haven't successfully bridged the gap yet.
@swyx article dev.to/swyx/svelte-for-sites-react... touches on this. But in the spectrum even Svelte isn't that far on the site side. Elder which the article touches on is like the frameworks I'm talking about today though. And from that perspective maybe Elder and Astro are on to something letting you use familiar tools. But ones optimized for this case can do even better.
Maybe that's true, but there's something magical about SPAs: they can be dynamic, like a game or other real-time morphing experiences. Starting with an MPA architecture then switching to an SPA (when it is decided that dynamic updating of the experience is needed) isn't as easy or convenient as simply starting with an SPA.
How do we let everyone write in the SPA paradigm, but have their applications be MPAs or SPAs as needed depending on use cases, while keeping the performance up?
I have a few ideas on how to achieve that. But nothing exists today meets what would be needed. Marko is closest, Qwik has promise. But you need to take aspect of basically both approaches and fast forward about 3 years. I can picture what it looks like mechanically but to actually bring it to where it needs to be, to be consumable is still years away realistically.
Could it be done at all, starting from an existing SPA approach? Or would it need a fundamental re-architecting from scratch?
It would be hard. I'm looking at this with Solid to a degree. But realistically it is much easier from MPA. I think Qwik is the closest to a SPA friendly approach and even Misko acknowledges the approach isn't compatible with any existing SPA framework because of the way you need to approach the parent child relationship. In Qwik all data is dependency injected.
props.children
is fundamentally awkward to deal with. I think a smart enough compiler could reconcile these differences and we are incredibly close to doing so with Marko but it takes starting from different core assumptions/restrictions. For instance all data passed between components needs to be serializable. That isn't exactly 100% the way it needs to be (that assumes components are the boudaries like in Qwik) but same category of considerations apply.I'm hoping as we learn more a path will form here. But right now between Marko and Qwik MPAs are leading the way on this. They will push the boundaries here further before SPA frameworks can catch up to what Marko was doing in 2014. Which is fine since this isn't what SPAs were made for. It's just going to take some time.
Take the reversed way, add a serializable tag/props in solidjs.
I work with e-commerce and this article is lovely! Thanks!
We struggle a lot with server performance due to the backend being a monolithic oracle Java app from over a decade ago, but I've been revamping the front-end and mid-layer. One of the targets was performance and responsiveness. Our competitors used to be far ahead on load times, then sightly ahead after the front-end revamp... But recently they've all moved to react/angular for their front-ends and I saw we are now outperforming them in load time as they've all degraded by moving to client side rendering. 🤷♀️ I'm sure their DX is much better, but I doubt their customers, or CEO would care 🙍
"The paradigm has flipped so much that it is the traditional Multi-Page Application (MPA) that requires explanation now that Single Page Apps (SPA) are becoming the ubiquitous product."
I’m often baffled (and I'd be lying if I didn't say sometimes "frustrated" too) when I have to explain traditional web development foundations, but you're right - it's been a decade - so thank you for a timely and important article.
What about WASM and WASI. How do these new technologies play into the future of SPAs and MPAs?
WASM has a lot of potential. But in terms of shipping less code I don't think it is particularly compelling. I think it means potential of bringing some really rich performant applications to the browser. I think it opens up new ways to run code of the server(or serverless) in more performant ways.
I expect we will see serverless WASM platforms to offer optimal performance using things like AssemblyScript. This might be a competitive edge. Maybe even new WASM based server platforms.
In the browser as we see more of the barriers ironed out WASM should get more performant. Which it will make it an easier choice for offloading heavy computational work. Still unclear whether it can compete with a SPA framework for rendering, all indications so far suggest not for a while but it will definitely be a key role player.
For traditional sites and MPA which are trying to shave overhead I don't expect it to play much of a role outside of powerful widgets you lazy load.
For the foreseeable future, while I see a lot of value in WASM I don't expect it to be game changer in terms of the core experience. But rather a really nice addition to the arsenal.
Magnificent.
What about if they develop a specific runtime or sandbox similar to how JavaScript runs in the browser, only made specifically for WASM?
Could that happen and would that spell doom for JavaScript?
I mean could something like Rust or AssemblyScript with full access to the browser DOM and browser APIs result in massively more powerful and more performant PWAs?
Could all the above translate to less bytes shipped to the client especially if the code can be sent already compiled for the specific binary interface of that runtime?
PS - Sorry if I'm misunderstanding how some of these technologies work or are supposed to play together. I'm new to the field of web development.
Hard to speculate when they get access to the DOM API if they'd be massively more powerful. I do think that if they could avoid the overhead of going through JavaScript bindings there are good improvements to be made. I wouldn't be surprised if it could be really good for app like experience. However, if I were guessing I wouldn't expect this reality for at least 5 years.
In the next couple years there will likely be some big improvements but to fully realize this is going to take a while. I wouldn't be surprised if we don't see this fully happen this decade. That sounds callous but like Web Components have been in the works for 10 years. WASM has been going for about 4 years now. Which is why I'm unclear if it is more likely JavaScript becomes more dominant than ever during this time and WASM ends up just a way to continue for it to take over traditional backend services. I'm basically saying I'm more likely to bet on the speed proprietary solutions(like a new backend platform) move at than that of the Browser platform which basically dictates the speed WASM can be adopted.
In terms of size I imagine WASM doesn't end up being smaller. However it's possible there is less parsing/execution overhead that makes up for that. I'd be surprised if it has any meaningful impact on this initial load scenario. So for traditional websites/MPAs I wouldn't really hold my breath. We might see exploration there but likely only after what I wrote about above.
I find this discussion interesting. I want to share my findings on the future of WASM, but I realised that they are just a tad too much for a comment here (bullet points and all). So here are my Notes on the future of WASM and JS (2 min read, most important facts, with sources). FWIW.
See esp. the Web IDL bindings proposal which would allow WebAssembly to directly access the native web API’s (which allow operating on the DOM). Imagine the possibilities...
Yeah that's pretty much what I've seen. A good summary. I'm aware of these proposals but these things take years. So what I was getting at is I give it about equal chance that JavaScript to WASM compilation gets in a good place before those proposals get implemented. To be performant enough to push JavaScript further into the backend before it's practical to take WASM approaches mainstream in the browser.
Are you aware of WASI? Interesting potential future for serverless services.
Yeah I didn't realize this had a name. This is an example of what I was referring to in using WASM not in the browser being a potentially more interesting application. It's cool that they are attempting to standardize this approach.
It's been an ongoing effort for a few years. I would love to see vendors support this. It seems like it could be an OCI (Docker) container killer.
A few interesting projects:
Just to throw in some complexity - it seems like the per-page routing for Next/SvelteKit would lend itself to MPA... so you get a kind of best of both worlds there (SPA-like for a given pageset, MPA-like for the overall app).
I mean a SPA could be built on any page hence we see SPA in MPA too.
But this per page routing is what I meant by all in. What I wanted to call out. It isn't equivalent. The problem is MPA style optimizations essentially deconstruct the app. If you model it like a SPA and then just turn off client side routing you still have an app written in a way that is difficult to optimize for MPA. You would need to apply one of the 3 approaches mentioned in the article and the popular solutions don't have tools for that. I just want to clarify we are not near a best of both worlds solution in those.
Cool, yeah, that makes a lot of sense.
After doing a lot of SPAs since the last few years, I can't help but appreciate the effectiveness and simplicity of purely server-rendered solutions, and conditionally sprinkle just sufficient enough javascript to add the beloved flair and interactivity we have come to expect from modern experiences. I was trying to actually use Fastify and Pugjs, for a fully server-rendered solution, with client-side JS only available on few pages(as per the need) and was amazed to clearly see how for we could go just with the classic web app approaches + modern vanilla JS.
Though, we wouldn't have probably reached here, without JS frameworks taking the plunge, trying to optimise, embrace what browser offered to replicate what server did, breaking the browser shell and going to the server taking its expressiveness, thinking universal-ity, SEO, aspiring to bank on the hype-train, enabling full-stack universal experiences, and then realising oh shit, we're back at what we did, with more fragmentations on the approaches to solve the same `ol problems. But Astro, Svelte, Solid (I don't get Qwik yet), all seem like superb choice to craft the next-gen web experiences.
After all, when you have chains of props running down through a component tree it's hard to break this apart :-)
Thank you for producing such great content around crafting mindful experiences, and SolidJS.
Good article. I've never been sold on using an SPA for larger projects due to the large upfront loading time. I primarily work with .NET (5, Core, Framework) on the backend which handles the routing and server-side rendering seamlessly, so I primarily develop MPAs.
The SPA centric front end frameworks can be troublesome with an MPA so I ended up developing my own library, Modstache. It works on DOM fragments or HTML strings, so can be used with components, prerendered or dynamic HTML or shadow DOMs. I like to use the Fetch API to get page components/partial updates, JSON objects and to submit forms. Modstache can be applied to these as needed.
I don't mean for this to sound like an ad for Modstache. It's just that I use it to help solve issues brought up in this post. Feel free to use it if it will help solve your problems.
Yeah there are a few different ways to attack this. SPAs can be made pretty slim, and slim enough that if the use case merits running everything in JavaScript it isn't a problem. Even with huge sites. It's just a question of if the type of site really benefits from it or cares about the upfront cost. And you can always have multiple SPAs.
I talk about how React Server Components don't handle the ruthless case, but they are more than adequate for the large site that would be a SPA. Some parts of the app probably work better server rendered. For a framework like Next, it means maybe removing the need for an explicit API service. Forget GraphQL just author your site. This is powerful technology.
But this can't account for the bottom-line case. If your business is built on page loads and secondary navigations mean they are already in the funnel, it's worth considering how much more streamlined this can be.
I've been wondering if there is an SSR framework that doesn't tied to specific back-end engine 🤔 (e.g node, deno)
I see most of SSR frameworks require Nodejs. Hope someday this trend will change.
Well there are platform required tools. It's a matter of not to be tied to them. We are seeing the adoption of pluggable adapters in things like SvelteKit which support a variety of targets like node or various serverless environments (Vercel, Cloudflare, Begin).
Marko has recently refactored to allow for use on non-node environments like Cloudflare workers. I think we are already seeing the shift.
That's a good news. I heard SvelteKit move away from Vite. So I'm guessing it is because some parts of Vite rely on Rollup which need to be run inside Node 🤔
Nevermind. I confuse it with svite 😅
I haven't seen that. To be fair there is a difference between development and deploy environments. I think given the tooling moving off Node is a huge effort and I expect things to stay there for the time being. But just because you use Node to build your solution doesn't mean it requires Node to run it. An app built with Vite is deployed without Vite. My Cloudflare Workers Hacker News demo for Solid is built with Vite but runs using that non-Node platform including streaming SSR leveraging Web (not Node) streams.
"Pull out" as in "throw away", or as in "bring forth"? Might be good to disambiguate.
I meant bring forth. I suppose if you were already using those technologies it could be seen as ambiguous. Although in context of someone using JavaScript framework I meant it isn't time to bring back those server technologies.
Great article, many thanks 😊