Data Fetching with React Server Components

Data Fetching with React Server Components

Show Video

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

2020-12-23 05:32

Show Video

Other news