Transcript >> DAN: hi my name is Dan Abramov and I'm
a software engineer on the React Core team at Facebook and later today I will be joined by
Lauren Tan who's my colleague on the React Data team and together we will present an update on
our teams' research into data fetching in React when I just got into software development I
heard about this principle that you can make something good you can make something cheap or
you can make something fast but you can only pick two so which two do you pick do you pick something
good and something fast but it's not cheap to make or do you pick something that is cheap to make
and fast but you know that it's not very good or would you rather go for something
that's really good and that's cheap but takes a very long time to make and so
this principle is about project management but I want to stretch it a little
bit and apply it to UI development so what I want in UI development is I
want to have a good user experience so I want to create products that are pleasant
to use and I want them to be cheap to maintain and of course I want them to be fast and
these three things are at odds with each other so let's see an example so for an example of a
good user experience I'm going to use my favorite app this is Spotify I love the way it's made
it's it has so many small design touches that are very nice um and I'm going to imagine that I'm
re-implementing Spotify which is not realistic but if I were to try to make a mockup I would
maybe structure my components like this so there's the artist page component
and there is some kind of a wrapper for the entire page that maybe like it shows
the cover and some details and then it has a content area and in the content area I put
two components top tracks and the discography and it's interesting if you look at the way
Spotify actually works if you try to click around you'll notice that if you click on an artist you
never see discography appearing on its own and then getting pushed down by top tracks and then
finally gets wrapped into this like artist details page um all of those things appear at the same
time and this is not a universal so rule of course there are cases in user interfaces where you want
things to appear step by step but you still want it to be intentionally designed and not something
that just happens in random order according to how the network responds so that's if if
we want a data fetching solution that satisfies these constraints that's the part
that we care about in the user experience but you also want the code to be easy to maintain
and cheap to maintain and in case of data fetching and the way I would look at this is before I have
data fetching if I'm just mocking up my app with some static data from json I might start like
this but then I have to add that data fetching and I end up with something like this and it
doesn't matter what library I use — it could be just fetch and useEffect, it could be redux, it
could be something else — but essentially I need to get some data in some place and I need to pass
it down and clearly there is nothing wrong about it — this is the way React works and it works
just fine — but for data fetching I kind of see a problem here where the API response becomes
very coupled to my components so for example if I later remove top tracks from the screen entirely I
might forget to remove it from the API response so I will be transferring all this unnecessary
data there or if I maybe add a field and use it in in one of the components but then I forget
to update another API endpoint under which that component also appears and so i'll have a crash
there so there are all these subtle things about tying your API with the components that use it and
really conceptually I want to write code like this I want to go back to this so I
want to have separate components and somehow each of those components determines
what data it needs and gets it from somewhere — and I don't mean that every component needs to
read its own data — but I do want to have a way to specify for some large blocks of the screen
where where do they get the data from without tying it back to the very root and passing
it through context and and all that jazz so I want my code to look like this and finally I want my code to be fast and it turns
out that this is not fast and the reason it's not fast is because let's just see the order in which
this code executes so we have these ArtistDetails does a fetch a fetch takes a while then the fetch
comes back and we go into TopTracks which also does a fetch because we we made each component
responsible for its own data fetching so TopTracks doesn't even start fetching top tracks until after
ArtistDetails has rendered it instead of like a spinner so this is called the network waterfall
because it goes like this like it goes in stages and to illustrate the problem more clearly i'll
just use a graphic so here's a server and client we have a parent and the child component
on the client because that's where React is make a request for the server it might take a
long time request comes back make another request and it comes back and the problem is all
this time we've wasted that we could have simply fired both requests at the same time
but because of how we structured the code that was not possible and so with this
approach we don't have fast performance we can compromise on something else so we can
compromise on the maintenance and go back to fetching all the stuff at the top which solves the
performance problem now we don't have a waterfall but now the components are not responsible
for their own data requirements we could also compromise on user experience
so we could decide that we're going back to each component fetching its own data and then
when we go to the artist page we might see discography first and then the artist details
wraps it and then top tracks pushes us down but it's just not a good user experience
so we've really compromised it and so maybe we can't have all three but
no this this doesn't make sense it's it's not a mathematical principle it's not a rule
it's just a way to think about constraints and of course it doesn't reflect all the all the
complexity and all the hidden variables and in fact we know that the problem does have a solution
because we've already solved it before and at Facebook we use to solve this problem
we use the combination of Relay and GraphQL so the way we do that is each component that
wants some data specifies which data it needs through a GraphQL fragment and then Relay is
this thing that composes those fragments together so that when we talk to the server to
navigate to a new screen we only get we get all of them in one go instead of going
back and forth like we have with a waterfall and so now we have a question if we want
to improve the performance of React apps across the ecosystem do we just
use GraphQL and Relay everywhere and I think it's clear that no this doesn't
make sense and it's not because they're bad we love using them they make a
lot of sense for Facebook products but they don't make sense in all cases there's
so many different cases and for example if you just starting and you write in your small hobby
apps unless you're specifically interested in GraphQL it probably doesn't make sense to have to
have a GraphQL back-end for your app to be fast um and similarly even in large companies
you um not everyone wants to adopt GraphQL you might have a lot of legacy backends it
might be a huge project to expose a GraphQL endpoint and maybe you just don't like GraphQL
and that's also okay, it's a technology, it's not necessarily for every use case and so we
had to go back to the drawing board and think can we come up with a solution that would address
the majority of needs in the React ecosystem let's take another look at this graphic so the
problem is that we have a waterfall but the reason the problem is so bad is because there is high
latency between the client and the server so one way to solve the problem is to fix the waterfall
as GraphQL does but there is also another solution which is to move our components to the server
so what happens in this case is that the client makes a request our parent component is on the
server so you can talk to the backend real fast render the child component which also talks
to the backend real fast and send the response wait did I say move React components to the server how do you even do that well
that's what we've been researching and these are regular React components still
but we're going to call them Server Components because they execute on the server and on the
server only they're never shipped to the client and we originally thought of Server Components as
a way to solve the waterfall problem however we found that they also solve many other problems
that we've been wanting to solve for a while and I want to be clear that Server Components are
not something that we're adding to React today but it's something that we want to introduce to React
and we want to share our research with the React community so that the development is transparent
and so to give you an idea of what it actually feels like to build an app with Server Components
I would like to invite Lauren Tan. Lauren? >> LAUREN: thanks Dan my name is Lauren Tan
and I'm an engineer on the React Data team over the past week we've been building a demo
application to showcase what Server Components are so let's get started the demo application we're
building is called React Notes it's a full stack application that's backed by a database and as
you can see i've already populated our database with some notes right now our application
doesn't do a whole lot but I did want to show you two components before we started adding
functionality the first component is App.server.js I've given this component the .server.js extension
to tell React that this is a Server Component Server Components are a new type of
component that we're introducing to React and this tells React that we only want
this component to ever render on the server at the moment our Server Component doesn't do much but it does import the NotesList component
which is a Client Component Client Components are not a new type of component these are
regular components that we've just given the .client.js extension to tell React that we
want this component to only render on the client in our Client Component we're
importing the fetch function from the react-fetch library react-fetch
is a thin wrapper around the fetch API and we're using this to fetch our
list of notes from our backend what's really interesting about this
fetch API is that it works as if it was synchronous so you don't have to wrap
it in an effect or anything like that now let's take a look at the rest of our
component at the moment it doesn't really do much it's just mapping over our our list of
notes and then rendering that into our sidebar so this component doesn't have any interactivity
and it does have a data requirement so this could be a really great candidate
to be a Server Component so let's do that all right so i've converted this to a Server
Component so now I'm telling React that I only want this component to render on the server but
I'm still using the fetch API and it's really neat because the fetch API works on both the server and
the client so I don't have to change any code here but you might also be wondering if we're
already rendering this component on the server why am I fetching the notes from the server again
well this fetch is happening on the server so in practice this is going to be really fast and
it's going to be much faster than fetching our data from the client so let's take a look at
our UI now and refresh the page and you can see that I've converted the sidebar to a Server
Component and it's still working as I expect all right so we've converted the sidebar to be a
Server Component but one thing that I don't like is this timestamp we're rendering it as
a raw string and it looks really ugly in our NoteList Server Component
I've extracted each list item into a new component called the SidebarNote component in the SidebarNote component I'm importing two
functions from the date functions library which is a utility library for formatting dates and then
I'm using those two functions to format the date if it's today then I want to show the time that it
was last updated at and if it wasn't edited today then I want to show the date as a month date and
year string and for those of you who are not in America I apologize for this abomination
the rest of the world uses date month and year so I apologize for this travesty but
at the moment this component really isn't very exciting but I did want to draw your attention
to the date functions library that i've imported as you can see this library is about 21.2
kilobytes uncompressed and it's about 5.9 kilobytes when it's gzipped so it's actually
a pretty heavy dependency just for formatting a date but let's look at an interesting property
of Server Components we've refreshed the page and now we can see our formatted date I'm going to
pop into the Sources tab in the Chrome DevTools and I wanted to show you what webpack
has built to render this application so when we pop open the src folder in the
webpack source I can see that none of the Server Components that I've defined so far
have been included in the client bundle and what's even more exciting is that the date
functions library that I used which was about 21 kilobytes and about 6 kilobytes when it
was gzipped is nowhere to be seen in our client bundle and that's really powerful because
I no longer have to make my user pay the cost of downloading dependencies that are really only ever
going to be used once and then never used again okay our sidebar looks a lot better but I also
want to add some interactivity each of our notes has a content so I want to be able to click on
one of these items and then see a preview of the contents of the note so let's go ahead and
do that as a quick reminder the SidebarNote component here is a the component that we're
using to render the list item within the sidebar as you can see I brought in a lot more external
dependencies now which are pretty large but fortunately this component renders on the server
so that's great now I want to talk about one constraint of Server Components and that is that
Server Components cannot have any interactivity so that means that we can't do things like use
state or event listeners and because we're going to toggle whether or not the list item is
expanded we need to do that on the client so that it can be interactive fortunately
Server Components can import Client Components which can have interactivity so I just need to
make sure that I put all of my interactive logic into the Client Component I'm not actually
going to show you the Client Component right now because it's fairly straightforward I'm
using state and if the Client Component is expanded then I'm going to show a prop and
if it's not expanded I'm going to hide it so let's go look at our Server Component again I've used the Client Component here but I'm
also passing props to that Client Component from the Server Component and this is really neat
because Client Components can receive more or less any of the kind of props that you might
expect that you can pass to a component with a few exceptions and the key thing to
note here is that we can only pass props to a Client Component from a Server Component
if that prop is serializable over the network so for example if we were serializing to JSON
that means that we can only use values that can be encoded into JSON so as an example if I pass
in a function here and I call it like fun I guess in this case React would throw an error because
this is a function and it cannot serialize that function over the network and the Client Component
would actually not be able to use this function at all but props that are serializable
are totally fine and JSX is serializable one interesting thing about using
JSX within a Server Component as a prop to a Client Component is that the JSX
will be rendered by the Server Component before it gets to the client so
what exactly do I mean by that so as you can see here I've highlighted what I'm
passing to the Client Component as children and at the moment this is just JSX but what happens if I
extracted this into a new component what would get sent as a prop instead so let's create a new file
and I'm going to call this the SidebarNoteHeader I'm going to export the function and this function is going to take a
prop which is the note and I'm going to return the JSX that I used here I'm also going to need the logic that I use for
formatting the date so let's grab that as well let's grab the oops the imports as well so
I'm going to need the date functions to import and this looks good I have the formatted
date and I have my date functions and so this should be totally good now
so let's clean up our sidebar component and I'm going to import that
component that I just created and instead of passing the JSX this
time I'm going to pass the component with the note as a prop so we can look up the date so what I meant by that that Server Components
pass rendered props to Client Components is that the thing that gets passed over the
network isn't going to be this Server Component like that looks like this instead we're going
to pass the JSX that's fully rendered already so that means that the this instead of having
lastUpdatedAt this would already have the value in the JSX when we send it to the client so
now if I refresh the page you can see that our sidebar is interactive and if I pop
open the sources tab really quickly we can also see that we did not download the
sidebar note header component we only download the SidebarNote.client component which we
needed for the is expanded interactivity all right now that we have the ability
to expand a note so that we can get a sneak preview of its content I also want
the ability to click on a note so that I can see the entire note's contents being
rendered into the preview on the right as a quick reminder the sidebar note Client
Component is the component that's responsible for the interactivity in our sidebar so when
we click on that button we want the ability to somehow tell our server to re-render the
component tree the Server Component tree with but this time with the selected note
rendered into the preview so how do we do that in our demo application we do that through
setting something known as a location now a location is not a new React concept this
is just something custom that we've set up so that our infrastructure can refresh the Server
Component tree in our demo what happens when we set a location is we set this in context and our
routing infrastructure is watching that context and if that context value changes we refetch the
Server Component tree with those properties being passed to the server when the server receives
those props we will re-render the Server Component tree starting from the root and in this case it's
in our case it's the application Server Component but this time when we re-render this component
we're going to get a selected id now we're going to pass that selected id to our Note component
which is also being rendered on the server in our Note Server Component if we receive a
selected id we're going to fetch that from our API and then render that in the preview pane all
right so let me click on a note really quickly and show you that it is really performing a server
request to re-render the Server Component tree as you can see we're refreshing
the Server Component tree now I want to pause here really quickly and
talk about server side rendering for a moment if you're familiar with server-side rendering
or also known as SSR SSR is where you take your client-side application javascript and then you
run that on the server and render that into HTML the benefit of doing this is that you can serve
that HTML to your client really quickly and your client can see something happening while
the javascript is still downloading but Server Components are different so let's
see what we mean by that if you recall when we we have the ability to expand a note
and we can get a sneak preview of its contents and we're storing this all in a Client
Component so this is client-side state but Server Components are different from
SSR so that means when I click on a note the client side state is never blown
away it's always preserved and this is a really great property of Server Components that
is quite different from server-side rendering and the reason why we can do this
with Server Components is because Server Components don't render to HTML they render
into a special format now I did say I did compare Server Components with SSR but I don't mean that
they are they can't be used together in fact server side rendering and Server Components
are actually complementary and you can use both technologies together but again Server
Components are really interesting because we are able to preserve the client-side state
even when we re-fetch the Server Component tree okay we can view a note but I wanted to show
you an additional property of Server Components before we continue adding more functionality so in
the Note Server Component which is the component that's responsible for rendering the contents
of the note in the preview I've swapped out the implementation so now we're going to read the body
from a file instead of reading it from our API and in order to do that i've imported a
function from the react-fs library and just like react-fetch the react-fs library is
a thin wrapper around the Node.js fs module so now let's edit a note I'm going to hit save and then click on the note
and you can see that we're now rendering the contents of the note from our markdown file that's
local to my file system so this might really come in useful if for example I was building a blog
or something else that requires a lot of static content okay so we can edit a note in our
editor but it's not really a great experience and I want to have that edit functionality
exposed in our UI instead so i've already added the ability to edit a note so let's take a
quick look at the UI before I show you the code so this is our NoteEditor component and
as you can see it has two major pieces the first of which is a form where we can type in
our title for the note as well as the body for the note and then on the right we have a preview of
the note after it's been rendered into markdown now I want to talk about something that I've
shown you but I haven't really talked about before so in the Note Server Component and let me go
back to the UI really quickly just to show you so in the in the preview for a note when we click
on it the component that's rendering this markdown is the NotePreview component and we're importing
it in this component but you'll notice something interesting about this component and that is
that it does not have a .client.js or .server.js extension it only has a .js extension so what this
means is that we're telling React that this is a Shared Component. Shared Components can render on
the server or on the client and whether or not it renders on the server or client is determined by
what kind of component is importing the component so in this case this is a Server Component
so we're going to render this on the server and the note preview component will
not be downloaded on the client bundle but we're also going to use the same
exact component in our Client Component the NoteEditor Client Component and as I mentioned
because this is a Client Component we're going to render this on the client so what exactly does
this mean now here's a really interesting property of Shared Components and I'm going to refresh the
page so watch what happens when I click on a note you'll see that we downloaded the
EditButton which is a Client Component but the NotePreview component is nowhere
to be found because it was being rendered on the server but when we click on edit we're
now in the NoteEditor component and we do have a requirement for the or dependency of the
NotePreview component on the client so we have downloaded this component on demand and that's
a really great property of Shared Components and as you might expect if I
paste in some markdown here the NotePreview component is fully interactive
because this is not being rendered on the server this is going to be rendered on the client so let's add our last piece of functionality
to our application and that's going to be the ability to search for a note by title so what I
want to happen is whenever I type a title in the input in the search bar I want this list of notes
to update accordingly just to refresh your memory we are implementing this sidebar with this
NoteList Server Component and at the moment we are fetching our notes through this API call
but my good friend and colleague Dan has just told me that he forgot to add the ability to search
in our API so I'm going to need to improvise fortunately for me I know SQL so I'm going
to copy paste the SQL query that I pasted that I prepared earlier and use this to implement
my search I do want to say that if this was a real application I wouldn't recommend writing
raw SQL in your Server Component there are far safer ways of providing data abstraction
layers so that you have a secure and privacy safe way of accessing data but I wanted to show
you this query because I think it illustrates that you know Server Components you have the full
the full power of the server at your disposal so because it's a demo let's just use that power but
there's also another interesting thing I wanted to highlight and that is that this is only the only
shockingly this is the only thing I need to do to enable search so that probably sounds kind
of ridiculous so let me actually show you all right so I've refreshed the page so watch
what happens when I search I didn't keep track of any state I don't have um local state
management or client state happening this is all just being server rendered but you know this is
actually not even the most interesting part here here's another really interesting thing
that I want to show you so if you remember we implemented the ability to expand a note by
clicking on it so we can see a sneak preview and this is all stored in client-side state
now watch what happens when I create a new note components and I'm going to call it 2 and this
is a brand new note and I'm going to save it you'll see that we re-rendered the sidebar
component the whole sidebar component on the server but the client-side state as I mentioned
from a little bit ago is still expanded and that's really great and in fact
if I go ahead and delete this note this note is going to stay expanded as
well okay we're done adding functionality to this application so let's add a final
bit of polish before we wrap up the demo now we've used a lot of Server Components in this
application so you might be wondering what happens to the user experience if the server is really far
away or if my user has a not really great internet so let's see what we can do I've added a
Suspense boundary around our Note component and just to refresh your memory our Note component
is responsible for rendering the contents of the note onto the preview pane on the right our Note
component I've added an artificial delay through this fetch call and this fetch call doesn't do
anything but as I mentioned it adds about three seconds delay just to show you what happens if
the response takes a while to get to the client so I'm going to open the network tab really
quickly and then I'm going to click on note you can see that Suspense and Server
Components work really well together to show your user some kind of feedback while
they're waiting for the rest of the server tree to be rendered and the reason why
we can do this is because Server Components don't render to HTML they render into a special
format that we can stream down to clients so you can think of it this way as we get the first part
of the server tree in our response we can send it down immediately to the client so the client
can start doing something with that response and when it we can also tell the client
that we should suspend and that is what allows the client to you know show that
loading state while it's continuing to wait for the other pieces of the server tree
to be sent down another way that we can respond immediately to user input is through
transitions so I'm going to add an artificial network condition so this is now going to be
slow 3G and keep in mind that this is going to be slow 3G plus an additional 3 seconds that i've
introduced artificially so I want you to see what happens when I click on one of these note items I
want you to watch what happens to the color of the highlight so if you didn't see what happened when
I clicked on a note it immediately turned a dark gray because that's what I did when I defined
that component in a transition and the transition is what allows us to respond immediately even
before the response has started streaming down to the client and with that we're done with the
demo I really enjoyed building this application and I also really enjoyed the fact that Server
Components gave me this new ability to choose whether or not I render my components on the
server or on the client I hope you enjoyed watching all of the code is on GitHub and is
open source so don't worry if you missed anything now I'd like to hand you back to Dan who's
going to wrap up the rest of the talk >> DAN: thank you Lauren wow that demo was
a lot I'm totally going to rewatch it when we put the video out in the second half of this
talk I would like to recap the key points from Lauren's demo and talk about the path then the
next steps for productionizing Server Components the first thing I want to recap from
the demo is that Server Components have zero effect on the bundle size and I
mean zero so you can have a Server Component that imports a bunch of libraries that do some
kind of pre-processing on the data and you can be confident that you're not shipping this to the
user because we don't use any automated compiler you have to make decisions about
which components to put on the client and which components to put on the server but
we think that this ability to have control is good because you have a guarantee about what gets
sent to the client and what stays on the server the other key point is that Server Components
let you access the back end resources directly it doesn't mean that you have to but you have
that option so it's easier to get started for example if you're building something like a React
blog it's nice to just be able to read it from the file system and not have to create any kind of API
layer and maybe later you want to scale up and you read it from the database instead and maybe later
you actually create some kind of an API layer and then you can access that layer and so we want
it so that you're able to switch between these different ways of reading data without changing
the paradigm and this particular example is interesting because this is a Server Component
but the only feature it uses is react-fetch and react-fetch actually works on the client
so technically this is a Shared Component that works both on the server and on the client
and I guess for a blog this is not super useful but as Lauren showed there are use cases like
markdown preview where it's nice to have the ability to render something either on the server
or on the client depending on the circumstances you might have noticed that in the demo there
were a few libraries mentioned that you might not have seen before so it's react-fs
(file system), react-pg for Postgres and react-fetch and um collectively we're
calling this these kinds of libraries React IO which stands for input-output and this is not
something that we'll have to create this is something that the community will be able to
maintain because you can create your own React IO and if you're concerned why do I have to -- why
do we need these wrappers why can't I just access the back end directly um the design philosophy
behind React IO is that these are very thin wrappers I think currently they're about 100 lines
each very thin wrappers over the underlying APIs and so for example react-fs exposes the exact
same APIs with a subset of the node fs API and so the only thing that is being added there is just
teaching React how to correctly cache the result and you might be wondering what does that mean for
GraphQL are Server Components replacing GraphQL and not really at Facebook we use
both Server Components and GraphQL so in fact our Server Components
read GraphQL queries on the server and this is because GraphQL works great for
us and we already have a GraphQL backend and it's it's just very convenient but if you
don't and if you don't want to or if you want to adopt GraphQL later Server Components give
you that option we think they're complementary to GraphQL but for people who don't want
to use GraphQL they do offer an alternative the next key point is that Server Components let
you only download the code that you actually need and I don't just mean the fact that the Server
Components are not being downloaded to the client but also even the Client Components — we don't
have to download the ones that aren't being used — so this is interesting consider this
Comment component which is a Server Component and we only want to show the
toolbar that lets you edit the post if this is your if this is your comment or
if you're an admin which is something that we happen to know on the server because that's
where the data is and so there is no point to downloading if you're visiting a comment
thread where you haven't posted and you're not an admin there is no point to downloading the
EditToolbar code and so what happens here is that even though the code looks like idiomatic React
code there seems to be nothing special about it the way Server Components are compiled
we're actually going to make it so that the server will only send the instruction to the
client to download EditToolbar if it is present in the server output so if you're visiting a
thread that doesn't have any of your comments you're not going to download that
chunk the bundle of javascript at all so this might remind you of dynamic imports but
it happens automatically behind the scenes without you having to do anything about it and so this is
possible because we integrate with the bundler so we've written an alpha version of a
webpack plugin for Server Components and this is still something it's not production ready
it's a proof of concept but we will be developing it together with our collaborators on the Next.js
team and the goal is to get the plug-in to a state where everybody can use it both Next.js users
and people who don't use Next.js and we're also talking to the Parcel maintainers who've also
expressed interest in developing a similar plugin the next key point is that Server Components
let you decide the trade-off for every concrete use case and so if you have some code that does
some data fetching and just some pre-processing it makes sense to put those components on
the server and then if you have some code that needs fast interactions to respond to input
immediately it makes sense to put it on the client but because there is no technological wall and
you're within the single technology a lot of the code can actually be shared and we expect
that the majority of components would be Shared Components that can run both on the server and on
the client and for example if you're developing something like a content management system where
you have some kind of articles it makes sense to render those articles on the server but then in
the admin panel where you're able to edit them it makes sense to render them on the client
so that they can preview changes immediately and so this is what being in a single paradigm
and unifying client and server gives us the last thing I want to recap from Lauren's
demo is that Server Components let me create user interfaces that feel modern and app-like
but the way I write them kind of reminds me of building an old-school web page so what I mean by
this is here's a search results Server Component that accepts search text as a prop and I
don't really need to think about how exactly the client server interaction happens instead I
can focus on describing the UI that I want to see and in this case I want to see the search input
and the list of results and that's it and so the search input here is a Client Component that
has its own state but it also triggers a refetch of the server tree with the new search text
and so we're back in the search results Server Component but this time the search text
is different and so we're going to get the new results and we're going to emit a a list but in
the client React is smart enough to figure out to only do the parts to only update the parts
that changed so in this example it's the list itself that might have changed right so we might
have had we might insert some new DOM nodes for new search results and remove some of
them or maybe update them but it's smart enough to understand that the search input has
not changed because it's in the same place so it doesn't destroy its state and it's really curious
what kind of features you can build on top of it like for example you could have a CSS transition
on some property and then whenever a server responds with a different value for that property
the animation will fire on the client because the DOM has not been destroyed and I personally
find that use case fascinating um and so in the way Server Components kind of sure like you can
think of client and server but they also offer you a different way to look at it which is to
think of your React app as a single tree that contains both client and the Server Components
and in this mental model you don't think as much of the client's fetching data but it's more
like the Server Components passing data to Client Components as props so it's for some problems this
way of looking at it makes things a bit simpler so to recap Server Components have no effect
on the bundle size, they let you access the backend resources directly, they enable
automatic code splitting for client code with support of a bundler plugin, you can use as
much Server Components or as little as you like, and you can choose where to place them
according to what makes sense for your product but they let you have a modern app-like user
experience even though writing them kind of feels like writing old-school web pages Server
Components are completely opt-in we're not going to force anyone to use Server Components if
you like your existing client apps that's fine um in fact we can think of existing React
apps as just apps that happen to be entirely composed of Client Components but we want to
give you the tools to make the right trade-off for your app and Server Components are still in
research and development so we're sharing them in the spirit of transparency to explain what we're
working on and how we envision the future of React but it's not something you can plug
into your production app tomorrow and we expect that the initial adoption will
happen through frameworks such as Next.js who we are collaborating with but we're not going to
create any framework specific pieces so we will be collaborating on a webpack plugin together with
the Next.js team but the goal is for anyone to be able to use it and the reason initial adoption
happens to frameworks is just because you need the control over the server and the bundler and
the router and how those pieces are tied together but after we figure this out if you have a custom
setup you will be able to copy what the frameworks do we've had a few milestones that we needed to
hit with this work so we needed to design the architecture make sure that you can actually build
something with this component model implement the streaming protocol check that all the pieces can
work together and run a real production test to verify that this approach doesn't have any glaring
holes in it and we've hit all of these milestones which is why we felt confident doing this talk and
in particular so I want to share some numbers so that you get a sense that is like not completely
hypothetical but I want to preface that by saying that they don't really mean much but in our first
production experiment where we automatically we run conversion scripts that automatically
convert components that are compatible to be Server Components and as we test it on
a single page in a single place in the product and on a limited number of users but two weeks
ago we saw 18% bundle reduction just from those automatic conversions and as we fixed a bunch
of places where the things that we were passing were not serializable and fixed our infra to
handle it better 10 days ago it was 21% reduction and by the time I'm recording this talk it was
29% reduction so of course we can't expect that this will extrapolate so that in a few months we
won't have any anything in the bundle but it is an interesting dynamic and it is an encouraging
dynamic considering we're not even using product code that was written with Server Components
in mind so this this really encouraged us although we're starting to experiment with Server
Components in production it is still an ongoing research project for example we're still missing
some of the APIs that would be necessary for example to build a Server Component router so this
is one of the things that we're currently doing the other thing that we're busy with is we're
working to finalize Concurrent Mode because it is an important optimization for Server Components
um Concurrent Mode is what allows streaming so it lets us stream the output from the server
and as this output arrives we can already start rendering Client Components with their props in
memory and then we can put them to the screen as soon as we have a decent loading state that we
can show to the user and so we don't we don't want to wait for the whole response to come back
then render all the Client Components and then show them to the screen so Concurrent Mode is an
important optimization there and we're currently adding some tweaks to it to make it easier
to adopt but this will take some more time um the the other future area of work that I want to
specifically specifically call out is we need to build an HTML renderer so Server Components render
to a intermediate format that is necessary to transfer the tree to the client without
removing or blowing away the state but we still want the fast first render and use
as much of browser capabilities as we can so it makes sense to have an HTML renderer and
so the way we imagine it is that there would be a renderer that takes in the Server Component
output stream and emits an HTML stream and so this is something that we would need to
integrate into frameworks first as well so if you're wondering if now is a good time to
play with the demo absolutely we loved building it we hope that you have fun playing with it it
has some rough edges in the way the bundling is set up so it's it's not super polished in that
sense but the parts that are in the src folder are pretty representative of how we think Server
Components would actually be used in practice so we hope that you'll enjoy playing
with it and let us know what you think and we'd love to hear from React community
so do you love the idea do you hate the idea let us know spill it all out so we're we're
excited to have a conversation about this topic and to hear your feedback on the RFC so there
are some other things that many of us might be tempted to do and I totally understand this but we
would be we would appreciate if you didn't do this but of course we can't stop you but it
makes it more difficult for us to share our research in the open in early stages so if you
don't do that thank you we really appreciate that and so the link to the demo you can find it in
our blog post and you can also find there a link to the RFC so if you have thoughts on the RFC has
some technical details so if you have any thoughts on those parts we'd love to hear them it is
not completely exhaustive but expect that we will post more talks and more RFCs covering more
specific technical aspects in the coming months Lauren and I would like to thank all of our
colleagues on the React Core and React Data teams who helped make this project happen
including Sebastian Markbåge who came up with the idea of Server Components and
all the contributors including Luna Ruan Joe Savona Juan Tejada Andrew Clark and Andrey
Lunyov and we'd also like to thank our external partners and collaborators including the
Google Chrome Web SDK team and the Next.js team in conclusion today all React apps are collections
of Client Components and if that's your use case if you're developing something that is
completely interactive like a graphic editor for example that is still
a use case we want to support well but we also want to give you the tools to tweak
it and to to make the trade-off better so maybe if you want to do some data fetching and you
currently do it in different Client Components and you have waterfalls we want to help you remove
those waterfalls by moving that work to the server or maybe you're working on an e-commerce website
where most of the content is mostly static but then maybe you have a separate flow
like a checkout flow that is very dynamic and so that kind of flow would be using mostly
Client Components or maybe you're working on something like a blog where the majority of
components are Server Components but you still need little bits of interaction here and there
and they don't want to completely reload the page every time you navigate so this is something
that we we want to support better as well and ultimately every app is different and we
don't want to tell you what kind of apps to build we don't want to be prescriptive about it but we
want to give you the tools to adjust the trade-off so that you don't have to
choose between maintainability and performance and so that
you don't have to choose between the client and the server because
we believe that you can have both thank you