skip to content
Podcast cover art for Live with Dan Shappir
Podcast

Live with Dan Shappir

Dan Shappir and Misko Hevery join JSJam to discuss SSR, partial hydration, performance, and how frameworks like Qwik compare to React Server Components

Open .md

Episode Description

Dan Shappir explains the hydration problem in modern JavaScript frameworks and compares solutions like Islands, React Server Components, and Qwik's resumability.

Episode Summary

This JavaScript Jam Live episode features Dan Shappir, performance tech lead at Next Insurance and W3C Web Performance Working Group member, discussing the performance costs of hydration in modern JavaScript frameworks. Dan walks through how single-page applications evolved to use server-side rendering, which introduced the hydration problem — the need to re-execute all JavaScript on the client just to restore interactivity. He then classifies the major approaches to solving this: avoiding frameworks entirely, progressive hydration as seen in Remix, the Islands architecture popularized by Astro, React Server Components, and Qwik's resumability approach. Qwik creator Miško Hevery joins to explain how resumability eliminates hydration altogether by serializing server state, and Theo Browne contributes insights on how meta frameworks are really backend frameworks. The conversation turns to real-world adoption challenges, with Dan citing Chrome User Experience Report data showing only 20% of Next.js sites achieve good performance. The group debates whether the upcoming shift from FID to INP as a Core Web Vital will finally force the ecosystem to confront hydration costs, and Dan shares his excitement about compilers reshaping JavaScript development while expressing concern about the growing complexity gap between what developers write and what actually runs.

Chapters

00:00:00 - Introduction and Guest Setup

The episode opens with the JavaScript Jam Live hosts — Scott, Ishan Anand, and Anthony Campolo — getting their audio sorted out and welcoming listeners. They introduce Dan Shappir, the performance tech lead at Next Insurance and an invited expert on the W3C Web Performance Working Group, who also co-hosts the long-running JavaScript Jabber podcast.

Anthony highlights Dan's upcoming conference talk comparing how modern frameworks tackle the cost of hydration, which has been accepted to React Next in Israel. The hosts set the stage for a deep technical conversation about partial hydration, performance, and the future of client-side frameworks, encouraging audience participation throughout the session.

00:06:34 - What Is Hydration and Why It's a Problem

Dan provides a thorough explanation of the hydration problem starting from first principles. He describes how single-page application frameworks like React and Vue originally rendered everything client-side, leading to poor initial load performance, and how SSR and SSG were introduced to send pre-rendered HTML from the server. However, the resulting page is static until the framework re-executes all its JavaScript on the client to restore interactivity — a process called hydration.

He explains why this is particularly damaging: users on slower devices face unresponsive pages, rage clicks occur when buttons don't respond, and the digital divide between high-end iPhones and mid-range Android devices means hydration can take an order of magnitude longer for many real users. The bandwidth competition between downloading JavaScript bundles and actual visual resources like images further degrades the experience.

00:13:09 - Progressive Hydration and the Islands Architecture

Dan moves through the first approaches to solving hydration. Progressive hydration, pioneered by Remix, uses native browser features like HTML forms as fallbacks until JavaScript loads, though this raises the question of why use JavaScript at all if fallbacks suffice. He then covers the Islands architecture, credited to Jason Miller and implemented in Astro and Fresh, which renders static content on the server and only hydrates small interactive components.

Ishan draws on his experience building React Storefront, where lazy hydration was used for e-commerce product pages. Dan notes that Islands work best for content-heavy sites but effectively require multi-page application navigation, losing the SPA benefits that motivated frameworks like React in the first place. The discussion touches on Marko as an early innovator that implemented many of these ideas years before they became mainstream.

00:24:34 - React Server Components and Their Tradeoffs

Dan explains React Server Components as a hybrid approach that preserves single-page application navigation while rendering static content on the server. Unlike Islands, RSC allows the client-side router to fetch new server-rendered HTML for subsequent pages without a full page refresh. However, he identifies two key downsides: React itself has grown heavier to support the mechanism, potentially offsetting the savings, and the complexity burden on developers has increased significantly.

Theo Browne joins the conversation to argue that meta frameworks like Next.js should be understood as backend frameworks, a perspective he's been actively promoting. Dan and Theo discuss the overlap between Islands and Server Components in terms of developer experience, while Dan highlights the awkward dichotomy between server and client components, including the fact that client components also run on the server.

00:39:56 - Qwik's Resumability and the Migration Question

Miško Hevery, creator of Angular and Qwik, asks Dan to evaluate Qwik's resumability approach. Dan explains that resumability eliminates hydration entirely by serializing the application state on the server and sending it to the client, avoiding the need to re-execute JavaScript. He identifies the main downsides as being extrinsic — the framework's newness and the effort required to migrate — rather than intrinsic architectural flaws.

Miško elaborates on the distinction between intrinsic and extrinsic properties, noting that hydration is an intrinsic limitation of most frameworks. He describes Qwik React as a migration path that provides Islands-style behavior with built-in inter-island communication, solving one of the key pain points of the Islands architecture. The group discusses practical recommendations for teams choosing frameworks, with Dan noting that most developers prefer sticking with one tool and that React's dominance stems partly from being the safe career choice.

00:51:39 - Core Web Vitals, INP, and the Future of Performance

The conversation shifts to web performance metrics and their relationship to the hydration problem. Dan reveals that only 20% of Next.js sites achieve good Core Web Vitals scores, worse than React's already low 36%. He argues that the current FID metric fails to capture hydration's impact on interactivity, and that the eventual switch to INP will expose how poorly many sites actually perform, potentially dropping passing rates dramatically.

The group discusses the history of metrics including TTI's flaws and CLS improvements, with Ishan sharing frustrations about TTI penalizing smart preloading strategies. Dan closes by expressing excitement that performance has become a mainstream concern rather than a niche specialty, and reflects on the growing role of compilers in JavaScript development — noting the irony that developers still call themselves JavaScript developers despite rarely writing vanilla JavaScript anymore.

Transcript

00:00:30 - Miško Hevery

Welcome, welcome, welcome, welcome.

00:00:35 - Scott Steinlage

Welcome to JavaScript Jam Live. Yes, this is Scott.

00:00:42 - Ishan Anand

Yeah, welcome.

00:00:45 - Anthony Campolo

I don't hear you, but I see you're talking. Maybe it looks like... Yo, yo, looks like the mic is back.

00:00:51 - Scott Steinlage

Speaker.

00:00:52 - Anthony Campolo

Can you hear me?

00:00:53 - Scott Steinlage

Hold on, folks.

00:00:55 - Anthony Campolo

There we go.

00:00:56 - Scott Steinlage

Can you say something again? Ishan or Anthony?

00:01:00 - Anthony Campolo

Test, test. Oh, there we go.

00:01:01 - Scott Steinlage

I can hear you now.

00:01:02 - Ishan Anand

Thank you.

00:01:03 - Anthony Campolo

Yeah, we were just saying we got the maestro the mic back.

00:01:06 - Ishan Anand

Yeah, welcome back, Scott.

00:01:09 - Scott Steinlage

Yeah, I'm a little rusty here. Absolutely. Thank you all so much.

00:01:18 - Anthony Campolo

We also got Dan Shappir up here with us. Thank you so much, Dan, for joining us. It's going to be a great conversation. I made sure to get Ishan up here as well because you two have many shared loves and interests around performance.

00:01:31 - Ishan Anand

I am so excited Dan is here today, given your background in performance. Thanks for joining us. Why don't we start with a round of intros, and then we'll intro our guest and go from there? I'm Ishan Anand, VP of Product at Edgio, co-host of JavaScript Jam Live. JavaScript Jam Live is an open mic, we like to say, on anything JavaScript or web-development-related. If you're a beginner or an expert, we want to hear from you. Don't feel shy — feel free to raise your hand at the bottom of the space, and we're happy to talk about anything and everything web development or JavaScript related. As Anthony mentioned, we have a special guest today. I'll let Anthony introduce himself and then hand over to Dan.

00:02:25 - Anthony Campolo

Hey, hey. My name is Anthony Campolo, developer advocate at Edgio. We'll be talking about performance, hydration, partial hydration — the future of client-side frameworks. It's a big, heady topic, but it's something I've been following now for over a year, and Dan's got a great talk he's been working on in this same area. So, Dan, feel free to introduce yourself and let our listeners know who you are, what you do, where you work, all that kind of stuff. You're currently muted if you're here and speaking.

00:03:17 - Scott Steinlage

Can you hear me now?

00:03:18 - Dan Shappir

Yeah.

00:03:21 - Scott Steinlage

Excellent. Let me just try one more time to connect my headphones and see if that works. If not, I'll use the phone as is. Just a second.

00:03:33 - Ishan Anand

Sure. To kill the dead air while we're doing that — Scott, you want to introduce yourself and then let Dan jump in once he gets his headphones back?

00:03:42 - Scott Steinlage

Sorry, just a minute. Can you hear me now?

00:03:46 - Anthony Campolo

We can, yes.

00:03:47 - Scott Steinlage

Excellent. I can use my headphones. Great.

00:03:53 - Dan Shappir

Perfect. We'll just continue on.

00:03:56 - Scott Steinlage

Okay then. So, as you guys said, my name is Dan Shappir. I've been doing software development in general, and web development in particular, for a really long time. I'm currently the performance tech lead at Next Insurance, an insurtech unicorn. I'm also an invited expert on the W3C Web Performance Working Group, and I'm a host and panelist on the JavaScript Jabber podcast, where, happily, we've had Anthony as a guest.

00:04:33 - Anthony Campolo

Yeah, really. It's, I think, the premier JavaScript podcast — as someone who runs a JavaScript podcast, I can say that. It's been going now for 13 years. You can actually go back and listen to the creator of Knockout and Backbone have an argument, or Ember and Backbone have an argument, about which is a better framework. So it's a really incredible historical resource and a really incredible current resource for everything going on in JavaScript.

00:05:05 - Scott Steinlage

Just to say that I've not been there for 13 years. I joined JavaScript Jabber three years ago, but Chuck, who founded the whole Top End Devs network, is still going strong, and so is AJ, who's been there from the start, as I recall.

00:05:22 - Anthony Campolo

That's right, yeah.

00:05:25 - Ishan Anand

Yeah, it's a great podcast. I was just listening to the episode you did the other day on hydration, and as Anthony mentioned, I heard you've got a talk you're workshopping on partial hydration. Do you want to give us the abstract, the pitch, for audience members who may not have a full understanding?

00:05:48 - Scott Steinlage

Well, happily, this talk has actually been accepted to at least one conference so far — it's been accepted to the React Next conference in Israel, which is a fairly large conference with something like a thousand participants. So I'm really excited about that. It's a talk where I compare various ways in which modern frameworks are trying to overcome the overhead and cost of hydration in terms of performance. Partial hydration is one option, there are several others, and I basically go through each and every one, describing the benefits and limitations of each.

00:06:34 - Ishan Anand

Do you want to explain, for anybody in the audience or who listens to the recording later who doesn't know what hydration is — if they're maybe coming at this as a total beginner — just set the stage for the problem before we dive more deeply into it?

00:06:49 - Scott Steinlage

Oh, sure thing. So the issue is this. We are using today frameworks like React and Vue that were created for the single-page-application approach. That means you download the JavaScript, then download the data, and then the JavaScript builds the user interface on the client side, and all the navigation also happens on the client side. This was done in order to make the behavior of these websites or web apps more application-like, because you don't need a full page refresh whenever you're transitioning between pages — you can update parts of the page independently of each other. That's great. But it turns out that this approach had a real problem in terms of the initial performance of loading the page. If you're building a client-side-rendered single-page application, for the initial content to be displayed you first need to download an HTML document, which is usually effectively just a blank page — a body with nothing in it, just a couple of script tags that get the ball rolling. Then you need to download all the scripts, then download the data via some sort of AJAX fetch request.

00:08:26 - Scott Steinlage

Only then do you actually construct the HTML on the client side, and then the content starts downloading — images, fonts, and so on. The result is that the actual visual content is the last thing to load, which obviously results in a really bad initial experience in terms of performance. Contrast that with how the web works by default, where all the content is in the HTML. As the HTML streams down, the browser is able to parse it even before it finishes completely downloading, identify resources referenced from it like images, fonts, and CSS, and start downloading them immediately as it encounters them. The result is that with client-side-rendered single-page applications, the initial load performance — as measured by Largest Contentful Paint or even First Contentful Paint — is pretty abysmal. To overcome this limitation, frameworks introduced the concept of SSR, or server-side rendering, and also SSG, static site generation. Instead of downloading an empty page and doing everything on the client side, you use the exact same code — it used to be called isomorphic code, though I don't hear that term used much anymore — running on the server side, either at runtime (SSR) or at build time (SSG), to generate the initial view.

00:10:06 - Scott Steinlage

Anyway, it runs the exact same code on the server side to generate the initial view. The HTML actually is fully constructed in terms of its content, so the browser can start downloading resources as soon as it encounters them. So with SSR or SSG, the view performance is effectively as good as it is with multi-page applications. But the problem is that the HTML that's downloaded is totally static — not dynamic. All the interactivity created by the JavaScript is not hooked up. It's like a picture of the page rather than the actual functioning page. When the framework runs on the server and generates the HTML, the application state is not actually sent down to the client, just the resulting HTML. So all the event handlers aren't hooked up, all the components aren't defined — none of that is there. In order to get the interactivity, you actually need to go through a process called hydration, which effectively means rerunning all the JavaScript that ran on the server side.

00:11:47 - Scott Steinlage

Again on the client side, just in order to recreate the initial state of the application. You need to download all the JavaScript you had on the server and run all of it — not to update the DOM, the HTML stays the same — but just to hook up the event handlers and recreate the initial framework and application state. That is called hydration. And you could say, well...

00:12:21 - Anthony Campolo

Just for a quick second, for sure.

00:12:23 - Scott Steinlage

I will ramble on forever if you don't interrupt me.

00:12:27 - Anthony Campolo

The only thing is your gain is really loud right now. Are you able to move a little bit away from your mic?

00:12:34 - Scott Steinlage

Yeah, I will.

00:12:36 - Bro Nifty

Cool.

00:12:36 - Miško Hevery

Yeah.

00:12:38 - Scott Steinlage

How about this?

00:12:39 - Anthony Campolo

Cool. Can I hear Ishan talk a little bit real quick?

00:12:43 - Ishan Anand

I thought that was a great summary of the problem of hydration. How's that comparatively on volume?

00:12:50 - Anthony Campolo

A little bit better.

00:12:50 - Theo Browne

Yeah.

00:12:51 - Ishan Anand

Okay, cool. Go ahead, Dan.

00:12:56 - Scott Steinlage

All I was saying is, just to finish the story: why is hydration problematic? Okay, so we download the JavaScript and run it again — we already have the visible page, so at least the user sees the page really quickly. It has this kind of optimistic attitude to it, which says something like: a person visits the page for the first time, they don't know exactly where things are or what to click. It takes them a few seconds to orient themselves on the page. Hopefully during that time we can finish the hydration process, and then by the time the user actually tries to interact, everything is ready to go and the performance seems great. The problem is that's not always the case. First of all, some users try to interact with a page fairly quickly, before hydration finishes — occasionally even before it gets to start. Other times, there's just so much JavaScript in the application that hydration takes a long time, and the user tries to interact before it finishes.

00:14:19 - Scott Steinlage

Finally, Alex Russell — who we also had on the JavaScript Jabber podcast — talks a lot about the current digital divide: the huge difference on the mobile web between the devices that people like us tend to use, which are the latest iPhones, and the devices that a lot of our users actually have, which are mid-range or even low-end Android devices. There's an order-of-magnitude difference — not twice, not three times, but an order of magnitude — in terms of performance between these devices. So hydration might be really quick on your brand-new iPhone with a 5G connection, but it could be pretty abysmal on somebody's low-end Android device with a slow 4G connection. The upshot of all this is that in many cases hydration doesn't actually finish before the user tries to interact with the page. And in some cases it doesn't even get to start. When the user tries to interact with the page, the page doesn't respond because it hasn't finished hydrating. In many ways, that's actually even worse than poor performance because it's effectively an unresponsive page.

00:15:51 - Scott Steinlage

It results in things like rage clicks, when people try to repeatedly click a button. Sometimes it then catches multiple clicks of that button, which is pretty bad — for example if it's a purchase button. Or maybe it just totally ignores the person. If somebody tries to interact with the page and the page is broken, doesn't respond to their interactions, they'll just leave. And that's the problem with hydration.

00:16:20 - Ishan Anand

Yeah, thank you. I am so glad you are talking about this and bringing attention to it because, personally, I have a background in performance as well, and it's kind of felt like a slow-moving crash over the last few years, where the front-end ecosystem was throwing more and more JavaScript at things and almost ignoring the problem. I remember back in 2018 or 2019, when we were working on React Storefront, a framework for e-commerce, and we had to introduce lazy hydration because the cost of hydration on certain pages was hurting the LCP — the Largest Contentful Paint, for the audience who isn't familiar with that metric. It feels like only recently we've started to see the ecosystem and the newer frameworks start tackling this. Do you feel like that's an accurate characterization? And if you agree, why do you think it's only suddenly that there's more news about it and more frameworks trying to solve it — like Solid and Qwik — than we saw, say, four or five years ago?

00:17:39 - Scott Steinlage

Well, to be fair, I think four or five years ago most websites weren't even using SSR or SSG, so the problem didn't exist — not because hydration isn't problematic, but simply because hydration wasn't even used. It's only thanks to the more modern meta frameworks, or rendering frameworks as they're now occasionally called, that we're actually getting to a world where we have SSR and SSG. Think about when you heard the term JAMstack for the first time — and now, again, it's another term we hardly hear anymore. I think Netlify started pushing it something like four or five years ago, maybe six.

00:18:37 - Anthony Campolo

2015 is when the term was officially debuted in a talk, and then it took years to actually pick up steam. But yeah, 2015 is when Matt gave his first talk about it.

00:18:50 - Scott Steinlage

Yeah, exactly. And if we're looking at the React world, I don't think SSR was so widespread before Next.js became the big thing. So really, the issue is that we didn't encounter the problem because we were stuck on the previous problem of really bad performance with client-side-rendered applications. And by the way, if you're using a solution like WordPress, there's no React, no hydration, nothing. It's just a multi-page application, and it's not even an

00:19:31 - Miško Hevery

issue.

00:19:34 - Ishan Anand

That makes a lot of sense. Back when we were encountering that, it was before Next was as big as it was, and we were basically hand-rolling server-side rendering ourselves, and it was really hard to do. Then people stopped doing that and just said, let's start using Next or JAMstack. Sorry, go ahead.

00:19:51 - Scott Steinlage

No, I totally agree. These days you've got a couple of options — even in the React world you can do it with Next, with Remix, or even by yourself with Vite. But none of these existed in widespread use five years ago. So it's a relatively new problem. We actually encountered it earlier than most. When I was working at Wix, before I worked at Next Insurance, I was the performance tech lead at Wix, and Wix started doing SSR earlier than most. Wix uses its own custom proprietary meta framework because its use cases are really different. So we encountered this problem earlier — we started doing SSR around 2018, and that's when we started encountering it. We kind of ran into it first, but it just took the market a while to get there.

00:21:02 - Anthony Campolo

Yeah, I included my blog post about partial hydration that Scott linked up top, and I run through the history of this. Most people don't really know this, and it's still unfortunately not a very well-known framework, but Marko is one of the first I could find that, going back all the way to 2014, started taking this problem really seriously and implementing things that are essentially what we today call partial hydration. Then there was kind of a six-year dead zone where you had SSR and regular hydration. But it wasn't until things like Astro started coming around that people were asking: how do we selectively decide what JavaScript we want to ship and what we don't want to ship? So this gets us into the Islands architecture, which we should probably define next.

00:21:53 - Ishan Anand

Yeah. By the way, it's the different solutions.

00:21:57 - Scott Steinlage

I just wanted to say it's a funny thing that Marko more or less innovated everything, which is kind of funny since not so many people know about this framework, given the fact that it's not a proprietary eBay framework. I mean, it's open source, it's out there, but as I understand it, it's hardly used outside of eBay.

00:22:18 - Anthony Campolo

I do my best to tell everyone I can about it, as frequently as possible.

00:22:23 - Scott Steinlage

Yeah, it definitely innovated a whole lot of things. Almost any new and innovative feature that some framework comes out with, you can say, ah yeah, but Marko did it first a few years ago. Funny that way.

Anyway, so these days we have this problem with hydration where, as I said, the main problem is that the page is effectively broken until hydration finishes. But there are additional problems, like you mentioned. For example, it can actually hurt visibility metrics, even though the content is in the original HTML, because you've got competition for bandwidth — while downloading the main image, you also need to download all that JavaScript to make the page interactive. The problem with the naive approach to hydration is that you download all the same code you had on the server because you need to run everything, and because the application after that first page becomes a single-page application, which means all subsequent pages are client-side. So basically, you need all that code on the client.

00:23:57 - Scott Steinlage

You download a lot of code, especially in the reality of npm where you pull in some library and you pull in the entire internet, it seems. You very often see JavaScript bundles in the hundreds of kilobytes, or even a few megabytes, despite being minified and gzipped. So that's a lot of bandwidth contention for the actual visual resources you need. Definitely. Yeah, go on.

00:24:34 - Ishan Anand

Yeah, I was going to ask: should we start classifying the different approaches to solving this? Whether it's React Server Components or what Solid is doing.

00:24:47 - Scott Steinlage

Yeah, so let's do a quick rundown. The first approach is the obvious one: just don't use a framework. Like I said, if you're doing your website in WordPress, you couldn't care less about this whole problem because it just doesn't exist. It seems flippant to say it, but if you talk to Alex Russell, he'll tell you that in many cases this is actually the preferable approach. Use some server-side technology, do the page as a multi-page application, and in many cases that's enough. If you need a little bit of interactivity, do it in jQuery. It feels backward and leaves a sour taste in our mouths as JavaScript developers, but it works, and very often has better performance. By the way, WordPress is still 40% of the web — like three times all the frameworks put together.

00:25:56 - Ishan Anand

Yeah, I'm just going to jump in here for some context on who Alex Russell is for the audience — and by the way, he's actually been on the JavaScript Jam podcast. We have an episode with him in the archives if you go to the website. He was on the Chrome team, he's now part of the Edge team, and he was one of the folks who coined the term Progressive Web App. The point is that this is not somebody who's anti-JavaScript by any means. He's just thinking about the problem user-first. Sorry, keep going, Dan.

00:26:30 - Scott Steinlage

No, exactly, you're absolutely correct. He's also been one of the driving forces for Project Fugu, which is about bringing modern capabilities into JavaScript, being able to talk to hardware devices...

00:26:46 - Anthony Campolo

You work on AMP, right?

00:26:47 - Scott Steinlage

Potentially. I try to ignore the fact that AMP ever existed.

00:26:51 - Anthony Campolo

I don't think he's apologizing.

00:26:52 - Ishan Anand

Oh, wait, maybe we should tackle that one at the end. I have to say, I think AMP is probably one of the most misunderstood frameworks. I gave a talk at CascadiaJS on this. I'd love to drill into that at some point, but let's get to...

00:27:09 - Scott Steinlage

Yeah, all I can say is I've never really had to deal with AMP during my career, so I don't have a lot to say about it. But anyway, moving on.

So we said one option is basically don't use a framework. The next option is something called progressive hydration. The idea here is that I use built-in features and functionality of the browser to provide some sort of fallback functionality until hydration finishes. For example, if there's a form on a page, after hydration the form is handled by JavaScript. But before hydration is done, the form just works as a regular HTML form. Which means that if you click the submit button after hydration, it works as a single-page application. But if you click it before hydration, it will work like a multi-page application, with an entire page refresh — but it will still work. That's a big benefit, because like I said, the big problem with hydration is that otherwise nothing works before it's done. One of the frameworks that innovated this approach is Remix.

00:28:48 - Scott Steinlage

I know many others have adopted it now — I think Svelte uses this approach as well. The thing about it, though, is that there are still two issues with it. First, to comment: Remix even takes it to the next step, which is to say you can configure Remix not to download the JavaScript at all and not to do any hydration, just use these fallbacks. In that case, Remix works like a multi-page application, like a PHP application, only with JavaScript on the back end instead of PHP. Which kind of raises the question: if I can get good enough behavior and interactivity without JavaScript, then why am I even doing this whole JavaScript thing? And alternatively, if I can't get the behavior I want without JavaScript, then it isn't really a solution, is it? So that's the limitation with this approach.

Another limitation is that the hydration process, by default, was this kind of long-running JavaScript function — hydrate everything: you call this function, it hydrates the entire page until it's done.

00:30:11 - Scott Steinlage

As we all know, while a long-running JavaScript function is running, the main thread is blocked. So even if you have this fallback functionality, it won't actually respond while the hydration process is running. That is addressed by splitting up the hydration code into parts — partial hydration, or there are other terms for it — basically breaking up this long-running single call into chunks. It could be like 50-millisecond parts, or run until a user interacts, and you can actually even detect that on newer Chrome browsers. So that's the other approach. A problem with that is that changing the framework to support this kind of breaking up of the hydration process into parts turns out to be kind of hard to do, which is one of the reasons why React 18 just took so long to be released. Think about when React 18 was first announced, and where are we now — what is it, three years?

00:31:37 - Ishan Anand

Yeah, maybe we should clarify. There's...

00:31:39 - Anthony Campolo

Well, it has been released — it's out right now.

00:31:42 - Scott Steinlage

Well, is it a beta or is it official or a release candidate? What is it?

00:31:46 - Anthony Campolo

It's officially official. It was released in beta either last year or the year before, and now it's actually officially released. And I know this because Redwood is trying to integrate it right now, because we were holding off until it was actually officially released.

00:32:01 - Scott Steinlage

Yeah. But some parts of it I think still aren't completely done — like the React Server Components, I think, aren't officially fully done.

00:32:08 - Anthony Campolo

Thinking of maybe Next — with Next they've integrated it, but they're still saying it's beta within the meta framework. Within React proper, though, they consider it fully released, as far as I know.

00:32:22 - Scott Steinlage

Yeah, potentially. But it took a long time whichever way you look at it. And part of the reason is that this also requires effort from the developer because you need to create all these suspense boundaries that didn't exist before. I kind of joke that the way to tell a modern web app from a legacy web app is that these days on startup, instead of one big spinner, we have lots and lots of little spinners, because all of the suspense boundaries become hydrated or become interactive separately, or even become visible separately. Anyway, so that's that approach.

Another approach is the one you mentioned — Islands — which I believe was made popular, if not coined, by Jason Miller, who also created Preact. I know it's now used predominantly in Astro and also in Fresh, which is a framework built on Deno with Preact. Maybe it's used in other places. I know Ryan Carniato from Solid is looking at it, but I don't think it's actually implemented in SolidStart.

00:33:57 - Scott Steinlage

I might be mistaken. But anyway, the Islands approach basically comes from this thought: when you look at modern web apps, but certainly at websites which are primarily content sites, the majority of the page is actually fairly static or totally static. Think about a blog post. The blog post itself you just read — it's totally static. There's the title, the image, and the content. The only interactive parts might be, I don't know, a like button and maybe the comments section. That's not the primary content of the page. Are you with me on that?

00:34:53 - Ishan Anand

Yes, yes. In an e-commerce background, where I've typically dealt with this, it's like certain parts — like the image carousel — but the copy and description of the product aren't interactive. You either read them or not. And so why are we executing that JavaScript just to make everything for that component live in memory, when it can just sit there in the DOM as it is?

00:35:18 - Scott Steinlage

And even the carousel can more or less just be done with CSS, in which case it's also effectively kind of static. The only really dynamic parts of the page would be, I don't know, the purchase button and the shopping cart icon. So if you're looking at a page like that, you're saying: why am I hydrating everything? Why am I downloading and running the JavaScript code that generates the blog post from the raw data in the CMS, when there's no interactivity associated with it? The whole concept of Islands is saying: let's generate the static part the old way, on the server side like we did with PHP, and specifically denote those dynamic parts as parts that require interactivity and hence require hydration. So only those parts are actually done as React components or Vue components or whatever, and only they get hydrated. Once I take this approach, I can even be smart about it and say: I'll first hydrate components that are in the initial visible area, and the parts below the fold

00:36:50 - Scott Steinlage

I'll only hydrate them if and when the user actually scrolls down the page. When I take this approach, the amount of JavaScript and the amount of work I need to do is dramatically reduced.

00:37:06 - Ishan Anand

And like I said, the approach we took in React Storefront with lazy hydrate was basically: let's wait for things to scroll into view, and then we'll hydrate those pieces. Sorry, keep going.

00:37:19 - Scott Steinlage

No, well, yeah. So it's a great approach. Astro does it really nicely, and Fresh uses it as well. You can also have custom implementations of this approach. But there are also problems with this. The two main problems I see are: first, you kind of need to be a multi-page application, because the whole idea is that you're not downloading all the JavaScript required for the entire site, and that the majority of the site is actually rendered on the server side. So every time you navigate between pages, you need to go back to the server to get the next page and effectively download the JavaScript again. Now, that's not as bad as it seems because it's probably cached in the browser cache or the CDN. But still, we introduced React and Vue and Angular to do single-page applications — to have state that persists on the client side between pages, to avoid a full page refresh whenever we move between pages. And now we are back to that.

00:38:43 - Scott Steinlage

So that's the main limitation I see with the Islands approach. Oh, for sure.

00:38:50 - Ishan Anand

Yeah. So I think that's an accurate characterization of how it's implemented in Astro and some of these other frameworks, because they are built for multi-page apps. If I recall correctly, when we did this in React Storefront, we made sure the router itself still came along — that part was fixed, and the other parts were islands. So we were able to maintain a single-page-app feel. But you still didn't get as great a benefit as you might get from Astro, where it doesn't need to pull the router down. I guess I separate that out as not necessarily tied to the islands concept — it just happens to be the way it gets implemented.

00:39:31 - Scott Steinlage

I actually would, and I'll tell you why. Put aside the routing code. Think about the next page — the static part of the next page. Where is it rendered, on the client side or on the server side?

00:39:49 - Ishan Anand

You're going to have to render it client-side, so you need to pull that code ahead of time.

00:39:54 - Scott Steinlage

Yeah, so effectively it's not really classic Islands. It's kind of Islands for the first page, but you end up downloading all the JavaScript of the whole application. I don't know if I'd fully call it Islands. It's somewhere in the middle between the Islands approach and the selective hydration approach.

00:40:23 - Ishan Anand

Okay, it's a classification — we're just classifying it differently. That makes sense.

00:40:29 - Scott Steinlage

Which brings us to the next approach, which is kind of similar — which is why a lot of people actually confuse them or conflate them — and that is server components. Currently it's called React Server Components because I think React is really the only framework that officially implements this approach. Maybe Marko does as well, I don't know what they call it — Marko implements everything. But in terms of a released mainstream framework, as far as I know, only React implements it. So instead of just "server components," we call it React Server Components, or RSC. This approach is similar to the Islands approach in that the static components or the static content part of the page are rendered on the server side, and only the code for the dynamic parts needs to be downloaded. So you get kind of the same benefits as Islands. The difference is that it is a single-page application. The router code actually downloads, and then when you navigate to the second page, that happens on the client side. But here's the funny thing: even though the navigation to the second page happens on the client side, with the router on the client side, the static parts of the second page are actually rendered on the server.

00:42:03 - Scott Steinlage

The client is actually able to go to the server and get additional HTML from the server that's implemented by these server components. In fact, the root of the page is a server component. Effectively, the router goes back to the server, gets the root content of the page with the HTML and data for the interactive components in it, and then kind of integrates everything together. This requires a lot of magic and is kind of difficult to do, which is again a reason why it took React such a long time to come out with React 18. But once it works, it really is magic in the sense that you've got a single-page application, all the functionality you're used to with React, you don't have to mess about with keeping all your state on the server side, you can keep state on the client side — especially component state — and it flows between pages. And that's all great, but you still avoid downloading a whole lot of HTML and data associated with the static stuff. You don't need to hydrate those parts on the client side.

00:43:27 - Scott Steinlage

So it sounds like a perfect solution, but it turns out there are problems with it. The two main problems I see: first, like I said, it's a lot of magic. It's really difficult to implement all this stuff in React, and as a result React itself has increased in size to provide this functionality. It might turn out that all the savings you've made from keeping your code on the server side are offset by React code that needs to be downloaded and run on the client side to support this mechanism.

00:44:14 - Ishan Anand

So one step...

00:44:15 - Scott Steinlage

So that's two steps back. Yeah. Now, I understand that's not true by definition. Ryan Carniato from Solid has said that he's looking at ways to implement this approach that are much lighter weight, and time will tell. If he does, maybe everybody will follow his lead. But that's one problem. The second problem...

00:44:45 - Anthony Campolo

Yeah, we got. You should do a station break around this time just to encourage people to come up and ask questions.

00:44:52 - Scott Steinlage

Oh, for sure. Like I said, I will talk forever if you let me.

00:44:56 - Anthony Campolo

Yeah, I've listened to your podcast many times.

00:45:00 - Dan Shappir

No worries. Yeah. Thank you so much for sharing all that so far, and we look forward to hearing more from you. This is really great. It's been a wonderful time. Thank you all so much for joining us today. This is JavaScript Jam Live. We do this every Wednesday at 12:00 p.m. Pacific Standard Time. We have awesome guests like Dan today and so many others. We also do this open-mic process where you can come up to the stage and ask questions — please just request to come on up. We would love to hear from everybody. Whether you're a beginner or whether you've been doing this forever, it doesn't matter. That's how folks listening get the most value out of this as well — from people participating. One last thing: if you have not subscribed to our newsletter at javascriptjam.com, please go to javascriptjam.com and subscribe, because it has all this amazing information — upcoming things happening in the JavaScript and web development world, including who we're going to be talking with, and links available there as well.

00:46:08 - Dan Shappir

So please check that out if you haven't already. Thank you so much. And we're going to continue the rest

00:46:14 - Anthony Campolo

of our talk, and we got Miško up here with us. Miško is working on his own framework known as Qwik, which is very deep into these specific problems that we've been talking about. Do you have a question for Dan, Miško?

00:46:30 - Miško Hevery

Sorry, I had to figure out how to use this thing. Yes, I do. I actually want to hear his perspective on Qwik. I don't want to say anything about Qwik — I don't want to take the discussion somewhere else — but I would love to hear where you think it falls into this space. What is it doing well, not doing well, et cetera? I'd just love to hear the thoughts.

00:46:50 - Ishan Anand

Yeah, absolutely. That was literally going to be the question I was going to ask after the station break, so I'm so glad you're here to ask it. And by the way, for context for listeners, not only is Miško working on Qwik...

00:47:02 - Anthony Campolo

Sorry, Dan, can you mute yourself right now? You've got some background dog noise, it sounds like.

00:47:08 - Ishan Anand

Yeah, I'll be done. You might have heard of this framework called Angular — that also owes to Miško's creation. So definitely a granddaddy in the ecosystem.

00:47:20 - Anthony Campolo

AngularJS.

00:47:22 - Ishan Anand

AngularJS — sorry, the original, the OG.

00:47:26 - Miško Hevery

Actually, both Angular and Angular 2.

00:47:29 - Ishan Anand

Oh, okay, great. I learned something today. But Dan, I'm really curious to hear your answer to his question. What do you think of resumability and Qwik?

00:47:42 - Scott Steinlage

Yeah, well, I was basically saving the best for last, so I just hadn't gotten to resumability yet. So just to clarify to the audience: resumability is an approach which effectively solves the hydration problem by doing away with hydration. Instead of running all the framework code on the client side to regenerate the initial state, it creates that initial state on the server, but instead of throwing it away, it serializes it and downloads it as needed to be used on the client side directly, without needing to regenerate it again through the whole process of hydration. So resumability solves the problem by eliminating hydration entirely. Am I presenting it correctly, Miško?

00:48:47 - Miško Hevery

Yeah, sorry.

00:48:47 - Scott Steinlage

Hello.

00:48:48 - Miško Hevery

I was looking for the unmute button. Sorry. Yes, that's a good way of looking at it.

00:48:57 - Scott Steinlage

So from my perspective, there are two issues with resumability. One is the fact that it's simply just so new. It might be the best thing since sliced bread, but we just don't have that much experience with it in the field. So all the problems and limitations that we're familiar with in the older approaches are just not there yet. Maybe they exist, maybe they don't, but we just don't know yet. That's problem number one. Problem number two is that it requires a new framework. You can't take an existing framework and monkey-patch resumability into it. A framework needs to be designed for resumability from the ground up, which is exactly why Miško created Qwik instead of, say, refactoring Angular to provide resumability — because Angular just wasn't designed with resumability in mind, and you can't retrofit this into the existing architecture. Is that a correct representation?

00:50:20 - Miško Hevery

Yes, it is. You're spot on.

00:50:23 - Scott Steinlage

And consequently, if you have a project implemented in React, the only way to get resumability is effectively to rewrite it in Qwik, which means learning Qwik and then doing all the work of migrating all the code. I'm saying "eventually" because I believe you guys created a way for actually using at least some React components inside Qwik React.

00:50:55 - Anthony Campolo

I'm pinning a bunch of stuff to the thread right now related to this. I'm going to include the JavaScript Jabber interview on YouTube that you did, and I'll add a link to Qwik React as well,

00:51:04 - Scott Steinlage

which can certainly mitigate the hassle or the effort. But still, if you want to get the total benefit of completely doing away with hydration and getting all the benefits of Qwik, you eventually want to strive toward the point where everything will be done in Qwik. And that's an issue, first of all, because it entails the effort of a rewrite. Now, that's not the end of the world. I mentioned that I worked at Wix — at Wix, we actually rewrote the entire Wix web stack three times while I was there. We did a complete rewrite three times. So it's doable, and sometimes it's a lot better than just trying to bang on the existing thing and patch it again and again. But it's still an effort. And it's also the effort of learning this new thing, of understanding the concept. We really enjoy learning new stuff, at least I do, but it's still an effort. And a lot of people are using React because it's the safe choice.

00:52:24 - Scott Steinlage

You know, you don't get fired for picking React and Next. If the project fails, you can say, well, I picked Next — that's what everybody's using. When you're using a new framework, you're obviously taking more of a chance. So those are the downsides that I see now. They're not so much technological as conceptual, but they exist.

00:52:51 - Ishan Anand

They certainly exist. I have meetings with our customers and they ask us for our opinion. When we discuss this, it certainly comes up. They're like, React is the bigger ecosystem. We really like what Qwik is doing, but it's not at 1.0 yet — if they're going to change the API surface area before 1.0, we might want to wait to rewrite. So in that context, when somebody asks you what they should do — let's say I'm somebody starting with a net new app, I haven't built any code yet — what would you recommend? And then let's take somebody who's got a legacy React-based website. What do you recommend in both of those cases?

00:53:38 - Scott Steinlage

Oh man. I'm going to use the terrible answer: it depends.

00:53:48 - Ishan Anand

That's right.

00:53:49 - Anthony Campolo

Because after you give your answer, I'd be curious to hear Miško's response as well.

00:53:53 - Ishan Anand

Yes.

00:53:55 - Scott Steinlage

Yeah, it depends because it depends on the size of the application, the team you have, whether it's mostly a content site or more dynamic, or maybe it's content now but expected to potentially become dynamic later on. By the way, going back to Alex — we seem to be going back to him a lot today — when I try to distinguish between websites and web apps, I really like the distinction he makes, which is based on the depth of the interactions. If it's only like 2, 3, 4, up to maybe 10 interactions or so, then it's a website. If you expect the person to do like 50 or 100 or more interactions, then it's actually a web app. So it kind of depends which one of those it is. If it's a website, maybe you should do it in Astro, or maybe you should even just do it in Wix, because that will be so much easier.

00:55:07 - Ishan Anand

Sorry, go ahead.

00:55:09 - Scott Steinlage

No, ask your follow-up, please.

00:55:11 - Ishan Anand

We have Theo as a listener — he's also been a frequent guest. He and Alex Russell had a debate on React that was televised on YouTube. In that, they said e-commerce was an example. So let's pick that — it's also, selfishly, a lot of our market. So imagine it's an enterprise e-commerce website with a team of React developers. Let's use that as a specific example. What would you recommend?

00:55:43 - Scott Steinlage

Again, it depends. There's a good chance I might just recommend Shopify because, unless there are some really unique requirements, why not?

00:55:58 - Ishan Anand

Let's say it's an enterprise site and they've outgrown Shopify.

00:56:03 - Scott Steinlage

By the way, there are not that many enterprise sites that really, truly outgrow Shopify. We all think we'll be selling millions and millions of whatever, but most of us don't. And even when we do, a lot of custom sites aren't actually as performant, scalable, secure, or robust as a Wix or Shopify site. I'm sorry to say, but it's the reality. Another point though: I tweeted recently that I really loved the video Theo created with the whole diagram of choosing the best tool for the job, the decision tree that Theo made. And I totally agree with all the decision points he put in there. My main commentary on that decision tree is that, from my experience, most web developers like to pick one tool and use it for everything. They know React, they like React, they'll build everything with React. And it kind of works.

00:57:19 - Scott Steinlage

So why not? Having to learn like 10 different technologies just so you can use the best tool for the job — or even four — I don't see it that often. Most web devs that I know don't work that way.

00:57:37 - Anthony Campolo

And we got the man himself come up.

00:57:38 - Ishan Anand

Yeah.

00:57:39 - Anthony Campolo

Defend his decisions.

00:57:42 - Theo Browne

Yeah, thanks for having me on real quick. I'm supposed to be live, but I'm currently ironing a shirt and super behind. But yeah, I totally agree with the devs-like-to-know-one-thing thing. That is actually a problem I run into a lot as a person who likes to experiment with lots of different things — I've built in three different frameworks in the last two days just because I wanted to play with some stuff. I think that my video specifically was kind of built around that. I even got into some trouble because I specifically was going at the angle of a React bro, as I called it. The goal was to make the best possible diagram given that you currently like React some amount. Here is how I, as a person who prefers React and as a team that mostly prefers React, make decisions for the meta frameworks around React. I don't necessarily agree that the same mindset of "use one tool for the job" should apply for meta frameworks the way it does for the core JavaScript frameworks. You can use React with Vite, with Astro, with Next, with Remix, with Preact instead of React — you have a lot of these other options that allow you to keep the React mindset of "learn once, write anywhere" instead of "write once, run everywhere."

00:58:49 - Scott Steinlage

I agree that it's easier to migrate from one React meta framework to another than it is to migrate from one framework to another with a completely different mindset. Although, as I recall, you did mention Svelte in that video as an option. But even with meta frameworks, I think it can be challenging. Next.js has become like a monster, with server components being effectively a Next feature more than a React feature in a way, because you can't really use them effectively without a meta framework. So you really need to buy into this whole mindset. And once you buy into that, it turns out there's quite a big difference between building a web application in Astro with Islands versus in React/Next with React Server Components, even though theoretically Islands and Server Components are supposedly really similar.

01:00:09 - Theo Browne

It's really funny you bring up Islands specifically, because the only reason I've been able to get around server components and understand them at all is because Astro feels almost identical to server components in terms of the immediate DX. I've been very surprised at how much overlap there is in the mindset between those two things. I would say new Next with server components and Astro are more closely related than old Next and Remix, or even new Next and Remix. But there's a lot of mindset overlap.

01:00:38 - Scott Steinlage

But don't you find, for example, the whole concept now with Next — the fact that all components are server components by default, and this whole use client specifier, and the fact that server components can be async whereas client-side components cannot be async? Or the fact that client components also actually run on the server, which is an interesting thing — kind of a funny misnomer.

01:01:10 - Theo Browne

Anyway, Next is a framework for backend code. Next is a way to run code on the server. React now can be run more easily on the server, and Next is introducing the paradigms they're choosing to run with. I think that if you think of these meta frameworks as backend frameworks that build DOMs and build front-end code, and then the front-end framework takes over from there, it's a lot easier to understand how these decisions are made. And what I see here more than anything is Next doubling down on their direction as a backend framework.

01:01:40 - Scott Steinlage

Oh, I totally agree with that push.

01:01:42 - Ishan Anand

On what Dan's saying, though — what you're saying is you have to change your perspective. Does the rest of the ecosystem look at React potentially the other way? I think that's the question. Do you agree or disagree with that?

01:01:56 - Theo Browne

When you say that some look at React a different way, what do you mean specifically?

01:02:01 - Ishan Anand

Do you think people look at React and Next and think about it as a backend framework the way you said it, or do they think about it as a front end?

01:02:10 - Theo Browne

The most popular video on Vercel's YouTube channel is my tech talk about how Next is a backend framework, simply titled next.js is a backend framework. So whether or not the mindset is in one place, I'm actively working to shift it the other way because that's what all of these things are. Qwik and Qwik City are backend frameworks. Nuxt is a backend framework. Astro, in particular, is exclusively a backend framework — Astro has no real control over what happens once the page has made it to the user. And I think it's important that as front-end engineers we recognize the backend implementation details, costs, and consequences of the way that we build. I feel like that's been missed for a long time, and it's partially because of single-page apps. For me, the MPA revolution of going back to MPAs isn't that SPAs are evil and bad. It's: oh, I as the front-end engineer can make intelligent backend decisions to build the best experience for my user.

01:02:58 - Ishan Anand

You're preaching to the choir on this.

01:03:01 - Anthony Campolo

This is another thing Redwood was way ahead of the curve on, which we're probably never going to get credit for. But I digress. Continue on.

01:03:08 - Ishan Anand

Well, I guess what I'm saying is that, to me, that is a recognition that people look at it as a front-end framework — they don't think of it that way — and that's the mindset shift that needs to happen.

01:03:21 - Scott Steinlage

It's really funny how what comes around goes around. This whole move from multi-page applications to single-page client-side applications, and now back again to the server side. The only difference is that now the server side is JavaScript instead of PHP. Although the big motivation for having the backend in JavaScript is because the front end is JavaScript. So if we're kind of moving everything to the backend, then why does it need to be JavaScript?

01:03:57 - Miško Hevery

Do you mind if I jump in?

01:03:59 - Scott Steinlage

Oh, for sure. Go for it.

01:04:02 - Miško Hevery

I actually have a question for Theo. He said that he considers Qwik and Qwik City to be backend, and that kind of surprised me. I would like him to elaborate on it. I see Qwik as being totally front end, and Qwik City, yes, I can see being the backend, but I'm just curious why he thinks both of them are.

01:04:19 - Theo Browne

I should specify first that I have struggled for a while to truly draw the lines between Qwik and Qwik City. I've talked with Ryan a bit. I've meant to hit you up about it, but I've been way too busy lately. It's my understanding that both Qwik and Qwik City have a server, and Qwik City is more the routing rather than the actual server behaviors of Qwik. And due to Qwik's focus on resumability, some amount of runtime on a server is necessary for the core Qwik experience to work. Is that correct?

01:04:48 - Miško Hevery

I would say that Qwik City is the server and Qwik is agnostic. It can run anywhere, just like React can in theory run on any server, and it does in the case of SSR. Qwik is the same exact way.

01:05:01 - Theo Browne

I was misinformed then. Qwik City is a backend framework and Qwik is front end primarily.

01:05:05 - Miško Hevery

Okay. The other point I wanted to make is I find this whole SPA/MPA debate interesting. I think it comes down to where exactly the router is — is it on the server or is it on the client? I think Ryan will oftentimes agree with that. And the point I wanted to make here is that with Qwik City, we kind of blur this because we say: well, the router starts on a server, so it's an MPA, but then we can download it to the client if you want to, and then you can transition into a SPA. So the whole MPA/SPA difference, I think, is a side effect of hydration. And once you remove hydration, that whole side effect disappears.

01:05:46 - Scott Steinlage

Yeah, but Miško, do you ever really want to? Won't the majority of Qwik applications effectively run, most of the time if not all the time, as MPAs?

01:05:59 - Miško Hevery

I don't see why they would necessarily want that. It depends on the use case, right? If you're building an e-commerce website, then yes, you want an MPA. If you're building a complicated dashboard, then no, you want a SPA. So it's a specific decision — it's not a thing of the framework.

01:06:16 - Scott Steinlage

How do you make this decision? By the way,

01:06:20 - Miško Hevery

you choose whether you do an href or you do a link component, right? So if you say you want a link component, you're basically making a client-side navigation. If you just do an href, you're making a server-side navigation.

01:06:34 - Scott Steinlage

So by choosing the Qwik link component, I'm effectively saying the following navigation has to happen on the client side.

01:06:42 - Miško Hevery

No, it doesn't say it has to happen, it says it can happen on the client side. Things can always happen on the server, but in some cases they can also happen on the client.

01:06:55 - Scott Steinlage

Well, at the end of the day, I don't really care that much. If I can provide the user with a good experience, then why not do it as an MPA? And with the work that Chrome, for example, is doing with the transition API, we might get to the point where it's all good with MPAs — assuming Safari ever actually adopts it, which is a big if.

01:07:30 - Bro Nifty

I have to chime in. You guys are absolute legends up here. I have to chime in with a really cringe example. We used to make these apps in Flash — dashboard apps — and load all this data into the dashboard, and you get these sub-second response times because all the data is loaded there. It takes a few seconds to load it up, but once it is, it's bing, bing, bing. You can drill through data, do selectors and switches and different things. It's a Christmas tree, it's lighting up, it's so beautiful. This is very similar to an argument Sebastian Markbåge was making: okay, if we're server-routing and we have progressive enhancement with clients, so ultimately downloading to the client so you can have that in-memory, nice client-side routing, real quick switch, nice transition-type thing, and it's not hurting your performance because you're still getting all that server-sent stuff from the server.

01:08:40 - Bro Nifty

You're still getting all that data initially, but then it's progressively being enhanced by loading it and caching it on the client. So you get those quick switches and nice transitions.

01:08:53 - Theo Browne

I just wanted to pop up and say hey quickly and respond to the stuff about my decision framework.

01:08:57 - Ishan Anand

Thanks for joining live.

01:08:58 - Theo Browne

So if y'all want something to hang out in after this, come check out my Twitch. Okay, Bro

01:09:02 - Anthony Campolo

Nifty, can you summarize your question quickly? I'm not sure exactly what you're getting at here.

01:09:07 - Bro Nifty

Oh yeah. So Sebastian Markbåge made an argument for progressive enhancement. He was saying: okay, if you can still send it from the server and not lose anything by downloading it to the client — in other words, progressive hydration, like progressive enhancement and progressive hydration — so it's not hurting your experience. One thing Dan remarked on earlier with e-commerce was people want to click but they're not getting responses, so they eject and you lose the customer. That's bad. But what if you're not losing the customer? What if you get it all from the server initially, like React Server Components or whatever, but then you can also cache everything onto the client progressively?

01:09:57 - Scott Steinlage

So first of all, yeah, sure, why not? A potential big issue with that approach is that you no longer have a single source of truth. And you know the saying about what are the two most difficult things in computer science? Well, there are naming things, caching, and off-by-one errors. Caching is hard to do correctly. You need to make sure that you have the correct data, and you also need to decide which strategy to use when syncing data back to the server — are you using an optimistic approach? What do you do when the server rejects it? It does introduce a lot of complications. But yeah, if you can do it, you can certainly do it that way. And in a lot of cases, this whole thing about MPAs and SPAs is about where to hold this hot potato of state — am I going to manage state on the client side, or can I just do it on the server side?

01:11:17 - Scott Steinlage

And obviously it makes life a whole lot easier for the front-end developers if they don't really need to deal with state. Realistically, you do need to deal with some state because various components require it. But the global state — if you can keep it on the server, good for you. Hopefully that kind of relates to the point you were making.

01:11:45 - Bro Nifty

Yeah, so React has a thing where they say lift state up to the app level. Instead of keeping it in the component, pull it out of the component, lift the state up. So it would be like lifting state out.

01:11:59 - Scott Steinlage

Yeah. The whole server components thing, by the way, is also about how to manage state — where you want to keep as much state as you possibly can, I think, in the lowest possible server component.

01:12:15 - Anthony Campolo

I want to hit on this with Miško, because when I had Miško on FSJam, he gave a direct comparison between React Server Components and resumability. Would you be able to rehash that

01:12:25 - Theo Browne

for us right now?

01:12:29 - Miško Hevery

Was the question for me or for Dan?

01:12:31 - Anthony Campolo

Yeah, I was just curious if you could compare how Qwik compares to React Server Components. I remember you were saying that React Server Components was a nice stopgap, but it requires developers to think about things that they shouldn't necessarily have to think about. And you feel like resumability is the best way to actually achieve that fully.

01:12:50 - Miško Hevery

Yeah. Obviously I'm biased here, right?

01:12:54 - Ishan Anand

Yeah.

01:12:55 - Miško Hevery

So React Server Components basically have this kind of transition where you're on a server and then you say, oh, now I'm transitioning to the client. And you can only do this transition once — you're on a server component, and then you become a client component. Across this transition line, you can't pass just anything. You can only pass data. You can't pass in functions, listeners, state, or any of that stuff. So you're very aware of where that line is.

The nice thing about Qwik is that that line becomes extremely blurred. You can pass in functions, you can pass in closures, you can pass in state data. You can register listeners on a server and then have the listeners fire on the client. You can set up reactions on a server and have the reactivity happen on the client. As a result, every single component in Qwik basically starts its life on a server and then maybe transitions to the client, or maybe never does, depending on whether or not it's interacting. So it's a very different mental model than what React Server Components is trying to do.

01:14:03 - Miško Hevery

I will say, though, that given where React is, I think React Server Components is the obvious and the only choice they have in order to improve things. To do something completely different, you have to abandon the mental model you currently have, and that's a tall order, as you pointed out earlier.

01:14:23 - Scott Steinlage

I would add two things to that, if I may. First, I think if you asked a React core contributor, they might say that this separation or distinction between server components and client components is actually, quote-unquote, a good thing, because it kind of forces you to think in terms of the application architecture — what do you do where. You can debate that, but I think that's what they might say.

I do have to note two additional limitations with this whole server-components thing. One is the fact that server components only run on the server, but client components can run on the client or on the server, which is kind of odd when you think about it. Another issue: if you remember, one of the reasons we liked hooks so much when they came out is that it became very easy to transition between stateful and stateless components. It used to be that stateless components were functions and stateful components were classes, so every time you wanted to transition from one to the other, you needed to effectively refactor your entire component.

01:15:47 - Scott Steinlage

With hooks, you made it stateful by adding a useState, you made it stateless again by removing the useState. It was really, really easy. Well, transitioning between client-side and server-side components is not a trivial transition. Like I mentioned before, the asynchronicity model is completely different, one can have state and the other by definition cannot, and stuff like that. So we've created, again, this dichotomy between two types of components that you really need to think about when designing your application — because you can refactor it afterwards, but it becomes much more challenging.

01:16:36 - Ishan Anand

So I want to go back. We said we were going to ask Miško his opinion on what he would recommend to the two teams I talked about. Maybe the answer is Qwik and Qwik, but I want to give him a chance to respond to that. And then I actually have a follow-up for Dan if we don't have any other questions from the audience. But go ahead.

01:16:56 - Miško Hevery

Yeah, remind me the question again.

01:16:58 - Ishan Anand

The question is: imagine you're a team building something net new. What framework should you pick if you want to avoid this problem? I assume the answer would be Qwik. But what if you're a website that has an existing legacy codebase — a ton of lines of code, written in React, e-commerce let's say? What would you recommend they do? Should they rewrite the whole thing? Should they wait for React Server Components to see if it solves their problem? What's the practical answer? Because most of us aren't authoring frameworks — for the rest of us who are trying to build products and experiences on top of them, what recommendation can we give teams right now?

01:17:47 - Miško Hevery

Yeah. Before I answer that, I want to point out something else. We were talking about Qwik, and I think Dan was saying what the downsides of Qwik would be. When I talk about these things, I talk about this idea of intrinsic and extrinsic properties. The fact that Qwik is new — that's an extrinsic property. The fact that Qwik may not have the best documentation, the most blog posts, the biggest community — all those things are extrinsic issues that, over time, will hopefully be solved. An intrinsic thing would be like: oh, React has to do hydration — or rather, most frameworks have to do hydration. There's very little you could do to fix it. There are all these hacks and workarounds, but fundamentally it's an intrinsic property of the system.

01:18:37 - Ishan Anand

That's a really great distinction. Sorry, keep going.

01:18:40 - Miško Hevery

Yeah, I just wanted to point out that when we're talking about Qwik, all of the feedback about why not to use Qwik fell into the category of extrinsic properties. And one thing is also true — it's kind of on the border between extrinsic and intrinsic — which is that we just don't know. As you build complicated applications, we might discover that there are certain things that are actually hard in Qwik. I don't know. Time will tell. So that's kind of a mixture of both.

As far as when you should use Qwik: there's the generic answer, which is that Qwik was designed to really solve any problem that React, Svelte, Angular, Vue, et cetera, solve.

01:19:23 - Dan Shappir

Right?

01:19:23 - Miško Hevery

So it's a generic solution. Just to contrast this to something more specific, like Astro — Astro, even on the documentation side, says don't use us to build apps, use us to build blogs. So that's not a general solution; it's a specific thing for a specific problem.

01:19:37 - Anthony Campolo

So could you say that maybe Astro is for sites, but Qwik is for apps?

01:19:42 - Miško Hevery

Well, that would be a reasonable thing to say, except that my point is that Qwik will perform just as well for sites as it will for apps. It's the best of both worlds. You don't have to make a choice — am I building an app or a site? You can just build whatever, and in both cases you'll get the best possible outcome.

01:20:03 - Anthony Campolo

Because I feel like I heard you say the opposite on JS Party the other day. And this is something that Ben Holmes pointed out to me — he was saying that Qwik is not leaning into apps, they're saying they're for everything. And I was like, no, actually they were saying they're leaning into apps, not for everything. So which is it?

01:20:22 - Miško Hevery

I think the way the architecture of Qwik is set up, if you end up building a static website, we will deliver just static content.

01:20:33 - Dan Shappir

Right.

01:20:33 - Miško Hevery

So from the point of view...

01:20:35 - Anthony Campolo

But is that a good use case? Just because it can do it doesn't mean it should do it.

01:20:40 - Miško Hevery

Okay, that's a good distinction. We certainly heavily favor our focus on the application side of things because we think that's the harder problem to solve.

01:20:49 - Anthony Campolo

And I think you should lean into that, because we have people coming forward like Astro saying we're for content, not for apps. And we're looking for something to say we're for apps, not for content.

01:21:01 - Dan Shappir

Niche.

01:21:02 - Theo Browne

Yeah.

01:21:02 - Dan Shappir

Niche, yeah. The deeper you go, the nicher you get, the more virality and everything you're going to get, I feel like. Authenticity.

01:21:13 - Miško Hevery

Great. So the original question was when should you use Qwik? Given how new Qwik is right now, I think you should use Qwik if you have a complex application and you really, really need good startup performance — you need to fix the hydration problem. This is the place where, as of right now, Qwik has no competition. If you need a complicated application and hydration is really a problem for you and causing you a headache, then I think the only option you really have is Qwik. So I would say this is the best place to start. Over time, as these extrinsic problems disappear, I think Qwik will become a good fit for other solutions as well.

01:22:07 - Ishan Anand

Okay, that makes sense. So use it right now where it shines and differentiates the most, which is on the hydration issue. Would that mean even if it means rewriting your thousands or tens of thousands or maybe hundreds of thousands of lines of code?

01:22:24 - Miško Hevery

Well, no. We have a good transition story.

01:22:28 - Dan Shappir

Right.

01:22:28 - Miško Hevery

If you use a React application, you can do Qwik React. What Qwik React essentially does is the same thing as Astro — you get islands of reactivity — but it does it in a way where I think one of the hindrances with creating islands is the inter-island communication.

01:22:50 - Dan Shappir

Right.

01:22:50 - Miško Hevery

Within components, you have mechanisms for inter-component communication. But the moment you cross island boundaries, it's like: that's your problem, not ours.

01:22:58 - Ishan Anand

Yeah, right. You're on an island.

01:22:59 - Dan Shappir

Yeah.

01:23:00 - Miško Hevery

And the nice thing about Qwik is that Qwik solves the inter-component communication, and it treats React as an island, but it solves the communication channel around it. So you don't have to be like: oh, this is an island, and therefore how do I talk to this other island? The answer is easy — you just talk to it through Qwik because Qwik has all the fundamental mechanisms for component communication. So there's a migration story, and I think that's a pretty good one.

01:23:29 - Ishan Anand

Okay, that's really helpful. I was not aware of Qwik React, so thank you. Back to Dan: let's set aside what you think is the best approach. If you were to predict a year or two from now, which approach do you think is going to win in the ecosystem in solving hydration?

01:23:56 - Scott Steinlage

It kind of depends on your definition. If you're asking me which meta framework will likely have the greatest amount of use, I would probably bet on Next.js. Not necessarily because it's best or most appropriate, but because it's the future of React, so to speak. And React is the current king of the hill, and that's unlikely to change in the near term. I consider two to three years to still be effectively near term.

01:24:39 - Ishan Anand

Wait, I want to drill into that for a second. There are two ways to interpret that. One is React continues to win with Next just because of its momentum, despite the issues with hydration. Or you could interpret that as: even though it's an inferior solution, React Server Components solve it well enough that they keep going. Which is it in your head?

01:25:02 - Scott Steinlage

Well, I'll put it this way.

01:25:04 - Ishan Anand

Yeah.

01:25:05 - Scott Steinlage

Let's start with the current situation. The current situation with Next.js is abysmal. If we look at the Chrome User Experience Report data for the ratio of sites having good performance, for React in general it's around 36 or 37 percent. So about a third. You would expect that for Next.js it would be better because Next.js provides SSR. Well, guess what, it's actually worse. Next.js is only 20 percent. So the likelihood of getting good performance when you build a site with Next.js is currently one in five. That's not a good situation.

01:25:50 - Ishan Anand

Now.

01:25:51 - Scott Steinlage

Maybe server components will completely solve this problem. I don't know. Like I said, there are issues with it. The main issues are: first, React itself has become heavier in order to support server components, so we need to see how these things offset each other. The second issue is that just because Next.js supports server components doesn't mean all projects will immediately start using it. In fact, the reason they support both the app folder and the pages folder is because they know it's going to be a transition, and I don't know how long that transition will take. And the third point is that my experience is that many React/Next developers don't really know how to use React/Next very well. Again, it's a kind of harsh statement, but I think unfortunately it's true. And server components add complexity — they're not removing complexity, they're adding complexity in a lot of ways. This is like with edge functions: edge functionality is opening interesting use cases, but it's doing so by adding complexity, not removing it.

01:27:17 - Scott Steinlage

And if we are in a situation where most front-end developers don't necessarily know how to use these tools effectively, adding complexity may not be the ideal direction. So I'm hopeful, but I'm not really all that optimistic given the current reality.

01:27:42 - Ishan Anand

Interesting. So I interrupted you on your predictions. Your first one was that Next continues simply because it's the biggest. Was there more you had on what you predict would be the likely outcome?

01:27:54 - Scott Steinlage

Again, it's almost like predicting the stock market. There's an interesting story around Remix now because of the fact that Shopify purchased it. And Tobi Lutke, the Shopify CEO, even made the statement that he believes Remix or Hydrogen is going to win. And you know what? Shopify is big enough to really push Remix/Hydrogen strongly. They could create some sort of certification program where, if you want to be a certified Shopify expert or agency, you'll have to be using Remix. Time will tell. That won't mean they'll capture the market, but it does potentially mean they will have a significant segment of the market locked in to their approach, and a base for additional expansion. It's very difficult for me to say how successful they'll be. It kind of depends on the story they're able to tell and the experience they're able to provide. Qwik and Solid — I love them both — but it's early days effectively for both of them. It's really difficult for me to guess as to their success.

01:29:23 - Scott Steinlage

If we look at Svelte as a basis for prediction, that actually makes me a little bit less optimistic than I might otherwise have been, because Svelte has been telling this great DX story for a good number of years now. And how much market have they been able to take away from React? Let me check again — looking at the Chrome User Experience Report website, they have this dashboard where you can compare the performance of the various frameworks, but interestingly you can also look at usage numbers. They have something like 10 million websites in their database, and those are the top 10 million websites in terms of Chrome-based traffic. If we look there at React versus Svelte — can you guess how many out of those 10 million are React websites? I think I might have said the number before, but it actually surprised me how high it was.

01:30:50 - Scott Steinlage

It's over 900,000 on mobile. So on mobile, out of the 10 million websites in the Chrome User Experience Report, React is over 900,000. Svelte is 14,000. So maybe Qwik or Solid will be able to break through. We do see these occasional shakeups in the market — Angular was the king of the hill for a while, and then React came along and replaced it. So it could happen, but when it happened, nobody really saw it coming. So it's kind of hard for me to say.

01:31:42 - Ishan Anand

Yeah, that reminds me of the documentary on React that just came out, that people should check out. So maybe that's what you think will happen. What do you want to happen?

01:31:56 - Scott Steinlage

I think we need to have this sort of shakeup because, just from the perspective of performance, where we are is just not good enough. We're doing a disservice to our users. Like I said, only about a third of React sessions have good performance. With Next it's even lower. The numbers for the other main frameworks are similar. Qwik looks to have better numbers, but it's still early days. The number of sites they have in this database is so low that it's almost statistically insignificant. So yes, something needs to happen. Performance needs to improve. And by the way, we'll be transitioning from the FID metric for interactivity to INP. And when that happens, we're going to look back fondly on that 30 percent of sites with good performance, because it's going to drop like a rock — probably down to somewhere around 20 percent. So yeah, we are not in a good place in terms of performance.

01:33:23 - Scott Steinlage

Something has to change. Whether React Server Components are going to be enough — well, that brings me to the other half of the story. Like I said, I think React was created with these amazing DX principles of immutability and building a UI as functions by composing functions together. It's an amazing story which unfortunately did not quite pan out in reality. And the result is that today the story for React is much too difficult, from my perspective. Most React developers, from the way I see it, can't really handle React's complexity, and something needs to change, and currently they're only making it more complex. Now, I understand they're looking at something like a React compiler — I forget the name; maybe that will be the magic bullet, I don't know. Time will tell. But currently the DX story just isn't good enough. And so there's also an opportunity there, because I think Solid potentially has a better DX story, and Svelte supposedly has a much better DX story. And like I said, Svelte usage isn't skyrocketing.

01:34:49 - Anthony Campolo

The React compiler is called React Forget. I had never even heard about this. It's very interesting.

01:34:57 - Scott Steinlage

Yeah, and it's because the DX story is just becoming ridiculously complicated.

01:35:06 - Ishan Anand

And it has real cost because it makes it harder and harder to engineer systems when you deal with that complexity. Definitely there are organizations that are facing exactly what you're describing, on both sides. On the performance side, I think we at least have two really high-level economic mechanisms. One of the things I said in a panel a while back was that what's great about Core Web Vitals is it finally got people to care about performance. We've all known that faster sites have better conversion rates, but now we can say it might also improve your search-engine ranking. So whatever problems the Core Web Vitals shine a spotlight on — and as they migrate to INP, I think it's going to help drive attention in the ecosystem to people solving it. And I kind of asked the question earlier: why do you think people are paying attention to it now when before they didn't? And you made a great point that it was because people hadn't encountered it. I also feel like there is the pre-Core-Web-Vitals era and then the post one.

01:36:15 - Ishan Anand

These things are now more front and center in the mindset of not just engineers, but people adjacent to them, tied to the business ROI. And I think the other side... yeah, go ahead.

01:36:27 - Scott Steinlage

No, I totally agree with what you're saying. And again, if you look at the timelines, it's totally on the money that when Core Web Vitals came along — and especially this SEO angle that Google initially put on it, which I found kind of amusing because, with all due respect, you should care more about Core Web Vitals because of the bounce rate than because of the SEO impact. But it took SEO to get people to care, so who am I to complain? The funny thing about Core Web Vitals and hydration is that, in a lot of ways, hydration doesn't really get in the way as much as you might expect of the current Core Web Vitals.

01:37:11 - Ishan Anand

Oh yeah, most people pass FID even with really large pages. It's not a great metric in that respect. Sorry, go ahead.

01:37:20 - Scott Steinlage

No, exactly. So with Core Web Vitals, Google came out with two great metrics and one not-so-good one. LCP is great, CLS is great, FID not so much. And unfortunately FID is the one that measures interactivity. So like you said, even though a site can have horrendous interactivity, it could still potentially get a great FID value.

01:37:50 - Ishan Anand

I'm going to push back slightly there. I did not like the first version of CLS that came out. I thought it was very skewed against single-page apps because it would just accumulate the CLS, but they fixed that.

01:38:01 - Scott Steinlage

Yeah, you're correct about that. So I'm thinking about CLS as it currently is. But CLS is not really that dependent on whether or not you use a framework, and which framework you use — it's more dependent on whether you make proper use of CSS and some HTML tags. And with regard to LCP, again, you might create problems for LCP because you can get contention due to downloading resources, but then just make your JavaScript deferred or something — you could get around that in a lot of ways, especially these days with priority hints. So LCP is less affected by hydration, CLS is not really affected by hydration, and FID everybody passes with flying colors anyway. So the funny thing is that fixing hydration does not really impact Core Web Vitals that much. If you look at how Miško — I'm not sure if he's still on — the way they are currently promoting Qwik is less by showing Core Web Vitals and more by showing Lighthouse, because Lighthouse with the TBT metric is much more impacted by hydration. TBT is much more akin to INP in that regard. When Google switches over from FID to INP and everybody gets smacked in the face, solutions like Qwik will start to shine.

01:39:56 - Ishan Anand

Miško's back. He went back to listener, but looks like he's back on stage. Do you want to comment on that?

01:40:03 - Miško Hevery

Sorry, I kind of missed it because I pushed the wrong button and got kicked off.

01:40:06 - Ishan Anand

No worries.

01:40:08 - Scott Steinlage

I was saying that unfortunately the current Core Web Vitals don't properly reflect the bad impact that hydration has on performance, which is why you guys are primarily showing the difference using synthetic measurements like Lighthouse rather than Core Web Vitals. But that will change once we hopefully switch from FID to INP.

01:40:39 - Miško Hevery

I think the reason we show off Lighthouse scores is because they're just easier to get and measure. Core Web Vitals takes like a month of real-user data.

01:40:48 - Scott Steinlage

Yeah, that's also true.

01:40:51 - Miško Hevery

Super hard — you have to do a change and then wait a month and see if the change had an impact. I can tell you that on Builder.io's website, we did switch our landing page to Qwik and we went from failing to passing, and we're all green right now. So it is definitely having an impact. And I think Core Web Vitals does actually show that hydration is a problem. I'm not familiar with too many...

01:41:19 - Anthony Campolo

I'm sure Ishan probably has something to add here. He's a wizard at this kind of stuff.

01:41:24 - Ishan Anand

No, I want to hear the rest of what Miško has, and then I'll comment.

01:41:29 - Miško Hevery

I was just basically saying that I think Core Web Vitals does actually show this, but I'm not an expert on it, so I'll let you speak.

01:41:40 - Ishan Anand

I would actually agree with Dan, which is that in our experience, at least in the verticals we primarily have customers in, FID is not reflective of the actual JavaScript load that the page is facing. TBT is definitely more reflective, and when INP happens it will be, as he described, a slap to the face. One thing on Lighthouse though — I've always hated the TTI metric. I'm glad they're finally getting rid of that. I felt it was arbitrary and not necessarily reflective of performance in all cases. I have run into issues where TTI had heuristics that would penalize doing smart things like prefetching, and it would drive me crazy. TBT is a little more reflective. But the other key thing about FID is that, as you talked about, it's based on real user interaction. So if you can control when the person clicks, that affects your FID. If somebody clicks on the page and that's the first interaction, and for whatever reason you've held off your JavaScript, you'll still get a good FID.

01:42:52 - Ishan Anand

It's very easy to evade — like having a loading screen. As long as the handler is able to run, it could fool it, even if there's nothing useful on the page yet. And that's kind of why I think INP is promising, because it'll hopefully catch some of that, and it will create that economic incentive again — that feedback loop that'll start getting the ecosystem to pay attention to the problem and look for solutions like Qwik.

01:43:20 - Scott Steinlage

A few comments about what you just said. First of all, I really agree with the points you made. I will say that TTI is gone but not forgotten because TBT is actually measured from FCP until TTI. So TTI kind of remains, sort of, in the context of TBT. But putting that aside, I totally agree with what you said about FID and interactions. In fact, that was exactly a problem we saw when I was at Wix — initially it took so long to download some of the JavaScript that people would actually click something before the JavaScript even started running. Nothing would happen, but it would still count as a click, and consequently we would have great FID. And when we actually started improving the download time and making JavaScript smaller and got the hydration to run faster, FID actually degraded initially, which was...

01:44:29 - Ishan Anand

Yes, because you're changing the user behavior. Yeah, exactly.

01:44:33 - Scott Steinlage

But like you said, let's think about a store page where it takes a while to run the hydration, so I don't show the purchase button until the hydration is done, and I improve FID that way. But obviously that's terrible because if somebody looks at your page and can't find a button to make the purchase, again they'll leave. So you need to be careful when you're trying to optimize for metrics rather than for your actual use case. Should we pause right here?

01:45:10 - Anthony Campolo

I think we have someone from the audience who came to ask a question. Sean, first-time caller, I believe.

01:45:16 - Scott Steinlage

Yeah, thanks for having me, guys.

01:45:19 - Ishan Anand

I've heard some whispers about INP replacing FID. Is there a timeline on that as a Core Web Vital?

01:45:26 - Scott Steinlage

As one of the top three ranking factors

01:45:29 - Miško Hevery

or whatever you want to call it

01:45:30 - Scott Steinlage

for Core Web Vitals? From what I've heard from Google and from what I'm hearing in the W3C Web Performance Group, no, there is no timeline for it. They've not even said that it will definitely happen.

01:45:51 - Ishan Anand

Okay.

01:45:52 - Miško Hevery

So, yeah, just like time to first

01:45:55 - Scott Steinlage

byte, or the other one.

01:45:57 - Miško Hevery

I forget the other.

01:45:58 - Scott Steinlage

Yeah, they're still calling it a beta metric. The fact that it's now collected and shown and graphed makes me optimistic about it. But I think the problem is that they're worried the numbers will drop so low when they introduce it that some people will just give up and say, okay, we can't achieve good performance and that's it. So they're worried that switching to it might create more harm than good. But you'd need to ask the Google people about that — maybe Annie Sullivan or Michael might say something about that. I did notice the same thing with TTI back in the day: potentially functionally infinite TTI...

01:46:54 - Miško Hevery

if you've done preloading or pagination or...

01:46:57 - Scott Steinlage

Yeah, any of those otherwise relatively smart things to do. So I'm glad to see that retired. Yep.

01:47:06 - Ishan Anand

Yeah, I completely agree. That's why it drove me crazy. I had a talk I gave at JS Mobile Conf in 2019 where I put together a really trivial example, but I just kept doing what you would do for preloading, and the network never went quiet. So TTI thinks, oh, we're going on forever and the page is not done loading. But you could clearly see it was technically interactive. So there's an interesting Google Doc I found where Google actually released docs charting the history of how they come up with these metrics. It's actually a lot of work that they do. There's one for TTI, and it used to be called something else, but it had "interactive" in the name. And they work through how they empirically arrived at this — they actually looked at a basket of websites and then picked heuristics that seemed to capture, for most of them, the right behavior. But that means if you're smart and an outlier, you actually get penalized.

01:48:10 - Anthony Campolo

You made a tweet reply with that.

01:48:11 - Miško Hevery

[unclear].

01:48:13 - Ishan Anand

I actually haven't been able to find it again. I'll find it and try to pin it at some point. So I want to be respectful of time, Dan. I don't know how much more time you have. We've been talking about problems in web performance — well, first let me find out how much more time you have.

01:48:33 - Scott Steinlage

We can go for another 10 minutes, I guess.

01:48:36 - Ishan Anand

Okay. Well, I wanted to talk about how you didn't like AMP, but we can leave that for another day. If you've got a quick answer there.

01:48:45 - Anthony Campolo

It sounds like he didn't like the idea of AMP. He never actually worked with AMP.

01:48:51 - Scott Steinlage

Yeah, I didn't like the fact that it was a proprietary Google technology tied to proprietary Google services. That was my main issue with it. Also the fact that it created this kind of weird dissonance where you created a special version of your webpage. I worked at Wix, and back then Wix was a lot less responsive than it is today — I'm talking about responsive pages that can automatically adjust to different screen sizes.

01:49:30 - Ishan Anand

Yeah.

01:49:31 - Scott Steinlage

So you kind of needed to build your web pages twice, once for desktop, once for mobile. Just to clarify, Wix is a whole lot better on that front these days, but back then that was really the case. So in order to support AMP, you kind of really had to force the user to build the webpage three times: once for desktop, once for mobile, once for AMP. And AMP would have those weird restrictions that don't exist anywhere else. It was a really hard sell.

01:50:01 - Ishan Anand

Yeah, I can empathize with that. In the React Storefront framework, what we had to do was try to cross-compile your components from React components into AMP components. So I totally agree with that overhead. From a performance standpoint, I just thought there were a lot of great ideas in the framework that I think other frameworks are eventually going to pick up. Like the use of workerized JS was really ahead of the curve — it reminds me a lot of some of what Miško is doing with Partytown. So I thought there were a lot of smart ideas in there. I know signed exchanges are controversial, but I think it's a great idea. And what was most novel to me about it as a lesson is it was a framework that was user-first — it didn't put developer experience first, it put it second. And I think that's partially why it also failed. But I've seen comments from developers who say, as a user I love it, it's magical, the sites load so fast. But as a developer, I hate it because of all the things you just talked about.

01:51:11 - Ishan Anand

So that makes sense. But I still think it was a very interesting technology from that perspective. Maybe to close this out — I'm curious what you're excited about on the performance front as a whole. You mentioned, for example, one of the things you wish we had yesterday, which was the transition API. Maybe tell people about that. What else do you think is on the horizon for people to look forward to beyond hydration, which we spent most of our time talking about?

01:51:39 - Scott Steinlage

Well, first and foremost, what's really exciting for me is that performance is front and center. It used to be that only specific people within organizations would care about performance, if at all. I'll always remember a conversation I had with a product manager, who shall remain unnamed, who basically said, when I asked them why they don't spec performance as part of the requirements: first, I don't know how to spec performance. That has changed thanks to Core Web Vitals and other things. And second, his comment was, well, I expect developers to build fast software anyway, because that's what developers do. Turns out that's definitely not the case. And these days the situation is much improved — a lot more people are aware that performance is important, that you need to invest in it, thanks to Core Web Vitals, Google Search, and a lot of research that has come out around it. You don't really need to convince people that performance is important anymore. And that's good for me because I've really built a career around it.

01:53:02 - Scott Steinlage

That's one thing I'm really happy about. And it seems to me that in the framework world, performance is really front and center these days. Everybody is talking about how fast they can make their websites. So yeah, that's great. I'm really happy that frameworks are tackling the performance situation head on, because the current situation, as I said, is pretty abysmal.

01:53:33 - Ishan Anand

Yeah, that's a great sea change. Is there anything else on the technology front — like the shared element API, or other things — that you're excited about?

01:53:46 - Scott Steinlage

I'm really excited about — well, I'm simultaneously excited and scared by — all the work that's happening around compilers. I'm old enough to remember a time where we all just wrote JavaScript. Now it seems that nobody is writing JavaScript anymore. Everything is being compiled. The whole point of the web was that you would just write some JavaScript in Notepad, upload it by FTP, and do an F5 — no build step, nothing. Those days are long gone. Everything is compiled these days, and it seems like we're just doubling down on that approach. Nobody codes in JavaScript. This space is called JavaScript Jam, but nobody's coding in JavaScript anymore.

01:54:44 - Anthony Campolo

It's actually funny — Scott and I were talking about this beforehand, that Brad Traversy just released a 37-hour vanilla JavaScript course. And it's fundamental knowledge that a lot of web developers understand they need to learn. But you're correct that there's this layer of abstraction always created between what you're writing and what is JavaScript. This is why I think projects like Svelte and Solid are really good about having REPLs where you can compile what you're writing into the vanilla JavaScript so you can see that translation. I feel like that's a really useful exercise. But what you're talking about — where you just write the thing, upload to FTP, and F5 — for me the modern equivalent of that is push to Git, and my deployment platform then runs it for me. So it's even simpler actually, because it's a single step.

01:55:36 - Scott Steinlage

Oh yeah. Like I said, on the one hand I'm really excited about what's being enabled by compilers. I think Ryan made this point to me — and it's excellent — which is the fact that JavaScript doesn't really have reactivity baked into the language. And consequently, if you want reactivity, you either need to use some sort of heavy-duty library or framework, maybe something like RxJS or MobX, or you use a compiler. And when, for example, you write Svelte code, Svelte looks like JavaScript but it's totally not — it's a completely different programming language that has the same syntax but really different semantics, due to the fact that Svelte does have reactivity baked in. So on the one hand, I'm really excited about the possibilities this opens up. On the other hand, I'm kind of worried about the fact that we're losing touch with what's actually happening, and we're potentially deluding ourselves into thinking we're doing one thing when we're actually doing something else.

01:56:54 - Ishan Anand

Do you think, when we went from assembly to COBOL or Fortran, there was a similar sentiment?

01:57:06 - Scott Steinlage

Oh yeah, for sure.

01:57:07 - Ishan Anand

Right?

01:57:08 - Scott Steinlage

There's...

01:57:08 - Ishan Anand

Yeah, go ahead.

01:57:10 - Scott Steinlage

No, we had a great episode on JavaScript Jabber called The Story of Mel, which I highly recommend listening to because it kind of encapsulates that time period when people were writing stuff in — not even assembly, just, you know, the ultimate grey

01:57:32 - Anthony Campolo

beard is how I would describe it.

01:57:42 - Scott Steinlage

Exactly. So yeah, it is kind of similar. But the funny thing is that we still call ourselves JavaScript developers. And like I said, this space is called JavaScript Jam. When developers moved from assembly to Fortran, they knew they left assembly behind — they knew they were now Fortran developers. We've kind of transcended JavaScript in a way, but we still think of ourselves as JavaScript developers even though we're probably not writing JavaScript anymore. It's kind of a funny, weird situation that we're in.

01:58:26 - Ishan Anand

I think it's an interesting point. The only analogy that comes to mind is how we think of ourselves as the heirs to the ancient Greeks and Romans in some way, and it's like, well, we're not actually in those countries.

01:58:40 - Scott Steinlage

Yeah, exactly.

01:58:43 - Ishan Anand

That's interesting. Well, we're right at almost a minute to go. Dan, really thank you for this amazing run-through on hydration and performance. Miško for jumping in as well, and everyone else who participated — Theo, I know you're on your stream right now, and Bro Nifty Shah who came up as a first-time guest. But again, I want to make sure people know we call ourselves an open mic for everything web development and JavaScript related. You can raise your hand and come to the stage. Whether you're a beginner or an expert, we want to hear from you. And if you're not on the newsletter, javascriptjam.com — you can go sign up. You can also see our recordings of both the podcast, and if anyone up

01:59:32 - Anthony Campolo

here on the stage gave you some value, follow those people.

01:59:36 - Dan Shappir

Totally. They'll probably give you value elsewhere too.

01:59:38 - Anthony Campolo

You.

01:59:38 - Miško Hevery

Yeah.

01:59:39 - Ishan Anand

So Dan, any last words before I hand it over to Scott to take us out?

01:59:45 - Scott Steinlage

No, I think it was a great experience. I wanted to thank you a lot for inviting me on. It was awesome to get all these amazing people on the call all of a sudden — Theo, Miško, and all the rest. So yeah, it was a great conversation. I had lots of fun. Hopefully I can do it again sometime.

02:00:03 - Anthony Campolo

Great.

02:00:03 - Ishan Anand

Thank you, Scott.

02:00:04 - Dan Shappir

Fantastic. All right, everybody, let's use some hearts, some claps, some 100s, some love. Thank you so much, everybody, for participating and joining us here today. It's been phenomenal, really. This has been a really great one today. Thank you so much. And just don't forget: every Wednesday, 12 p.m. Pacific Standard Time, this is where we will be. Come and join us again, just forever, all right? Perpetually. Okay. All right, thanks y'all so much. Appreciate you, and we'll see you in the next one. Love that. All right, thank you so much. See you next time. Peace.

On this pageJump to section