React Server Components: Part 1 - JSJ 582

React Server Components: Part 1 - JSJ 582
Published:

May 16, 2023

Powered by RedCircle

Show Notes

Dan Abramov is a Front-end developer at Facebook and Joe Savona is a User Interface engineer at Facebook. They join the show to talk about React Server Components. They begin by explaining what it is, how it's implemented, the services it offers to the clients, and many more. 

On YouTube

Sponsors


Socials

Dan Abramov 
Joe Savona


Transcript


CHARLES MAX_WOOD:
Hey, folks! Welcome back to another episode of JavaScript Jabber. This week on our panel we have Dan Shapir. AJ O'Neil?
 
AJ_O’NEAL:
Yo, yo, yo, coming at you live from the clouds.
 
CHARLES MAX_WOOD:
Steve Edwards.
 
STEVE_EDWARDS:
Yo, yo, yo. Sorry, AJ, didn't mean to step on you there. Hello from a still cool and cloudy Portland wishing it was sunny like Tel Aviv.
 
CHARLES MAX_WOOD:
Nice. We also have a new host. That's Tejas Kumar. Who is on mute?
 
TEJAS_KUMAR:
Hey from kinda cold, kinda nice, Berlin.
 
CHARLES MAX_WOOD:
I'm Charles Max Wood from Top End Devs. We have two guests this week. We have Dan Abramov.
 
DAN_ABRAMOV:
Hi there.
 
CHARLES MAX_WOOD:
We also have Joe Savona, Joe.
 
JOE_SAVONA:
Hey, thanks for having us.
 
CHARLES MAX_WOOD:
Yeah, well we got you on to talk about React server components. And I know you've been on a few other podcasts kind of talking about the topic, but assuming that there are people that may not know what they are and assuming that they haven't listened to any of those episodes, do you want to kind of give us the 10,000 foot view what they are and why they matter? And then we can ask you all of our deep and scary questions.
 
JOE_SAVONA:
Sure, I can maybe start and then Dan can provide some more detail. I guess, so server components are React components that run only on the server. So that's a kind of common point of confusion. People think of server-side rendering, right? Server-side rendering is where you take your existing client application and run it, kind of pre-run it on the server. Server components are components that run only on the server. And so that means you can do things that a regular client component can't because that code is running on the server. So for example, you can access your database. You can access back end services that you don't want to expose to the front end. And then you can write async components because these are components that are running on the server. They're going to run just once. And so you can write async await and then choose which client component you actually want to render and then pass that data down to the client. So you can kind of think of it like, Server components are fetching data and then passing that as props to handing it off to client components for interactivity. And so this kind of opens up a model where you can really use a server for what it's good for, use the client for where you need an interactivity. And a lot of the complicated things that you might have to do today, like using an effect or storing server data in state and kind of managing that lifecycle. happens a lot more naturally because it just falls out of the server components model. That's the sort of high level view. So if you're familiar with using, you know, PHP with React on the front end or Rails with React on the front end, this is kind of like that except with server components taking the place of that traditional server-side framework. But kind of depending on where your background and where you're coming from, you might have different analogies for that. But I'm sure Dan has more to add.
 
DAN_ABRAMOV:
Yeah, I think it's, it's a little bit tricky to explain because the way you explain depends on the audience. Um,
 
CHARLES MAX_WOOD:
Hehehehehe
 
DAN_ABRAMOV:
I think maybe one way to say it is it, uh, it kind of lets you build full stack react applications, uh, where by full stack, I mean that it's kind of like the react backend as well as the react front end and the idea is that instead of writing. the backend and the front end in two different ways, or thinking about it from the perspective of exposing an API, you kind of think of the whole thing as a component tree. And so if you have been building web apps in early 2000s, you probably remember this simple mental model of, and if you haven't, I'm just describing, the way you would write it is, for example, page called About PHP or Index PHP or Feat PHP or whatever, just the entry points, the pages that the user can visit. And then you could call some kind of API or you could read the record from the database. You could use the database in abstraction, so some kind of database access layer. But the mental model would be... You can just grab some data, map it to some kind of output. And, you know, and that is the, that is the page that the user is going to see. And so this request response model is very nice to think in, because you only think about, you know, here's the page that the user wanted and, you know, here's the data that it needs. Here's how to get this data. And then let's just return the page. But the downside of this approach with traditional server-side technologies like PHP and Rails and so on is that the page cannot update. So if the user clicks on another link or the user modifies something in the database, the only way to, kind of like in this traditional model, the only thing you can do is really reload the entire page. So you know, the user clicks the link and then the browser... goes, fetches the new HTML page and displays it. And so this lets you stay in this kind of request response model. But from the user perspective, all the, you know, if you had a video playing, it will reset. There, there was no way to like animate this transition. If you have some kind of a shared state, it would get reset in the components because you're always replacing the page. And so in the, I think in the 2010s, the dominant paradigm for a lot of apps has shifted to client side, where you kind of, you know, you describe the UI on the client and then that allows you to do client side routing. So when you click a link, we just, we keep the page intact, but we just replace the parts, you know, maybe the part of the route that has changed, but we don't reset the state of the entire page. But then the, from the developer point of view, this is a much more complex model because you have to kind of think about state like server data as part of your state management, you have to think about how to cash it. You have to think about how to actually like trigger the fetches, how to do progress indication and a lot of those things, uh, they become pretty complex. And I think that's when people say they're kind of tired of SBAs. I think a lot of it is about, it's pretty hard to think, you know, in this model of continuously running app, as opposed to the model of I just go to the page and it returns some UI to me. And so really the, I think the idea of server components is what if we could really have both? So what if we could, you know, describe the UI as a React tree? But in parts of that React tree, they execute. uh, in the place, you know, on the server where you have the database, you have, uh, you know, easy access to like, uh, you can call your microservices without ever exposing them. You don't need to, you don't have to like build a publicly consumable API. So those components kind of live on the server, but then you can kind of progressively enhance them with the React you already know. So you can have, uh, you know, client components that have stayed. You can have like animations, you can have videos, you can have forms, like all these things that you use React today for. And then these things are a single tree. So you kind of write your code from the perspective of, you know, here's the request, here's the response, but then the user experience is more similar to single page apps where you can continuously navigate or continuously do something. uh, within the app and the page does not reload, you know, state does not get destroyed. Uh, it just stays there. And one, one thing that's worth clarifying because I feel like, uh, uh, a lot of discussions kind of miss this is when we say the word server, we don't necessarily mean, uh, like a literal server. It's more about, um, the fact that they run ahead of time. So for example, um, So Next.js is one of the frameworks that implement the server component specification and in Next.js the default is actually build time. So server components run at the build time by default. And in that case, your machine is kind of like the server and, you know, it happens during the build. And so this lets us, you know, if you're, you can do like fs.readfile in your server component and read something from, from a file, for example, markdown blog with a bunch of files, you can just read them in your React components. But then when you want to add a little bit of like, you know, like a theme toggle or some kind of, like a comment form or something like this, like that can run on the client. And then for some other routes, like maybe like a settings page, that could actually use the server. So it is flexible in terms of when exactly it runs. And then if you... So this is like from the perspective of like old school web development, but it could also contrast and compare it with today's approaches because it could also look at server components as kind of a react take on how to do like data fetching. And it has some, like, I think it has some overlap with things like get server side props in next GS. or remix loaders or Astro and Islands. So those are like different newer technologies that kind of address the same space. And then you could think of React server components as kind of what does it look like to address the space in a way that feels native to React? So what is the React take on how to do these kinds of things? instead of kind of bolting them on top of existing React. Maybe I can start answering and then Joe will follow up if there's more. I think I don't fully agree with the characterization that you could do everything. I think that's not strictly saying true, but it is in details. So one example is that you couldn't really componentize server or build logic. And I'll give you like a concrete example. So let's say you have a Markdown renderer component. And let's say that your site is static. So it's essentially like a blog. And currently, if you put this as a component on NPM, so you put a component on NPM, your Markdown renderer, that imports some markdown parsing library and turns that like into React tree or HTML. If it is on NPM, then the only way you can consume it in React is to consume it at runtime. So the only kind of way you can, you know, if you add it to your React powered site, even if you build it with a server enabled technology like Remix or Alt and XJS, then this markdown library will be shipped to the client bundle, unless you completely get rid of JavaScript and then you have nothing is interactive. But if you even have a little bit of interactivity, the default way to consume components is they're always shipped to the browser. And so this is pretty, for some cases, this is pretty inefficient, with this markdown example. If you're building a blog that is static, why can't you just do this at the build time? And we do not have any way to put a react component on NPM that does a bunch of stuff at the build time. Like there is, it's just not possible. Uh, you can put like a function that then you can tell, you know, call it from your remix loader, but then that's not composable because, uh, you know, like what if, what if you have like multiple, uh, places where you want to do that? What if you have like code highlight and you want to. do parsing of the code during the build, because it doesn't make sense to ship like a JavaScript parser to the client just for code snippets, if your code snippets are static. And so you can't create a code highlighter component that does this kind of work during the build. And then the thing is with server components, you have this flexibility. And the beautiful thing about it is that you don't actually need to do anything special for it. So if you have an existing code highlighter component that just takes some props, we're trying some output in the server components model. If you import it from a page that runs or like from a server component, then it will also run in the server only environment. And so it will not be shipped. Like the parser for JavaScript would not be shipped to the client as a dependency. Whereas if it's, uh, you know, if you import it from, uh, like a blog post preview page where. you're typing into an input and it's a client component and it updates the state and you want to render a live preview, in that case it will be included as well. So that's an example of a new capability. But you can also think bigger because, well, it would also enable you to componentize server-only logic. So imagine you could have a... some kind of like a dashboard component. Maybe your internal company, you know, you're building a bunch of components. You can have a dashboard component that you put you on your like private NPM registry or whatever you use for sharing code. And the dashboard component can call your microservice or can call your, like it can, you know, read from your database layer, but it is isolated. So it can specify, you know, how to load data for itself. And you could still compose it in the React tree of components. So I think that is a new capability. That's like, what if you could put server only or like build only logic on NPM and compose it and componentize it the same way that, you know, what React enabled for the client ecosystem to enable this same kind of composition for the server and build ecosystem and have these things work together because it's really, it's not... you know, one or the other world is it really lets you combine them seamlessly and have a component and PM that has both client and server parts. And you just, you know, just import it and render it. So I think that that is a new capability. Uh, but as for like the people being happy with react today, I think that's also an overstatement, like sure. Uh, it's, you know, uh, it is, it is usable, but If you listen to what people are complaining about, like a lot of the complaints, yeah.
 
CHARLES MAX_WOOD:
Hehehehehe
 
DAN_ABRAMOV:
But like, you know, people are complaining about like data fetching in user packs, for example, you know, that's, that's a big one. And in general, like people say, Oh, I wish it was easier to do data fetching. And if you try to do data fetching, well, like you have to think about, you know, how do I deal with loading indicators? Uh, how do I avoid, uh, loading waterfalls? Uh, how do I, um, you know, how, how do I, uh, kind of compose these things together? And then it's actually funny because one of the, like very early feature requests, uh, was for react, you know, as soon as promises was a thing, one of the earlier requests was like, why can't they just like async await and just like, do that affection this way? Like, why can't you just like a wave, a fetch and then return a bunch of UI and. That's something that people, yeah. So you, well, that's what it took us a long time to figure out. Because if you want to do that, you have to figure out, okay, what should happen while it's fetching? Like how do you express, uh, you know, where to put the load in state. And that is, uh, you know, that is suspense. So we figured out you put the load in state in your tree. That is how you solve it. Then you have questions of like. Well, but what if, you know, what if your component is waiting for something, but then the parent component updates a state. And so you have to like synchronously, uh, do something like typing into an input. How do you deal with a part of your UI kind of being stuck because it's fetching something. And so the answer to this, well, you just spread apart your tree into parts that run on the client. And so they have to be able to synchronously respond to input. And then parts that run on the server or during the build, uh, that are, that can be async because they're only triggered when you, you know, on the first load and then during a refetch or a navigation. So the, you know, when you just type something, it doesn't, it doesn't force them to the refetch. So there's a lot of kind of, you know, uh, complex questions, but I think one way to think about it is like, yes. Uh, You should be able to async away the inside components. It just took us seven years to figure out how. And that is our answer, like server components is our answer to how. Joe?
 
JOE_SAVONA:
Yeah, I think you really covered it. Um, people have been asking for, you know, how do I do data fetching and routing and kind of, and those things are very related, right? They've been asking for a long time and this is, this is like our answer. So. But yeah, Dan, Dan really covered it.
 
DAN_ABRAMOV:
Joe, do you want to take this one?
 
JOE_SAVONA:
Um, no, I think you, I think you're probably going to summarize it better. Um, I,
 
DAN_ABRAMOV:
Okay,
 
JOE_SAVONA:
I feel like to me it
 
DAN_ABRAMOV:
I can
 
JOE_SAVONA:
is like
 
DAN_ABRAMOV:
try.
 
JOE_SAVONA:
so many things, but yeah.
 
DAN_ABRAMOV:
I can maybe try like the thing that comes to my mind first. Um, I think it is, um, like there is a, the markdown example is, um, is a nice illustration of optimization, right? Because, uh, it's something that could run on either side, but really it's not necessary to run it on the client. If, you know, if they, if the, uh, if the blog is static, one thing to note there though is, uh, There are solutions that, for example, like Astro, where they really go into this direction of, well, if it's static, then it should just run only at the build or only on the server. And then you have, like, hydration only happens for so-called islands or like pieces of interactivity. that is important here is in the react, we want to be able to reuse code. Uh, like if it can run in either environment, so like with the blog post example, maybe on the blog post page, we want it to behave kind of statically because it doesn't change. So it doesn't make sense to ship code there, but it could use the same exact component, like you can literally import the same component in your, uh, in the part that like has a live preview. And so they are the same exact code. could work on the client so that it responds as you type. And you wouldn't download that code, you know, unless you're actually like on the compose post route. So unless you're actually like the author of the blog post. So I think that's one important difference with these approaches that try to be like, let's make it, you know, as much as possible static is that in Astro, for example, you couldn't do that. Because if in Astro, you start with like a static blog post and then you're like, Oh, I also need to show a preview of this on a different route as the user is typing. Now you have to rewrite it from like Astro piece to React piece. And either you have like code duplication or you have to deopt and like ship client code in the first example too. But as you said correctly, I think that's, that's just an example of just, you know, it nicely comes out of the paradigm. I think a, a more important piece. some components can only work on the server. And so this is different from optimization, right? It's like, imagine if you're familiar with Django, you know, this Python framework for creating apps, there's this plugin called Django admin that lets you generate these tables where it just connects to your database and kind of gives you like a default admin template where you can... like see different browse, you can like edit individual entries and so on. And that is something you couldn't really put into a component before at all, like in react land, because it has associated, uh, you know, server code with it that is server only. And so I think that that's like one key feature is that now you can write like componentized pieces that are server only. I think that's, uh, and, and we use them. I think that is important. Uh, But if we talk about like the big picture and like, why we're doing this at all, I think it's, uh, it's, it's just because, uh, the, like, we want to, we think the mental model of, um, just, just writing, um, you know, the, the mental model of like request response is incredibly powerful, incredibly like, uh, you know, It's very nice to express a data logic in it where you just take some data, wait for it, and then return the response and kind of don't think about it. Like it's not stateful and that's very nice for data fetching. And then the clients, you know, the parts that we use react for, where you're like typing something and something updates as you type, or you have some kind of complex forms or some kind of complex flow that like drag and drop, like something interactive. Like that is something that state is really, uh, is really good at and something that it's very useful for. And so it's, it's just about, why don't we give you a way to, uh, do data in a way that feels stateless. And so it's easy, easy to write, easy to wait for, and to keep using state for things that are, you know, uh, actually like stateful as in the user did something and we want to remember it, uh, and then. have those things combined together very seamlessly. So I think it's mostly about enabling this way of writing where you use both sides for what they're best at and then can compose them together seamlessly and you can componentize them so that, you know, different people, different teams can write pieces of it and like put them on NPM and just put them together. And that's kind of like what people like about React already. We want to do that for the server and for the build time as well.
 
JOE_SAVONA:
Yeah, I would just add, I think when you're faced with like, uh, kind of multiple different use cases, one way to approach that is to kind of have targeted solutions for different use cases. So you can say, oh, okay. Um, we're, we, we, you know, we want to make it possible to not have to download the Markdown renderer to the client in this use case. So let's try to find a targeted approach there. And then we want to do a nested routing. Let's find an approach there. And then we want to do, uh, make it easier to do data fetching. And know, that's often a reasonable approach is to think, you know, various, uh, kind of use case by use case, because you often don't need a more general solution. But I think in this case, it really was something where we began to see like that these, these are all related routing and data fetching are related. Um, the reason that we're downloading this extra code is related to the data fetching. Uh, and so then that all kind of having, having this kind of unified solution is actually simpler than attempting to solve each of these on their own. Um, And then once you build that, then a lot of things just naturally fall out of that different programming model. And so it kind of looks like, oh, like you're solving all these different things, you're getting all these different benefits. I think, as Dan said, the real key is the sort of data fetching piece and enabling to kind of have you access the server data easily. And then the kind of single rendering kind of programming model. And then yeah, a lot of nice stuff just solving the problems that people are facing. That's right. Yep. That's right.
 
DAN_ABRAMOV:
Yeah, I think that's, uh, you know, if, if we talk about, uh, like a classical data, you know, if you think of like a classical react, that are fashion example that, you know, people learn like in boot camps, it's usually, uh, a piece of state and some use effect that kind of fills in that state and it already kind of feels weird to write, like, you know, the shape of it looks kind of strange, but, um, even if we set that aside, Like why are we thinking of that data as state? Because state is something that is, uh, that you need to like, the UI needs to remember, right? Like classical examples of state are for example, like a toggle button, right? So it's stateful because it was in some initial states, like it was untoggle. The user did something and the button has to remember what the user did. So the button has its own memory and that is what state really is. And then this example of like a comments widget that has a state of comments that's like initially empty and then somehow just making that component appear causes it to like go to the server and fill in and then set some state. Like the user did not really do something to fill in the comments. It's not really like the comments widget trying to remember something. It's, and I think that is like the conceptual idea here is What if instead of thinking of a server as like a different thing or, you know, you, the file system, right? Like it doesn't have to be a server. It could be during built, but what if instead of thinking of this, like as a piece of state that the component remembers that somehow the component tries to keep synchronized using effects with something external, what if we just think of it as we just want to pass some props from the server and so it's, it's still this top down data flow where. things are, you know, the component takes comments as a prop. It just happens as this prop is not filled in by the client. It's filled in from the server. And then if you want the, uh, the other thing that's like really important about server components, and I think, uh, a lot of explanations miss it because, uh, of confusion, the server rendering. So this is, this is like a, uh, I think there's something we need to be very clear about that server components. doesn't really have anything to do with server rendering. These are like completely different technologies. It just happens that server rendering or rendering to HTML is beneficial for the first load. So we recommend to use server components together with, uh, rendering to HTML for the initial page load. But the important difference is that, um, in traditional server rendered solutions, uh, for react. So like the old next three S, uh, the, you know, Remix, Gatsby, like all of these solutions, server rendering or rendering your React tree to HTML, it only happens once, right? So it happens when the page loads. That's when we turn it into HTML. And then from that point on, the only thing that re-executes on the server, like for example, during navigations, or if you update some data, in this frameworks usually you can... only kind of refresh small pieces of code. So in Next.js, it's like get server-side props. So you can tell that thing to re-execute and give you new props. In Remix, you can tell the loaders to re-execute and give you new data. And then Server Components extends this to the entire tree. So in Server Components, you can say, I wanna refresh my tree. And so if the comments that they get from the database is different, the server is going to pass you new comments as a prop. So it's kind of server components puts, if you know this concept of unidirectional data flow in React, where things fall down as props, and then when you want to change something, you update state at the top and then things fall down again and they flow always down, you can think of server components as adding the server to unidirectional data flow, where you can say, I'm changing the comments on the server, like in the database, and it just like refreshes that, you know, your server component route and the new comments just flow down and you don't need to do anything extra to keep them in sync or like to refresh them. It's just like a unidirectional data flow refresh, the same as it happens on the client when they change the state.
 
JOE_SAVONA:
Right. So that, and that means like that we're, we're not blowing away client size state you're keeping. So if you had it, uh, you know, some, some interactive, uh, component within that, that's going to in, in kind of react terms, reconcile. Um, so it's just as if you'd re-rendered the, as if all that had happened on the client side, that, that existing interactive state is not lost as this, this server side refresh happens. Which is the thing, another, another piece where like, you know, you talked about other solutions can maybe approximate some of what server components can do. That's the kind of thing that often gets lost in these other approaches. Whereas server components are able to keep that, keep kind of the existing client side state around.
 
TEJAS_KUMAR:
Yeah, I had a question about all of this. Thank you, by the way, Joe and Dan, for answering. This is really educational. And the question I have, I think, is something that a lot of the listeners and developers would be interested to hear the answer for. So I'd previously thought wrongly, probably, that server components was the primary solution. Server components was aiming to make was around bundle size, because indeed, shipping, like this Markdown example, instead of shipping the entire. MarkdownRenderer, you ship just the output of it, as it were. And I always thought bundle size was the main theme. But hearing this conversation, it seems like data fetching is also just a huge part of it. So it sounds like Server Components is designed to solve a whole bunch, as it were, of problems. But you said, Dan, talking about data fetching, and the community asking, why can't you just do Async Await as function components? I hear that data fetching can be an answer. But at the same time, the question, and this may be a very silly question, but the question in my mind is, the async primitives on Node.js on the server are very close, if not the same to Node.js, if not the same to the browser, such that we can do async 08 in the browser also for client rendered applications. So the thing that I don't fully understand, I think a lot of developers listening would also probably like to know is, why can't we or indeed maybe we can have React function components called asynchronously at the render phase? Is that like it sounds like from the previous conversation that it was impossible, but what I know tells me this is actually possible is just probably not ideal. Yeah, yeah, definitely. And I think, so again, my assumption that may be wrong is while async components on the client side are technically doable in the browser runtime, the server component approach as it is right now solves that, but also a whole bunch of other problems like data fetching at L that we've discussed. But now I'm curious to hear what the team has to say.
 
DAN_ABRAMOV:
Yeah, do you want to go first?
 
JOE_SAVONA:
Yeah, I mean, I think you already kind of touched on this in one of your earlier answers, Dan. There's just because, so yeah, for sure. I mean, obviously, async-a-wait works in the browser, but that's only part of the problem. What do you show while a component is loading its data? You need a way to represent that. I think in the past, frameworks would basically, I think... and some, some version of Angular that you just have a, a promise. And if it was a loading, it just that, that, that property was null in your template, right. Um, which, okay, that works. Uh, but we really want to give the user more control over what is being rendered at any given point in time.
 
TEJAS_KUMAR:
But
 
JOE_SAVONA:
So.
 
TEJAS_KUMAR:
sorry to interrupt, but Suspense has a fallback prop that also runs
 
JOE_SAVONA:
Right.
 
TEJAS_KUMAR:
in
 
JOE_SAVONA:
And
 
TEJAS_KUMAR:
the.
 
JOE_SAVONA:
that's the point. That's what I was getting to. It's like, so you need suspense, right? And so, yeah, we had a needed, at least like the server components, like infrastructure to even make a lot of that possible. But yeah, I think like, Dan, you'd know like a little more the details of like the internals for why it's a bit more challenging.
 
DAN_ABRAMOV:
Yeah, yeah, I think I would maybe approach it slightly differently. And I think the question of like, why can't you do just do this on the client? The answer is primarily related to waterfalls. So if you imagine and it's the same, I think it's also an answer to the question of, well, why can't you just put a server component in the middle of your client tree. So it's also like a question about incremental adoption, because I think the first thing that people kind of run into is if you try to, you know, you know, they want to think like, how do I adopt this incrementally? Like I have this react tree, you know, it's like completely client. And then I want to like put the server component somewhere in the middle. And we have a rule that says you cannot import. And. Note I did not say render, I say import. These are two different things. But you cannot import a server component from a client file. And the reason for the simulation is, and it's the same as answer to like the question about, can't we just do async await on the client? Well, let's imagine that we do that. And let's think through the consequences. So I think there are... There are two different ways you could imagine, there are two different ways you can imagine the, this kind of playing out. So maybe like the first way is let's say everything is on the client, right? So there is no concept of like server components, your, you know, async await. We just add support for async await in component functions. And I think what you'll see is that it encourages incredibly inefficient. user interfaces, inefficient loading. And I mean, it's, it's fair to say that this is already status quo with use effect and data fetching, but we kind of have a slightly higher bar than because like when people do use effect for that affection, it's usually because they have just like two or three fetches or something like this. It's not that they, you know, they write their whole component tree where like fetch on every level. Because if you try to do that, like if you try to scale it up through any non-trivial app, then you'll see it's incredibly slow because you start rendering the, for example, the parent component, like a profile page and it does, you know, let's say it's like async awaits, it like awaits for some basic like profile data. And so that goes to the server. So you introduce a latency right away. Like that has to go to the server anyway, because that's where your data is. And then like it comes back and then you continue rendering and then you know, you bump into like profile timeline You know like oh no I have to go back to the server again and imagine if there is there's like some latency between server and client You know like it's like if there's like three seconds It's like three seconds on every single level that you want to get something and so it just doesn't scale the you know Do any non-trivial? data requirements. So I think that that is the answer to why we can just do this on the client only. But I can also answer the rest.
 
JOE_SAVONA:
Well, I think what you really want, what you're really describing there is to say, you want to be able to run, how do you avoid that waterfall? How do you avoid that? Well, the only option, when you think about it, from the implementation perspective, is that the server has to know, after I finish fetching this one query in the parent component, I'm gonna have to go and execute these next async functions in the client. How does it know what they are? Well, you have to actually render the parent component. on the server to figure out what client components are gonna be rendered with what props and what async functions are gonna get called there. And that's server components, right? So yeah, it's just that if you wanna avoid those waterfalls, you have to move all the appropriate logic to the server or else, yeah, there's no way around it. There isn't, there kind of can't be a JavaScript solution given that there's user code. Right, that's actually running in between the data fetches.
 
DAN_ABRAMOV:
Yeah, I want to clarify because I think it's, it's not about promise that all or something like this. It's, it's not sufficient because if you have a parent component and like, it wants to fetch something like, even if there is a, like, I want to clarify. sometimes waterfalls are just inherent. Like you can't avoid waterfall in principle in the sense that sometimes you need to, you know, go to like, imagine you need to go to one service. You know, that tells you some information that you can like start rendering stuff. And you use a piece of this information to go to another service, to fetch something. Like that's a waterfall you cannot avoid because the result, what you, you know, the child you're going to render depends on the data that the parent receives from the fetch, like it's kind of unavoidable. But the question is more about, uh, uh, what, like, where does that waterfall happen? And so the problematic case is like, we go to the server, you know, like we. Like there's like a lot of latency in between potentially. We figure out, okay, like here's what we're going to render. And now like we return that to the client, like return the data to the client. And then the next, you know, the component inside, now we know what the component inside is because now we know it's props. Now we know what's being passed down through it. We've found the parent components logic. And then that component is like, Oh no, I need to go to the server. It's like, imagine if you were. Like you had a shopping list and like the person who figures out, you know, the person who kind of, you know, the person who's who's cooking is like, I need, you know, I need you to like go go to the shop and tell me what you know, what fruits are are in the shop. And so you go to the shop, you figure out what the fruits are, you come back and you tell me, you know, they have like bananas and oranges. And then they're like, Well, I'm going to need some oranges. since they have oranges, let's also get some spices. And so you can't go back to the shop. That is silly. Ideally, you want to know, here's the entire list. If they have oranges, then get oranges and spices. If they don't have oranges, let's get some apples and some, I mean, I know this doesn't make sense as an actual shop on this, but yeah. But what I find is just like, you don't want to keep coming, you know, there is some inherent waterfall sometimes, but you want that waterfall to happen at the shop. Like you want to, you know, you have your list of like, what, you know, what thing you're cooking, you go to the shop and that's where you make the decisions about, you know, they have oranges, great, I'm gonna have some of those, or otherwise I'm gonna have these things. And so even if there's like inherent waterfall. We just want there to be just one request between client and server, but then on the server is where we actually like run this logic. And so this, this avoids going back between server and client, server and client and spending all this latency because that, that can be really slow. And that it happens at every single level of nesting.
 
TEJAS_KUMAR:
That
 
AJ_O’NEAL:
So my
 
TEJAS_KUMAR:
makes...
 
AJ_O’NEAL:
con-
 
TEJAS_KUMAR:
Sorry, go ahead. I was just going to say that makes a lot of sense. So the answer to the question that I asked, it sounds like theoretically you can do these async components on the client side, but it's probably not the ideal solution because server components solves the problem of bundle size and data fetching in its peak efficiency way.
 
DAN_ABRAMOV:
There.
 
TEJAS_KUMAR:
Correct. You mean...
 
DAN_ABRAMOV:
Yeah, but I also... sorry.
 
TEJAS_KUMAR:
I was just going to say, you mean the async client components encourages a less, if yeah, okay, that makes sense.
 
DAN_ABRAMOV:
There's also another part of it, which I think is really important and that, uh, that kind of answers the question of why can't you just nest, uh, why can't you just like put the server component in the middle of your tree as an adoption strategy, right? Like, why can't you just like render a server thing, uh, like somewhere in the middle? And the answer to this is actually related to, to this problem, uh, of imagine that you could. So imagine that you have like an async function in the middle of the tree, of your existing tree. Whether it runs on the server or in the client, it's actually the same problem. So imagine that you have this async function and then some state updates above this component. So like normally in React, when the state update, like you have a state update, you want to re-render the tree, right? Like the tree needs to be consistent. So if you're updating the state, you want to do rerenders. Like sometimes maybe you bail out of rerenders for performance. But still, like if you're passing some piece of state down as a prop, it has to go through every level and it has to re-evaluate, you know, the, what is the UI given this new value of this prop. And so imagine that you put like a server, you know, you could put an async function somewhere in the middle of the tree. And then let's say you add an animation or you add the form above it, or you add something that, you know, a theme toggle, like you add any piece of state above. And so now what do you want to happen when the property pass kind of flows down through that tree? And, but, you know, the naive way to do it is like, like you would actually, if we allowed that, you would accidentally trigger this async refetch all the time. And it would get stuck all the time because, you know, it takes some time to, uh, to kind of go to the server and back. And this is especially a problem if, uh, this component just does some prop plumbing, so, uh, maybe it just takes, you know, some prop from above and it passes down to something that actually needs it. And so now, uh, like maybe that prop has not changed, but it's still kind of like having to refetch this stuff. And so what server components forces you to do is to decouple these two data flows. So you have the server data flow that is only, you know, the data that's needed by the server. It flows down, uh, you know, on the server. And so you don't actually know what the client state is on the server. Like you don't know what, you know, you only know the URL or some kind of like where, which page you're rendering, but you don't really know, like, what is, what is the value of every checkbox and so on. And then you have the client logic that, you know, that, that response to state changes in, in real time. And so the, the beauty of this is that with the server components model, it's really like the server is kind of the first pass. So the server just figures out the data. And then like on the client, if a state updates, it never needs to, like it never triggers server refetching by default. Like if you update like a theme toggle. It just updates the client components because on the client, from the client's perspective, the server has already ran. So like the client only sees kind of the server output. So it just keeps over it. It's like it's pre-computed. So you don't have the situations where you just added a bit of state and suddenly you're refetching like 10 times more often. And that is like a big, you know, that's like a big thing we're avoiding. Yeah, I think
 
CHARLES MAX_WOOD:
I'm going
 
DAN_ABRAMOV:
it feels
 
CHARLES MAX_WOOD:
to jump
 
DAN_ABRAMOV:
a little
 
CHARLES MAX_WOOD:
in
 
DAN_ABRAMOV:
bit
 
CHARLES MAX_WOOD:
real quick.
 
DAN_ABRAMOV:
like learning. Oh, sorry.
 
CHARLES MAX_WOOD:
How
 
DAN_ABRAMOV:
Keep
 
CHARLES MAX_WOOD:
are
 
DAN_ABRAMOV:
going.
 
CHARLES MAX_WOOD:
you guys on time? Because we've got about a half hour left on what we've scheduled for time. But if you can stick around longer, I'd like to kind of see how far we go.
 
JOE_SAVONA:
Yeah, I'm good.
 
CHARLES MAX_WOOD:
All right, just tell us when we need to start wrapping up.
 
STEVE_EDWARDS:
Hey, Chuck,
 
CHARLES MAX_WOOD:
Alright,
 
STEVE_EDWARDS:
real
 
CHARLES MAX_WOOD:
go
 
STEVE_EDWARDS:
quick.
 
CHARLES MAX_WOOD:
ahead. Sorry, Dan.
 
STEVE_EDWARDS:
Chuck, I'm going to drop off real quick because I got a fire to put out and I haven't really been adding a lot anyway, being a view guy,
 
CHARLES MAX_WOOD:
Okay.
 
STEVE_EDWARDS:
so.
 
CHARLES MAX_WOOD:
Sounds good.
 
DAN_ABRAMOV:
Yeah, I wanted to say it definitely takes some adjustment to notice that there are, it's like two different data flows, but a single tree. And I think that is not obvious the first time you try it. I think it takes a little adjustment. And you also kind of learn some patterns of how to deal with it and like how to I think what I've heard from a lot of people who spend some time with it really, and kind of it's like at some point you just get it kind of in your brain and then it even becomes rewarding to be like, oh, it makes sense. Like I'm going to, you know, I'm going to thread this thing through here and thread this other thing through here. And I think the analogy that like comes to my mind is learning Nietzsche. You know, like when you, like you learn like a neat and pattern where, you know, you have to take the needle, you have to like put it through this hole, this other hole, this other hole, and you have a pattern. And I think it kind of feels similar in that like at first you're kind of clumsy and then it really becomes like a second nature and it just makes sense. And in you start noticing this like adoption, for example, with adoption strategies, I think a big one is again, like people kind of think of like, I have a client app, you know, it's like from. server components perspective, like all existing React apps today are like fully client. And so you think, Oh, I wish I could like try to swap out this, uh, leaf component, like at the bottom of the tree with like a server component, but that doesn't work because well, like how does it know which props to receive if it's a leaf? And so the things being passed through it depend on state potentially. So there's just no way for it to run ahead of time. And so the, the adoptions. Like you can adopt server components incrementally, but the adoption starts the other way around. It starts from the top. So what you do instead is like you have your entire client tree. And so in the server components model, that's actually a valid server components app. If you imagine there is one server component at the top, it just returns your root client component. And so it's kind of like a tree where there's one server component, the rest is client. Again, it doesn't mean that it ups out of server rendering. Server rendering is completely unrelated. Server rendering still works, but it's just, you have this one, one component at the root, and then you have this use client directive that says, uh, the module graph below, like, this is where we cut it off. This is where the server part ends and everything below is like, it kind of run on the client. But then gradually you may be, you know, like, I'm going to, like, you kind of think of this like. as a way to create some skeleton or some structure for your app, where you say, like, maybe I have like app component at the top, or like, I have like a profile page component and then, and the rest is client. But then later you say, okay, maybe I'm going to have a profile page component that composes a profile cover and profile details, and maybe that contains timeline and about, and then the rest is still client. So you kind of build out like a little skeleton where you can do data fetching at each point and you kind of pass like acing things down. And so you kind of gradually like lift the, like you kind of move those pieces where you transition from server to client world, like further down the tree. But you also don't have to. So the thing that sometimes people think of like use client is some kind of like an escape hatch or some kind of a bad thing. But it's really about, you're supposed to be able to use as much or as little of either side as you want. Like you can build the entire page with server components. You're going to have like one server component in the root and the entire page is client, or you can kind of like mix and match them and nest the, you know, server components into client components and the other way around. And so it's really like, as long as you follow the rules, you're not going to, you know, it's not going to allow you. Like one way I've liked, I was on some Twitter space and I've liked this, uh, at the start, it's like server components, uh, make clients serve with waterfalls, a compile error. Like that's, that's kind of what it does. And I think that takes some adjustment because we're used to accidentally introducing this server client waterfalls with these effects and so on. But it's, it's, it's really just the more efficient and I think it is a clearer model once you. Let it settle a little bit in your mind.
 
JOE_SAVONA:
Yeah, I think there's also probably some different ways of writing your client components to kind of work more naturally with server components. So for example, you can imagine a tab component that receives the list of tabs as React children, right? So now the tab component, it's interactive. It keeps track of what is the currently active tab. Forget things like. you probably want to actually do like route. Maybe you might want to integrate the route, but you know, keep considered just a simple, a simple tab component. It's going to keep state about which tab is selected. Well, there's no reason that the, just because that tab component has some clients at state, it can take children that are server components and that were, you know, right? And so when you structure your components in this way, so you're imagining tab component. Right? A server component can render the tabs, but it's also passing it. A bunch of components that are, that are a server components. Those server components are evaluated on the server. And then they kind of rendered output of them is passed down to the client to render inside this tab component. And when you have your kind of design components structured in this way, it allows you to, to like have a lot more flexibility and say, Oh, I don't have to, you know, I have a tab element that needs data. You don't have to go and rewrite the tab to somehow work on the server. That's fine because you can lift that tab component and to be a server component without breaking the kind of model. So once you start thinking and really using React children in that way, I think you get a lot of flexibility to have these apps that are almost completely server. You know, you could, if you want to have them be almost completely server components while still having kind of sprinkles of interactivity kind of around them without breaking the rules, as Dan said.
 
DAN_ABRAMOV:
I've seen this referred to as a donut pattern because it's kind of like this, this client, you know, this, like in this example, the, uh, the top bar or, you know, the top container component. I think when we think of components, we usually think of like rectangles, right? Like we think of this, like piece of the screen is a component. And I think what server component it's, it's not a new thing. So like we react has always supported this. But this pattern has become so much more important in the server components world is like, think of like, where do you draw the hole inside your components? Like in the top view component in top container component, you have tabs and then you have a hole for the content. And so this lets you, or, you know, some frameworks call them slots in the react. This is called like props that children, but it doesn't have to be called children. It could be, you know, anything that's passed from above. But this is why I'm talking about meeting, right? Like this, like put the needle through the hole. It kind of feels similar in that you think of your design system components as having holes and that lets you fill them in with more server component content from above or client components. So it gives you this flexibility, but you do need kind of to think of like which components are donuts, whether I want to leave a hole.
 
JOE_SAVONA:
Right. Because you're not that excited. That example children is props, right? So yeah, you can pass server components that are in the children prop to a client component. Exactly. Yep.
 
TEJAS_KUMAR:
But then how does that affect, you know, there was this statement earlier that you can't import a server component into a file that contains client components. But if you wanted to pass a server component as a child to a client component to props.children, you would have to import it in the...
 
JOE_SAVONA:
Right. So imagine you have, let's say, the root, and it's going to render a tab, and then it's going to render a few different profile pages as the tabs. So you have the root component is a server component. The tab is going to use use client because that's a client component. It has state. the root component is going to, and it's gonna return tab. And then within that, it's gonna say, profile details, profile photos, timeline, right, as like different components. And it's the root component, that is the one that's importing all of tab and timeline and photos, right? That's where the import is happening. And so it's not that the tab component is actually importing those elements, and that's why it works out.
 
TEJAS_KUMAR:
Right. So it's the root import. That makes sense.
 
JOE_SAVONA:
Right. Yeah. Yeah. And I think this is a really common pattern. I'm thinking back to if for folks who like maybe I'm dating myself, I think about like Rails examples, but like, you know, I think it's pretty common to have routing solutions that have like a layout, right? Like layouts are, I think, are pretty common in like nested routing solutions where a route can have like a slot that the kind of nested content goes into. And so this is kind of taking that notion of like layouts with like the kind of dynamic slots and... saying you can kind of use them anywhere in the tree separately from your routing solution. This is kind of like the idea that Dan's like, you're describing with the donut pattern, right? That really is like this, the same as a layout, but you can do that anywhere, right? A tab is like that as well.
 
DAN_ABRAMOV:
He can't do that yet. So this is, this is a part that we, uh, well, I guess like by the time this episode comes out, it's actually, um, I don't know what the schedule is, but it's, it's, it's, it will likely be available in some form, but we're currently, uh, that is what we're working on now is, uh, this ability. Uh, we're calling that server actions. So, uh, we. want to make it possible to pass a function from a server to the client. It would have to be annotated with a use server directive. So it has to be annotated that this is something you want to expose because it would otherwise be unsafe to expose arbitrarily callable functions from the server. You don't want to do that. But if it's something that you want to expose as, it is similar to RPC. So there are some popular solutions for RPC now. We don't think RPC is a good solution for data fetching. So RPC isn't like, and the reason is the same as, you know, if you do RPC for data fetching, and for those who don't know what RPC is, it's when it's remote procedure call is like an old term. But essentially it just means you call a function on the client as if, you know, as if it exists there, but actually behind the scenes is going to talk to some like server NPI endpoint that's like generated automatically. And then it's going to call like the actual function on the server that you write. So like RPC is this concept of like, I'm going to call a function, but actually I wrote it on the server and there's some layer in between. that kind of translates it and make sure that like the types match and that it actually works and that it actually like waits for it. Okay, yeah. Yeah,
 
AJ_O’NEAL:
But this
 
DAN_ABRAMOV:
for sure,
 
AJ_O’NEAL:
actually,
 
DAN_ABRAMOV:
for sure.
 
AJ_O’NEAL:
this brings up another, I think this is an important point. I think most people aren't very good at architecture. I think most businesses don't have a good architect. I don't think I've ever seen someone regret developing their API and then fielding it with their front end or their mobile app to be able to know that it works well, but I have seen terrible, terrible, terrible spaghetti mess. time and time again, where people try to map the way the back end will send data to the way that it's going to be used in the view. And then when they need to grow or scale the functionality or the accessibility to third party partners or whatever of their application there, they just got a steaming pile of spaghetti the view rather than the API.
 
DAN_ABRAMOV:
Well, I think that's just, uh, I think it's a slightly separate topic from mutations maybe, but if we jump into that, um, we're not really taking anything away, right? Like I think the, you can still build an API if that is what you would like to do. You can call that API from your server components and you know, you get to define what the API is. You can even keep that API private at first without exposing it. you know, to the entire internet right away. Uh, so this is something that you can do. Uh, the question is, I think, like, from this perspective, the question is like, should you have the option of not building an API and just using your data layer, your model layer, whatever layer you have directly? Like, should you have that option? And we think yes, of course you should. Like you, you know, you have that option. server-centric, like you've always had this option in all server-centered frameworks, like they don't force you to build an API layer with all concerns of like, you know, specific how to build it, but then if you want to build an API layer, you can certainly build it later, or you can like institute a policy, like
 
AJ_O’NEAL:
Can you
 
DAN_ABRAMOV:
we always
 
AJ_O’NEAL:
build
 
DAN_ABRAMOV:
build APIs.
 
AJ_O’NEAL:
it later though? Can you really build it later? That that's that's my
 
JOE_SAVONA:
Oui.
 
AJ_O’NEAL:
my concern is if so much of the focus is on render render render render then then you know the shape of the Application will take the shape of the render rather than the shape of the logic of how things are oriented
 
JOE_SAVONA:
Yeah, well, I mean, well, to be clear, like certainly you can build a separate standalone API for your, for your backend. So if you're, for example, if you're, if you were starting
 
AJ_O’NEAL:
Well,
 
JOE_SAVONA:
off, well, I mean,
 
AJ_O’NEAL:
I'm talking about practically what I get that. Yes, you can rebuild a new server from scratch and interact with the database, but then you're going to be copying all this stuff. And then, you know, so this is what I'm just saying. I think this is a peril to focus too much on the renderer and not consider what the API is going to be, because, yeah, you. Yes, of course, you can rewrite your application. But you can't just add an API on top once you've built all of this type of, if you've built your API to the renderer, you can't just add an API on top of it.
 
JOE_SAVONA:
Well, I mean, I guess it kind of depends on what API you're thinking about. So for example, if you're, if you're, if you're a startup and you, and initially you're creating a website. Um, and you know, uh, and you build, you know, you build a React server components app. Um, you've got some services behind the scenes. One nice thing as, as Dan kind of highlighted is that you're not forced. Uh, if you, if you, if you don't want to, you're not forced to kind of expose your initial kind of internal API to the world before you're ready. You could start by just building your app. When you get to the point that now, for example, you've got a mobile app or you want to start exposing your, you know, actually exposing a more, an API for other consumers, not your app. Right. I mean, by all means you can create a standalone, you know, API. I think what you're getting at is maybe the kind of, you've got, is there a sort of business logic layer that is developing inside of your next app? And you're, what you're getting at is that you want to like reuse some of that for this API. And, you know, that's obviously a question of just, you know, factoring
 
AJ_O’NEAL:
Why I?
 
JOE_SAVONA:
out that logic so that you can make it reusable. But I don't see how it's really, it does, it feels like if anything, it's kind of giving you more choice and more options and not really taking anything away, but maybe missing something.
 
AJ_O’NEAL:
I'm not saying that we shouldn't have the ability to render. I'm I just, I feel there's a great caution. Okay. You guys are big brains. You can probably start a project and know what you're supposed to do and have the right separation concerns, but there's, there's not any guardrails or encouragement. People are going to tend towards PHP, right? And it's going to end up being, I mean, you, I don't know how much react you guys see of you, what the little people are doing. You know, I'm sure that you work a lot with the big companies, but I don't know if you see what goes on at the small medium sized businesses because they're probably like really far below where your skill level is and where you but. But I mean, it's it becomes PHP eventually, you know, it's it's like if you look at some of these react apps that people are creating and this could go for anything right it's not necessarily just react, but I mean that the. There's so few separation of concerns. And that's kind of one of the things with the react movement was a throw separation and concerned out the window. We don't need separation of concerns, but that separation, that, that lack of separation of concerns kind of starts on the front end and as it gets closer and closer to the backend, it's more and more difficult to end up selling that product, right? You want to relicense that product or you want to, you want to sell your company and you have to go through due diligence and the, the, you know, Obviously this is a problem anywhere, right? But if you took rails, for example, you could sell a rails app. You could, you could, you could grow a company on rails and you could sell a rails app. There's a pattern there's prescribed separation of concerns. And if somebody needs to go in, unless you just, you hate rails and you're doing it completely wrong on purpose, you're going to fall into the pit of success with active record. And yeah, there's gotchas and whatever, but you fall into the pit of success. where if somebody needs to take your application and expose it to third third parties or retool it for white labeling or whatever, they're going to fall into the pit of success. And that's where that's kind of the distinction I'm trying to draw is that. You know, yes, if somebody is super expert, no, they don't need any handholding. They could take something, uh, and they can create good out of it no matter what. But by definition, 90% of people aren't expert. So that's why I'm, you know, I'm kind of saying it. Where's where's the help for the average developer to be able to end up with something that can be sold or can be integrated. Do you get
 
DAN_ABRAMOV:
I
 
AJ_O’NEAL:
what
 
DAN_ABRAMOV:
think
 
AJ_O’NEAL:
I'm saying?
 
DAN_ABRAMOV:
I
 
AJ_O’NEAL:
Now?
 
DAN_ABRAMOV:
can
 
AJ_O’NEAL:
Does
 
DAN_ABRAMOV:
try
 
AJ_O’NEAL:
that
 
DAN_ABRAMOV:
to,
 
AJ_O’NEAL:
make sense?
 
DAN_ABRAMOV:
yeah,
 
AJ_O’NEAL:
Does that, does that clarify?
 
DAN_ABRAMOV:
I can, I can try to answer this. I think, like a part of it is just we, I don't like the distinction between this like big and little or, you know, small brain,
 
AJ_O’NEAL:
Well, you might not,
 
DAN_ABRAMOV:
big
 
AJ_O’NEAL:
but
 
DAN_ABRAMOV:
brain,
 
AJ_O’NEAL:
it exists
 
DAN_ABRAMOV:
but
 
AJ_O’NEAL:
in the
 
DAN_ABRAMOV:
no,
 
AJ_O’NEAL:
world.
 
DAN_ABRAMOV:
no,
 
AJ_O’NEAL:
Ha ha ha ha.
 
DAN_ABRAMOV:
no. Please let me finish. The, because like, for example, like at Facebook, uh, like I've seen some of the worst react code in my life. Like, I think you're really overestimate and, um, you know, it's, it's, and it's not because like engineers are like stupid or something like this is because like people work on different projects. They don't always have the context. They don't always, uh, like sometimes you have like somebody who works primarily with backend, but they need to write some front end code or the other way around. Like they don't know sometimes like project, you know, requirements change or like frameworks change. So it's, it's pretty natural that like some code is messy. And I think what we, you know, on the react side, we don't really like the paternalistic prescriptive approach of, you know, here's, here's a capability that. makes sense, but we're not gonna give it to you because you're not smart enough to use it. Like, I think we don't like this. I think we, you know, if we think it makes sense for, you know, your user interface tree to resolve asynchronously, we think it makes sense as a concept on the React layer. And then from that, it necessarily follows that you would be able to, you know, either like call your data layer. that can be, you know, all, all around. So that's not too far from what rails does it, you know, you, it could be something, uh, you know, on the framework level, uh, for example, like you could build a framework on top of react server components that is maybe more opinionated about the way you structure data, and then it would like force you to expose everything as an API. Uh, but because we think that there are many valid use cases where you don't want. to build a generic API. And in fact, server components, like one of the inspirations is just kind of realizing that the, like you could make a mess in either direction. Like if you push everything to the front end, you can make a mess there. If you write like a beautiful API, but it doesn't actually correspond to the shape of what the renderer needs. And that like we've seen that a lot. Uh, where you, you can safely like remove something from API because you have no idea how it's being used, uh, and so on. So we think that we, you know, we don't want to limit that ability. We actually like want you to be able, uh, like to, to make choices there. And then we think that the developers like, yes, you can make a mess of out of it. And by the way, a lot of. Pretty big products were made with PHP and people were able to figure it out. And then there's a lot of spaghetti code in the React code basis. But one thing that's, I think, very like important from the, like, if you're worrying about spaghetti code in particular, um, one thing that's important. Like if you, if you compare spaghetti JQuery code and spaghetti React code, there is one big difference there. And the difference is composability. The difference is that in React, you can take a piece, like you can take a component, you can throw it away and you can like, you know, remove it. And it, it definitely, it usually doesn't break anything. And that's because the data flows down. And so you can, you know, you can take a piece, you can replace it. Like you can rewrite the component to take the same props and then, and then it works. And so it lets you kind of, you know, iterate and Uh, you know, I think maybe Ryan Florence, uh, had this read about like it let react. Let's me, uh, you know, fill a bunch of boxes with garbage, but then it connects this go boxes in a way that makes them, makes them swappable. And when there's a problem, we can actually replace it. And server components preserves this property where, yeah, like you've, if you make a mess somewhere, you can replace that part. Uh, but I think kind of more guidelines about. how do you do like API structure, like all that kind of stuff. This is something that frameworks can enforce and the React server components is not a framework. It is kind of a tool for frameworks.
 
AJ_O’NEAL:
There's
 
JOE_SAVONA:
I
 
AJ_O’NEAL:
a difference between enforcing versus making it easy and clear. And so that's one thing I didn't. I'm not trying to say that it should force something. I'm saying that as you come into it, you know, you begin to fall into the pit of success. I'm all for escape hatches. I'm all for libraries that say here's the function that does everything with the defaults and usually does what you need. And then here's the four functions you need to call if you
 
JOE_SAVONA:
Yeah.
 
AJ_O’NEAL:
know that the defaults don't work and you need to get low level. I'm all for that. I love that.
 
JOE_SAVONA:
I would just call out though that I think it's very easy in, for example, rails, uh, to fall into the mistake of putting, uh, too much logic in your controller when it should have been in a model, right? Um, right where it's, Oh, wait, I, why am I repeating myself in this other controller? Like because it turns out that actually that was like really just like more business reusable business logic that should have been in the model layer. Like I think the reality is that any solution is going to make it easy or even to have a tiny bit of logic in your template. If I recall correctly, ERB still let you put a little bit of logic there, right?
 
AJ_O’NEAL:
Well...
 
JOE_SAVONA:
It actually still technically kind of worked, right? And even what data, what properties of the record are you fetching is actually logic that's sort of vacant in the template. The point is that
 
AJ_O’NEAL:
You
 
JOE_SAVONA:
it...
 
AJ_O’NEAL:
can always get it wrong. Yeah, I agree.
 
JOE_SAVONA:
Yeah,
 
AJ_O’NEAL:
You can
 
JOE_SAVONA:
you could
 
AJ_O’NEAL:
always
 
JOE_SAVONA:
always
 
AJ_O’NEAL:
get
 
JOE_SAVONA:
get
 
AJ_O’NEAL:
it
 
JOE_SAVONA:
it
 
AJ_O’NEAL:
wrong.
 
JOE_SAVONA:
wrong. And I think, and in particular, like the, like the, the model versus controller was like an incredibly, uh, easy, easy thing to, to, to, like to, to mistake, like to mistake in the rails world. And, and I think in, in, in, in very similar NBC systems. So I think like, there's like, there's only so much we can do there, but I think it's really about, um, giving people the capability and yeah, like I would be great to see, uh, you know, we've seen things like, um, uh, somebody from expo, I forget, was it, I think it was, uh, Might've been James Eday who worked on, and others who worked on a version of the the Facebook end system. So end is a framework, a framework you have internally that makes it easy to do data loading, but with kind of attached authorization, like can this, can this user see this object, right? Is it think something that that's often kind of missing, right? And then literally every single piece of data that you fetch off of that. So you first of all, you get a user and then you want to see. their posts and can I see their posts? Right. And it's just kind of walk the graph, like it's doing all the correct checks. And so, um, the folks at expo released like a JavaScript library, like it would be great to see more things like that, that are helping to make like kind of really good scalable data libraries for JavaScript. We think that that should exist. Um, and we think that server components would be totally complimentary to that, right? But again, how are you going to build those things if you can't easily fetch data in your react components. Right.
 
AJ_O’NEAL:
Yeah, I meant that.
 
DAN_ABRAMOV:
Yeah, I can try to answer this. So I think it is like on the specification versus implementation side, it's a little bit blurry because we actually do provide some of the implementation pieces on the React side, but not all of them. So the parts we provide are the parts that interface directly with the React. So we provide the thing that executes your server components, uh, kind of like the renderer and we, that, that renderer produces our protocol that lets us stream a react tree from the server to the client. So that's, uh, we basically provide the thing that like advanced them and serializes them. And serialization is actually like what triggers execution of server components. So that's, that's why, like, if you. render, you know, a top container, and then they have like a profile tab inside. And so as we serialize the response into our protocol, we're like, oh, this is like a tab container. Um, it's a client component. So we need to tell the client how to download it. Like where is this script tag, you know, where to get the JavaScript chunk to download the code for it. And then we're like, okay, now we've got to pass, you know, now we need to serialize these props so that they can be passed. And so as we serialize these props, we're like, oh, this child is like a piece of JSX. So we're going to assume it's a server component. We're going to run that. And so, and so that's, that's why it's possible to nest, uh, server components and the client components, uh, because of the serialization process. And so we provide the piece that does the serialization and we provide the piece that does the deserialization. So the protocol is not like something that anyone needs to conform to or know about. It's really an implementation detail of React. But we provide this thing that can read this protocol and construct a React tree out of it. So we provide the thing that executes server components and we provide a thing that kind of turns that output into a normal React JSX tree that you can then render. And that's really how it works. But then the pieces that we don't provide are, you need a bundler integration on a pretty deep level, because Server Components is kind of a futuristic architecture that assumes a next generation bundler. So it doesn't just rely on what exists today, it's also kind of our vision for what bundlers should be able to do. And to give you like a sense of the... Um, kind of the gravity of the step is like, it's, I think of it as like, um, the things that we want from a bundler are on the same level of, uh, you know, advancement as, uh, code splitting, uh, was an advancement compared to, uh, always, you know, uh, bundling everything as a single file. So like in, you know, 2007, maybe like, I think, like, uh, I think maybe Google had. Um, like GWT or something like this, like maybe that was one of the first, I'm not sure, but I think it was one of the first production kind of implementations of code splitting and it slowly made its way into open source. So like we've seen, you know, I think a required dot JS, there used to be this bundle, uh, that, that did not have code split in, but I think, uh, browserify maybe had it and like webpack, I think is the one that brought the concept of a code splitting really to mainstream. uh, with required dot insurance and like this, and later, you know, it got, it became a specification with this like dynamic import syntax that gives you a promise and then behind the scenes, the bundler actually generates a chunk whenever it meets the dynamic import. And so server components kind of, uh, in server components, that part is the specification part. So, uh, and it's, it's. Conceptually, it's very simple. It's just that there is this. directive called use client that acts as a split point. So by default, the module graph starts on the server. So, you know, your code doesn't get, you know, into client bundle at all by default. And then the moment the module graph meets a use client import, that's a client entry point. So use client doesn't mean you need to like add it to every single component that executes from the client. That's not what it is. It's really the boundary. It's like where the server kind of enter. It's like the door to the client world. That's what use client is. And so we, uh, the boundaries need to be able to kind of, uh, use this, use client entry points is like, Oh, this is where a client tree might start. So I better create chunks for this parts so that they can be, you know, that the client can download them. later, it's kind of similar to dynamic imports, but it is tricky because it means that the bundler kind of needs to know about your server module graph ideally as well, because it needs to know, oh, here's a use client that I kind of reached as I was traversing the server graph, and I'm going to need to tell, you know, that there's, there needs to be a client bundle for it. And so. we see this as like a next generation feature for bundlers where it's not even specific to react like use client thing it's not about components again it's really about bundling and we I think like turbo pack is the only bundle right now that implements this completely natively so it's like it's a first like turbo pack was actually designed to treat server and client graphs It's like first-class concepts. I know that there are plugins for, I think for Vita, for ES build, with, yeah, I think Bun is also built in first-class support, but there are, there are different attempts to like build plugins for existing bundlers. For example, Next.js doesn't ship TurboPack by default, uses Webpack by default and then Webpack, I think like it, I think it uses, well, I'm actually not sure if it uses Webpack or some other thing, but. Uh, in a distant bundler, so you can approximate this, uh, and like, it kind of works, but it's not the most efficient way to do it. And so this is part of like why it's, um, you know, if you wanted to make a server components framework today, uh, you kind of need to be a bundler engineer because you need to solve this problem. You need to design the next generation bundle or you need to design, uh, an integration into existing bundle. That was not designed with this in mind. So you kind of. have to hack it in. And that's what people have done. Like, you know, Gatsby has a, um, kind of a prototype of this integration, but they haven't finished it. So it only works for production builds. It doesn't work in development. So that's, you know, we can't really develop if it doesn't work in development. And like next actually, you know, like fully, uh, fully is implemented as fully. And we, we also see some people in the community experimenting with like making it work with this build. making it work with Avite and so on. And so I think with time, like we'd like to see more server components, frameworks that, uh, can take full advantage of it. Uh, but I think we will see more of that when there are ready to use off the shelf bundlers, they just have this as a built in feature. So it actually, you know, you don't need to reinvent the bundler because the other thing, like if you want to make a full server components, uh, kind of framework integration. You have to solve routing, bundling and like rendering. And so we only give you the piece for rendering. We give you a specification for bundling and then for routing, you kind of have to figure it out and deployment. Yes. So like you also have to think about like how, you know, how are you going to avoid like versions queue and other problems? So it's just a big project.
 
CHARLES MAX_WOOD:
Thanks for watching!
 
DAN_ABRAMOV:
I'm not sure that VIT is like best positioned for this. Um, I think partially because like in, in this architecture, you really have like the server graph and the client graph. And I don't think VIT has a concept of two different graphs, like talking to each other and also of course, like from VIT's perspective, that's just like an unproven idea, so they're not rushing into implement it because like it's not standard and you know, that's fair. So I, I, and the other thing that's really important is routing. So like Vita doesn't really have any concepts of routing, uh, you know, from its perspective, there's just like one output, uh, and you could have, like you could layer it on, uh, with like a framework built on top of Vita, uh, but I don't know if it's sufficient, you know, so I think that is something, that is something we will see, and maybe Vita will evolve to be. sufficient. Yeah, it's a bit... I don't know, do you want to take this one or...?
 
JOE_SAVONA:
I'm not 100% sure. I think a lot of this comes down to we can, I don't see why we couldn't in theory make that work. But
 
DAN_ABRAMOV:
That
 
JOE_SAVONA:
from
 
DAN_ABRAMOV:
was
 
JOE_SAVONA:
a kind
 
DAN_ABRAMOV:
one
 
JOE_SAVONA:
of,
 
DAN_ABRAMOV:
of the earlier proposals actually.
 
JOE_SAVONA:
yeah,
 
DAN_ABRAMOV:
Like
 
JOE_SAVONA:
actually
 
DAN_ABRAMOV:
there was a proposal
 
JOE_SAVONA:
we had them
 
DAN_ABRAMOV:
exactly
 
JOE_SAVONA:
mixed.
 
DAN_ABRAMOV:
like
 
JOE_SAVONA:
Yeah.
 
DAN_ABRAMOV:
this in like 2019.
 
JOE_SAVONA:
Yeah. I think yeah, the original or even earlier, yeah. But I think part of it is also things like code review. Um, you know, you often in a code review, so, so there's basically making it harder to mess up for developers so that you know exactly what is a server component, you know, what, what code is exposed to the outside, you know, to the world and what is like, you know, safely, um, server only callable. I think it's pretty important. And when you think about it, it's, it's like, it kind of maybe seems silly at first, but think about code review where, okay, somebody's adding a new call to some like kind of sensitive function. and you just see like, you know, that the standard GitHub, you know, UI for like, for, or, or, you know, code review a UI for, for that change. Is that in a server, is that server or not? Right. Now I've got to go expand the whole file and like look upward and see what's that are used, you know, was there a use server or use client here when it's literally at a file level, it's a lot easier to check. Now, again, she still might have to go check like the very, very first line of the file or whatever, but it's a lot easier when it's at a, at a per file basis, uh, because you really don't want to have. you know, uh, functions that are, that are not meant to be exposed to the world accidentally exposed because of these types of mistakes. So I think there's, there's some kind of just balance here. Um, and also doing it at a, at a file level, I imagine makes it a lot easier as I can just imagine how I'd be implementing it right at a file level is probably a lot easier for the, for the bundler. Uh, so I think a bunch of considerations, there might be more that I'm missing, but, uh, those are the ones that kind of immediately come to mind.
 
DAN_ABRAMOV:
I would slightly,
 
CHARLES MAX_WOOD:
up.
 
DAN_ABRAMOV:
I think I would slightly like amend that. I think with. So I think we've kind of actually walked back on some of this thing, because like early on we were thinking of like, it's super important like in code review and so on. But I think that actually shifted because like in the current model, you actually can't tell like when you look at a component, because like not every client, not every component that executes on the client actually has the directive. So like the directive is not something that you... put to say like this component is, is a, is like runs on the client. It's really contextual. So like, if you're, if this component is imported from a tree, it's like already on the client, then it will act as a client component. And if it's like a component that's imported from a tree, that's like already on kind of like the module graph is already on the server and then by default, this is him to be on the server. And I think like the way our thinking has changed there is. It's really not so much about like, when you look at the file, it shouldn't really matter from like React perspective, like where does it run? Uh, you're, it's more like working with types because when you make a mistake, you get immediate feedback on like what the mistake is. So for example, like if you start with a component, it's just a function. It doesn't have any, you know, special features and you're like, I want to add some state to it, so you don't use client at the top at this moment. You just use state, you just add some state. And then, you know, if you don't get an, and you, like you get immediate feedback from your development server. Like I think in next JS case, they have like a TypeScript plugin that does it. So it's, it's the same kind of live feedback as you would get from TypeScript. Uh, so if you're already like in a client graph, then you don't need to do anything else, you're fine. If this component is in a server graph, uh, then it will say, hey, like this is a client feature, and it doesn't exist on the server. So you need to add the use client somewhere, but it doesn't mean in this component necessarily. It could be anywhere in the parent module graph. So for example, if you're like, you're like in this text field component, you just add a state to it, and it says like, you need to add the use client. Next actually tells you, you can add it to text field, or you can add it to like, uh, you know, checkout form, or you can add it to like checkout page. And maybe you're like, this checkout page is like mostly client side logic. I'm just going to slap you as client there. And then I don't think about this at all. Uh, or maybe this text field is used like in different places. And then sometimes you would add it. So there are these decisions and then like with server only logic, you know, if you kind of like have a database call, well, your bundler is just not going to let you. you know, import like MongoDB on the client, because it's not going to let you bundle it. But then the, the way, you know, if you don't want to leak secrets or you don't want to, you know, you don't want to expose a bunch of like, uh, things that, like, if there are things you never want to be bundled, we have a mechanism for this that is separate. It's, uh, it's a special package called server only. So if you just have like import server only, it's kind of like a poison pill. It's like. that will prevent it from ever getting into a client bundle and letting you ship that. And so that's what you put into your credentials file or any files where you're like, features you haven't released. That's one of the cool cases about server components is you can use it to gate features, which you want to not leak the fact that they exist. So as long as you only gate, you add server only so that you don't mess it up accidentally. and like put an import in the wrong place. Uh, but that is a poison pill. So I think like the, like these kinds of things together where you, but mostly you just, you want to add a feature. You just add it. And then if you get the feedback that actually you can't do it in this part of the tree, you're just going to rewire the tree a little bit to, you know, to resolve just like you do with types. When you like a different type of this thing is passed, you either fix the thing that's passed or you fix the type. It's kind of similar. But then the reason you can do this in the middle of the file has more to do with, um, like in a single file, you kind of execute, uh, you kind of expect, uh, like a single execution environment. So like you expect that you can share variables between them. And it gets like really confusing. If you like, you have a function call, like you have some variable and then you like, either you can't use it below or like, you don't know, you know, how, how that is going to be shared. I think. That is where it gets really confusing. And so we settled on files as the boundary. Yes, but not for what you would think it is because people would think that use server is, uh, so it's not, it's also like not in a released piece. So this is why you don't see it. Um, because again, like you might think use server means make this a server component, but again, that's not how it works. Use, if you think of like use client, that's not the marker of the component. It's a place in the module graph where you cut off the client tree. It's like a door from the server to the client. And so by this logic, what is use server? It's the door from the client to the server. So use server is the thing that lets you do mutations like in the future. It's like, it lets you import a function from the server and make it callable.
 
CHARLES MAX_WOOD:
Mm-hmm. Yep. So one thing that I'm wondering about with a lot of this is, does any of this stuff work with React Native? I mean, we're talking about components and things like that. A lot of the rendering happens on the phone, just like it happens on the web. Some people are using React Native web. So... Mm-hmm.
 
DAN_ABRAMOV:
Yeah. So we, we, we don't, uh, well, in, in principle, it is designed to work with any react renderer and, um, it's actually a little bit, uh, like server components are inspired by many technologies, but one of the inspirations is our internal native frameworks. So at Facebook, we have frameworks that we use for native apps, uh, that are like You know, we use react native for some parts. Uh, but actually like one of the things that is very limited for react native is that it doesn't let you drive the view logic from the server right now. And we have an existing solution that does. So we have an existing mobile framework that is similar to server components, but for native and it's not, it's not in JavaScript. Like it's, it's in hack. So PHP. Um, but it is, uh, it's, it's like part of why we know this, this architecture works because that's actually what we use for a lot of our, uh, native code and the, um, like we would like to extend this to react native. We're not working on this right now, but kind of in the, in the big model, of course, like we'd like, you know, we act to let you target all platforms without compromising on like, uh, you know, like the same, I feel like there's, there's this. uh, react ethos of like use each platform for what it's best at instead of the lowest column common denominator. And so this was always this idea behind react native is like, we don't just build a cross platform thing where you, you know, you have like a component that looks the same way on every platform, but it's not actually using the platform features. No, we want to give you like a way to use, you know, iOS. Like you get all features like iOS text field, like Android is like Android text field. Selection works natively the same way that it works in native apps. And I think server components kind of applies the same idea to the split between client and server, because it's like, you don't run the same code everywhere.
 
CHARLES MAX_WOOD:
Mm-hmm.
 
DAN_ABRAMOV:
It's like, you run the things that work best on the server on the server, run the thing that worked best on the client on the client, and we just give you like a way to combine them. And we'd like to bring that React Native as well.
 
CHARLES MAX_WOOD:
Yeah, that sounds about right. I mean, as far as things go, right? I mean, sometimes you can render some of the same things across React and React Native and sometimes you can't. And so, yeah, I mean, the idea that, yeah, I put a server rendered thing, you know, component up there. And, you know, if I have a proper renderer on my backend that can turn it into whatever the Android or iPhone app uses. Yeah, there's no reason why it couldn't do the same kinds of things. It depends. I've seen some things you can get away with, but yeah, that's usually actually in a WebView, not in a NativeView.
 
DAN_ABRAMOV:
It's tricky, but I think the part that is disallowed is like kind of hard swapping native code, right? But I think the boundary between like, what does it mean to render on the server? Like you don't add any new native components with behaviors that Apple can't check. It's just
 
CHARLES MAX_WOOD:
Right.
 
DAN_ABRAMOV:
orchestration of the components that are already on your device. And you think like, you know, There's this gap between like, I'm returning some data or like, I'm just returning the UI tree of like process data. It's, it's not really such a big leap. It's just, you do a bit more work ahead of time.
 
CHARLES MAX_WOOD:
Yeah, well, and
 
DAN_ABRAMOV:
Don't take my words
 
CHARLES MAX_WOOD:
yeah, some
 
DAN_ABRAMOV:
as,
 
CHARLES MAX_WOOD:
of that remains
 
DAN_ABRAMOV:
yeah,
 
CHARLES MAX_WOOD:
to be seen. Yeah.
 
DAN_ABRAMOV:
you need to invite some people from Apple and maybe they will tell you.
 
CHARLES MAX_WOOD:
All right, well, I think we're getting to the point where people actually need to pull off. We kind of went over a bit. And I think somebody just tried to come in because Xfinity is probably here to look at my internet. So let's go ahead and do some picks real quick. Let's have Tejas start us off.
 
TEJAS_KUMAR:
Awesome. Do you mind explaining what picks are for?
 
CHARLES MAX_WOOD:
It's just shout outs about whatever, yeah. Dan can go first. Dan, show us how it's done.
 
TEJAS_KUMAR:
Great.
 
CHARLES MAX_WOOD:
Awesome. Tejas, go ahead.
 
TEJAS_KUMAR:
Thanks for teaching me that, Dan. So about conferences, huge pick. I was just at React Miami, in case you can't tell, and definitely a huge pick. A lot of people have been complaining that a lot of the talks weren't about React, but I think these people kind of missed the point that React is an ecosystem more than just a library. And so there were some fantastic talks about CSS and... and their applications for our weather apps. And I actually kind of liked that it was so community driven and focused. It was a great time. And also the sightseeing in Miami and so on was very nice. So plus one to that. We've also been watching Beef, phenomenal show. I have two picks, really. Shout outs that I think are worth appreciating. Blue Sky, I got access today. And it's tremendous, the capabilities of this quote unquote alpha. I don't honestly think it's an alpha. This is the best alpha I've ever used in my life. Um, the engineering quality, the way things just work reliably, some, some parts are even more stable than twitter.com. Um, so absolutely love blue sky. Um, and then the other pick that I had is a, a beautiful book, um, that has just helped me a lot because, um, I, you know, I, I, um, I, I can do have. interest in mental health psychology and as navigating my own mental health, but also things like motivation and addiction and things like that. And there's an awesome book called The Molecule of More that has just been fantastic and understanding kind of health and how we, how we find motivation, where does it even come from and things like that. So The Molecule of More, a fantastic book that I've kind of been exposed to lately and has just been changing a lot of the ways I've been. It's getting that critical mass. And their head of developer relations just opened her account. And I'm already talking about how can we get an API? Because I would love to create some type of open source. I post to Twitter and then automatically goes to Blue Sky. And at some point, I can just reverse and post to Blue Sky. Anyway, I won't take up too much time. Those are my picks. I will I guess we pass it around I'd pass it to Joe
 
CHARLES MAX_WOOD:
Yeah. Well, I need to go next because I need to go see if my kids trying to walk in here were
 
JOE_SAVONA:
Go for it.
 
CHARLES MAX_WOOD:
the Xfinity technician before he runs away. Um, real quick, I'm going to throw out a couple of picks. My may or my board game pick this week is Iberian gauge. Um, it's another one of the train games, kind of like Irish gauge, which I picked before. And, uh, yeah, it's a little different cause you buy stock in the company and then you spend the company's money to build the trains. And yeah, then you kind of tally it out at the end. So it's not a terribly complicated game, but it does have some unique gameplay elements to it that I really liked. So I'm gonna get the board game geek rating here. And then I'm also just gonna shout out, yeah, it's a weight of 2.32, so easy casual game for people. The other thing I'm going to just shout out about is that I am doing the game dev Meetups on Thursday mornings at 9 a.m. Mountain time. So that should be doable for people in Europe as well And yeah, we're just working through the course and building games and then we'll see where it goes from there So those are my picks Dan. Why don't you go next?
 
DAN_ABRAMOV:
Sure. Yeah, yeah. Sure. Yeah, actually, yeah, I wasn't sure what the what the put in the beginning, but now now I have a better idea. So also shout out to beef we started watching my wife and I and I want to give a shout out to another show called White Lotus. Because we watched that one before. And we were really like, we wanted to have something that has like a similar, I guess, like mood. And I think it has some, yeah, like it has this vibe of like, you kind of, like, you don't find characters, like, you don't necessarily like find them very nice, but you do, you really like feel for them and you kind of see each, like, they all have a point, like they all have some kind of perspective. And I think that like, if, you know, both White Lawless and Biv kind of have that in them. Um, so we really appreciate that. Um, also another shout out to blue sky. One thing I want to specifically call out there is if it has this feeling that like they know what they're doing, which I don't get with Twitter anymore. Uh, and specifically like one of the first things that I was like, wow, that's, that's, that's such an obvious decision in retrospect, but your blue sky handle is a, uh, it's kind of like a domain. Like you can have a, uh, you can, if you own a domain, you just verify it and that becomes your handle. And it's just so obvious in retrospect that this is how, you know, we already have a system for verification. It's not like pay, you know, seven, like $8 to Elon Musk. It's like pay Elon, pay $8 to go daddy. But I mean, it's just nice that it's portable. And so, and like, A lot of people already have it. And that was like a design decision that I was like, oh, it seems like, you know, they're doing something that, that actually like has some sense. And then the UI is actually nice. And, uh, I mean, they're, they're still like working through a bunch of stuff. Um, but yeah, I'm pretty excited about the build, the people building it. And yeah, shout out to blue sky. Uh, I want to give shout out to Terrence Tao, who's like a. famous mathematician. But he wrote a book that I've been working through for the past like maybe a year and a half. I'm still in chapter five, so I'm like in the beginning, but it's called Analysis. And if you ever wanted to kind of learn math from first principles from scratch, you know, without assuming any university education, anything like this, in a way that's rigorous, and that kind of just like explains how math works almost from like a program and perspective where, you know, if it isn't written, then it doesn't work. Uh, so this books, like this book gets you from, uh, like axioms that are necessary to establish even like, you know, zero is a number, like one is a number and so on. And then you're forced to prove literally everything. So like there are exercises, like you have to prove like a plus B equals B plus A. Until you prove it, you can't use it. And so I've been doing this like for the past year and a half and it's, I do this kind of for fun. So I'm, I think I've done like maybe a hundred exercises so far. Uh, but it's, it's just a really nice way to understand how mathematics actually works. Um, and I think maybe, maybe that's, uh, I think that's it for my picks. So, uh, I'm going to. Yeah, it is.
 
JOE_SAVONA:
That's cool.
 
CHARLES MAX_WOOD:
Sounds like fun though. All right, Joe,
 
DAN_ABRAMOV:
It is.
 
CHARLES MAX_WOOD:
what are your picks?
 
JOE_SAVONA:
So I've been playing, so you mentioned board games. So Dragonimo has been a hit. So I have a six-year-old and a two-year-old. And so it's really hard to find a game that the three of us or the four of us, if my wife plays, can actually play together because the two-year-old can't, she just grabs things and destroys. But that game is just simple enough that she can, with a little bit of help, actually place tiles and she loves getting dragons. And like picking, you know, getting to pick the eggs. So it's like perfect for if you have young kids and are looking for a board game, that's a fun one. Tragatomo. And then I've been learning guitar and trying to wrap my head around like the basics of music theory and like scales and stuff. It's just been a very different way of thinking, totally different from programming. So it's a very nice like way to just escape all the stuff that I'm usually thinking about and just like, just kind of, it's almost like meditative. Like, just like me, guitar, music in front of me and trying to make it. trying to like actually replicate what I see there. So that's been a really fun experience. That's all I got.
 
CHARLES MAX_WOOD:
That one's not actually on Board Game Geek. Usually I can find them on there and tell people about how it is, but yeah, it definitely looks like it's a kid's game. So.
 
JOE_SAVONA:
Yeah.
 
CHARLES MAX_WOOD:
Yeah, there are a lot of terrific kids games. I've picked some of them on the shows too, so if you're interested, you can actually just DM me on Twitter or something.
 
JOE_SAVONA:
Oh cool, yeah, we'll
 
CHARLES MAX_WOOD:
I can
 
JOE_SAVONA:
do.
 
CHARLES MAX_WOOD:
hand you a whole bunch.
 
JOE_SAVONA:
Awesome.
 
CHARLES MAX_WOOD:
But yeah,
 
JOE_SAVONA:
Thanks.
 
CHARLES MAX_WOOD:
cool. Well, thanks for coming guys. This was super awesome.
 
JOE_SAVONA:
Yeah, this is great.
 
CHARLES MAX_WOOD:
And
 
JOE_SAVONA:
Thanks for having us.
 
CHARLES MAX_WOOD:
yeah,
 
DAN_ABRAMOV:
Thank you for inviting.
 
CHARLES MAX_WOOD:
we'll wrap it up here. Till next time folks, Max out.