React Server Components: Part 2- JSJ 583
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.
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
Picks
- Charles - Iberian Gauge
- Dan Abramov - Watch BEEF | Netflix Official Site
- Dan Abramov - The White Lotus
- Dan Shappir - Go speak at conferences
- Joe - Diagonals
- Tejas - Watch BEEF | Netflix Official Site
- Tejas - Bluesky
- Tejas - The Molecule of More
Transcript
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.
React Server Components: Part 2- JSJ 583
0:00
Playback Speed: