Multi-page apps have come a long way. The browser helps incredibly. There's something called paint-holding, so if you're on a page and go to the next page, the browser doesn't show the next page until it's ready. You can do cool tricks with streaming where you can have the app shell show right away the content and show loaders and stuff in multi-page apps. It feels almost like a client-side app. But there are trade-offs. You are loading all your ad scripts again. You can't do cool animations, right? There are still reasons you'd want client-side routing, right?
Luckily, you might have heard some news, this gif looks terrible large, but essentially, what about view transition API or flamethrower or turbo? They've been using this in the Rails community for a few years, right? It basically replaces your HTML without reloading the whole page. Well, on the surface, this makes a lot of sense. If you have a static site that you built where each page is independent, and now you want to switch between those pages, this works great. But it's a little bit more complicated when you want to persist state, when you're trying to build something that's actually an app. I don't mean keeping your video player playing across pages. You can do that. I'm talking about shared state, like things you put in a global store, right? You can even keep islands or references across pages. It is a little bit tricky in some of these frameworks, you have to be explicit about IDs, but these are solvable.
What do I mean about the state problem? If you've ever wondered, I'm using React-type syntax, but I want you to understand if you go and render a page on the server, initially, the client state is going to be nothing, right? If you could pretend we had a counter that started at zero, you render on the server, it shows the first path of code, and you're fine. But if you're now on the client, and you click the counter ten times, and now the count is ten, and you go to the next page and you load this component, how does the server know that it's ten? It doesn't, generally speaking. Unless you encode it into the URL. Basically, it will see zero again, render in this case, if it is zero, it will render some other component, and then you get to the client, and the client goes to wake it up to hydrate it, and it thinks some component should be there, and what do you think we get? I don't know if you've seen this one before. This is from Next, to be fair, but I think we've all seen this error if we've done any server rendering, generally speaking. Hydration errors are kind of painful, and the truth is lazy hydration is pretty much always dangerous prospect, because, at any point, if the data on the client changes between the time you server-rendered it, and you interact with it, it is probably going to break. This isn't restricted to routing. This is something we have to be conscious of. Now, again, we can solve this. We can be selective when to render components on the server or when to render them on the client. My point is, you start going down this path where something that is simple like throw an island on the page starts becoming tricky, right, because you break them into smaller pieces, now you need to share a state. You want to share it across pages. You basically end up building a framework on top of a framework. So what if you just started with all these assumptions already in place, and maybe take care of a few others? You might end up with something like this. Right? And those additional things that I didn't mention before, like how do you handle, you know, async data? How do you handle things like out-of-order streaming, coordinating between the different islands? It could be done with islands, 100 per cent.
Comments