DEV Community

Cover image for An Annotated Guide to React Server Components
swyx
swyx

Posted on • Edited on • Originally published at swyx.io

An Annotated Guide to React Server Components

The React team announced React Server Components this week with a talk, RFC, and demo. It is a lot to go through (especially for a holiday week), but I did. Here are my notes.

Apr 2021 update: they have now published an Architecture Q&A, notes below.

TL;DR

What are React Server Components?

They are an experimental, upcoming feature of React that lets you render Components only on the Server. This has a few implications; here are my top 2:

  • RSCs have Zero client JS bundle impact, so they can greatly reduce your overall bundle size. Despite only rendering on the server, they don't have to be static; you can refetch Server Components and the server will stream updates down, without losing state in Client Components.
  • You can directly query your database inside a Server Component without setting up GraphQL, API endpoints, or state management - and keep the query up to date as your serverside data changes. These queries are also faster because you save client-server roundtrips and waterfalls.

Note: They must be named with a .server.js extension and follow some constraints - mainly, they can't use state, effects, or DOM APIs.

What problems do React Server Components solve?

They solve for Good User Experience, Cheap Maintenance, and Fast Performance in React apps (as defined in the talk notes below). There are multiple benefits for both developers and users, and the size of benefit depends on the use case, which makes this difficult to fully explain.

However the headline opportunity here is to greatly reduce production React app bundle sizes (tests have seen as much as 29% reduction, but can easily be higher depending on your app) while not sacrificing modern app-like user experiences (this again has multiple meanings - demonstrated in the demo below).

Finally, React Server Components make it easy to create hybrid apps - giving you the power to pick a sliding scale between a fully clientside app or a fully serverside app and everything in between - and not have to do major rewrites to change paradigms as requirements change.

Annotated Talk With Timestamps

I will link to the timestamps with my commentary below, but you can view Dan Abramov and Lauren Tan's full talk here:

  • 1:45 Dan introduces the main constraints that React is trying to solve for:
    • Good User Experience - we want to orchestrate intentionally designed loading states. Items that should appear together must appear together, instead of jumping around on screen based on async API requests resolving.
    • Cheap Maintenance - we want to optimize for change. Make it easy to delete and move code around from component to component or from client to server or from stateless to stateful. To do this, data requirements should be delegated as low down the component tree as possible, rather than hoisted up to the highest common parent.
    • Fast Performance - we want to decrease JS bundle size, avoid client-server roundtrips and network waterfalls. If components are not dynamic, we should render them once on the server (and fetch their data), and not send their JS to the client. We should cache results on the client if possible. Requests that can be done in parallel should not be done in sequence.
    • Historically, React forced you to choose 2 out of 3 of these constraints. With React Server Components, you can have all 3. (Facebook already had all 3 with Relay and GraphQL, but not everyone has a GraphQL backend, nor should they. React Server Components are a more general and easily adopted alternative.)
  • 12:05 Lauren introduces the React Server Components Demo
    • Server Components are indicated by the new .server.js extension (separate Module Conventions RFC here).
    • Client Components are also indicated by a .client.js extension. You can switch Client Components to Server Components simply by renaming them.
    • (Explained later) Shared Components just have the standard .js extension.
    • (Explained later) There are three new React I/O libraries used in the demo:
      • react-fetch (wraps the fetch API)
      • react-pg (to access PostgreSQL)
      • react-fs (to access the Filesystem)
      • These are caches that let you Suspend rendering while data is being requested.
    • Fetching data on the server is much faster than fetching from the client, so this is a good optimization
  • 16:10 Server Components have zero bundle size impact
    • React doesn't download any JS for Server Components, including for any of their dependencies. This is a great strategy for heavy dependencies that are only used on the server.
    • (Explained later) JSX props/children will be rendered by the Server Component before it reaches the Client. So you can pass them Shared Components and save on bundle size too.
  • 17:25 Limitation: Server Components cannot be interactive
    • No useState or useEffect, no event handlers (e.g. onClick)
    • Client Components must receive serializable props from Server Components (e.g. no functions. JSX children/props is fine)
    • The RFC has more on the limitations of Server and Client Components.
  • 22:50 Difference between SSR and Server Components
    • You can refetch the Server Component tree so that HTML updates stream down, without any extra JS for the refetched Server Components.
    • But the parts of the app with clientside state are preserved. This is the main difference!
    • Lauren later elaborated: "SSR of client JS apps is an illusion. You render your JS on the server into HTML. You serve that HTML to your client so it appears to have fast startup. But you still have to wait for your JS to reach the user before anything can be interactive (hydration). After hydration, SSR can't be used again - it's typically only used for initial loads. We can refetch React Server Components as many times as we like."
    • The RFC FAQ also comments on the differences and complementarity of SSR and Server Components.
  • 26:45 Shared Components
    • Shared Components can render on either the server OR the client. They just have a .js extension.
    • Shared Components have the combined limitations of Server and Client Components, explained in the RFC.
    • Shared Components rendered on the server won't be sent to the client, unless they are rendered on the client, in which case they will be downloaded on demand!
  • 30:26 Server Components can directly query the database
    • Because we can refetch the Server Component tree (as explained above)...
    • a single Server Component that takes dynamic props and runs a database query (like a Search component) can update live!
    • No local state management or API requests needed. Just changing props and refetching the Server Component.
    • This Component stays updated even as you add new items to the database!
    • Don't skim over this part - This is a literal WOW moment - see us realize this at the 1h 10min mark on the React Serverless Components demo livestream
  • 33:21 Suspense and Slow Network UX
    • When the network is slow, we should show some immediate feedback to users as they wait. Suspense and Server Components work well together for this.
    • Method 1: We can use Suspense fallbacks to show user some feedback on Server Components, even while waiting for the rest of the server tree to be rendered (eg due to fetching data)
      • This is possible because Server Components don't render to HTML, they render to a special format to be streamed down to clients.
    • Method 2: We can also use Suspense transitions to respond immediately even before the response has started streaming down.
  • 36:50 Recap of Demo Points. Server Components...
    • 36:54 have ZERO effect on bundle size
      • having the ability to decide which components to put on the client or on the server gives you more control over bundle size
    • 37:42 let you access backend resources DIRECTLY
      • You can use the same paradigm for server & client data fetching
      • The community will be able to create more React IO library wrappers to cache results for more data sources
    • 41:04 let you only load the code that is necessary
      • if a Server Component conditionally renders a Client Component, the server will only send an instruction to download the Client Component if it is present in the server output
      • This works like dynamic imports, but is automatically done instead of requiring manual loading
      • To enable this, Integrated plugins are being written with webpack, Next.js, and Parcel teams.
    • 43:17 let you decide the tradeoff for every concrete usecase
      • Eliminate the artificial boundary between client and server:
        • Put data fetching and preprocessing code on Server
        • Put fast interaction response code on Client
        • But they expect that the majority of components will be Shared.
        • Example: CMS where you render articles on the server (so can be Server component most of the time) but when in admin panel you want to edit them (so need to render on client)
    • 44:25 provide modern UX with server-driven mental model
      • create modern and app-like UI's
      • but write them like an old-school web page
      • Example: the Search component in Lauren's demo is a Server Component that refetches based on a Client Component's state, but that Client Component's state persists
      • Usecase: CSS animation on property change can fire because now the DOM will not be destroyed
  • 47:14 Recap of Recap & looking ahead
    • It's Opt-in, still in R&D (missing core APIs eg Server Component Router, and need to finalize Concurrent Mode), and will be available to everyone even those who don't use Next.js
    • Production tests at FB have seen up to 29% reduction in bundle sizes
    • Don't make courses on this or put this in production. Just play with the demo.

You can also see more commentary on the Twitter thread here.

Demo Walkthrough

The React Team also released the demo shown in the talk: https://github.com/reactjs/server-components-demo/

However there are some difficult setup steps and a lot of things to try in the demo. I recently did a 2 hour walkthrough of every part, with timestamps.

You can also put Server Components into a serverless function, as I found today with a lot of difficulty.

Personal Reflections

This is the beginning of the end of a very, very long journey in React stretching as far back as 2014, when Jordan Walke first mentioned Async Rendering (the old name for Concurrent React) was a possibility.

My relationship with React Suspense started just after Dan Abramov's JSConf Iceland 2018 talk introducing it. It blew everyone's mind and ripped up everything I thought I knew about how React apps could and should be written. I stayed up all night to write a walkthrough of that demo. I had no React presence at the time but I've been following this idea throughout the ensuing 2.5 years.

I suspect how React Server Components look to people who have followed the journey are wholly different to people who are only just looking at this today. Kind of like how you might really enjoy a movie just for your snobby annoying friend to tell you "the book was better".

To me, "the book" provided a whole lot more context that, while it is irrelevant today, gives me a great deal more appreciation for how we got here and how things might work under the hood.

Here is all the jargon we did NOT discuss at any point in the talk or demo (because they are implementation details or irrelevant today):

Instead, we are given one concept today - Server Components. If you squint hard enough, you might even observe there is no API.

Takeaways

Because the React team has consistently communicated their thoughts through the years, the main benefit of React Server Components is the same as I've commented on in my writing and speaking.

Given a baseline React runtime, React Server Components let you:

  • Greatly reduce real-world app sizes by making it easy for you to not send down unnecessary JS (the proverbial disappearing app)
  • Have Client and Server components seamlessly operate in the same tree so you don't have to change paradigms when requirements change.
  • Serve data much faster and easier by skipping client-server waterfalls and directly accessing backend resources.
  • Preserve clientside state and DOM nodes even when loading Server Components so you can even do page transitions, CSS animations and persist input focus.

This is a wonderful new area of opportunity for React developers, and the ecosystem is set to see tremendous growth in 2021. I feel certain that it is also going to spark similar efforts in other frameworks (because the case for Concurrent Mode has for the first time been made beyond time slicing and lazy loading components).

Related Reads

I will update this with selected other pieces over time.

2021 Architecture Q&A notes

  • 5:15 What's left?
    • Everything about Server Components connects both to server rendering and the client and specifically the part of how Suspense works.Β So there's a few missing pieces in our serverΒ rendering story:
    • Streaming Server Renderer. "We're currently working on a newΒ implementation of the streaming server renderer which has some new interesting features butΒ particularly that's how we plan to integrateΒ the data stream from Server Components so that youΒ will be able to server render into HTML together with Server Components."
    • Smart Bundling Strategy. "The other parts that areΒ kind of missing is we want to make sure that whenΒ you're bundling the output, Server ComponentsΒ kind of implicitly gives you this fine-grainedΒ bundle splitting built-in, but we want toΒ make sure that there's a particularly usefulΒ bundling strategy that doesn't just regress theΒ strategy because if you're splitting your bundlesΒ into too small pieces then that can be worse thanΒ not splitting them at all. So we're working onΒ at least providing a prototype or ideally a fullΒ implementation of a webpack plugin that will letΒ you have a pretty decent out-of-the-box experience and there's other ways you can do that and I'mΒ interested to see kind of what the community comesΒ up with with various types of bundling strategies.Β But we want to at least be able to shipΒ our best thinking so far in this space."
    • Data Fetching. "And then there's an another pieceΒ which is how does this connect to the API you use for actually kicking offΒ the fetch like routing or pagination or other things like that. We don't necessarily seeΒ ourselves being particularly opinionated about that but there are certain patterns thatΒ work well and certain patterns that don't work well so we want to at least provide a prototypeΒ and a demo showcasing how you can think about solving those problems."
  • 7:50 When?
    • Hopefully this year. we're working towards having aΒ Release Candidate of the Client aspects and we're hoping to introduce both the new release for aΒ React 18 version together with a Server Components MVP, and possibly some streaming rendering asΒ  kind of a preview package, hopefully this year.
  • 8:30 GraphQL cache shared between server and client?
    • Jae: "Following on from what you saidΒ about it how it ties into server and client rendering and data fetching, our app is builtΒ around GraphQL and specifically Apollo GraphQL, which means it's built around this GraphQLΒ cache that is warmed during server rendering, transferred to the client, and thenΒ on a user's journey through a session that cache gets modified by new queriesΒ and mutations. How are you thinking about things like this, things like a GraphQL cache thatΒ right now is shared between server and client, are you planning on making something that worksΒ  with Server Components, or is it something that the ecosystem and and us as developers will haveΒ to rethink how we interact with data in that way?"
    • Joe: "So, we kind of seeΒ it as a sort of progression of how you might evolve your app that uses GraphQL or even otherΒ data fetching approaches.
      • The first step is to go from non-Suspense based data fetching toΒ using Suspense. The idea being instead of fetching in a useEffect or something, toΒ switching to Suspense-based data fetching. To make that work with serverΒ rendering, that would require that some of the pieces that Sebastian talked aboutΒ in terms of the new Suspense streaming-aware server rendering work. That's kind of the firstΒ piece, and what that gets you is the ability to mostly keep the same patternsΒ that you use in your app today, and to continue doing server-side rendering.
      • But the thing is that that sort of gets you the ability to fetch at multiple points in yourΒ tree, and to have all those queries sort of happen on the server while avoiding round trips forΒ your initial page load. But what that doesn't really solve is now you're on the client and nowΒ you want to do a page transition or something, now you're kind of going to be back in theΒ world of: you start rendering, maybe you you hit multiple queries as you're rendering your app, andΒ those could cause waterfalls, and so that's where we think Server Components can help.
      • But that'sΒ kind of a like a second stage after you've moved to Suspense with data fetching, and in termsΒ of the broader question of how does GraphQL or other kind of normalized data stores fit intoΒ the Server Components world, we don't foresee that really going away. There are going to be partsΒ of your app that are interactive that require data consistency on the client and those willΒ continue, I think, to make sense to build with the existing approaches that we're all using today.
      • And there's lots of good approaches: GraphQL, REST, and various different data libraries. IΒ think what's really going to change is for the parts of your app that makes sense to convert toΒ Server Components you start to want to think about splitting up what's sort of state and what'sΒ sort of canonical server data a bit more.
    • Seb: The strategy in general is like you need a Suspensey... allΒ this builds on the Suspense API, so you have to build that regardless. And we expect a lotΒ of these libraries that exist today to build some kind of support for that out of the box, andΒ  that lets you do the Server Components approach including colocating your data fetching in yourΒ component without the waterfalls for initial load. But if that collocation or thatΒ transformation could cause a regression compared to what you're doing today,Β if you have a very optimized solution, and then Server Components could be theΒ solution to that. So sometimes I suspect you'll actually want to wait to roll it out, evenΒ  though that it's a two-step adoption process, until you have both pieces just so that you don'tΒ regress performance overall in the meantime.
    • Jae: I guess just to makeΒ sure that I'm understanding correctly is that we're looking at the componentsΒ that are Server Components will not be updating in response to updates in theΒ cache so we're looking at Server Components being things that are rendered using kind ofΒ canonical data like data from a CMS or something, but not things are part of interactivityΒ and those things would be Client Components.
    • Joe: IΒ don't think it's necessarily that the data that you fetch in Server Components, that might veryΒ well come from GraphQL, it might come from the same data source that your Client Components areΒ fetching data from, but often, within the data that you fetch, some of it changes at differentΒ regularity. Just to take the Facebook example, like perhaps the text of a story might not changeΒ very often especially if it's a post that you haven't written, the only time that data is goingΒ to change is if you actually just refetch the whole story to begin with, at which point you'reΒ going to the server so you could just refetch the actual Server Component output. And so there'sΒ just different types of data and so some of it changes less frequently and therefore you couldΒ just re-fetch it in full, and when you do you just refetch the Server Component instead of fetchingΒ the data and then re-rendering the client-side, so it's kind of about the sort of rate of changeΒ of the data and how how consistent it has to be.
    • Seb: the wayΒ to think about it is that you're writing a Client Component first and then if you see thatΒ  that component doesn't have any state or effects you can convert that to a Server Component. ButΒ it doesn't have to be that you kind of go all-in to converting a whole tree or a whole subtree ofΒ components. It can be that you're just converting individual components as you go. So some of themΒ in the tree might be fetching client-side or as part of initial server rendering and some ofΒ them might be Server Components embedded in one tree.
    • Andrew: a theme here is that there are some components that don't update veryΒ  frequently and there's other components that are like highly interactive and have more localΒ state, like UI state... and maybe it receives data from from the server but like youΒ can pass it from a parent component.
      • So a lot of folks today who are already using aΒ data framework like Apollo or Relay are probably already writing code in roughly that patternΒ where there's some some sort of separation between super highly interactive Client ComponentsΒ versus things that are really about managing data and passing it down. That patternΒ works really well with Server Components.
      • But there might be some folks who are justΒ kind of throwing everything into the same kind of source of state, maybe likeΒ a store or something like that, and those those patterns might take a little bitΒ more work to migrate to this world where you're kind of thinking a little bit more carefullyΒ about what types of data that you have.
  • 16:50 Streaming server rendering
    • Yen-Wei: I was specifically curious to understand how you're thinking about the interop betweenΒ Client Components and Server Components, Client Components and server rendering,Β all together.
    • Seb: Client Components and server rendering,Β all together. Yeah so for server rendering there's a couple of pieces where we're buildingΒ server rendering with the Suspensey approach in mind. So that is decoupled from Server Components:Β  if Server Components didn't exist that would still be a thing. That approach allows you to streamΒ chunks of HTML in if you have, for example, one slower data source than another, so you can kindΒ  of see the UI progressively streaming as you go. And it kind of ties into the whole SuspenseΒ approach in general. But then you can see that each of those Client Components could be convertedΒ to a Server Component and what happens then is it's similar to what happens on the client.Β  I think of the server renderer as more of a simulated client environment whereΒ  the server renderer is the thing that receives the original requests. ButΒ  then it can request data just like the client can request additional data, and thatΒ  data could be a subtree of Server Components that then gets fed into the server rendererΒ that acts as a client, and then streams out the resulting HTML, and then it also embeds the ServerΒ Component output in in the HTML as JSON data.
    • Seb: One key distinction there is that currentΒ approaches tend to embed data in its rawest form, so if you're fetching a REST API on the serverΒ you might embed a REST response in your HTML for use with hydration. But in the Server ComponentsΒ approach, we're embedding the result of the Server Components in the JSON which means you're gettingΒ kind of denormalized and processed data in the output which can sometimes be bigger but fasterΒ  to render, and sometimes be smaller because you're you're just loading the the data that you actuallyΒ needed for that component rather than the whole REST response.
    • Andrew: I personally find it very confusing sometimes even though I know theΒ  difference between all the pieces, just because the naming is very confusing because nowadays whenΒ people think "well, it's called Server Components, I already have a thing called a server renderer,Β well the server renderer must be rendering the Server Components" but it's actually notΒ quite that. The thing that outputs HTML, the thing we traditionally think of as server renderingΒ  today, before Server Components β€” in this new architecture, that thing doesn't actually renderΒ  Server Components. It only renders the Client ones which is kind of mind-bending. It actuallyΒ receives already β€” see, I'm even struggling to think of the words to use right now, but there'sΒ like a layer that runs your Server Components, it sends that to a client renderer, andΒ then there's two types of client renderers: ones that runs in the browser and one that runs onΒ the server. I don't know if I'm clarifying it at all but but there's this distinction there betweenΒ the thing that outputs HTML and the thing that fetches the data and generates this streamingΒ output that you can then turn into HTML. If that helps at all.
    • Yen-Wei: Yeah, so I guess in this caseΒ the server renderer is like the simulated client runtime, basically, right? And so I guess kindΒ of following up there does that also mean that the assumption that Client Components only runΒ on the client is kind of false in that world?
    • Andrew: yeah, by default Client Components do run on the NodeΒ server environment and output like initial HTML or they run in the browser. There is a useΒ case for like some components that maybe you don't even want to try and render the initialΒ HTML on the server renderer β€” so we're thinking of an APIΒ where you can just bail out and say, just don't bother to try and render this this treeΒ on the server and we'll pick it up on the client which is a pretty nice feature because it givesΒ you some granular control over which things are able to run in both environments and whichΒ things aren't. But yeah, in general you're right: Client Components in this world don't necessarilyΒ mean you can just like access window and all these browser-only APIs. If you want to take fullΒ advantage of streaming HTML generation then same restrictions apply.
    • Seb: In terms of naming, I thinkΒ there's some other interesting ways of looking at it because the Server Components is really aboutΒ utilizing the server for what it's good at: like close to the data and relieving some resourcesΒ and having code already loaded. Whereas the server rendering is more like a magic trick and I thinkΒ that's a good way of looking at it because it's just about rendering this snapshot that the userΒ gets to see before they can interact with it. But hopefully with, especially with, progressiveΒ hydration approaches it won't feel any different when you try to interact with it but that'sΒ really the purpose of the server rendering. It's to provide this magic trick of a fastΒ initial snapshot. It's similar to kind of how on an iOS app where you can see a snapshotΒ in terms of pixels of what was previously there when you start it and then it actuallyΒ starts. It's a similar kind of trick making it feel like it's starting fast whereas the ServerΒ Components is really about this is a permanent approach that helps navigations further down in the app and permanentlyΒ avoids having to load that code.
    • Andrew: Yeah I like the "snapshot"... if anyoneΒ has a good suggestion for naming by the way we're open to them. This "snapshot" thingΒ I like because it reminds me of like a V8 snapshot.
    • Lauren: I think one term I've been usingΒ personally is "bootstrapping", it kind of like bootstraps the page just so that React can takeΒ over and actually do what it needs to. But yeah, it's the server-side rendering that gives you thatΒ initial skeleton to actually do anything off of.
    • Jae: Yeah, at FindMyPast we've often called itΒ the "pre-render" because server rendering made people think of like ASP .NET MVC kind ofΒ application. It's not really what it's doing so we started calling it the pre-renderΒ because it is this kind of optimization.
  • 25:00 Performance of Server Components
    • Jae: one of the things when I first talked about Server Components withΒ a colleague that is a principal on the front-end platform team β€” one of the thingsΒ that he immediately was concerned about was our server render β€” server pre-render β€” so it'sΒ already like quite a resource-intensive piece of our stack and that's just pre-rendering like onceΒ per session and he was thinking what is it going to be like, what are going to be the performanceΒ characteristics of this Server Component provider that is going to have to do much more work overΒ the lifetime of a user session both in terms of connections and in terms of processing with ServerΒ  Components. Is there going to be any built-in optimizations for, say, caching or memoizing theΒ result of Server Components that might be the same even for different users or even for the same userΒ across the session requesting it again and again?
    • Seb: It's not super resource-intensive for us at Facebook so far that we've seenΒ  in comparison, and I think part of that has to do with just how resource-intensive is yourΒ REST API today, or the processing of the data, or the GraphQL endpoint. And the otherΒ part is that the Server Components subsequent requests are not necessarily asΒ intensive as the initial server rendering because it's only the Server Components and notΒ the Client Components, and it's also a subtree. So it will have this ability to kind of re-fetch theΒ subtree but it's definitely a concern that we have that we want to meet by having that abilityΒ to refetch a subtree rather than kind of re-fetching all the data for a whole pageΒ when you're when you're refreshing it.
    • Seb: And to the caching point, we have some ideas aboutΒ ability to cache subtrees in various forms. So caching is always kind of tricky because youΒ have to make sure that you can invalidate it properly. But it also ties into context whereΒ because we have the ability to fetch subtrees like I just mentioned, you wantΒ to preserve that ability, then we'll also have the ability to cache thoseΒ subtree responses within any particular tree. But we have to encode theΒ inputs to that which is, for example, if you're having an HTTP fetch or a fileΒ read, all the inputs that go into this other than just the initial props or all the dataΒ that you read need to participate and give us a way to invalidate that β€” whether it's a timestampΒ or a file watcher or a subscription approach. So we haven't quite figured out what theΒ API for that invalidation is going to be and it might be tricky to add after the fact soΒ we're still kind of figuring out should that be something that is a part of the data fetching APIΒ contract from the beginning so that you don't lose that ability later, or is it something that youΒ can gradually adopt later on.
    • Lauren: I want to add that at the client level, the Server ComponentΒ response is also cacheable, determined by the needs of the product. So for exampleΒ if you have a part of your application that is really static, and the rate of change for theΒ data that powers that, those components β€” like let's say a navbar β€” so you don't have toΒ re-render the Server Components necessarily if those initial Server Component responsesΒ are cached. And there's nothing really special or unique about these ServerΒ Component responses that don't make them easy to cache. So for example in RelayΒ we do cache the Server Component response and we essentially make use of that ifΒ the data has not changed. Instead of refetching the Server Component, weΒ just restore it from the Relay store.
    • Joe: One thing to add is that you mentioned that yourΒ server side rendering β€” what you described as pre-rendering β€” is currently resource-intensive.Β  I think one thing to note there is that for certain libraries, the only way to do serverΒ  rendering with data fetching and useEffect right now is to kind of... certain libraries in theΒ ecosystem are doing multiple passes over the tree just to figure out what data the UI needs. AndΒ once the cache has been then warmed up then they can actually do like a full render, but obviouslyΒ that's doing multiple passes over the tree. With Relay we don't see that because we'reΒ actually fetching all the data upfront, and one of the benefits of Server Components isΒ that it makes that a bit easier to do. So with Server Components, it makes it a bit easier toΒ structure your app so you can actually avoid the need to walk the tree again and again just toΒ figure out what you're rendering. Also the new streaming Suspensey server rendering will actuallyΒ be able to resume work. Fetching with Suspense, we can resume work where we left off as opposedΒ to having to start over so I think that even in terms of that initial baseline of seeing thatΒ pre-rendering today is maybe expensive, that might change too, right? It's not just about "ohΒ we're adding more work" it's actually potentially making all of the work that you're already doingΒ a bit more efficient as well.
    • Seb: I have a question: where is your GraphQL implemented, is that aΒ  JavaScript service or a different language?
    • Jae: Yeah, GraphQL is mostly in JavaScript but it'sΒ a distributed graph β€” so we have a central Node.js server that proxies differentΒ requests for different parts of the schema to back-end services written in aΒ variety of languages but mostly Node.
    • Seb: I think the reason I ask is because there's some overhead in just the runtime itselfΒ and if, for example, if you have a REST API today and the REST API is built in Node, you can justΒ add Server Components as an additional layer to the end of the same runtime. And similarly if youΒ have a GraphQL implementation in Node or even in front then you can just add Server Components atΒ the end of the same service to amortize a little bit of the overall cost because you're utilizingΒ the same service for both processing your data and processing your Server Components becauseΒ  essentially it's just a data processing pipeline.
  • 33:10 Caching Server Component responses
    • Yen-Wei: Yeah so I think this is kind of a continuationΒ  of the previous question. So we talked about caching of Server Component responses andΒ I'm kind of curious if like β€” you know, today something we do is we cache the resultingΒ data in a client-side store or a provider. We use Redux in our app. I'm wondering if β€”Β talking about Relay store caching the responses for Server Components β€” is that something thatΒ React itself is gonna be opinionated about or is that something that's just going to be up toΒ  userland and sort of the needs of the product?
    • Seb: Yeah I was just gonna tie it back to what IΒ was saying in the intro about the pieces that are missing. There's a piece here aboutΒ routing and triggering the fetches which also includes the caching. And we have someΒ ideas around how you might want to do that without any additional library, justΒ like the simplest possible you can do, where you would have the cache β€” there's thisΒ Cache primitive built into React that would hold β€” it's actually both used on the server toΒ hold the responses that you use on the server and a cache that holds the response on theΒ client as well. But the Cache is also used for any ad-hoc thing you might fetch on the client,Β  so for example you might want to have images in there to support kind of like Suspensey imagesΒ technique, or you might want to have one ad-hoc client request that also goes into the sameΒ Cache. So that that's kind of the basic approach and we have some opinions about howΒ that's rooted β€” it's rooted in β€” certain subtrees have a lifetime in React, and that lifetimeΒ controls the Cache. But then you can also build this into an existing cache that isΒ more globally rooted, like Relay for example.
    • Andrew: if you've ever played with Suspense,Β like the preview versions of Suspense that we've published in the past, we have very glaringlyΒ not solved this caching issue. We've kind of just given you like a recipe for how to doΒ a user space cache and we've kind of just put a giant TODO in front of the wholeΒ area of like how you doing invalidation or how you decide which which parts of theΒ tree need to be consistent. So the API that Seb is alluding to is the thing that weΒ are now going to have more opinions on. And so if you are using Suspense, there willΒ be this unified built-into-React Cache API that different frameworks can hook into. AndΒ so each framework might have different implementations for how it fills in thatΒ Cache but there will be a unified pattern for, this is how you should invalidate it or thisΒ is how you decide which parts of the tree to be re-fetched or which parts of the tree need toΒ be updated after a server mutation or something. There'll definitely be additional layers onΒ top of this that a framework like Relay will have particular implementation opinions on,Β but the lowest level substrate of where does the cache actually live, we will have an API forΒ that.
    • Seb: And to fill in what the purpose is β€” this is kind of a deep dive β€” the purpose ofΒ that Cache is to provide a consistency for the subtree. So if you imagine you're doingΒ a fetch for Server Components but your Server Components can layer in Client Components, and theΒ Client Components might also do fetches around the same time, filling the same Cache. And the idea isΒ that you can invalidate all of that as one unit, and you get a new server request for freshΒ data, but you also get client requests for fresh data as well for the same subtree. And it'sΒ all tied with that subtree in React on the client.
  • 38:10 Error Handling in Server Components
    • Jae: So I was wondering what your thoughts are onΒ what if there's an error in a Server Component, what if the service providing the ServerΒ Component becomes unavailable, is there going to be a way for the client toΒ say something like "well if you can't fetch the subtree, display this in the meanwhile" orΒ is it a case of if there's some some subtrees that fail to fetch from Server Components, the appΒ  isn't in a state where it can continue rendering?
    • Seb: So I can start by kind of talking about theΒ general mechanisms, and how it can fill in with best practices. There's a coupleΒ of places that errors can happen.
      • There's errors that can happen in the runtimeΒ outside of React itself. That's more up to the infrastructure metaframework to handle those.
      • And then there's errors that can happen as as part of network, maybe you don't get theΒ response at all or you get part of the response but the connection errors.
      • And then there'sΒ errors that can happen within a Server Component.
    • Seb: So when there's an intentional thrown errorΒ within the Server Component that is on the server, there's two things that happen.
      • One, you getΒ to log it on the server so that you can kind of track this. If they don't even end up onΒ the client you still want to know that that you have some kind of errors happening.
      • TheΒ other part is that it gets embedded as part of the response. And then that component, where itΒ kind of abstractly conceptually gets rendered in the tree on the client, an error is rethrown soΒ that the client's error boundaries can handle it.
      • If an error happens because of, for example,Β you've gotten piece of the response but not not all of it, or even if you didn't getΒ the response at all, the client runtime throws an error for all the pieces of theΒ tree that haven't already rendered. So if you render a part β€” remember, this is aΒ streaming protocol so you can partially render the data that you already have, but theΒ error happens in the places that haven't yet rendered β€” so the nearest error boundary toΒ those places is where the error gets handled. And then it's really up to the errorΒ boundaries to determine what to do with that, whether it should display the errorΒ or if it should retry that request.
    • Jae: Yeah that sounds very flexible and like it willΒ give us a lot of options for all of the different error handling cases that you have and it soundsΒ easier than how things are right now about errors on the server, errors on theΒ client.
    • Seb: Yeah one thing that is a little bit tricky in this space is that you might haveΒ a general-purpose error boundary that just renders an error message for all theΒ  errors. But in this world if if you're never using errors like I/O errors to be thrown asΒ  an error boundary then those boundaries might not be aware that they should special-case I/OΒ boundaries or maybe rethrow if it's an IO error. So it's a little tricky now that an error boundaryΒ has to be aware of I/O errors as something special so that it can know to delegate those or knowΒ to handle it itself. Because otherwise if you have a deep boundary that handles the I/O error,Β it might not refetch, whereas if it would have bubbled through that error boundary it would haveΒ gotten the parent that knew how to refetch it. So that's still a little tricky but I thinkΒ  it's pretty flexible still.
  • 43:05 Pagination
    • Yen-wei: One thing we werecurious about was specifically in terms of β€” aΒ  lot of our pages are basically giant feeds β€” so pagination is something that we think aboutΒ a lot. And I'm curious how that would look like in terms of like Server Components andΒ pagination and fetching subsequent pages.
    • Joe: Yeah that's a great question, andΒ I think being very honest here, we're not sure yet. We've thought about this,Β we've explored it, but currently, for example, we're using Relay for our pagination, soΒ for example we're using Server Components for individual items and I don't think actuallyΒ we're using Server Components within a feed-like situation yet. But if we were, it would likely beΒ kind of Relay on the outside, Server Components on the inside, and I think our idea is to graduallyΒ explore that space.
    • Joe: I think oneΒ challenge there is even with Relay, we're still evaluating what is the rightΒ way to do streaming pagination with Suspense, where you want to have new items arriving fromΒ the server and getting incremental rendering. But obviously with Suspense integration so thatΒ you show the first item and then subsequent items even if maybe the second item is readyΒ first, right? So it has to be integrated with SuspenseList. So yeah this is like a non-answer,Β others may have more thoughts, but that's the current state of where we're at, what actuallyΒ works that is known.
    • Seb: I think that there's actually more known there than it might seem becauseΒ there's a bunch of possible versions that we don't think are gonna work. We don't have theΒ exact API but we think roughly the same structure. We've explored various forms for example,Β if you refetched the whole page and told the server to now include more in that list, thatΒ would be one approach. But the approach that we think is going to be there, which probably seemsΒ the most intuitive too, is you imagine each item in a list being its own subtree and we will haveΒ the ability to refetch just a subtree picking up the context for where you left off.
    • Seb: So the ideaΒ is basically you have a Client Component that is managing the list and it's sending a requestΒ for "give me this list of extra items" and it server renders those, or Server Component rendersΒ those, and then you get the result back and that's what you render at the end of the list. That'sΒ effectively what we're doing in Relay. There's nuances in exactly how you design that API butΒ I think that's the general principle, and some of the reasons for that particular approachΒ is that the page itself is kind of stateful in the sense that where you are in the list is aΒ client concept. If you just refetched β€” and this is especially true with Facebook becauseΒ every time you refresh the newsfeed you get a completely different order β€” itΒ doesn't have any inherent order.
    • So because the underlying data can change, the listΒ can change throughout time. So we don't actually want to refetch the list itself as a part of thisΒ request, we just want to add an extra page and just fetch that page and add that to the data weΒ already have. And to do that we need to be able to pick up the context. But which context should itΒ be β€” should it be the context of the freshest data or should it be the context that you rendered withΒ at the time that you rendered the outer list? And we think that it probably should be the contextΒ that you had when you were rendering at the outer list. So there's a lot of things that we concludedΒ and the end results ends up looking a lot like like Relay paginations, so I would look at that asΒ an inspiration.
  • 47:53 Testing
    • Jae: so another environmentΒ where all of this will have to run that we're thinking about is tests. So rightΒ now we have quite a few tests running React against jsdom, for some quick tests thatΒ can be run more quickly than, say, Cypress end-to-end tests that actually run a browser.Β So I've been wondering how Server Components fit into that. Will it be a case of beingΒ able to have this Server Component provider running locally as part of the same process thatΒ is running the tests, or how do you imagine that?
    • Lauren: Currently in our prototype we do have testing but the only tests we have are basically end-to-endΒ tests where we do actually run the Server Component rendering infrastructure in that test.Β I think the unit test story is still kind of at least not super clear to me, so others mayΒ have thoughts on that. But yeah we do run our tests end-to-end so we get to see the actual fullΒ end-to-end flow of rendering a Server Component and then making it into the initial load and thenΒ any interactions that might be expressed in the end-to-end test, those are all testable there.Β So it should plug in into existing end-to-end frameworks assuming that you can run your ServerΒ Component rendering infrastructure as well. But the interesting thing about Server ComponentsΒ is that there will be paths that we're exploring like we're currently researching some ways toΒ run Server Components in a different environment, like not on your server, like maybe in a WorkerΒ or something like that, that could help with the unit testing story.
    • Andrew: there'sΒ different types of unit tests. I don't always know what people mean by that, I think it usually meansΒ some part of the layer is mocked out or stubbed.
      • So like if you wanted to unit test a ClientΒ Component that expects Server Component data then that'd probably be pretty similar toΒ today where instead of rendering it inside of a Server Component you just render insideΒ something else that gives it props.
      • If you wanted to unit test the Server ComponentΒ itself, since Server Components can render a UI, the way I would probably do that is actuallyΒ simulate the request environment and actually generate the output. AndΒ then feed that into the, what are we calling it, the pre-renderer API. And then assert onΒ the React output the way you would for a client component unit test. You probably shouldn'tΒ assert the actual data format that this spits out so I guess it depends on what layer or partΒ of the stack that you're trying to test.
    • But even for things that I call unit test,Β I usually find it valuable when you keep it as "end-to-endy" as possible. So yeah IΒ probably wouldn't recommend asserting on anything except for the final tree output ifΒ that makes sense.
    • Seb: I'll add also that a lot of what we call Server Components are actuallyΒ Shared Components that you can run on either the client or the server, and one way if you're justΒ looking to test the logic and not the integration is to just render them as a client just like youΒ would test them today. I do think though that our observation is that moving more towards theΒ direction of end-to-end, whether that is more of a simulated end-to-end like a jsdom environmentΒ or a richer full browser end-to-end test, seems to be the way a lot of things areΒ going because it definitely simplifies testing a lot of asynchronousΒ behavior, like Promises.
  • 53:12 Testing a Subtree
    • Jae: I guess that the end-to-end testing, especially like fullΒ browser, removes a lot of complexities setting up the environment, but there's still a trade-offΒ there in between performance and how many tests you can write and still have them runΒ  performantly. So yes, specifically I was wondering like yeah this kind of like, butΒ  we want to test just a subtree in jsdom and especially what happens if that subtree includesΒ both Server Components and Client Components, and can that just be run in-process in JestΒ or is it a thing well no you have to spin up a separate server worker process thatΒ does the Server Component stuff and then?...
    • Seb: That's a good question because the infrastructureΒ is a little tricky with this environment just because we special-case how imports areΒ handled so in general the server can't... well, ideally it's set up so that the Server ComponentΒ renderer is its own process from even the "pre-renderer", that "bootstrap" rendererΒ thing, but you can run them in the same environment as long as they're built as separateΒ module systems. So for example a lot of production environments for server rendering use webpackΒ bundling before it's loaded in Node. And since webpack has its own module system and graph,Β you can put two of those in the same process.
    • Sev: But also if you're able to run it as aΒ Client Component, it more or less behaves similarly. It's not exactly the same but puttingΒ a Client Component where a Server Component would have been inside of a client tree as is more orΒ less the same, and that's the idea. You mentioned towards the beginning that one of the thingsΒ you're thinking about before releasing is a webpack plug-in. I'm wondering if there are plansΒ for first-class support for non-webpack bundling and also whether or not bundling on the serverΒ for example is actually a requirement for Server and Client Components. Yeah, so we'reΒ doing webpack first but we want to support first-class bundling for any bundler that canΒ support a good experience out of the box for this for the client.
    • There's a few constraintsΒ there, particularly the reason even the runtime is coupled to webpack right nowΒ is because we're kind of relying on some internals to be able to synchronously extract and requireΒ modules lazily even though they've already been loaded and pre-load them early. So to get reallyΒ the ideal of performance we're relying on a lot of these features that are not necessarilyΒ part of the standard API but there's more other bundles that support the same things weΒ can definitely support that. The other part is just getting the bundling strategy which weΒ don't really know exactly how that will work. But definitely something that could be builtΒ for others and we could even maintain it as a first-class package if it's a high-qualityΒ  implementation and we're happy to help with that.
    • The other part of the question is whether theΒ Server Components, the server part, needs to be bundled. And none of this needs to be necessarilyΒ bundled as part of development, and I think there's a large shift now in the ecosystem tryingΒ  to explore other ways of development where the development experience can be faster. For exampleΒ by not bundling. But we also think that an ideal developer experience forΒ debugging could actually be to run the server part in the Service Worker which mightΒ require some kind of bundling or at least some partial bundling or partial compilation toΒ get JSX and stuff. But then even our demo doesn't actually bundle the server and I think this isΒ actually the big missing part that it doesn't.
    • And the reason I think it's ideal to do it butΒ you don't have to, it's two things. One is that it's a little bit faster to just have a bundleΒ running in the Node environment in general.
    • But the other part is that we might want toΒ use the graph that we determined during the bundling of the server to determine what the bestΒ bundling strategy for the Client Components are. I know Tobias from webpack has some ideasΒ of even designing webpack to have a shared graph between a server bundle and a clientΒ bundle so that it would have this information. But that really depends onΒ  what your bundling strategy is. At Facebook we use a data-driven bundling approachΒ where we see previous visits and try to determine using a statistical model how bestΒ to group certain Client Components.
    • But if you don't have that you have to get asΒ much information as you can from a static build and a lot of the information is dependent on theΒ  server graph. So for example if you have a Server Component that always pulls in theseΒ three Client Components, you want to be able to know that as part of building the ClientΒ Components so that you know to group those.
    • But you don't have to because you can just buildΒ all the Client Components as a separate graph and treat all them as entry points but you don'tΒ have a lot of information then about how to group the best chunks. There's middle ground hereΒ  too, you could have something that doesn't actually run the bundling of the server but justΒ uses that as an analysis to feed into a client's bundling. But I think that the first approachΒ that we want to build, the missing pieces, is a unified approach where the out-of-the-boxΒ experience is that you build the server first and use that as input to build the client.
  • 1:00:30 Styling Server Components
    • Jae: Β I was thinking about CSS as well and with the Server Components can render UI, how will theΒ CSS get to the client at the right time when the Server Component UI is fetched, both inΒ CSS-in-JS and also CSS Modules. Especially if we're talking about how theseΒ Server Components might not... the code that runs them mightΒ  never be downloaded to the client, how does the client know to download theΒ  right CSS and put it in the right place?
    • Seb: There's basically three differentΒ strategies of these that we observed.
      • The strategy that we currently use at Facebook is basically aΒ static analysis where we analyze the file and then we create the CSS bundles, they're basicallyΒ  one bundle that has all the CSS more or less, and in that world you just haveΒ  to make sure that the analysis is able to traverse these files so that it doesn'tΒ  just traverse the client, it has to traverse β€” and that kind of ties into the previous question too,Β right β€” you have to have something that traverses the server files to find the CSS in them.
      • TheΒ other strategy is more like in the out-of-the-box experience with webpack with no plug-in whereΒ you can import a CSS file as part of the module. In that case it's kind of implied that ifΒ you load that file that the CSS file will be loaded with it. But there's noΒ explicit connection between the CSS file and the component, it's justΒ that you import it and it's there. That needs a little special consideration because thatΒ module won't be pulled into the webpack client bundle, so the dependency won't be there inΒ the graph. That's part of the thing that we probably want to add in our official webpackΒ plugin since that's a basic webpack feature, plugin since that's a basic webpack feature, and we have to do something clever like transformΒ the file so that it injects the call so that we know that this file is associated with thisΒ component somehow.
      • But the third option, I think, is the more common one which is whetherΒ you do it static or at runtime there's somethingin the component that determines that thisΒ  class name is associated with this component and it needs to be injected. Either it needs toΒ download the dependency or it needs to be done dynamically injected on the fly.Β And you can certainly do that, kind of, in userspace third-partyΒ code, but I think we actually want to expose a particular API for this case so thatΒ  you can say that "this is the class that I want to associate with this output". And if thisΒ output gets included in this part of the subtree then there's some metadata that goes alongΒ with that in the Server Component's response and then the client can inject that to load thatΒ CSS or to include that CSS in the server renderer. But I think that's going to be a missing pieceΒ that we'll have to add before it's really useful.
      • Lauren: I just want to add something really quick, notΒ specifically about CSS but I think this is also generally in the class of problems whereΒ some side effect that used to happen on the client now happens on the serverΒ so you need some way to keep track of all the side effects that happen β€” whether it'sΒ  logging or an error is thrown or it's CSS-in-JS that's being used β€” and thendepending on theΒ needs of your product replay that on the client.Like in the error case where we re-throwΒ the error or like in the CSS case you might need to request for that CSS or addΒ inject some CSS class to those components. So I think it's a very similar classΒ of problem that we were working on.
      • Seb: Yeah and we have a similar issue with Relay,Β right? Where we we want to emit a data dependency because we know from theΒ server that we need this data to be part of the clientΒ component we're about to render.
    • 1:05:30 Preparing for Server Components
      • Yen-Wei: Is there anything we should be doing today to makeΒ it easier β€” obviously we want to be able to adopt Server Components as soon as it comes out β€” isΒ there anything we should be prioritizing in our own codebase to help that migration eventually?
      • Andrew: so there's multiple layers to this. We mentioned upfront at the beginning ofΒ this chat that there is a dependency on some concurrent rendering features,Β  we've talked about this in the past before. Our next version of React, ReactΒ  18, will support concurrent rendering. Not all features of Server Components dependΒ on you being a 100% compatible with Concurrent Mode. But just by start adding Suspense boundariesΒ and starting to use Server Components in parts of your app you're kind of opting in those subtreesΒ into some amount of concurrent behavior. So we thought a lot about this and our rough strategyΒ is that you will upgrade your app to React 18 and basically almost nothing will change in termsΒ  switch to the new root API then there's like a fewΒ very subtle legacy quirks that we've gotten rid of but everything will still be synchronous. And thenΒ  as you adopt feature by feature, screen by screen, component by component, and some things will getΒ a little bit into the more Concurrent Mode side of things. So if you want to start preparing todayΒ there's some fixed upfront costs that you have to care of. And then there are thingsΒ that you can incrementally do later on. So one of the fixed ones, if you don't already have Node running, you might want to figure that out so that by the time you get toΒ like later this year or whenever that happens, that's already solved. A lot of people areΒ  already in that world if they're using Relay or to be Strict Mode compatible.
      • Andrew: We have an API today is you can start getting your componentsΒ  to be Strict Mode compatible. We have an AI called Strict Mode that we released a few yearsΒ ago that was designed to surface in development certain concurrency issues so that you can solveΒ  them now before Concurrent Mode is released. The basic things it does is it'll warn about someΒ  old class component lifecycles that just don't really work well in Concurrent Mode. A reallyΒ  important thing it does is it'll double-invoke pure render functions, only in development, toΒ try and flush out any possible side effects.
      • Andrew: We have a whole document describing how you can start wrappingΒ this Strict Mode around certain parts of your app to incrementally get things migrated over.Β That general strategy of starting small and then gradually spreading it out until you get more ofΒ your surface covered is roughly how we're going do it in a post React 18 as well. One thing that'sΒ important to emphasize is i think we might have been a little overly pedantic in the past whenΒ communicating about Concurrent Mode compatibility.
      • Andrew: What we've realized converting Facebook surfacesΒ to Concurrent Mode is that a lot of things that are theoretical problems just don't reallyΒ come up in practice that much. I mean it is annoying when they do arise but we've been ableΒ  to convert large swaths of our app with really not that many problems. So we are going to haveΒ  a way for you, even once Concurrent Mode is out to, for instance, if you have some old classΒ  components with unsafe lifecycles that are running in a part of your tree that's not usingΒ y concurrent features, there's really no reason for us to warn you about that. So we'll have a wayΒ to either opt out of those warnings and delay them until later once you actually do start adoptingΒ things, or use the Strict Mode component API to fix those ahead of time. But the generalΒ  message is we're working really hard to make sure it's gradually adoptable, and you only haveΒ to pay the cost of migration once you start using new features in a particular partΒ of your app.
      • So yeah, short answer:
        • if you want to start today you can start usingΒ Strict Mode to fix those issues and you should be hopefully very ready once the day comes to startΒ  incrementally adding features.
        • The one other thing I'll mention is that there is β€” my whole thingΒ  about how in practice you don't really tend to hit Concurrent Mode bugs β€” that is true of componentsΒ and Hooks. It's less true maybe of frameworks or infra-level code. So there will be some work, thisΒ is why we're planning to do a release candidate\ before we do a final release, because we're goingΒ  to do some work with open source library authors, particularly things that do a lot ofΒ state management type stuff or read from external data sources. Those are the onesΒ that tend to have the most concurrency issues, and so that's really important for us to addressΒ that the ecosystem is unblocked from being able to... by the time we go wide with the actualΒ release, people are unblocked from being able to migrate. But the nice thing about it, evenΒ  though that sounds scary, the nice thing about that is if we fix, for instance, I'm just gonnaΒ pick Redux, if we fix Redux for Concurrent Mode, we fix it for everyone. We already did this withΒ Relay at Facebook, we fixed a bunch of concurrency compatibility things in Relay, and as aΒ result everything at Facebook that uses Relay, which is tons of stuff, kind of mostly just workedΒ after that. Hopefully that provides some insight.
        • Seb: The other part is around how you do data fetchingΒ today. If you're interleaving data fetching into a normalized store and you're mixing and matchingΒ state and data that way, then it can be hard to to know how to separate the clientΒ  parts from the server parts. or a certain part of your app you mightΒ want to keep that ability, but for the parts where you're really thinking Server ComponentsΒ could be helpful, it's nice to be able to split out the data fetching parts from the state parts.Β And a pattern that's particularly useful for that is getInitialProps or getServerProps in Next.jsΒ because it's very clear that this is all the data that you need for the initial rendering pass orΒ  even you could potentially invalidate it too. And then for anything else that you need to do forΒ data to be more dynamic, that's a different thing. So that pattern, whether you use Next.js or not,Β is a good way to prepare because you can mostly put all of your getInitialProps or getServerPropsΒ data fetching into Server Components once you adopt them.
        • Lauren: I also wanted to add that inΒ addition to the points that Andrew and Sebastian were highlighting, when Server Components areΒ released in open source I think we'll also aim to open source some of the internal lint rules thatΒ we've written along with the conversion scripts that should help you get someΒ of your components converted to Server or Shared Components. For the conversionΒ script in particular, it doesn't actually change your application architecture orΒ the structure of your component tree, but it will identify components thatΒ can be or are Server- or Shared-safe, and if they are, then it tries to convert thoseΒ components and does a bunch of other stuff to make sure that renamed files are importedΒ correctly and whatnot.
  • Dan: From all of the points that Andrew mentioned and Sebastian in particular where if you can separate your client side state fromΒ the data requirements, that will go a long way in helping the conversion script understand whichΒ components are actually Server- or Shared-safe, and then it can do the conversion for you. We'llΒ  try to aim to release these along with Server Components. The timing may not necessarily matchΒ up but I will certainly try my best to do that.

Top comments (6)

Collapse
 
layzee profile image
Lars Gyrup Brink Nielsen

What do you think about Server Container Component wrapping Client-side Presentational Components?

Collapse
 
swyx profile image
swyx • Edited

let's not continue using that terminology. Dan has been distancing himself from it for 4 years and people keep repeating it like it is a necessary pattern in React. discuss this in 2020 terms - if you need the component to have state or effects, it should be a Client Component. If it doesn't, then you can make it a Server or Shared component.

When in doubt, make it a Client Component, that's what we've been doing all along anyway. Server Components are a purely optional addition.

Collapse
 
latviancoder profile image
Sergey Ryzhov

The props passed to client components need to be serializable though and most of the time containers are passing down callbacks which aren't serializable.

Collapse
 
layzee profile image
Lars Gyrup Brink Nielsen

How are we going to communicate up the component tree between client and server components?

Collapse
 
ahmetcetin profile image
Ahmet Cetin

Server Components rather looks like kicking the can down the road to me. Instead of getting "data-only" over the wire, now you send "html+css+rendered data". Plus if any child client component uses the data, you send that data as well.
twitter.com/ahmetcetin/status/1343...

Collapse
 
swyx profile image
swyx

put it in the RFC!