Conf42 JavaScript 2023 - Online

React Server Components: A Deep Dive

Video size:

Abstract

React Server Components have been a trending and often misunderstood concept. In this talk, we will look under the hood of Server Components and understand how they work and when to use them.

Summary

  • Tejas Kumar: Today we're going to talk about react server components. We'll explore the architecture of react, including server components and how react was ten years ago, how it is today and how it might be tomorrow. This is going to be a really fun session and I'm really excited about it.
  • The thing about react is it's multiple things. It is a library, but above and beyond library, it's an architecture as well. Over time the tooling has matured so much that we forget it even exists today. But react server components introduces a whole new wave of tooling.
  • React server components is multiple things. It's a way of rendering and orchestrating applications and servers. That includes the server at every level of the virtual DoM. Tremendous benefits for data fetching performance and user experience.
  • A dog site is just a client app. We need to benefit from a little bit of server rendering. Let's start by adding a server. And then we'll add server components to the server. Next video will be something we did in the last video on Nextjs.
  • We can use server components to turn our components into async components. How do we convert promises and other things into react elements that we can then send over the wire, aka server components?
  • We need to account for both cases where type is a string and wheretype is a function. Anything that can consume the server component's output. Can take this big JSX tree that we've made and turn it into HTML. Let's try.
  • We need react on the client side. How do we do that? Well, we already have this RSC output, the server component output that the server side understands. But symbols don't go over the network when they're serialized. We need to somehow swap out the symbol for something the client can understand.
  • So we have server components and we have them working on the client side. On the server side, we implemented an IRC server to turn them into this is how server components work. It takes a react JSX tree, turns it into an object, serializes it, sends it over the network, and then react.
  • We looked at the interplay between react server components, client side rendering, and server side rendering. Are server components better than client components? Absolutely not. Client components have their place, server components have its place, and it's really on us to weave them together.
  • You want to fetch data as early as possible, before any state is set. The earlier you fetch data, the better your chances are of adopting server components. Number two is you'd want to reconsider your interaction boundaries. I think these three tools will help you really adopt server Components.
  • Dan Abramov: The react community has had some issues lately with the discourse getting more and more hostile. If you're enjoying these videos, please subscribe to the channel, hit the bell and drop a like. Also, if you found the content useful, share it on social media.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Tejas Kumar and I'm a developer relations consultant. What that means is I work with developer oriented companies, companies in the past and present, including companies like liveblocks, Crab Nebula, Opensourced, Versailles, et cetera, do their best devrel work and reach developers effectively. To do that I need to be in touch with the industry and kind of be up to date with some of the things we're talking about. And that's why we're doing this video today. Today we're going to talk about react server components. It's going to be really exciting. We'll start from really first principles, thinking about what even is React really how was react in its early days back when the development tooling wasn't as mature like today we just npxvit but in the past we had to write webpack configs and so on. And I feel like server components is in that area where the tooling hasn't yet caught up. But it stands to be a fundamental shift. We'll explore the architecture of react, including server components and how react was ten years ago, how it is today and how it might be tomorrow. From there we'll dive into react server components themselves and we'll implement server components from scratch. From first principles we'll follow the guide that Dan Abramov wrote on GitHub. There's a link to that under the like button. Once we identify that, we look at some more architecture diagrams of how data flows. Well, we'll look at them. I mean we'll just examine them, we'll discuss them, we'll verbally look at them, we'll talk a little bit about how they work in terms of data flow and we'll ask the question is server components for everybody? Finally, we'll talk about how you can increase your adaptability, as it were, of server components, making sure you're in a good spot to make the shift if and when you choose. And finally, we'll highlight some community notes. This is going to be a really fun session and I'm really excited about it. But before we get started, I want to emphasize that this video and this channel is separate to my consultancy work and is really just part of my willingness and joy and effort in spreading knowledge to developer communities and helping us do our best work. And in keeping with that, I'd like to thank the sponsor of this video that makes all this possible. That sponsor is Crabnebula Dev. Crab Nebula is a great platform that deploys. Their mission is to make shipping, distributing and packaging applications securely and instantly worldwide, much like how versel has this git push and then your website is instantly live everywhere. Crab Nebula's platform aims to offer something similar where you get push and your native or mobile application is everywhere. Native desktop or mobile is everywhere instantly. This is from the team that built the towery project and I'm very excited about the project. So if you are interested as well, I'd encourage you. There's a link under the like button. Crabnebula Dev is who they are and what they're after. With that, let's get into server components. Let's talk about server components, and I want to talk about it by asking you a question. What is react to you? Like when I say react, what comes to your mind? It could be multiple things. A UI for building sorry, a library for building user interfaces. A framework for building many things. In fact, in the previous video where we built a makeshift next js from scratch, if you missed that, I'll leave a link up there. We identified some of this terminology, library framework, et cetera, and disambiguated a little bit. The thing about react is it's multiple things. It is a library, but above and beyond library, it's an architecture as well. And follow me a little bit, because react, when it started ten years ago, introduced JSX and with JSX introduced a way of shipping and building user interfaces. The formula view equals function of state and really championing what was called the flux architecture of one way data flow. Data starts at the top and kind of makes its way down. In that way. You can think of react as an architecture or a take on an architecture. That is the flux architecture. You can also think of react as an architecture in terms of the tooling that was in and around react at the time that wasn't widely used before React. Frankly, we did use gulp and grunt and things to bundle, but we never really had to use transpilers mainstream. But with the advent of JSX, we ended up adding more tools to our chain. Those tools, of course, were not as well developed as they are today because they weren't as widely used and it required some assembly, some assembly required. I remember myself writing a few webpack configs by hand and learning the difference between things like Babel, preset, envelope, preset, react, et cetera. I'm sure many of you have that also context, and if you do, let me know in the comments. But architecturally, there was a lot of stuff going on, a lot of tools that needed to be assembled the right way so you could do react. And this was one of the early criticisms, and to this day is some of the criticism. Right? A lot of the view community says you can just include view from a CDN over script tag. Boom, you have a view app, you don't need any tooling. So react does have architectural elements as well in terms of tooling. However, over time the tooling has matured so much that we forget it even exists today. I'm guilty of this myself. I'll create a basic client side react app and I'll do something like NPX vite and it will just work. And that's amazing. But I often don't recognize it as amazing and just take it for granted. Right? But the tooling has matured for client side and potentially server side react. And this is important as we dive into server components. So react ten years ago, had NPM install, you'd have to do react React Dom, but also Babel webpack, webpack plugin, Babel Babel plugin, React Babel preset, and we had to do all these things. And today it's NPM install react NPxvit done. And tomorrow it might be NPM install react React Dom next. And that's it. And next, the framework would handle this for you, including adding typescript and things as you need. So that's where we were, that's where we are, and that's where we're going. However, react server components introduces a whole new wave of tooling, next generation tooling that doesn't even exist in our session together, we're going to talk about why and how it does that and where we might be once the tooling catches up. But before we get into that, I want to quickly talk about what even is react server components or RSC. And just like we've talked about what React is, it is indeed a library. React server components is multiple things. Some would say that it's basically the react team's shipping suspense for data fetching. Really. I think it is that it is also a way to execute, I mean, mechanistically, react server components is a way to execute components on the server and on the client, but specifically the server, and then send the output of those components to the client and let the client do its job. The benefit of this, of course, is smaller bundle sizes, better data fetching, et cetera. We'll get into that, but it is that for sure. Above and beyond that, I think react server components, just like React, is an architecture. It is an architecture. It's a way of rendering and orchestrating applications and servers. And I do mean servers plural. We'll get into that such that your applications are performant and have better user experience. If we could write a long sentence about what react server components are, we would say react server components is an architecture built on next generation tooling that is still experimental and not yet production ready. That requires rethinking. React to go from client first to hybrid or server first, depending on who you ask. That includes the server at every level of the virtual DoM, so it's not currently as in before react server components, you could server render a page, but then all the components in the page are still client components. But with server components you can server render just like a single element, a card, a blog post, while the rest, maybe its parent, could be a client, et cetera. So you can really include the server where and when you need. For example, if you have a bulky thing like a date formatter or a markdown for something like that, you could then turn that into a server component. Again, we'll look at practically how we do that in a minute. So that includes the server at every level of the Dom. That unlocks tremendous benefits of which we'll explore. And finally, tremendous benefits for data fetching performance user experience. Data fetching performance user experience. So that's the sentence. I'll say it one more time. React Server components is an architecture built on next generation tooling that is still experimental and not production ready that requires rethinking. React that includes the server at every level of virtual Dom unlocking. Tremendous benefits for data fetching performance and user experience. Now I've reached the point in the video where I kind of realize, okay, I am talking too much and I'm starting to get bored. So let's create something with react server components together and then we'll talk about what we did and recap from there. To do that, we're going to go over to the computer. I've got this application called my dog site and you can see there's a list of dog breeds. If you've been part of the channel for any amount of time, this shouldn't surprise you. I really like these dog breed apps. What we have is a rotating doggo. Here we have a field for your name and we have server time. Okay, I don't know why I just did that. And indeed it navigates. So when you click on briard, you go see the briard. This once again is just a client app. So we're running NPX VT in case you're wondering. And if we look at the source code, we'll understand how it works. But what I want to highlight here is the navigation. There is no client router. The navigation is fully like multi page application style. So we're actually doing a full page reload every time. And you can tell by my state here being blown away tagis. And if I change the page, it goes away. And also this thing, as I navigate, resets its animation. So if I click here, it jumps. You see that it doesn't keep going in a smooth circle. That's kind of annoying. Okay, so let's look at the code now. So we have an index TSX. And what we're doing here is we get the breed and we communicate breed over search params. So that's why we get the breed and we hydrate the document with the layout. And we have a little basic router, meaning if the path matches list, we show list. Otherwise we show the detail page. Okay. And we pass in the breed. That's what's happening here. Let's look at our layout component. Our layout component is exactly what you'd expect. It's a layout. It has HTML head, everything here. It has our little doggo has the title with a link back to the root and input, and so on little date here. Let's go look at the list component. The list has some use state. So all of these are held in state. The breeds and the images you kind of see in the background are held in state. We fetch. Let me just give you some more space here. We fetch the dog API's list and then we get it. And this is the array. This is the array of breeds. But once we have the array of breeds, remove that. Once we have the array of breeds, we then also get an array of images per breed. And we return both of them breeds and images, and then we set them. Okay, it's a very long, very maybe inefficient way to do it, but here we are. And then we have some markup. So welcome to my dog site, P and Uls. Similarly, if we go into the detail page, what we'll see is, let's go to detail. It's similar. So we get the image. Adorable. We get the image and then set the image and so on. Okay, so there's of course some problems with this. For example, we are fetching only on the client side. Not only are we fetching only on the client side, we're rendering only on the client side. So if I come back here and view source, there's nothing, right? So we're fetching and rendering on the client side. And this isn't really ideal for search engine optimism, et cetera. We talked about this in the previous video on nextjs, and where we made a makeshift nextjs from scratch. I'll put a link at the top if you missed it. But step one, let's maybe add a server. Again, we're not going to do the whole deal, but we do need to benefit from a little bit of server rendering. So let's start wet our toes a little bit by adding a server. And then we'll add server components to the server. So if you've been around for the last video to add a server, we have server TSX. It's an empty file. We will import react from react. We'll import exprs from Exprs, we'll import render to string. We're using render to string just for simplicity you should be using something stream based. And then we'll start our, start our application. So we'll say const app is exprs and we'll listen to the public. We'll use the disk directory to get static assets. This is like things like CSS and images and stuff. Then we'll get on the root but we'll call it path here. And lastly we'll listen on port 3000 and we'll say server is listening on port 3000. Fantastic. Okay, so now we need to dynamically load, we need path based routing. And this is something, again this is something we did in the last video on Nextjs. The link will be in the description and I've put it up there a few times, path based routing. Let's go. So what we're going to do is we have two pages detail and list and they come along the query parameter path. So we'll turn this into an async function. And what we'll do is we'll say const page is we'll do a dynamic import and we'll join, I need to import join, don't I join? We'll join the current working directory with disk pages and the path just like that. And then when we have it we'll say const components is the default export. And we'll say the, we can just say the HTML is we render the layout and the component and we'll res end with the HTML. This should give us what we want, I think. Of course we also can do props. So let's just wrap props in the rec query save. So now we are server rendering a little bit also with path based stuff. Let's see what happens. So if we come here we'll NPM run build. If I can type, we'll start that server and it should start. And now let's go visit localhost 3000 list. Great, it works. But we're not fetching data and that's because we don't have react on the client side. So we can easily fix that by adding maybe here script sources client and we'll rebuild the server. Okay, cool, it works. We have server rendering. But once again we have server rendering without data and notice the state is still blown away. So if I go here, yeah, it's not really good. Also we have some server rendering. For example, we have RSC thingy and stuff, but we don't have the list of dog breeds, we don't have the data. So our server rendering is a bit of a waste. Okay, now this is where in the last video we did some nextjs stuff with get serverside props. This is our opportunity to refactor this, to use server components and turn our components into async components. Okay, so let's do that now. So if we go to list, let's start with list. It would be great if we remove all this nonsense and just turn it into a nice async component and fetch. So let's get rid of this and we'll say const breeds is we just want this up to here. That's it. And then we can say const images is this right? And we can get rid of all of this noise. We need to close this bracket. Promise. All breeds map. This looks good. I don't know why you're complaining. What we need to await. Nice. I love typescript. Okay, so look at that. We simplified it a lot. And best of all, look at me. Best of all, watch this. We can do this. Amazing. Okay, so now we have an async component and logically it should work. Let's try, this is, by the way, a server components. This is a server component, an async component that can do cool data fetching stuff that you trust because it's on the server. Okay, but let's see if it'll run. So we'll save this, go here, kill our server, restart our server and everything and. Okay, we have a typescript issue because it doesn't know that components can be async. That's fine, we'll just say this is any for now, not a big deal. Okay, let's go back, reload and a massive crash. Because look at the error. Objects are not valid as a react child found object, promise. What it needs is a react element. So we need some way to turn objects and promises into what react recognizes as elements. How do we do that? Well, react has a special indicator on its elements, dollar, dollar type of, and its value is a symbol for react element. This is how it knows it's an element. So we need to take this promise somehow, await it, turn it into a react element and send it to the client. This is what server components do. A lot of people say they send HTML to the client. They don't do that. They send react elements, literally javascript objects, react elements to the client and then react on the client side can work with it. That's how server components work. You need to pay attention to that. So how do we go about this? How do we go about converting this promise and other things into react elements that we can then send over the wire, aka server components? Well, we need to start by transforming JSX into this tree. Okay, so let's do that through some functions. So if we come back to the code, what we're going to need on the server side is some type of function called like const, turn JSX into client object and we get JSX. And here we need to process this JSX somehow. We need to handle it. And JSX can be many things. What do I mean by JSX? I mean this. So it's an element here it's text here it could be a number, et cetera. So we need to basically just do a massive like if or switch and handle the different things JSX can be and process them. Okay, so let's do that. So what we're going to do is we'll start simple. If it doesn't exist, we'll return null, which is a valid react element type or a thing that react understands. If it's a string or a number or a boolean includes type of JSX, then we just return it as it is. Great. If it's an array, good. Thank you copilot, we'll return that. But we want this to be async because we want to await those things. So we'll just await promise all instead. Okay, this is good. Next if it's an object. Now it gets interesting because all react elements are objects, but not all objects are react elements. So how can we make sure that this is not just an object but an object that is a react element? We check the type off property. So if JSX dollar dollar typeoff equals the symbol for react element, then we need to do some things. Now a react element looks like this. So you have tag or type, which is either a div, you have props and you have children. If this is hard to grok, there's a video on YouTube of me teaching react from first principles called deconstructing react. I'll put a link up there and under the like button. But this is basically what your JSX becomes. It becomes type props, children. The thing is, type could be a string if it's a built in components like a div, or it could be someone else's react component like this, right? So you don't know what it is. And we need to account for both cases where type is a string and where type is a function. So we'll do that. So we'll say if JSX type is a string, that's actually not how we do that. We do type of string, then we do something. And also if it's a function, we do something else function. So let's handle the string case first. If it's a string case, we just need to return whatever it is, but also work with its props. Specifically, we need to process its props because its props might be children. So we need to turn those also into a client object. So that's done. Now we handle the function case. If it's a function, we get its JS. Like all react components that are functions like this return more JSX. So we need this stuff. We need the JSX. So we'll say const components is the type, is the function. And we have props, of course, is JSX props. We say const rendered thing is, we just call component with props. Now keep in mind, components can be async, remember? So we'll await that. And what do we return? We further recursively process those things. So rendered thing. We're just like recursively processing all these things until they're objects. We're going all the way down. Okay, fantastic. Lastly, if we're just doing this on props, and the props are not JSX, we need to handle that case as well. In this case, props are always an object. So if it's still an object, we'll come here and we'll say the keys. Well, we don't want keys, we want entries. Really, we want entries. And what we'll do is we'll say const processed entries is entries map. And we get here prop and value. And we'll just return prop and await. Exactly. And we'll process the value. Now, we can't await because this is not async. So we'll turn this into an async, turn this into an async function here. But now this needs to be promise Ald and it needs to be awaited. And lastly we can return object from entry. So we're just getting back an object again of processed entries. This looks good. So we have this thing that takes a bunch of JSX like this and turns it into a big react Javascript object. It's fully serialized, except functions aren't serializable. Maybe you won't get to that in this video, maybe the next one. But we've serialized into a big object and now if we send that object from the server to the client, then react can probably render it and do its job. Let's try. One thing to note is that client in the context of server components means anything that can consume the server component's output. That is the big JSX tree. You know what else can consume the server component's output outside of react on the client side, react on the server side, it can take this big JSX tree that we've made and turn it into HTML. So let's do that. But first let's see what we just did. So what I want to do is instead of render to string, we'll say const client JSX and we'll await turn JSX into client object and we'll just copy this into that instead. And we'll render this to string. But I want to also see, let's just for fun show what we serialized. So we'll do this and we'll run the server again. Hopefully it works good. And we'll go to port 3000 and what we'll see is this is what we get, a big tree. Let's look at the raw data. So it's just a big thing where it's type HTML, it's just a bunch of react. So yeah, it's just like a bunch of elements. So HTML has children, head, meta, et cetera, and then body. So it's just a big thing with type, props, et cetera. Just a big object. Okay, so anyway, let's come back here and take this object and under it to a string and then serve the client the string that this object becomes. So we'll kill the server again, restart it, and it's instantly replaced, notice. And that's because we're using react on the client side. So if we get rid of this for now, we'll restart the server and we should have, there we go. We have server rendered server components because the server consumes the RSCs and gives you output. So this is great. We have working server components. Does it work on the sub page? It doesn't. Probably for the same reason we need to go and update breed the detail page as well. So instead of all of this we'll say equals await. Say image URL alone equals await fetch. This looks good. And instead of calling set image URL, we'll just return this. Perfect. And again we can get rid of use effect, which is always nice. Okay, perfect. That's it. And this is async and we need to tell typescript not to worry. Okay, do this again. So now the detail page is also server rendered with server components and we can navigate. This is pretty nice. So we have it, but we don't have react on the client side. And it kind of defeats the point of react because what react does is it helps you persist state across things. It helps you have single page application like behavior. What I mean by that is this. Have a look. So if we come here and we enter some state, my name is Tejas, this is also spinning. If I navigate, I shouldn't lose that state. It should feel like a cohesive app experience. I think we can amplify this further by changing the background color. So we'll say the background color if the rec param path is list is white, otherwise the background color is black. Right. It should be a smooth transition. It shouldn't just jump like a legacy old website. So look, yuck. That's very abrupt. And also my state goes away. Not good. We can solve this using react on the client side. That's literally react on the client side's job. That's what we've used react for, for, I was going to say millions of years, but for the last ten years. So we need react on the client side. How do we do that? Well, we already have this RSC output, the server component output that the server side understands. We just need to get the client side to understand it. Let's look at how we do that. So if we look at our client side app calling hydrate root and we're using the components here, we need to use the RSC output here. So what we can do is we can fetch the RSC output, but that will introduce another network waterfall. Since we're already rendering the output here and including a script tag, let's include that script tag again. What we can do is just inline the RSC output, literally because we have it right. So we'll say we'll res end with HTML, but we'll also add script and we'll just inline the RSC output. So we'll say window RSC output is and we'll json stringify the client JSX look done. And while we're at it, we can also just load react just like this. Save. Did I change anything here? I don't think I did. Okay, save. Great, let's take a look. So I'll kill the server again, start it, reload. And it died. It died really badly because my network died. That's interesting. I'm being rate limited. Let's try this again. Okay, cool dog, Dusty. It was working, but our application crashes. And if we look at the console, lots of issues. Text content didn't match, objects are not. So it's the same thing. We found object promise, et cetera. It's just not really doing its job. And that's because we're not swapping the output here. So we'll do window dot since we're adding it on the server side, window RSC output instead of the components we import, and we can get rid of all the imports here. We can ts ignore this because we know it's there. Okay, so let's restart the server. Okay, so now we've gone from bad to worse, right? Because there's a lot failed to execute a pen child. Oh my gosh, oh my gosh, oh my gosh. There's just a lot of things going wrong. The reason for this is because what we're sending in the inline over the network isn't actually react elements anymore. Keep in mind, the identifier of something being a react element is the dollar dollar type of the symbol. But symbols don't go over the network when they're serialized. So in our JSON stringify off this tree, we need to somehow swap out the symbol for something the client can understand such that the client brings back the symbol. If this sounds a little bit weird, let's just write code, I'm sure it'll make sense. So what we'll do is we'll go back to the server, and instead of this JSon stringify, we need a function called Const sanitize JSON, and it gets the key and a value from the JSON object. And if the value is symbol four, this is the identifier of react elements. If it's that, notice we use that also here, right? So if it's a react element, we will return a new value, which is just the dollar sign. Otherwise we'll return and this could be anything. By the way, it doesn't matter otherwise we'll just return the value, sanitize JSon so we'll inline that instead. Similarly, on the client side, now we need to desanitize JSON or revive JSon. So we'll say revive JSON and if the value is the dollar sign we just basically do the other thing. We swap it and here we'll JSon parse the RSC output with the revive JSON function. Good. The second argument here just like swaps out values for other values, save that, restart the dev server and now there we go, we have it. We have react on the client side we have server components working, but unfortunately we're still blowing away the state. Look at this state and I click clumber and it goes away. It's not ideal. The final thing we have to do is override link clicks and use our own navigation client side navigation once client side react takes over and this will help persist the state and have a nice shared layout and give you a nice experience while also giving you multi page application performance. It gives you single page application user experience. Okay, how do we do that? This isn't going to take very long. Let's go. So what we're going to do is we will add an event listener on the window. This is react also does this, they wrap event listeners. And what we want to do, let's just say this is any, because I don't know what it is. And we'll say if e target tag name is not, if it's not an anchor link, then we don't do anything. Otherwise we prevent default. We maybe push state. So we'll push this onto the history stack and we'll navigate to e target href but of course this function doesn't exist, so let's define it. Navigate. You may recognize this from nextjs or something too, but anyway we'll navigate to where do we navigate to and what do we want to do? What we need to do now, whatever that is. We're not doing that. What we need to do now is fetch the JSX, the react tree for the next page and then rerender with that new output. Really, that's what we need to do. We need to fetch just the JSX tree and then rerender the page. We don't do a full navigation, so how do we do that? Well, in terms of pseudocode, we need to do const next page is await. So this is now async await fetch we'll say two and we'll maybe add a query param JSX true. And what we'll do is we'll get this as text and then what we'll do with that text is we'll say JSon parse the JSX using our revived JSON function. So now we have the next page and we just need to root. Keep in mind, we get the root from hydrate root, so root render the next page. That's it done. Fantastic. So everything's defined. Now we just need to add this to our server. So if we go to our server, we're already getting the JSON tree. So we'll say if rec query JSX is true, then we just return this, right? We just return the JSON string. That's it. Okay, we don't even need to return it, we just send it and do that. Perfect. This looks good. Kill it, start it again and reload. Okay, let's test. So now, logically, if I type something hello, this should persist between navigations. Indeed it does. Not only does it do that, the background color fades, it smoothly transitions instead of an abrupt change, and the good doggo never loses its rotating status. It's always continuous. So we have server components and we have them working on the client side. On the server side, we implemented an IRC server to turn them into this is how server components work. It takes a react JSX tree, turns it into an object, serializes it, sends it over the network, and then react. Picks it up on the client side and does what react does, which is make really nice updates that I hope was helpful. And with that, let's continue. So what we looked at was the interplay between react server components, client side rendering, and server side rendering. Client side rendering of course is pretty bad because you need to first download the Javascript bundle. It needs to parse, execute, run, and then if you need data, it will go fetch data. There's lots of waterfall. It's not ideal. Also, you don't ship a lot of markup to your users or search engines. It's highly problematic. The solution then is server side rendering. Indeed, that's what we did, although when it came to data fetching we server side rendered some parts, but we had like holes where the data was, which is what led us to require react server components. That fetches data nicely, turns it into a JSX tree, and feeds it into a client. A client can be a server that then sends a string to another client, or a client can be a browser client in the context of RC means both things. Let's talk lastly about how it actually works. We saw how it works in that sense, but I think the value is being able to have any element, any level in the tree, be async, so long as there's no interactivity there and you can fetch data wherever you want. So then the question becomes, okay, so are server components better than client components? Like if I use client, should I feel bad? Absolutely not. Client components have their place, server components have their place, and it's really on us to weave them together. Well, in keeping with that, I think it makes sense to draw this boundary between server and client components really well using adoption principles. I think if we talk about how we can gradually adopt server components, or how we can approach adopting server components, then we're in a better place to identify where client components fit in and where server components fit in. So with that, I'd like to give you three tools that you can use in moving towards server components. This will not help you go to server components overnight, but will put you in a good spot to adopt them once they're ready and stable. Number one is you want to fetch data early. You want to fetch data as early as possible, before any state is set. Before we talked about it also in the next JS video, again, link under the like button. You want to fetch data even at the server level, like before. And the earlier you fetch data, the better your chances are of adopting server components. Number two is you'd want to reconsider your interaction boundaries. What I mean by that is we usually have interactive pieces of our reactories currently that are interleaved with non interactive pieces. Consider like an application, like a blog post. You have the title, you have a paragraph and you have a little button. And from the most code bases I've seen, all of these are within a card. So you have card header, content button and all of these are one file because it's relatively short. The problem there is that the interaction boundary is only at the button. So the button in this case needs to be its own components. So you need to have a card, a header, a title and then a button not be part of this card component or the title and content, but be its own component. Meaning the onclick handler isn't a separate file basically. And the reason for that is because on click handlers cannot be serialized. Therefore buttons cannot be server components. And so you'd put yourself in a good spot to adopt server components. If your interactive things with handlers or functions or non serializable props like on click, et cetera, your interaction boundaries are in their own separate modules and those are as granular as possible. Number three, a lot of our applications use react context, and context is great for literally that, for providing context to your application. For example, who is the logged in user? What are their preferences? Do they like toast? Then show them YouTube videos about toast. Even we use context sometimes for personalization. On the server side, you don't get to use react context because that context is usually shared across multiple clients. And so the better alternative there is to use server side cache. You could have a cache namespaced by user, for example. You could really do the same things or similar things that you used to do with context with server side cache, and then you get that as well. I think these three tools will help you really adopt server components. If not, put yourself in a good position to adopt them once you feel like you can, and once they are more mainstream. And with that, I'd like to quickly come to the end of this video, but I wanted to address one thing before wrapping up, and that is we talked about a lot of what react server components are, an architecture, a way to fetch data, et cetera. I think one thing that RC is above and beyond all of that is that react server components is a community effort and by extension react itself is a community effort. And I think I would be remiss if I didn't mention and acknowledge the fact that we haven't been the best community. The react community has had some issues lately with the discourse getting more and more hostile and ultimately leading even the most patient and kind of us, Dan Abramov and others, to burn out and not really enjoy being here. It feels like an obligation instead of a joy, and that's pretty unfortunate for a community. And my hope is that in calling it out, it helps us take a moment to reflect and improve and really be the community that we wanted to be and that it once was, and that I believe it could be again. With that, as usual, we covered a lot of content. I'm really thankful that you stuck around if you did. If you're enjoying and or benefiting and learning from these videos, please subscribe to the channel, hit the bell and drop a like. It would really help and it's just a great easy way to support me. Also, if you found the content useful, I'd encourage you to share it on social media, LinkedIn, Twitter, blue sky, whatever you like, and really spread it so that people can understand react server components and learn. And also that I would feel supported and be more likely to make great content. Ideally, hopefully great content like this, all of this stuff is going to be in a GitHub repository that you can access as well. I'll put a link under the like button. And I want to say thank you for being here. Thank you for watching. Thank you for your interest in web technology and computer science. I'll catch you in the next one. Peace.
...

Tejas Kumar

Chief Developer Advocate @ Unnamed Full-Service DevRel Consultancy

Tejas Kumar's LinkedIn account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways