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