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.