View transitions: a knockout blow to SPAS

View transitions: a knockout blow to SPAS
Abstract, technology-themed image that symbolizes the transition from single-page applications to multi-page applications / DALL-E

This edition's topics:

  • View Transitions are a win for MPAs
  • Server-side mental models
  • What makes Nuxt's version of server comps unique?
  • πŸš€ Changelog review
    • Remix 2.5
    • Next.js 14.1
    • Astro 4.1
    • SvelteKit 2.4
    • Angular 17.1
  • πŸ§‘β€πŸ’» Tool links
  • πŸ—žοΈ Blogosphere

View Transitions are a win for MPAs

It's real easy to look back on old trends and wonder why we all jumped on the bandwagon. You had a Tomagotchi. I had a Tamagotchi. Let's just not talk about it.

The industry has had almost a decade of React dominating the zeitgeist, which is a rough estimate of how long single-page applications (SPA) have been a popular option for building web apps.

But it's 2024 and looking back, everyone seems to be leaving the SPA bandwagon. Much as been written about why - huge JS bundle sizes, the security implications of huge JS bundle sizes, complex state management, SEO hurdles, the initial load time, potential memory leaks, etc, etc - so I don't need to dive deeper into the reasons.

But I do want to point out why, despite all the reasons to the contrary, SPAs still have a huge amount of legitimate pull.

When you click a link, the page doesn't do a full reload.

When written out, it sounds so simple. But this, in my opinion, is the killer reason why a team's product manager isn't going to blindly pull the SSR switch. If that page has to do a full reload, your users are going to groan.

Users have come to expect certain websites to feel like native apps. This is a UX issue that multi-page applications (MPA) just can't compete with.

This is why I'm so interested in the work around view transitions. The phrase has grown to mean slightly different things depending on the environment/implementation, but in general it is a way to control the way the browser navigates from one page to the next.

If this is just in the browser, then you don't need a fancy JS framework to help. The native implementation relies largely on CSS animations, meaning very little JS is even needed.

View transitions become MPA's (or like we used to call them, web sites) one big blow to the case for SPA argument.

And for me, it becomes the *final* blow. I previously gave a Meetup talk about my initial research on view transitions in August 2023. Since then, Remix has added support, SvelteKit wrote a blog post walking through how to integrate the native implementation, and I had my own ignorance busted when I realized that Astro wasn't the only framework with support at the time. (Nuxt added support in April 2023.)

Of course, the native implementation is still not supported in all browser. When that happens, then it likely won't matter what your framework supports.

But I'm impatient. So I'm planning to do another deep dive into the world of view transitions. In the vein of TodoMVC, I'm going to build a dummy MPA that needs some transitions and compare the way each framework handles it. Give me a month or so to see what I cook up. (I suspect Astro will have the most intuitive but we'll see.)

Until then, just know if one of these has the killer view transition api/feature, than they've made a big dent in the SPA argument.

Cartoon, a comically anxious circus animal juggling various technology items while balancing on a circus ball / DALL-E

Server-side mental models

I'm looking forward to the server component world - React or otherwise - we're about to enter. But all the understandable attention being devoted to the topic does seem to sweep under the rug the tradeoff we're all about to make.

Components are going to get a bit more complicated.

I noticed when I first started using Astro and it's island architecture. Before, a component was a component. But now you need to decide if it's a server component or a client component.

Frameworks will likely have a default assumption about your components - like how Astro assumes everything is a server component unless you explicitly tell it otherwise. This will help.

But once I declared a component as client, my mental model took a while to adjust. Now that my components are on islands, how do they talk to each other? How do I pass props from one to the other? Can I pass functions between them? Promises?

Every framework is building different answers for these things but devs are going to have keep them in mind. You'll have to be aware of when you have a valid reason to change the defaults and when you're standard prop passing techniques aren't going to work.

None of this is a deal breaker. But it's just another thing we'll have to keep in mind and another thing I can see junior developers tripping up on. Imagine the debugging sessions around a client component that has a child server component while a product manager keeps checking in on you.

My hope is that the framework teams are doing what they can to make the APIs that clearly match the tradeoffs and to explain not just the cool new features, but the way our mental models need to update. Otherwise, there will undoubtedly be some devs that just make everything a client component because it's simpler. (Kind of like how there's a gazillion useEffect calls in your team's component right now? πŸ˜œ)

As an example, in the RSC world at least, you're most benefited by thinking about your applications leaf components. Due to the RSC nesting rules, those are likely your best candidates for client components while everything likely is best suited as defaulting to a server component.

Not hard. But it took me a good amount of time working through the best way to structure my DOM before I stumbled across that light bulb in a comment in a thread I can no longer find.

Ideally that stuff will become front-and-center over time.

A server radiating various common web UI components, like a dropdown or accordion / DALL-E

What makes Nuxt's version of server comps unique?

After last issue's focus on React Server Components (RSC) I was pleased to come across a useful (albeit dated since it's from July 2023) run down of the Vue/Nuxt approach to server components from Nuxt core team lead Daniel Roe.

It's hard to comment too deeply on it without first getting my hands dirty with Nuxt. But there were a couple of highlights from the "What makes this different from React" perspective.

The first is Roe's characterization of RSC as "an entirely different approach to rendering server components which is often linked to streaming responses from server to client." (Emphasis mine.)

I'm quite curious how others took that line. From early 2023, when I first started reading about RSCs, to now, I haven't really heard too much chatter about the streaming aspect. It's a cool feature for sure - I found Remix's early implementation quite pleasant - but I wouldn't say I've seen people pining for RSC for that reason.

But maybe I'm in a bubble.

The second, and probably way more interesting tidbit, is this nugget regarding islands.

[Island architecture] is an architecture which embeds dynamic 'islands' within more static surroundings. The Nuxt approach is the opposite - we embed static 'islands' within a dynamic Nuxt app.

This seems like an important definition of the default for devs. If your mind defaults to client, Nuxt might be more intuitive. If your mind defaults to server - as mine does - you might feel more at home in Astro.

Based on my little time playing with Astro, it definitely feels like a closer match to my mental model.

I wish it more common place for frameworks to call out their differences like this. But then again, maybe that's what this newsletter is for.

πŸš€ Changelog review

Remix 2.5

SPAs ain't dead yet! Remix has a SPA mode! Reading through the summary, it does sound like it effectively becomes a React + Vite + React Router setup. I might advocate you just use Vite directly, but adding the React Router for you is a time saver. And doing it this way leaves you one config setting awar from going back to MPA set up. This also brings Remix in line with Next.js, which allows you to go back and forth. My only request would be the ability to flip SPA/MPA per route (which would really bring it in line with Next.js).

Next.js 14.1

The most noteworthy thing here is actually a doc change. There are now doc revamps in order clarify how to use Next.js on things other than Vercel. This is undoubtedly a good thing for the ecosystem since folks can have more guidance on self-hosting. I always assumed the lack of docs on self-hosting was an understandable business decision designed to make the easiest path to just use Vercel.

On a technical front, this is actually a pretty jampacked release. Much better error messages, detailed cache logging, and more options for the next/image package all seem like tangible features.

Astro 4.1

The most notable feature is the nice addition to the island strategy which allows you to hydrate a component "when it is near the viewport, rather than hydrated when it has entered the viewport." *chef's kiss*

SvelteKit 2.4

SvelteKit 2.0 came out in Dec 2023 with a blog post and 2.4 is already shipped out the door. Fast paced over there! 🏎️

I'm most impressed by the new filesystem functionality which uses Vite magic to bundle things but the DX still feels like you're reading from the filesystem like normal. Now you won't be blindsided by FileNotFound errors when you deploy to your serverless function.

Angular 17.1

I'm looking at Angular docs in 2024. What a time to be alive.

Signals is what grabs the attention in this release as signal-based inputs are now a thing. On the surface that doesn't seem like much but, as notable Angular contributor and author CΓ©dric Exbrayat puts it, "this is a first step towards signal-based components." Skimming through the RFC for these new components leaves me thinking they might be on to something here.

πŸ§‘β€πŸ’» Tool links

  • It does feel like the existence of next-safe-actions might say something about the complexity of Next.js' server actions, but that bullet point is coming next.

πŸ—žοΈ Blogosphere

  • πŸ˜• Vercel's Lee Robinson wrote up what I'm sure is a genuinely helpful blog post guiding people through common app router mistakes. But look how long this list is. Something else if off here. If there are still this many common mistakes, maybe the docs need to be looked at. Or, even worse, maybe the change to everyone's mental model is coming too quick. (That ones a lot harder to fix.)
  • πŸ–ΌοΈ On some level, we're all just building reactive components. That's the root problem most of us are trying to solve. That's why I enjoy write-ups that just go deep on reactivity. But those are usually longer. Hence why I'm sure we're all glad Vladimir Klepov included a graphical cheat sheet in his deep dive into Svelte reactivity.
  • 🌢️ It's getting a little spicy in the React world. Some venting from Cassidy Williams, Tom MacWright, and Tanner Linsley
  • 🀀 I never get tired of "You have too many useEffects." This great talk from XState's David Khourshid has been added to the growing list.
  • πŸ•΄οΈOn the one hand, Postman's Jean Yang's reminder that your company is not a FAANG company is both important and insightful. I still believe the biggest reason React and SPAs took over the zeitgeist is because every one was copying Facebook. But the Facebook website of 2014 - with all its real-time pokes and likes trying to keep you logged into the app for that sexy VC "engagement" - was nothing like any of our boring SaaS apps. On the other hand, I wouldv'e hoped we would've stopped idolizing these companies a long time ago. But alas, here we are.
  • 😱 You'll either hate or love React Postgres Components but I guarantee you'll feel something.
  • πŸ“ˆ I love it when someone approaches a web dev convo with an academic sensibility. Jake Lazaroff hits the mark with his 2D web app classification system. A matrix like this is useful for figuring out what tool is good for quandrant.
Colby M White

Colby M White

A software developer with more than a decade of experience. Currently collaborating with the RedwoodJS team to add a AutoForm to its ecosystem.
Austin, TX