RFC: React Server Components

In this RFC, we propose introducing Server Components to React. We recommend watching our talk introducing Server Components before reading.
View the formatted RFC

Will any part of the server-side be tightly coupled to Node, or could it run on a different JS runtime (for example, Rhino in Java, embedded V8 using a library such as ClearScript for C#, ChakraCore, etc)?  The only mention of Node in the RFC is around debugging ("you would debug your API in Node") but it's unclear as to whether server-side components would be tightly coupled to Node or not. Perhaps this is intentionally an open question at the moment.
I see a comparison to the older ASP.NET WebForms technology in the RFC, but it'd be interesting to compare it to ASP.NET Blazor too, which is a newer model where the components can either run server-side or client-side (via compilation to WebAssembly).

From what I read, meta-frameworks refers to other React Frameworks like Next.js and Gatsby

There are some things I really think will help. As I saw, the following questions came up.
Use SSR
If we use SSR, there will be two scenarios:

First, Using SSR and server components at the same time: This absolutely ignores the idea.
Second, Using SSR and server components as part of the application: I think this is a challenging idea. Although, this scenario parts our project into two sections, and it's not cheap.

Without SSR
We send our texts, images, and many pieces of information using JSON. How should we deal with SEO?

Will any part of the server-side be tightly coupled to Node.js, or could it run on a different JS runtime

@Daniel15 No, React Server Components are decoupled from the JS runtime and can work in Node.js and other environments. The main thing to note here is that there are some aspects of how server/client components interact with packages, see the related RFC.

From what I read, meta-frameworks refers to other React Frameworks like Next.js and Gatsby

@8brandon Yup, we're referring to frameworks such as Next.js and Gatsby. I'll update the text to clarify.

@josephsavona other half of that question:
how feasible is it for any of this server functionality to work if your backend is not JS-based (ie, Python, Java, Go, etc)?

@josephsavona other half of that question:
how feasible is it for any of this server functionality to work if your backend is not JS-based (ie, Python, Java, Go, etc)?

Yes, also very interested because this would allow to push for React on many areas where other server tech dominates and cannot be replaced.

how feasible is it for any of this server functionality to work if your backend is not JS-based (ie, Python, Java, Go, etc)?

This an interesting area for potential future exploration. As noted in the RFC, one of the benefits of React Server Components is that they allow developers to use a single language and framework to write an application, and share code across the server and client. We can foresee an ecosystem of packages forming around Server Components (libraries to design to be called from Server Components or Shared Components) which would not be available to developers attempting to use aspects of the Server Components architecture from other languages. Similarly, using a different language for the server would likely prohibit (or at least complicate) code sharing. Further, we expect to continue iterating on the response protocol for Server Components ("streaming JSON with slots") and are not yet ready to standardize it, which would be a prerequisite to making interop libraries for other languages. In summary, this is an interesting idea but it feels a bit premature.

Server Components are great idea, it will change the game!
One thing is that it would be pretty good to allow insert Server components into Client components as memo component. So every time when the props are changed we request server component to rerender and return the output.
import MyServerComponent from "./myServerComponent";

export function ClientComponent() {
  const [id, setId] = React.useState(0);
  return (

      <button onClick={() => setId(Math.random())}>Select other id</button>
      <MyServerComponent id={id} />

  );
}

So there will be pretty seamless integration and it will simple to extract heavy logic to server.
One question is how to import server component as you can't literally import this file.
Maybe something like this
const MyServerComponent = React.foreign(() => import('./myServerComponent'));
So there will be actual HTTP request to server, and server will be able to understand what component it needs and return an export object for react, also this component can be placed on any arbitrary URL. IDE along with TypeScript will understand what component is actually used in MyServerComponent variable. In addition you can delegate such kind of code to bundlers or transpilers so they can optimize it if you need, anyway in raw JavaScript that will also work.

heh, translating:
"It's still experimental, we're still iterating, we're really focused on doing everything in JS for now for simplicity's sake.  We won't rule out it maybe working with other languages, but we're not gonna worry about that for now".
Fair summary?

The "why not use async/await" section of the FAQ IMO needs more detail. I think y'all have made the wrong call here.

Why don’t use just use async/await?
We’d still need a layer on top, for example, to deduplicate fetches between components within a single request. This is why there are wrappers around async APIs. You will be able to write your own. We also want to avoid delays in the case that data is synchronously available -- note that async/await uses Promises and incurs an extra tick in these cases.

A layer to deduplicate fetches sounds great, but that library could use async/await, too.
As it stands, libraries like react-fs and react-fetch appear to be synchronous, and they might be synchronous, depending on the status of the cache, but they might not be synchronous; there's no user-visible way to know. https://github.com/facebook/react/blob/master/packages/react-fs/src/ReactFilesystem.js
Using async/await will make this code substantially easier to understand, and the cost of a "tick" is trivial (and worth the price, especially in server components).

@markerikson I appreciate that you're trying to get a clear takeaway. However, there are a lot of considerations here and I worry that trying to distill the complex tradeoffs I alluded to into a short summary may not be helpful to folks.

My initial thoughts after watching the video are this:
I would say that the 'status-quo' has been all Components in peoples projects can either be thought of as 'Isomorphic' if that codebase is using server-side rendering, OR if that code base is not using serer side rendering then they're all 'client' components. For me personally I feel that introducing an API like this will now cause a abstraction layer where people using server side rendering will now need to think about 3 kinds of components instead of 1 (server/client/isomorphic).
For me and our team currently the biggest problem we have is scaling React applications which seems to start getting very hard around the (350+ routes) mark, I feel like this RFC although helps performance it hurts scalability as now we need to consider the implementations and find bugs in 3 types of components instead of 1.
Would be good to hear other peoples thoughts on this.
These are some observations on the API which a purely based on my opinion:
BundleSize / Server side code.

Removing a 83KB (20KB gzip) library isn't a big deal, I would say the bigger problem here is that you're using a 83KB library to format dates.
There's already methods to remove these libraries and allow for sever side code
1: babel-plugin-preval allows you to use server-side code (at build time).
2: NextJS has an implementation for getServerSideProps (server) and getInitialProps (isomorphic) that use the current implementation of React to achieve server side code, and potentially tree shaking in a very simple abstraction.

// tree shakes out date-fns
ComponentName.getServerSideProps= async (ctx) => {
      const { format } = require("date-fns");
     return {
           formatted: format(new Date(), "M/d/yy")
     }
}

I will concede that the API you're proposing is more powerful. However the point being made here is that there are already methods out there currently that exist to achieve the majority of this API's functionality in peoples projects.
Data Fetching

Already possible with relay as mentioned in the video
Already possible probably through build tools if your routes are structured in a way that can be statically analyzed you can probably use a combination of pre-rendering, examining the data dependencies and "lifting" that into the parent during build time. (No implementation's seem to exist yet, but I feel like NextJS is starting to cause alot of innovation in this space).
Already possible in an infinite number of other ways as JavaScript is a very dynamic language I've posted a simple implementation below.

export const Person(data) {
     return {data.name}
}
Person.data = () => api("/api/person")

// and if that Person has a dependency to fetch its data.
export const Person(data) {
     return {data.name}
}
Person.data = (id) => api("/api/person", {body: {id: 1}});

Just traverse your React sub-tree from the parent and run all the data methods. Your API is definitely cleaner and I wouldn't recommend to anyone to use the above code, its just there to show that its possible and its definitely possible in other ways as well.
XSS

Just going to leave this here as a note that if you allow JSX to be serialized and sent over the network just XSS needs to be considered as people could save user-input as a script with dangerouslySetInnerHTML OR a iframe with data:uri with a script tag. There's definitely some ways to implement this RFC that can avoid this being possible just thought I'd mention it.

One of the reason I loved hooks is that it solved REAL problems for us that were currently preventing scale in our React applications, where-as I feel like for me personally this doesn't solve real problems I'm currently facing in my React projects.

I really liked the bundle size reduction for the code that is rendered on the server, specially when it comes to third-party packages that are not doing great a job in code splitting and tree-shaking,
however the data fetching has limited use cases IMO.
The idea of decoupling backend and client for large scale applications (microservice architecture) will really stop people from thinking to fetch data from components, I still strongly believe it has it's own use cases for static marketing websites or smaller scale apps.
I am still impressed with the work, thank you for making web development easier and more accessible everyday.

I feel this RFC should discuss the nuances of how deployments will need to be handled. Deployments require two versions of the server side code, and two versions of the client side code to all play nicely together.
It's relatively common to ensure an API is backwards compatible for one or two deployments before cleaning up the old code. However, what does it mean for a Server Component to be backwards compatible?
For example, the heuristics with an API: "adding new fields" is just fine, "removing fields" needs extra care.
What are the heuristics for a Server Component? Currently it seems like a size (height or width), scroll-type, or even theme change will be backwards incompatible.

I read the RFC and I am very confused by this sort of code:
import db from 'db.server';

function Note({id}) {
  const note = db.notes.get(id);
  return <NoteWithMarkdown note={note} />;
}

All the Node APIs are async - so in the above db.notes.get(id) returns a promise (or blocks Node.js for every other user using it). How are users supposed to work around this in server components since according to the RFC there are no effects or async/await?

XSS

@ShanonJackson Thanks for raising this point. We considered security from the start when designing this proposal and the streaming protocol guards against injection attacks. I'll add a note to reflect this.

Actually I installed the experimental version of react-fetch and I see it's just suspense - it might be beneficial to release an adapter for "generic" Node APIs that throw when the promise is pending.
Interesting.
(As a random nit - you're using Resolved to mean Fulfilled in the code)

This is interesting concept, however I'm not sure for how large portion of the react community it actually solves any problems. If I understand correctly I can't use this (or I'm limited in using this) when I'm

not running javascript on server
using mutable state (ex. mobx)
using non-serializable state (ex. symbols, classes)
depend on reference equality

Considering these points I'm very unlikely to ever use it, so let me ask - how pay to play is this? How aware do existing react packages need to be of this existing? Does it affect performance/bundle size even when I'm not using it?

using mutable state (ex. mobx)

Why would that not work?

As a side note, I think it's worth exposing (in a react-server-components package or something) the utilities used throughout things like react-pg and react-fetch like createRecordFromThenable and readRecordValue.

@benjamingr I may be wrong, but I don't think the server side component can be made observable, so it wouldn't update when property of an object passed in through prop changes. I also believe observability is stripped from object when going through serialization (getters/setter/proxy information is not serializable).

@dfabulich (and @benjamingr) With respect to async/await and the data-fetching APIs uses here, I've updated the FAQ to include more context.

I feel this RFC should discuss the nuances of how deployments will need to be handled. Deployments require two versions of the server side code, and two versions of the client side code to all play nicely together.

I think it would be fair to consider this outside of this scope. My expectation atm is that this will lead to bundlers outputting something like a manifest from which you can find out whether a chunk is relevant for the server and client. Then you'd have a thing in the server which knows how to read that and use ReactDOMServer to render the relevant bits.
Now to get to your point: In that model you'd just need to be able to point the thing towards the different build artifacts depending on, for example, a parameter in the HTTP GET.

Please, rather than demonstrating server components on a TO-DO app that doesn't even require login, consider trying to solve more widespread challenges in your demos. Such as validating an e-mail address on a form, both client and server side. Client side to check formatting quickly and server side to check both formatting and if the entry already does exist in a backend db. Form validation is something that always needs to be done server side because of user trust issues and also client side for non-malicious user friendliness.
Also please, consider making these server components run on any JS environment such as https://github.com/phpv8/v8js and make sure they work on clustered environments and with keep-alive connection. Consider making already rendered server components to be re-usable between different clients. Don't let the same code re-run and components rerender on every request.

Really interested what this would look like in a serverless environment. (react lamba?)

I'd love to see a section about (unit) testing be added to the FAQ.
I.e. Jest today works without "bundling" code, it will read code from FS and execute it in either a Node based environment or a DOM (via JSDOM) based one. Is the idea that in order to run tests you'd have to create separate bundles ahead of time based on whether you wanna test the server or client side (or a third bundle which somehow combines the two) or some sort of clever renderer that does the correct thing? Or is the current thinking that people keep writing the same tests they do now, but ensure to only render one side of the "equation" (client or server). Or maybe even some sort of deeper integration to do something that makes it more seamless

make sure they work on clustered environments

@phaleth the RFC says:

We are running an experiment with a small number of users on a single page, with encouraging results (already ~30% product code size reduction)

and Facebook probably has one of the largest server clusters in the world 😄 . Anything that's built has to work "at Facebook scale"

It would be nice to support a custom serializer for props. In our codebase, we'll transfer data across JS contexts and "resume" their prototype. I think it will also apply to the Server Components. A class T is loaded on both server and client, and the same serializer is configured then it's possible to serialize T from server to the client.

All Components in peoples projects can either be thought of as 'Isomorphic' if that codebase is using server-side rendering,

It seems impossible from the current demo, because useState and useEffect() will no longer be supported.
I probably took a look. From the overall demo, it seems to be useless, because our components cannot be all server components, nor can they be bundled with zero, because we need useState() and useEffect(), these are not available on the server, unless the same as ssr twice water injection, but in that case, why don't we use ssr?

Congratulations and great explanation! This is going to make awesome to generate static pages.
Then I saw several things:

I don't see any mention that the server component props come from the parent component server or the Request object of Node.js, besides, Node.js is not mentioned once
The development tools should not show anything about what the server does(This means that React does not store too much information from the server), it would be a security problem if someone installed a React Developer Tools extension and saw everything the server does to exploit it.

Having this system in other server languages such as PHP 👀, would also be impressive to use as my preferred template system.

For PHP, bridges might be made with v8js or webassembly. Also via wasm it should be possible to link other languages like C and Rust.

This is great! Only downside is having to maneuver the interactive pieces into separate components. It might be useful to add a built in ClientComponent wrapper into the top level React API that on build could be bundled into its own separate client component. I would see a lot of value in something like this:
// MyServerComponent.server.js
const serverData = fetch(“http://localhost:4000/data”);

  return (

{serverData.title}

          <React.ClientComponent uniqueIdentifier=“my-example”>

I’m a client component rendered inside a server component

              <button onClick={() => console.log(“clicked!”)}>Click Me</button>
          </React.ClientComponent>

)

React Bundle on build:
.
├── src
│   ├── Foo.js
│   └── Bar.js
│   └── extracted-client-component-my-example.js

I was a little confused in the demo... why can't you achieve serialization of functions by just using JSON.stringify() and comparing the implementation?

Congrats on the release of this! There's obviously been a huge amount of work on the design, implementation and presentation.
I really like the idea of rendering per request - like Dan said in the video, it feels a little like the good old days. I do hope that we're not also going to go back to a situation where every navigation action requires React to contact the server - but it sounds like that's going to depend on how routing is handled. I'm very curious to see more discussion on the research you're doing on this.
I'd also love to hear the story on authentication. The way I see it, authentication information is part of the "request" that the server is rendering - and probably should be handled by the router. However, at non-facebook-scale, authentication is often handled by client-side APIs provided by the likes of Auth0, Google or AWS. If routing happens on the client, this is easy enough to integrate. But with server components, routing needs to happen on the server. And while auth APIs do provide ways to generate separate tokens for use on the server, connecting it all up in such a way that you can consistently get the same result from a fetch() called on the client and the server takes some work.
Another comment as a non-facebook-scale developer is that I want a mechanism to make multiple IO calls in parallel, similar to Promise.all, but for Suspense. From what I understand, the current idea is that because IO is running on the server, each IO call should have a low cost, and thus the waterfall effect should be insignificant. However for smaller companies, the reality is often that to render a single page, we'll need to access multiple data sources across different regions
.
As an example, some content may be accessed via a headless CMS API hosted in the Midwest, while other data may be hosted on a Heroku Postgres db (which only provides non-specific "us" and "eu" regions that could be located anywhere). If you want to check that the auth token hasn't been invalidated, then that's another check to probably another region. And there's no guarantee that the web server orchestrating all these requests will be anywhere near any of these services. While a Promise.all equivalent won't solve this completely, it'd certainly make it a little less painful.
One last thing I'd like to see more discussion on is how data fetched on the server can be automatically passed to the client to use as the initial value for a cache, without needing to manually extract it on each request and pass it as a prop. For example, say you make a GraphQL query in a server component, and you want to then start a subscription to that same query on the client. How do you do this cleanly, without making an unnecessary request on the client, and without needing to duplicate code across the server and client components?

On a different note, while I can see that this will certainly simplify application code in a lot of cases, I'm a little worried that this will cause a split in the ecosystem similar to the python 2/python 3 days. At the risk of stating the obvious, server components require a server. React, at least until now, hasn't required a server. Any improvements in DX that server components provide will only be available to people who are willing and able to deploy a React server. Many legacy apps won't be able to do this, while many others will choose not to. In effect, we're going to end up with two very different tools with two very different ways of doing things. I'm worried that it'll be a little confusing if they're both called "React".
This really does look pretty neat though. I'm looking forward to giving it a try.

Throwing my two cents in! It seems like Server Components relies on the theory that rendering components on the server will always be "faster", but it is glossing over how much "work" that entails to be true at scale.
Introducing web server(s) that might get hit with anywhere from 5-10 "component requests" per page on average, each of which might be requiring database queries or third-party API lookups, is only going to work if you really invest in an infrastructure that keeps all of that data close to this "component server", constantly up to date, and automatically scalable for any sudden traffic spike (because if the server gets overwhelmed... you're frontend is gonna be stuck loading forever). And of course there would have to be a great deal of thought put into deployment/rollback synchronization, caching, etc. of this component server to ensure the deployed frontend assets always match the server, otherwise your client-side hydration would likely fail.
Maybe Facebook doesn't have to worry as much about introducing these infrastructure architecture challenges, because there is undoubtedly an army of engineers on standby to solve that. But many of us have to think critically about budgeting time to maintain API's with all of those same reliability & scalability requirements, but now we'd have to add another critical system to our infrastructure, just to make a handful of UI components maybe render a few milliseconds faster.
It just doesn't sit right with me that a UI library would introduce all of these infrastructure requirements (it is weird we are even talking about infrastructure in the React repository!), especially given that there are a lot of improvements that could be made to the existing process of server-side rendering, something that almost all of us depend on, and frameworks are already doing some really interesting work around this.

I have created similar working solution some time ago.
You program components which are fully server-side inside your browser using React-like syntax.
You can use anything nodejs has (fs, databases, etc.).
It also stores state (like you can see in demo counter variable).
Browser only receives JSON-structure of what it should render and sends actions to server via websockets.
It also has lifecycle - component is created on server in separate process until user navigates away from it.
If you are interested, I can share some info in more detail.
https://user-images.githubusercontent.com/5667073/102872479-66ebde00-4448-11eb-9d9a-7e767a2cb4b2.mp4
On the left side you see a browser with code editor + component previewer.
On the right side you see opened VS Code with the file which is saved by a component.

I understand that it is similar to using the hack to avoid hydration, but that it also avoids downloading the JS involved, that's awesome! Moreover, it makes automatic dynamic imports... It looks very good, but I wonder if this will have a downside of doing the imports automatically...
As I see, the initial loading of the example downloads 6 .js files. They are small but there are 6. What happens in big applications where there is a lot of content with a big scroll? Is downloading only the components that are visible to the viewport and it downloads the rest progressively while scrolling? Or is it something that we will have to continue controlling?
Even if HTTP 2.0 is used, I understand that more than 20 req per page to download all the client components could be harmful, and IMO it should prioritize those components that are visible in the viewport.

How about Server Component with auth?
Server Component with logined state? JWT? Session?
Should I Handle permission before render Server Component?
If Server Component require some sensitive data?
React Server Component is awesome.
But, we still need time to get a best practice.

This looks exciting. Perhaps I've missed something, but is it not possible for server-side components to subscribe to data and send subsequent changes to the client? This seems like a glaring omission, particularly for dashboard monitoring type screens.
We've been working on our own server components system for the past couple of years but ours is quite different to this. Our system allows any component to be given a corresponding server-side portion that deals with data fetching. When the component is mounted on the client-side it subscribes to the server-side which effectively "mounts" the server-side (although it's only for data, it doesn't do any rendering), which in-turn allows the server-side to subscribe to data that might change and send those change events down to the client. It's effectively an extra layer of state, although we don't allow the client to make changes to it directly, and it's provided through a context object on the client.
The server-side portion can also declare actions that can be called by the client-side, but they can only run if the server-side component was allowed to mount in the first place, which makes permission checking so much simpler.
React clearly needs something to make it easier to fetch data directly on the server and this proposal looks like it will help with the initial rendering case, but it doesn't seem to address ongoing subscriptions and I would be interested to hear what the React team thinks of our approach to this.
We're generally working on 'live' multi-user dashboard type applications so perhaps our use case is very different. We don't currently have a way for a component to load some data from the server-side portion without keeping an active server-side subscription, which isn't really appropriate for a more traditional website where you just want to load the page once for the user to read. Although I'm sure it would be easy for us to do this.

I must admit, after reading and watching the video - I fail to see how this isn't just a form of view data wrapping the actual requested data, and do not see what additionally it provides that couldn't be done in a resolver or standard api. The example of reducing bundle size equally applies to doing date formatting server side and optionally requesting it via a graphql call or such.

Seeing as you are still making trips to the server, I fail to see how Server Components will be any faster overall.
If you have three components and two of those are server components, wouldn't that require two trips?  How is that faster than two api calls?
I can understand the performance if they are all nested under a single top Server Component, which is the only trip to the server but this seems like a least useful implementation.
Example
non-performant server side components
import SpotifyArtist from './SpotifyArtist.client';
import SpotifyDiscography from './SpotifyDiscography.server';
import SpotifyAlbums from './SpotifyAlbums.server';
import SpotifyArtistInfo from './SpotifyArtistInfo.server';

<SpotifyArtist>
    <SpotifyDiscography artistId={artistId} />
    <SpotifyAlbums artistId={artistId} />
    <SpotifyArtistInfo artistId={artistId} />
</SpotifyArtist>

performant server side components
import SpotifyArtist from './SpotifyArtist.server';
import SpotifyDiscography from './SpotifyDiscography.server';
import SpotifyAlbums from './SpotifyAlbums.server';
import SpotifyArtistInfo from './SpotifyArtistInfo.server';

<SpotifyArtist artistId={artistId}>
    <SpotifyDiscography artistId={artistId} />
    <SpotifyAlbums artistId={artistId} />
    <SpotifyArtistInfo artistId={artistId} />
</SpotifyArtist>

Am I missing something or not understanding something with this proposal?
Wouldn't a better method be a way to chain all the api fetching method together so that all three calls are made at once (parallel)  and then resolved all together?  That way you get the best of all three world (fast, good, cheap).  Something to how dataloader works but with api calls? This could even be tied into Suspense, but you get the ability to wrap each Component in Suspense and your UI feel like a single page while if you need to update a single component down the line, only it would be  held in Suspense.

Am I missing something or not understanding something with this proposal?

@Prefinem as the proposal stands it’s not even possible to use client side components if the top level component is a client side one as client side components can never render server side ones, at least not directly. So it’ll always be the “performant” case

As @cangoektas just mentioned in a now collapsed comment, "Server Components are praised as a solution to the waterfall problem when they would only (as of right now) minimize the symptoms of it."
Waterfalls haven't been eliminated, they've just been moved to the server.  For something like the demo, where the database is running on the same machine and you're making simple queries against tables with 5 rows, yeah, it's no longer a big deal that there's waterfalls.
But the further your frontend server moves from your backend API servers, the more pronounced network latency and therefore the waterfall effect is going to be.  For Facebook, where these servers live in the same data centers, the network time is likely much less pronounced.  But if you have APIs whose latency is primarily due to computation time or you're running your frontend server on the edge but still have centralized backend APIs, I doubt this is a fully solved issue.  I'm not saying moving the waterfall to the server is without benefits.  I am saying "No Waterfalls" is a bit disingenuous.

@Prefinem as the proposal stands it’s not even possible to use client side components if the top level component is a client side one as client side components can never render server side ones, at least not directly. So it’ll always be the “performant” case

Then isn't this just SSR?  I assume that once an app has loaded on the client, there will be components if they are loaded, they will make the trip to the server (hence server components).  From the demo, when a note is selected, it loads the note in the app without doing a full page request. (at least this was my thought when I watched it)

All the Node APIs are async - so in the above db.notes.get(id) returns a promise (or blocks Node.js for every other user using it). How are users supposed to work around this in server components since according to the RFC there are no effects or async/await?

All of the calls in the demo are asynchronous. We model reads as reads from the cache, and if the entry is missing in the cache, we throw and retry when it's fetched. We'll describe this mechanism and the reasoning behind it in a future separate RFC.

Another comment as a non-facebook-scale developer is that I want a mechanism to make multiple IO calls in parallel, similar to Promise.all, but for Suspense. From what I understand, the current idea is that because IO is running on the server, each IO call should have a low cost, and thus the waterfall effect should be insignificant. However for smaller companies, the reality is often that to render a single page, we'll need to access multiple data sources across different regions
.

Please note that calls in sibling components are parallelized with Suspense. However, for server Parent-Child waterfalls, when those become a problem, there would be an ability to "preload" requests early as an additional opt-in optimization.

However the point being made here is that there are already methods out there currently that exist to achieve the majority of this API's functionality in peoples projects.

Indeed, none of these problems is unsolvable in isolation. But we felt that there was no cohesive solution that solves them together in a way that feels idiomatic to React, in a way that scales up and down, and in a way that doesn't require specialized knowledge. This proposal is a refinement and a remix of different ideas from different sources.

The development tools should not show anything about what the server does(This means that React does not store too much information from the server), it would be a security problem if someone installed a React Developer Tools extension and saw everything the server does to exploit it. As they do now with GraphQ, that from the client you send and GraphQL gives you what you want.

We were only referring to the development environment — where the code would likely run in a Worker rather than a Server. It should not be possible to access a production environment in this way.

I was a little confused in the demo... why can't you achieve serialization of functions by just using JSON.stringify() and comparing the implementation?

Functions close over other values, so you can't transport code this way unless you literally transfer the JS bundle, which puts us back at where we are today.

Introducing web server(s) that might get hit with anywhere from 5-10 "component requests" per page on average,

To be clear, there are no separate "component requests". We request the whole Server tree — one request per navigation, with a streamed response. For refetches, we'd be able to request a refetch of either the whole tree (similar to a page reload) or a subset (e.g. a sidebar), with refetch granularity determined by the developer.

If you have three components and two of those are server components, wouldn't that require two trips? How is that faster than two api calls?

Same, you wouldn't have two responses for the same reason that when you request a page from Django and it uses two templates, you still get only one response. They are composed on the server.

frameworks are already doing some really interesting work around this.

This proposal was designed in collaboration with the framework you link to. :-) There's undoubtedly good work there, and we want to provide the missing building pieces to make it more powerful. But nothing stops you from keeping to use the existing techniques if they fully satisfy you.

As I see, the initial loading of the example downloads 6 .js files. They are small but there are 6. What happens in big applications where there is a lot of content with a big scroll? Is downloading only the components that are visible to the viewport and it downloads the rest progressively while scrolling? Or is it something that we will have to continue controlling?

I think you're misreading the example and seeing the sourcemaps — i.e. the original files. There are way fewer bundles than that. Still, the work to determine an optimal bundling strategy and heuristics will be a part of productionizing the bundler plugin. The actual granularity is not inherent to the approach — we can make it as coarse or as granular as needed.

but is it not possible for server-side components to subscribe to data and send subsequent changes to the client?

Server Components are not stateful by design — they don't "run" on the server. They are much more similar to a classic request-response model. You can still use Client Components to subscribe to streams of data.

But the further your frontend server moves from your backend API servers, the more pronounced network latency and therefore the waterfall effect is going to be.

@mlrawlings Servers tend to have better connections though, so a waterfall on the server-side isn't as bad as a waterfall on the client-side. Servers typically have very fast (1 Gb/s or 10 Gb/s) connections that are higher quality with a lower contention ratio than residential connections.
It's also easier to optimize the server-side. For example, if the database is in a different location to the web server, you could have a Memcache server in the same location as the web server to cache hot queries. Similarly, it's easier to batch similar queries together on the backend, which is what we do at Facebook (if there's multiple concurrent requests to load data from the "users" table, it'll combine them all into one query).
I agree that the heading "No Waterfalls" is not ideal though. Maybe it should be "No Client-Side Waterfalls"?

@gaearon I appreciate the response! The core point I was trying to raise is, the level of work involved to successfully leverage server components is quite high, and the pitch of server components obfuscates that point.
To be clear: I'm not making an argument that Server Components should never be implemented, I certainly think with more refinement the API could land somewhere quite useful & neat. But I do hope this doesn't reprioritize the roadmap away from fully implementing partial rehydration and other SSR performance improvements that could have immediate wins for everyone already relying on SSR & an existing architecture/codebase they need to maintain.

this definitely looks interesting, similar approaches have been taken by other platforms like Phoenix LiveView https://github.com/phoenixframework/phoenix_live_view

This is super exciting and the RFC is really well put together. Did the team consider allowing for server components to be nested inside of client components? I understand why this isn't allowed because it would be a pretty big foot gun that could reintroduce waterfalls on the client side again. I can think of a few really useful examples of wanting to do this, ex: you might want to render a server component inside of a modal that only opens when the user takes a certain action.
Is the suggested way to do something like this have a server component that passes the modal to a client component and add a query param like ?modal=share to the route to signal that a modal should be rendered?

Overall, I really like server components. I think it's wonderful addition to the React model, and it's something novel (at least to me) that fundamentally changes React to more than just a CSR lib.
There were previous comments that discussed some hesitancy to this model because of this but my opinion is that that's okay — what they're trying to do requires this careful orchestration that's not possible without some of the React core model updates. They'll release some webpack plugins, some babel plugins, and some new client-side APIs but what I always appreciate is that these new tools are opt-in and current React is still React.
Before I get into some of my other comments, I just wanted to say I really appreciate that you're working with the Next.js team to bring this to life. Next.js already gives our app a lot of performance benefits by utilizing pre-rendered SSRed pages (i.e. the "jamstack") and working with them should create a well-rounded, performant vertical that's relatively cheap to host if paired with pre-rendering/the jamstack.
Next.js has already made us comfortable making similar tradeoffs between what's client-side rendered vs what's server-side rendered, and what's dynamic vs what's static. Adding another choice between server component vs client component should pair well.
To talk more on the Jamstack, I can already see a future that combines pre-rendering with server components. During a build, Next.js could pre-render all server components and then cache them on the edge for effectively zero runtime on the server too lol
To repeat my first point, this all requires careful orchestration and infrastructure so, Next.js paired with Vercel is kind of the perfect pairing of infrastructure, bundler, and framework to make it possible (though admittedly kind of monopolistic).

I have 2 feature requests/concerns
Reuse more work from SSR
I apologize if this is already the case but my impression was that the current implementation does not behave like this.

Does this replace SSR?
No, they’re complementary. SSR is primarily a technique to quickly display a non-interactive version of client components. You still need to pay the cost of downloading, parsing, and executing those Client Components after the initial HTML is loaded.
You can combine Server Components and SSR, where Server Components render first, with Client Components rendering into HTML for fast non-interactive display while they are hydrated. When combined in this way you still get fast startup, but you also dramatically reduce the amount of JS that needs to be downloaded on the client.

Why don’t you just use HTML instead of a custom protocol?
We do want to use streaming HTML for the initial render, but the custom protocol lets us transfer data (component props), and reconcile trees so that the client state as well as DOM focus/scroll/state doesn’t get blown away.

Reading the RFC and the above, it does not seem like it's a goal to re-use the work done from SSR when trying to hydrate server components. Maybe this is complicated because of some constraints with reconciliation, but I think there's an opportunity missed if this goes without.
Let me clarify with an example where the traditional SSR + CSR hydration model falls short:
When writing a blog post component with Next.js today (as an example of typical SSR + CSR hydration), the client first downloads the fully server-rendered version of the blog post as HTML. This HTML contains all the content of the blog post in already in the HTML yet the browser downloads this content again in the JS when it goes to download the code to re-hydrate the server rendered version.
Since server components are non-interactive, it seems like it should be possible to re-use the work done in SSR so that that content only needs to be downloaded once. This is where I think it make sense to use some variant of the "custom protocol" that is also HTML so that SSR work can be re-used during hydration. The logic could be "check DOM if server component is already rendered, otherwise make network request to server".
My assumptions might be wrong here but that's what I read into when reading "custom protocol". Any clarification on this would be greatly appreciated!
Allow no-op useEffects in Server Components (e.g. for shared components)

Sharing Code Between Server and Client
❌ May not use rendering lifecycle hooks such as effects.

This kind of took me by surprise. I understand that they cannot work but I don't yet fully understand why I can't put in a useEffect that will simply no-op in the context of a server component yet work in the context of a client component.
Maybe I'm just coming from the perspective of being used to writing SSR and CSR compatible components, but I'd love any help explaining why it won't work or why it just doesn't make sense.

The reason we loved hooks is it allowed us to SIMPLIFY a lot of our stateful logic and scale through reusability. There was a tradeoff with abstraction where now we have to think about closures and dependency arrays but this trade-off was judged to be worth it.
The reason we loved Suspense is it allowed us to SIMPLIFY a lot of logic related to data fetching and spinners allowing us to write "synchronous" looking code, the same way async/await allows us to write "synchronous" looking code. Again There was a tradeoff with abstraction to include throwing promises in your data fetching logic and thinking where to position your Suspense components.
The reason I don't like this is that it doesn't simplify for the consumer, it makes things significantly more complex for the sake of a tiny performance gain. I would rather optimize my bundle size and critical network path through other methods before resorting to server/client components. If you're adding abstraction the trade off must be worth it and for me in this case its not.

@gaearon  I agree that the things listed in my earlier post here AREN"T idiomatic React, however if the benchmark we're setting is for a solution to be idiomatic React this RFC is also not idiomatic React. It's trying to mold idiomatic React to include differentiating components by render environment.
Here's some more thoughts just generally about the direction being taken here and why I like it, but just not this RFC
Should React really be shifting their focus from innovating in the client to innovating in the server? Does this make sense as a frontend framework? (I think yes, but not for this feature, but again the community should have a say).
I do however think there is a case for 'no' it shouldn't be innovating on the server, not everyone uses SSR and not everyone has a NodeJS backend. I think only a small fraction of the community actually uses this functionality and a micro-fraction of that fraction has the same problems Spotify and Facebook do at scale. I do not think the problems of a small minority should be driving the direction of the library.

How would server components support cancellation and race conditions between server tree re-fetches? Would there be a mechanism to invalidate and ignore stale responses (on client) and to stop processing existing renders (on server) based on the recency of incoming requests? (E.g. A find-as-you-type component powered by server side components)
Promise based APIs are notoriously bad at this and it would be nice if developers didn't have to worry about Signals and AbortControllers for each server side component they develop.

Server Components are not stateful by design — they don't "run" on the server. They are much more similar to a classic request-response model. You can still use Client Components to subscribe to streams of data.

I think this is the reason why React has become a framework. In fact, it is impossible for all components to be stateless, so 0 bundle size is also impossible.
I think the mental burden of this feature (stateless, no runtime) are very heavy. In the future, users should not only care about class components, hooks components, but also server components. React has become more and more frameworked, which is not a good thing. At least for me.

The example in the video mentioned moving the date-fns dependency to the server as a benefit of server components.
Wouldn't this actually be a pitfall since the Date library depends on local timezones of the machine and this code would now be executing on the server (using that machines timezone)?
Some of the limitations of this pattern are outlined, such as not using state or DOM functions, however it seems that, as occurred in the example of the announcement, it will be very easy to let hard-to-find "bugs" be introduced when writing code for server and client components.

Wow! This looks very cool. Really excited to try this out.
@gaearon you briefly mentioned using Server Components with GraphQL, would it be possible to have some examples to see how this would look like when paired together and how to use those two technologies optimally?

How about to use server components in the future in the React Native?

Further to my previous thoughts... isn't this just a new "content-type" for a returned API call "text/react-component" - as essentially all we are doing is reformatting the API call that we make. We could then fetch these / stream or whatever we need and treat them as data.

But I do hope this doesn't reprioritize the roadmap away from fully implementing partial rehydration and other SSR performance improvements that could have immediate wins for everyone already relying on SSR & an existing architecture/codebase they need to maintain.

I don't quite understand what you mean by "partial rehydration" here so it would help to clarify your expectations about this concept. Generally saying, we've already implemented the kind of SSR improvements that are possible in the React model without breaking its guarantees. In Concurrent Mode, we can:

Start hydrating parents before all the code for children has finished loading.

Try our best to preserve unhydrated HTML even if the relevant code isn't loaded yet.

Hydrate in chunks instead of stalling the main thread.
Prioritize hydrating the part that the user has started interacting with.
Replay some of the events that happened before full hydration.

But there is a limit to what we can do here. So Server Components is about taking a bigger step forward, with async data fetching, automatic code splitting, and so on. They build on top of SSR improvements, not replace them.

Did the team consider allowing for server components to be nested inside of client components? I understand why this isn't allowed because it would be a pretty big foot gun that could reintroduce waterfalls on the client side again. I can think of a few really useful examples of wanting to do this, ex: you might want to render a server component inside of a modal that only opens when the user takes a certain action

Note you can nest SC into CC as long as the nesting itself happens in another SC above it. But generally saying, there is always some kind of an "entry point" into the SC world, and you're right in some cases it makes sense for this entry point to be "lazy". We shouldn't make this too easy like you said, but technically this capability will definitely exist, including for the use case you mention. Although that use case might also have a more idiomatic solution on the server side.

Is the suggested way to do something like this have a server component that passes the modal to a client component and add a query param like ?modal=share to the route to signal that a modal should be rendered?

Yes, something like this might work. Routing is still an open research area, and lazy interfaces like tooltips, modals, etc, will be a part of that research. We need to get Server Context support in first before exploring this.

To talk more on the Jamstack, I can already see a future that combines pre-rendering with server components.

Yes, this is definitely something we want to support.

Since server components are non-interactive, it seems like it should be possible to re-use the work done in SSR so that that content only needs to be downloaded once. This is where I think it make sense to use some variant of the "custom protocol" that is also HTML so that SSR work can be re-used during hydration. The logic could be "check DOM if server component is already rendered, otherwise make network request to server".

The intention is for the first render to never need another request to the server. The HTML streaming renderer would embed the JSON chunks in the HTML response so that we both get the fast non-interactive render, and then get to interactivity as soon as possible. There is still some duplication between HTML and JSON, but note how this is different from today's solutions that serialize the whole server-side cache content — because we only serialize what's actually on the screen. Additionally, we can be clever about the encoding and avoid repeating text — e.g. the JSON could have special markers like "$H" that tell React to reuse the HTML text node's value. Since we know it won't change until next navigation, and it's opaque to the actual JS code anyway.

Ensure the use case of pre-rendered Server Components is covered (Jamstack)

Yes, running Server Components at the build time is part of the paradigm.

This kind of took me by surprise. I understand that they cannot work but I don't yet fully understand why I can't put in a useEffect that will simply no-op in the context of a server component yet work in the context of a client component.

In Client Component SSR, the initial render result is just a non-interactive "snapshot" of the initial visual state. So it makes sense that effects are noops there. But for Server Components, they're never shipped to the client at all, so the effect would never run. If you want that effect, move it into a Client Component, which you'd import from a Server Component. Then for the first render (traditional SSR) you'd see a mix of both SC + initial render of CC (which may have noop effects).

The reason I don't like this is that it doesn't "simplify" for the consumer, it makes things significantly more complex for the sake of a tiny performance gain.

We don't expect the performance gain to be "tiny" at all, but you're welcome to ignore this and still do data fetching on the client side. Suspense works in both places, although it's more powerful on the server.

I agree that the things listed in my earlier post here AREN"T idiomatic React, however if the benchmark we're setting is for a solution is to be idiomatic React this RFC is also not idiomatic React. It's trying to mold the definition of idiomatic React to include differentiating components by render environment.

This is obviously subjective but I find the proposed solution the most idiomatic solution for "data fetching on the server side" (https://github.com/facebook/react/issues/1739) than anything else I've seen before. I'm curious if you don't consider this a worthwhile problem at all, or if you have a more idiomatic solution to compare with.

Should React really be shifting their focus from innovating in the client to innovating in the server? Does this make sense as a frontend framework? (I think yes, but not for this feature, but again the community should have a say).

I'd phrase it differently. React isn't shifting focus from the client — today all of React is client! It's just that the server has been vastly underdeveloped, and we want to have parity. Then you get to choose the tradeoff for your app.

I think only a small fraction of the community actually uses this functionality

We can say with confidence that this isn't correct. E.g. our recent community survey has shown ~30% respondents use Next.js, which has server rendering. npm downloads tell the same story. SSR is important to the ecosystem, although there will definitely always be apps that don't use it, and we want to support them well too.

I do not think the problems of a small minority should be driving the direction of the library.

Again, we don't agree with this framing and we consider excessive bundle sizes, long stalls during client rendering, and network waterfalls very common problems across the ecosystem, especially at smaller companies that don't have the kinds of resources Facebook or other companies might have to invest into solutions to perf problems. Like I emphasized in the talk, the reason we're excited about Server Components is because we genuinely believe they will benefit the vast majority — big and small, professional and hobbyist.

How would server components support cancellation and race conditions between server tree re-fetches? Would there be a mechanism to invalidate and ignore stale responses (on client) and to stop processing existing renders (on server) based on the recency of incoming requests? (E.g. A find-as-you-type component powered by server side components)

Race conditions are handled by the Suspense paradigm — you read from cache during render synchronously, so you can't get the "wrong" result. Cancellation is more tricky. We'll have a built-in AbortSignal that's tied to fetches under the hood, but we might have to not be as aggressive about cancellation as some other solutions due to technical constraints. However, keep in mind that the responses fill the cache so they're not entirely useless either.

In fact, it is impossible for all components to be stateless, so 0 bundle size is also impossible.

Pretty much the whole point of the proposal is that you can interleave Server and Client components as much as you want. Your app's total bundle size is quite unlikely to be zero, but you can be confident that Server components don't contribute to it. Again, you don't have to use them if you find no need for them, but in our experience a lot of components just want to grab or transform some data, and actually don't need state.

In the future, users should not only care about class components, hooks components, but also server components.

By this point it's pretty clear that the React community has embraced Hooks, so we expect classes to start fading away and only show up in legacy code (which we'll keep supporting).

The example in the video mentioned moving the date-fns dependency to the server as a benefit of server components. Wouldn't this actually be a pitfall since the Date API depends on local timezones of the machine and this code would now be executing on the server (using that machines timezone)?

Indeed, and this is another example of how we can make product-specific choices. E.g. if this is a problem or if we want relative dates, we can make our <Timestamp> a Client component without changing other code. It lets you make those decisions and then revisit them on a per-component basis.

you briefly mentioned using Server Components with GraphQL, would it be possible to have some examples to see how this would look like when paired together and how to use those two technologies optimally?

You can imagine it similar to this:
function Post({ id }) {
  const post = readQuery(/* your graphql */)
  // ...
}

There's not much more to it.

How about to use server components in the future in the React Native?

We've investigated an initial proof of concept and will likely come back to it, but for the initial rollout we're focused on the web.

Further to my previous thoughts... isn't this just a new "content-type" for a returned API call "text/react-component" - as essentially all we are doing is reformatting the API call that we make. We could then fetch these / stream or whatever we need and treat them as data.

Yes, you can look at it this way.

Exciting proposal! Good work everyone!
My only request is please use a serializer like superjson which supports serialization for Date, undefined, BigInt, Map, Set, etc in both directions. devalue is another option but is only safe for server to client, not client to server.

What an exciting proposal! This will introduce new gates of improvements at many levels, nevertheless, I wonder the following things:

Security: for each http request (even if the domain is localhost) the server components will be performing, what if there is an access token needed? What if there is an authentication and authorisation needed, should the server components authenticate themselves first, and ask for an access token to be authorised to access some data resources?
Performance: could we cache the server render result of a given server component when the input is the same?
Maintenance costs : if the server that is responsible for the rendering of our server components is no longer reachable for some reason (say DDOS attack), does this mean that we will have to handle a new type of errors, errors of type: component currently not available? And could this be properly tested ?

Reiterating my feels toward this feature, this is really exciting and possibly opening new ways of thinking in react 🥳

Are optimistic updates/rollbacks something that this proposals plans to tackle on or leave to userland solutions?

Fantastic work on this, really feels like a neat solution to a whole bunch of things and the missing piece to the puzzle. Cudos for a really well written RFC and great presentation and demo too!
I want to highlight and expand on this from @jamesknelson:

One last thing I'd like to see more discussion on is how data fetched on the server can be automatically passed to the client to use as the initial value for a cache, without needing to manually extract it on each request and pass it as a prop.

I'd like this too, but not just for initial value but updating it on refetches too. Many data fetching libraries populate some kind of external cache so that you can read from that in many parts of an application without having to pass props down. It is likely that both server and client components will want to use the same data, so those solutions will still be important in many apps. Hydrating that cache with data passed from the server is currently tricky in all SSR-metaframeworks because it technically needs to happen before the render to avoid mismatches, but no such opportunity is provided, and it seems like the Server/Client-components boundary would have the same challenge?
Many workarounds today involve just writing to the cache in render which isn't great. React Context is kind of unique here since you can "add stuff" to it in render safely with context providers, but writing to an external cache is not safe. Feels like a point of contention with existing libraries worth investigating more even if it eventually just ends up in a documented recommended approach?

Here is my feedback. I am not super excited when comparing with the react hooks introduction. I personally think this is not a right direction. I will use above the fold or below the fold to justify server components approach.
If I need to speed up the components which are above the fold, the existing sever side rendering approaches with the store initialization has already solved client side's waterfall issue and delivered the fastest and best experience to users. So I will not use/change to use server components handle the components which are above the fold.
I can see server components might be able to speed up the lazy loading components which are below the fold with the data fetching afterwards. Without server components, I still can increase threshold in order to load the components and fetch the data earlier even if they are still below the fold. Because of that, I will not use/change to use server components either.
Both relay + graphql and server components encourages us to have some server work in order to speed up our app. If I need to have some server work, why do not invest relay + graphql as the long term solution at the very beginning. So my question is will the pattern for server components help us to move relay + graphql easily when I need? If the answer is no, I will not consider the server components approach at least for me. Other than that, I want to know the difference between server approaches and relay + graphql in term of the amount of effort to setup the same infrastructure.

First off I like the idea of minimizing/loosening the contract surface between the browser and server.
Questions

Is this new "jsxon" format / server component format going to be react / javascript only?
How are breaking changes going to be handled, eg. breaking changes in server component contract?

I have a suggestion for the name :)
Cloud Component instead of Server Component
I imagine about Cloud services in future we'll have a new  type of service called CAAS (Component as a Service)

I think SC will help us decide whether component reside in Server or Client. Also reduce bundle size in client. Especially when you have 4MB library that your app is depending on. The challenge is how to maintain the state e.g. in Redux when your dealing with Route or Micro Frontend

I like this a lot!

I have an idea :
Before we did SSR of client component, we needed secondary hydration and injected events and lifecycles.
However, in the future, we only do SSR of server component, so we do not need secondary hydration.
This will be more pure. This is also the only benefit I can see from the server component, because the loss is huge - let react become a framework.

I wanted to address some feedback on Twitter, but it's a long response so I figured it would be better to post the reply here.

This doesn't solve the waterfall problem, it just makes it less noticeable.

A prior version of our RFC didn't describe this accurately, and we've since corrected it. It'd be more appropriate to say that React Server Components help solve client -> server waterfalls, but server -> server waterfalls may still exist. But it's also true to say that server waterfalls might not be as big of a problem. And that there are proven ways of solving them on the server that are difficult to replicate on the client.

Bundle size might be reduced, but that doesn't mean that total data used is reduced as well. This could impact old/low-speed devices negatively.

Large bundle sizes means more JavaScript to download, parse, and execute. On low end devices this is a huge problem, because they don't have as much compute power to do this work quickly. It's true that with React Server Components you may see an increase in overall data transfer in long sessions. But:

That data isn't JavaScript that needs to be parsed and executed, and
You would have had to do a round trip for the data regardless. Might as well do some of the rendering of that data on the server.

Also, re: 1., React Server Components render into a "precompiled" instruction to the client that allows React to render the resulting server tree much quicker than it would be if it were done on the client.

This seems like it'll complicate code bases. I want a clear separation between server and client-rendered components, not an intermingling of the two.

Today we already intermingle data fetching logic in client side JS apps. This often leads to complex state management and data fetching solutions. React Server Components can actually simplify the programming model here. If you had a chance to check out the demo, we had to do very little state management because of this new paradigm. So in many ways I think React Server Components actually help us separate data fetching from interactive client components. I also expect that teams will want to continue to write their backend services in the language of their choice. Frontend teams, if they choose to adopt React Server Components, could create frontend APIs/BFFs written in nodejs that compose those backend services. The nice thing here is that you can now do this all in one language and one tech stack.

Server rendering could lead to hard-to-find bugs, especially when it comes to managing user sessions.

I do think this is no different from before. Ultimately, it's going to depend on your team's backend and error reporting infrastructure here.

This might become more expensive for applications. In the search demo, finding those search results plus rendering them on the server is a more expensive operation than just an API call sent from the client.

We are moving some of the rendering to the server–so it's true that your server will be doing more work than before. But server costs are constantly going down, and far more powerful than most consumer devices. I think React Server Components will give you the ability to make that tradeoff and choose where you best want the work to be done. And that's not something that's easily possible today.

You'll be able to use React Server Components without WebSockets or HTTP/2. In our demo we use chunked encoding which is HTTP/1.1 compatible and straightforward to enable in most server frameworks.

I think this RFC could solve vercel/next.js#11897 and flareact/flareact#93. Sometimes pages can only be rendered on the server, can only be rendered on the client, or can be rendered either way! Right now, projects like Next.js have to make a decision based on where it can be rendered by what methods you have exported on the page component. The only problem I see for that library is: How could they determine when a component needs to be run at runtime, or is safe to run once at build time?

Is this [...] format / server component format going to be react / javascript only?

The exact format for encoding Server Component output (the "Server Component protocol") is currently an internal implementation detail and we expect this format to change -- possibly significantly -- before Server Components are stabilized. We strongly recommend not building anything that makes assumptions about the exact protocol format.
Also note that we actually have two (similar) implementations of this protocol, one that is built on Node.js streams (and used in the demo) and one using plain JSON for embedding inside another JSON-based protocol (and used internally, where in our case we embed the Server Component response inside a GraphQL response). Each of these versions requires support in React, however, so we anticipate having a fairly small number of options provided by React for common situations.
Support for other programming languages was asked about above, see my earlier answer.

How are breaking changes going to be handled, eg. breaking changes in server component contract?

The short answer is that this is definitely something we are considering as an open area of research (as part of categories such as routing and partial refetching). However this is also something that different frameworks or apps may want to handle differently and we may end up documenting a set of recommendations for frameworks rather than implementing a specific approach as part of React itself.

I'm just gonna write this with really good intentions so please don't take it the wrong way.
I've been reading all the negative comments (here, twitter...) and I couldn't say nothing that I really don't understand why people are against the Server Components feature. Please understand that React is an open-source software maintained by Facebook. All React core developers work at Facebook. Most likely Facebook needs this feature for their use-case and the engineers on the team believe implementing the Server Components is the right choice for Facebook's use-case.
Don't use Server Components if it's not helping your software or use-cases. Period.
The only time these negative comments would make sense is when React API changes and break your software. It's been 5 years I've been using React and its API has been consistently stable.
Honestly I think some people have a tendency to see the glass half empty.

I'm surprised why the option, Headless Browser, was not discussed.
For these tasks we successfully use IBM solutions - Browser Functions
This is a truly unified execution environment, understandable and convenient for the entire front-end development team.
The performance and transparency of this approach is much higher than standard SSR solutions.

Would React become Rails-like ?

Would be great if usage in service workers would be a consideration. We'd be able to have minimal code in the UI thread, and move most of the bundled code over to a worker / service worker. The "server" code, here running in a service worker, could output strings and a super light-weight UI thread could apply the deltas.

Thanks for good research. Does the size of React itself will be increased, if the application is just using CSR? I mean the serializer of the intermediate representation of the tree is something that will be added to React itself, no matter what environment It will running on?

I've written down some thoughts about removing the restriction that Client Components aren't allowed to import Server Components at #191 which could make Server Components considerably simpler to use.

[Proposal] Idea to simplify overall design
The restriction that Client Components aren't allowed to import Server Components is the source of complexities. I'm guessing the purpose of this restriction is to avoid the waterfall situation of rendering going back-and-forth between client and server. Is that the main reason for the restriction?
AFAICT removing this restriction would considerably simplify the usage of Server Components, and I'm wondering if removing this restriction is possible, in a performant way:

When the server renders a Server Component, all descendants of the Server Component are rendered on the server-side, including all descendant Client Components. (In order to avoid rendering going back-and-forth between client-side and server-side.) Once the virtual dom computing goes server-side it never goes back client-side.
Whenever the client-side wants to render a Server Component, the client calls an endpoint /_react/render and the server computes and returns the virtual dom and the list of context objects used. The client passes the context objects and the state of all the Server Element's descendant Client Elements so that the server has all the information needed to be able to compute the virtual dom. The client then uses the returned virtual dom to perform reconciliation, and uses the list of used context to know whether to request a re-render whenever a context object changes.
When a Client Component is rendered by the server, the server only computes the virtual dom while the hydration on the client-side takes care of running the Client Component's useEffect & co. Similarly to what is being done today with SSR where Client Components are allowed to run on the server but hydration takes care of the client-side stuff.
The webpack react plugin removes the server component source code from the client-side bundle.

AFAICT this should work, or am I missing something here?
The benefits would be many, amongst others:

No routing needed. (Routing can be done simply by having a stateful Client Component orchestrating Server Components.)
No central caching unstable_getCacheForType and unstable_useCacheRefresh needed.
The client-side can cache the rendering of Server Components by using shouldComponentUpdate/memo, preventing unnecessary network round trips.
More things can be moved to the server. For example, the note preview (and its included heavy markdown dependency) in the left side panel of the demo can't easily be moved to the server with the current design, but, with the proposed design, this would be trivial.
The /_react/render is the only Server Components endpoint needed.
Migration is easier: add a) the react webpack plugin, and b) the /_react/render endpoint — that's it. Current React 16.x apps work as before and Server Components can be progressively added without changing the app's architecture.

The main and overarching benefit being that I can create components that are concerned only about themselves: no shared infrastructure (no X-Location, no unstable_getCacheForType, etc.), I can use Server Components wherever I want, and I can write them independently of the rest of the app. When I enter the world of a component I can think locally, whereas the restriction that Client Components aren't allowed to import Server Components forces me to think globally.
Also, this would make it possible to use Server Components without a framework.
What do you think?
I really like Server Components, and if we can simplify its usage it could become quite a perfect thing.

@brillout I don't fully understand your proposal, but I understand and agree with your reasoning for it.

Just saw the proposal on the React website, and watched the demo with the awesome Dan Abramov :-)
I thought I'd drop by and raise some concerns / proposals for this RFC.
Firstly, I'd like to ask about different versions of React. Let's imagine the server is using React 30 (fake). When the client uses React 31 (fake), which introduces a different protocol schema, what would happen? I bet React would include backwards compatibility for older platforms, as they have done in the past, but this still seems like a valid concern.
What if server / client components were in separate Git repositories, and the maintainer forgot to update one of them? Has this use-case been covered?

(To be clear, right now the code is using a, uh, very surprising pattern to make asynchronous code appear synchronous: if the result value is cached, it returns the value synchronously, but if not, the fetcher throws a Promise.  When React catches a Promise (a thenable) it awaits the result, caches it and then re-runs the React component; now the component won't throw a Promise and will run to completion normally.)

Slightly off-topic, but I've never really liked this pattern. It feels like a hack on language features which were never designed to support this use-case. In most scenarios, throw is used to signal fatal errors, not promises to tack on "synchronous" code.
IMHO, this is forcing algebraic effects into a language which doesn't really support it.
Further to this, I do worry about the performance implications of such a mechanism, too. V8 deoptimises try / catch blocks and unwinds the stack (IIRC), because it assumes the use of throw equates to an application error.
On another note, how much extra code is this functionality going to add to the React package? I've never really been comfortable with React's large bundle size, and I worry this proposal will append even more bloat for features I'm never going to use. Could this functionality be replicated with a custom reconciler / renderer?

Will any part of the server-side be tightly coupled to Node.js, or could it run on a different JS runtime (for example, Rhino in Java, embedded V8 like with ClearScript for C#, ChakraCore, etc)?

I'm shocked to see that nobody has mentioned Deno. They support a substantial amount of the major Web API's (WASM, etc.) so I don't see why React wouldn't support this environment. As Deno is up and coming in web development, it's becoming quite a viable platform. Theoretically, if serialisation / deserialisation is decoupled from the HTTP server, support for alternative platforms should carry a low cost.

Zero-Bundle-Size

This isn't really true though, is it? For starters, you're using a special format which needs to be serialised / deserialised on the client, plus all the extra cruft of communicating with the rendering server.

Please understand that React is an open-source software maintained by Facebook. All React core developers work at Facebook. Most likely Facebook needs this feature for their use-case and the engineers on the team believe implementing the Server Components is the right choice for Facebook's use-case.

Don't use Server Components if it's not helping your software or use-cases. Period.

With respect, I think you're missing the point. I've seen some people compare this proposal to Hooks, but I feel like this introduces quite a substantial amount of ambiguity in comparison. There are also concerns about the implications of this proposal on bundle size. Remember, this is a Request for Comments, and it should be treated as such. Constructive criticism should be encouraged.
Furthermore, after watching the demo, I'm not sure the end justifies the means with respect to the Notes application. Batching calls to fetch can be done without all this extra cruft / server load, so I personally don't believe it gave a solid use-case for this pattern.
P.S. extraneously large dependencies aren't a good demo for this proposal. If you're only using a subset of a large dependency's functionality, perhaps consider swapping it for something else :slightly_smiling_face:

I'm shocked to see that nobody has mentioned Deno. They support a substantial amount of the major Web API's (WASM, etc.) so I don't see why React wouldn't support this environment. As Deno is up and coming in web development, it's becoming quite a viable platform. Theoretically, if serialisation / deserialisation is decoupled from the HTTP server, support for alternative platforms should carry a low cost.

Deno is TypeScript. TypeScript can run JS code without any issue. Designing the server part to be Node.js compatible makes more sense as it covers both.
I'm expecting the server implementation will be designed as an API to plugged into any Node.js servers as a middleware.

With respect, I think you're missing the point. I've seen some people compare this proposal to Hooks, but I feel like this introduces quite a substantial amount of ambiguity in comparison. There are also concerns about the implications of this proposal on bundle size. Remember, this is a Request for Comments, and it should be treated as such. Constructive criticism should be encouraged.

I wasn't referring to comments like yours. Constructive criticism is always needed and as you mentioned that's exactly why they shared the idea. And with respect again I think you missed my point. I would still let the team implement the feature and if after tree-shaking there was a huge difference in the React core size or breaking backward compatibility then raise the flag. Though I'm sure the React team will design the feature to be modular with stable API as already mentioned.

Furthermore, after watching the demo, I'm not sure the end justifies the means with respect to the Notes application. Batching calls to fetch can be done without all this extra cruft / server load, so I personally don't believe it gave a solid use-case for this pattern.

Maybe the demo didn't described the use-case well but that demo seems to be a simplified version of their use-case at Facebook and as they mentioned it reduced 29% bundle-size in their app. That should be enough to justify it.

P.S. extraneously large dependencies aren't a good demo for this proposal. If you're only using a subset of a large dependency's functionality, perhaps consider swapping it for something else

Sometime replacing large dependencies is not an option. So I wouldn't dismiss this fact that easily.

Deno is TypeScript. TypeScript can run JS code without any issue. Designing the server part to be Node.js compatible makes more sense as it covers both.

I was referring to the use of proprietary Node.js lib modules, which would hamper compatibility with alternative runtimes. While things like accessing the file-system are harder to implement in a cross-platform fashion, I personally believe the serialisation of JSX can be done without any dependencies on Node's standard library.
As I said, it may be worthwhile to decouple the server from the serialisation, so a separate Node-specific middleware function would do nicely.
In theory, if this were implemented as such, React could also be used with web-workers, although I question the usefulness of that pattern. which seems to be documented as a use-case in the specification.

Maybe the demo didn't described the use-case well but that demo seems to be a simplified version of their use-case at Facebook and as they mentioned it reduced 29% bundle-size in their app. That should be enough to justify it.

I'm glad this has gone through real-world testing. That's rather comforting to know. Thanks.
P.S. I left a few review comments, see above :-)

I was referring to the use of proprietary Node.js lib modules, which would hamper compatibility with alternative runtimes. While things like accessing the file-system are harder to implement in a cross-platform fashion, I personally believe the serialisation of JSX can be done without any dependencies on Node's standard library.

That's an interesting point. I'm sure this feature will require some basic FileSystem APIs but that doesn't mean they should live inside React itself and can't be opted-in. A good example of this would be how React and ReactDom separate the concerns. I would assume the Server Components will have small pieces that work together but they will be framework/platform agnostic based in Node.js. React team has already mentioned this so I wouldn't worry about that for now.

As I said, it may be worthwhile to decouple the server from the serialisation, so a separate Node-specific middleware function would do nicely.

I totally agree. In fact, there is only one SSR scenario on the server side, and all other scenarios are reverse to back.
But I think this kind of intermediate code is an abstraction, suitable for many places, such as worker-component?

Am I missing more detailed info on the JSON format? I ca't seem to find anything on it. Was looking for a spec, but it doesn't have to be that far along. Just something that shows and explains an example would be nice. Sorry in advance if I did in fact miss some obvious public place this information exists.

I don't want to undermine the work done, but server components rather looks like kicking the can down the road to me (can = state management). 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. Also adding pressure to precious server compute power to render the page is the bonus.
The benefits of server components:

cleaner frontend code (less maintenance of state in frontend)
sending less js code over the wire

When you don't maintain state in frontend, you need to do it in backend.   Better to use graphql.
"GraphQL doesn't make sense in all cases, for example you write in your small hobby apps...": well, I wouldn't over-engineer my small hobby app for thinking which parts should be rendered on server or client as well.
When I need to optimize my small hobby app, I'm not sure if I'd choose server components over graphql.
About sending less js code: Now you should add a fetch wrapper (react-fetch: 8.4 kb) plus the additional code in react.js to support Server Components.

@ahmetcetin correction: Server Components aren't just fancy PHP. They don't result in HTML snippets, but in a streaming format that basically seems to serialize React.createElement calls combined with Suspense.
I think this is a good idea, and it can certainly improve some harder use cases, like filtering/sorting huge data sets. It is definitely not the best/only way to work. That depends completely on the application.

What saddens me a bit is that Suspense isn't officially released yet, and now we have this added to the mix. Perhaps because of the interaction with SSR. It looks like SC will be the only way to get Suspense in SSR and thereby streaming single-pass SSR.
But that causes code duplication: if you want to make a Single Page Application that has streaming SSR (for good SEO), you have to use Server Components. But after the app loaded, you want to fetch only the data on the client so you can use a local cache. So then any components that were Server Components and fetching data now need to be Client Components that fetch their own data?
Is there a way to make a Suspense-based data getter work both as a SC and a CC?
const Detail =  id => {
  const item = getItem(id) // uses GraphQL on server and client, throws a Promise while loading
  return <ItemDetail value={item} />
}

But it seems to me that a SC is replaced with some sort of proxy in the client vDOM, so once you render once with SC, you're forced to keep rendering on the server, unless you replace the entire vDOM with a duplicate one without SC. This means that you need to write the same logic in Detail.server.js and the Detail.js that you replace it with.
TL; DR: how to use SC only once on the server and from then on keep using CC?

@wmertens thanks for the correction, but still if your SC has lots of elements and/or css-in-js, regardless if it's serialized React.createElement or pure html/css, it still needs to send those in rendered component. What bothers me also, btw I didn't test personally, just saw in the demo, if the client child component(s) of the SC are using that data, you send the rendered SC including the data rendered, and additionally sending the raw data to be used by the client, not a good idea.
My point is, using SC is not a quick and easy solution. You just need to plan well how to organize SC and client components, not only considering the state management, but also styling/interactions, CCs shouldn't require the same data, code duplications etc.
In some edge cases SC might be useful indeed, but presenting it like a solution to messy state management in frontend, or "I want to write my component that simple", or "using GraphQL doesn't make sense" is not really satisfying.

@wmertens You don't need server components for SSR. Regular components (non-server, non-client) will work as they do now regarding SSR. Those components will function as they currently do now.
You would only add server components to your stack if you need heavy processing or server-specific functionality in your app. In that case, it's still possible to get them to render once for the initial page load (or new route request), by designing them so that they don't need to be re-rendered. This can be accomplished at any level of your app hierarchy by passing server components down your virtual dom tree via props or context.
I think the important thing to remember given your concern is that regular components aren't going away. Server components don't replace them. Server components handle a very different set of use-cases, allowing you to embed lots of functionality you would have normally outsourced to api endpoints into a single monolithic react app (if you want).
Perhaps because my project is the ideal use-case for server components, I've found loads of possibilities of how it could help. For instance, right now I have an admin app that embeds a view app in an iframe to show live updates. Using window.postMessage makes all of that functionality more difficult, more slow, and more prone to errors. But with server components, I could merge the two apps, and determine based on authentication if a user should get the very light view-only or the heavier admin-wrapped app. No more postMessage for me, and no extra kbs of logic on the view end to support being embedded in an iframe.
My sales website's blog, help docs, and basic pages are all written in markdown. To keep the site up-to-date without having to redeploy for every change, I have to jump through a ton of hoops. It requires piles of mental overhead. And for a single developer actively developing over 2M lines of code, it would be much nicer to collapse that complexity down. No more api endpoints. Just a server component that hits the github api, converts the markdown to html, and caches the result for that particular set of props. Right now, it's a Next route that hits an api that does the processing, then passes that data down to a component that does the rendering. One file vs three at minimum, more in practice.

@mikestopcontinues Yes, SSR works right now for me, but I have to run 2 render passes (the first one to trigger data fetches) and I can't stream. I would like to use Suspense so that I can do the SSR using a single pass. It looks like Suspense in SSR will only be available via SC.
Passing the SC down the tree is interesting, so you import the component and then pass it as a prop, to get around the importing server code rule in CC, right? So that might be used to, in the browser, replace a SC with an equivalent CC that uses graphql. Hmmm. Too bad there's no such thing as a "server hook", I like using hooks for GraphQL and polymorphic SC/CC would require using components again, ah well.
You give good examples, I totally agree SC is very useful for resource heavy things and I'll be happy to have it in the toolbox.
@ahmetcetin no, the SC will basically generate the props that are needed for rendering, and then send that to the client. The client will load the CC it needs to render, give them the props and they will render. CSS-in-JS will be entirely in CC, it can't work on server-side. So if you have complex DOMs, it's best to use SC only to generate props and pass it to client components. I think.

Passing the SC down the tree is interesting, so you import the component and then pass it as a prop, to get around the importing server code rule in CC, right?

@wmertens you wouldn't be able to do that because the component can't be serialized to pass it from a SC to CC.

@lucasecdb that was what I thought at first, probably a CC is a boundary for rendering? Then it won't be able to call the SC indeed.
Universal components would work but they would mean a lot of duplication in the SC render response if you have to do prop passing

@lucasecdb that was what I thought at first, probably a CC is a boundary for rendering? Then it won't be able to call the SC indeed.

yeah, when React is rendering the server component tree it replaces the client imports with a "client reference", which it will use during the reconciling process to determine which client components needs to be rendered. This way you can't even use the client component implementation because the webpack plugin is literally replacing it with a static reference. Even if you tried to call the CC function you couldn't (you can try this and see the error in the demo).

Server components streaming back HTML would solve all my problems with SSR. Otherwise, the project is, to say the least very interesting to follow.

The restriction that Client Components aren't allowed to import Server Components is the source of complexities. I'm guessing the purpose of this restriction is to avoid the waterfall situation of rendering going back-and-forth between client and server. Is that the main reason for the restriction?

Not quite: the reason is that Server Components allow direct access to server-only resources such as filesystems, databases, etc. So they can't be imported by Client Components because they can't run on the client. But it is possible to fetch the results of Server Components from Client Components: that's what the Notes demo app is doing to load basically the entire page - note that there's actually one client component at the root. This means that you could, if you chose, fetch multiple distinct Server Components at different levels of your app to create waterfalls and hurt your app's performance. It isn't prevented by this proposal.
However, we are intentionally not encouraging that as a pattern because it's already easy to introduce waterfalls in React apps. These waterfalls are a common source of performance problems, and the idea of Server Components is to give developers an easy to use, powerful approach for avoiding client/server waterfalls.

[...] this would make it possible to use Server Components without a framework. What do you think?

First, note that you won't have to use a framework to use Server Components. We are starting with some framework integrations in order to make it easy to try using Server Components and to provide an example of how you can integrate them into your app, but you won't be required to use a framework.
As for the proposal, I'm skipping over quoting over the details of the proposal for brevity, but my interpretation of your idea boils to two key pieces:

Allowing importing SC from CC, but swap them out so that rendering the SC causes its output to be fetched
Have a mechanism that exposes an endpoint for the SC output to be fetched.

This is roughly analogous to the key integration pieces proposed by this proposal already: a special mechanism for importing CC from SC, and framework/app integrations for matching routes to SC. So it doesn't appear that this proposal ultimately simplifies the implementation or that it provides new capabilities not already achievable (as noted above, you can already go out of your way to create waterfalls if you want to).

I really like Server Components, and if we can simplify its usage it could become quite a perfect thing.

I highly encourage trying out Server Components for real. As we started building our first apps with them we had a lot of "aha" moments when we realized that SC let us achieve things we hadn't even considered initially. That said, yes we absolutely will consider ways to improve Server Components based on user feedback.

Firstly, I'd like to ask about different versions of React. Let's imagine the server is using React 30 (fake). When the client uses React 31 (fake), which introduces a different protocol schema, what would happen? I bet React would include backwards compatibility for older platforms, as they have done in the past, but this still seems like a valid concern.

@resynth1943 Versioning is something we're still evaluating; it's particular acute if we want to support React Native, as clients may never update. We haven't decided on an approach here but it's very much on our radar.

IMHO, this is forcing algebraic effects into a language which doesn't really support it.

A similar concern was raised above re the Suspense mechanism and why not use an alternative such as async/await (see the FAQ). We plan to write a separate RFC to document the design of Suspense and the various tradeoffs that led us to the current approach.

Am I missing more detailed info on the JSON format? I can't seem to find anything on it. Was looking for a spec, but it doesn't have to be that far along. Just something that shows and explains an example would be nice. Sorry in advance if I did in fact miss some obvious public place this information exists.

@drkibitz No, you're not missing something! We haven't published details of the response format yet as it's an internal implementation detail that is highly likely to change.

@josephsavona what are your thoughts on using SC on the server once for enabling single-pass streaming SSR, and then somehow only using CC+regular components on the client, never rendering those SC again? https://github.com/reactjs/rfcs/pull/188#issuecomment-752651155

(aside: I replied to a few questions/ideas that stood out and appeared not to have already been answered by other commenters. I'm out of time but will I or other team members will check in on the discussion after the new year).

IMO decreasing bundle size will help people a lot but at the same time some people will argue of introducing such complexity into react applications. But I think it's too early to decide on this.
I want to know that with this Server components concept Server Sent Events mechanism will work as expected or will there be any change in that too?
Seeing video makes this pretty clear that we cannot have any sought of animation/ client interaction with components rendering on server side. I am curious to know why it is a challenge to support that?

The utility of server components lies on the flexibility of the wire format. The reason for this is because I believe a client, can and should be able to benefit without requiring any corresponding server infrastructure and maintenance. Take PHP, the reason it exploded years ago wasn't because of the syntax, but because of how easy it was for hosting providers to offer it in a shared and very affordable environment, and affordability, I am not only talking about money. I believe whatever the format may become, it should aim to be the foundation to stand a possible shared server component environment. Where is this coming from? It is rather easy to imagine that an initial version of all this (maybe this version) couples the client with the server so much, that the format is actually dependent on component definitions mutually understood by the server and client. To keep the format as compact as possible increases the likelihood of this coupling. Without going into too much detail, or writing a full proposal here, I would just want to suggest one thing. That is that the format is based on decoupled component definitions, with importable / exportable schemas. I would like to imagine a client that may be built with a server component schema, to communicate and depend on that server's components, regardless of whether that particular client is actually served by that particular server.

@drkibitz no worries, the coupling happens via bundler ids. As long as all servers are running and serving the same code, any server can handle a render request for SC

Security: for each http request (even if the domain is localhost) the server components will be performing, what if there is an access token needed? What if there is an authentication and authorisation needed, should the server components authenticate themselves first, and ask for an access token to be authorised to access some data resources?

Maintenance costs : if the server that is responsible for the rendering of our server components is no longer reachable for some reason (say DDOS attack), does this mean that we will have to handle a new type of errors, errors of type: component currently not available? And could this be properly tested ?

Server Components shift some rendering work to the server, but in many aspects you can think of their refetches as you would about any API calls. I don't know what would make these points different compared to how you normally deploy and interact with an API.

Performance: could we cache the server render result of a given server component when the input is the same?

Theoretically, yes. In practice, we won't be focusing on this in the initial iteration, but might explore this in the future. React I/O libraries would need to be aware of this caching mechanism.

Are optimistic updates/rollbacks something that this proposals plans to tackle on or leave to userland solutions?

For many user interfaces, we've come to a conclusion that naïve optimistic updates are not the right user experience. E.g. if posting a piece of content makes it immediately appear in the list, the user might close the tab before the mutation goes through. So we're thinking that in well-designed UIs, many optimistic updates should actually have a separate design (e.g. a "posting" shim with a progress bar) instead of just putting things into the cache. Such a shim would be a Client Component, so it fits into the paradigm despite the real refetch happening through the Server. This also solves the problem that server output might end up being different (e.g. due to post-processing). Of course, you can keep specific interactions (e.g. "liking" a post) fully Client-side.

One last thing I'd like to see more discussion on is how data fetched on the server can be automatically passed to the client to use as the initial value for a cache, without needing to manually extract it on each request and pass it as a prop.

Can you be more specific? Are we talking about SSR, or about Server Components (or how they work together)? The neat thing about Server Components is that you don't really need to serialize the cache itself because it's really the render output that you're after. The cache that runs on the client only caches server responses, but the data you've fetched on the server isn't even needed by the client. Only the rendered result.

Many data fetching libraries populate some kind of external cache so that you can read from that in many parts of an application without having to pass props down. It is likely that both server and client components will want to use the same data, so those solutions will still be important in many apps.

With the idiomatic Server Components model, you "pass" things by passing props to Client Components. Including refetches. Nothing more, nothing less. This is a different model than traditional normalized caches — it's denormalized. In this model, the client doesn't need the normalized data because you prepare the render result on the server.
It's hard for me to comment in more detail unless you expand on this point with a more specific scenario. But broadly speaking, Server Components don't require transferring the server cache to the client.

The performance and transparency of this approach is much higher than standard SSR solutions.

I find it very challenging to believe that a Node server talking to the browser can be more performant and less resource-intensive than a Node server alone.

Would React become Rails-like ?

No, but it should provide better building blocks if you want to build something Rails-like on top.

Would be great if usage in service workers would be a consideration. We'd be able to have minimal code in the UI thread, and move most of the bundled code over to a worker / service worker. The "server" code, here running in a service worker, could output strings and a super light-weight UI thread could apply the deltas.

This is actually what we started with in 2014. This experiment didn't pan out for various reasons (https://github.com/facebook/react/issues/7942#issuecomment-254984862) and gave us insights for the current React architecture and its approach to concurrency. But the idea of two types of components originally comes from that research.

Does the size of React itself will be increased, if the application is just using CSR? I mean the serializer of the intermediate representation of the tree is something that will be added to React itself, no matter what environment It will running on?

On another note, how much extra code is this functionality going to add to the React package? I've never really been comfortable with React's large bundle size, and I worry this proposal will append even more bloat for features I'm never going to use. Could this functionality be replicated with a custom reconciler / renderer?

There are some things we're adding to the Client-side React, but they're useful on Client-only too. Such as just general support for Suspense data fetching. These features are currently within range of 1% to 3% as far as I know.
The (de)serializer is separate and won't get pulled in if you're not using it. So you're not paying the cost for what you don't use.

Firstly, I'd like to ask about different versions of React. Let's imagine the server is using React 30 (fake). When the client uses React 31 (fake), which introduces a different protocol schema, what would happen? I bet React would include backwards compatibility for older platforms, as they have done in the past, but this still seems like a valid concern.

The intended integration would be through frameworks (or your own infra that works the same way). A framework would always use one version of React. There are questions about what happens during deployment, but it's a more general question (and not just about upgrading React) and the solutions there are also more general.

What if server / client components were in separate Git repositories, and the maintainer forgot to update one of them? Has this use-case been covered?

I don't understand how this is different from what you get today in a server-rendered app.

Slightly off-topic, but I've never really liked this pattern. It feels like a hack on language features which were never designed to support this use-case. In most scenarios, throw is used to signal fatal errors, not promises to tack on "synchronous" code.

Thanks, we're definitely aware of what throw is used for. As noted several times throughout this thread, we will write another RFC to explain why we think this is the right approach given all the tradeoffs. I'd like to ask to not focus on this in this thread because there'll be another one.

I'm shocked to see that nobody has mentioned Deno. They support a substantial amount of the major Web API's (WASM, etc.) so I don't see why React wouldn't support this environment. As Deno is up and coming in web development, it's becoming quite a viable platform. Theoretically, if serialisation / deserialisation is decoupled from the HTTP server, support for alternative platforms should carry a low cost.

Sure, we'd be happy to accept a PR for Deno bindings. As you correctly say, as long as something can run JavaScript code and has some kind of streaming API, we can very likely make it work.

This isn't really true though, is it? For starters, you're using a special format which needs to be serialised / deserialised on the client, plus all the extra cruft of communicating with the rendering server.

The point is that you can keep adding zero-cost abstraction layers on the Server while being confident that your bundle size doesn't keep growing one bit. I don't see how this isn't true.

P.S. extraneously large dependencies aren't a good demo for this proposal. If you're only using a subset of a large dependency's functionality, perhaps consider swapping it for something else 🙂

Judging by the community response, heavy dependencies are very much a pain point. Yes, any small demo is going to feel convoluted, but having the freedom to add arbitrary dependencies without the bundle size cost is something people clearly appreciate so far.

I was referring to the use of proprietary Node.js lib modules, which would hamper compatibility with alternative runtimes.

You can make your own React I/O bindings to any modules. In fact part of the idea behind react-fetch, react-fs and others, is that constrained cloud environments could even swap them out for more "native" implementations where it makes sense.

Am I missing more detailed info on the JSON format? I can't seem to find anything on it. Was looking for a spec, but it doesn't have to be that far along. Just something that shows and explains an example would be nice. Sorry in advance if I did in fact miss some obvious public place this information exists.

It's an implementation detail that's expected to change a lot over time. There is some grammar description here.

When I need to optimize my small hobby app, I'm not sure if I'd choose server components over graphql.

You're welcome to keep using GraphQL if it works well for you.

Perhaps because of the interaction with SSR. It looks like SC will be the only way to get Suspense in SSR and thereby streaming single-pass SSR.

Yes, this is the current plan.

But that causes code duplication: if you want to make a Single Page Application that has streaming SSR (for good SEO), you have to use Server Components. But after the app loaded, you want to fetch only the data on the client so you can use a local cache. So then any components that were Server Components and fetching data now need to be Client Components that fetch their own data?

I don't follow this argument. Using SSR doesn't really affect the refetching strategy. When you want to refetch, you send a request to the Server, and it delivers the updated Server tree in the response. That's what's being rendered (and cached) on the client. Like in the demo.

This means that you need to write the same logic in Detail.server.js and the Detail.js that you replace it with.

Sorry, I don't follow this at all.

TL; DR: how to use SC only once on the server and from then on keep using CC?

No, but I don't understand why you'd want that.

What bothers me also, btw I didn't test personally, just saw in the demo, if the client child component(s) of the SC are using that data, you send the rendered SC including the data rendered, and additionally sending the raw data to be used by the client, not a good idea.

My point is, using SC is not a quick and easy solution. You just need to plan well how to organize SC and client components, not only considering the state management, but also styling/interactions, CCs shouldn't require the same data, code duplications etc.

We already use "references" in the protocol for the same objects so they never appear twice in the output stream. We could conceivably do something similar for strings if that proves to be a problem. We haven't seen that be a problem in our production testing yet. I think you're worrying about a premature optimization here. Also, we shouldn't lose sight of how much data and code we're not sending because it's not needed by the client anymore.
As for styling, it's definitely an open research area but it's not something you would need to worry about as a developer. It's something we need to figure out.

Security: for each http request (even if the domain is localhost) the server components will be performing, what if there is an access token needed? What if there is an authentication and authorisation needed, should the server components authenticate themselves first, and ask for an access token to be authorised to access some data resources?

Maintenance costs : if the server that is responsible for the rendering of our server components is no longer reachable for some reason (say DDOS attack), does this mean that we will have to handle a new type of errors, errors of type: component currently not available? And could this be properly tested ?

Server Components shift some rendering work to the server, but in many aspects you can think of their refetches as you would about any API calls. I don't know what would make these points different compared to how you normally deploy and interact with an API.

Performance: could we cache the server render result of a given server component when the input is the same?

Theoretically, yes. In practice, we won't be focusing on this in the initial iteration, but might explore this in the future. React I/O libraries would need to be aware of this caching mechanism.

Are optimistic updates/rollbacks something that this proposals plans to tackle on or leave to userland solutions?

For many user interfaces, we've come to a conclusion that naïve optimistic updates are not the right user experience. E.g. if posting a piece of content makes it immediately appear in the list, the user might close the tab before the mutation goes through. So we're thinking that in well-designed UIs, many optimistic updates should actually have a separate design (e.g. a "posting" shim with a progress bar) instead of just putting things into the cache. Such a shim would be a Client Component, so it fits into the paradigm despite the real refetch happening through the Server. This also solves the problem that server output might end up being different (e.g. due to post-processing). Of course, you can keep specific interactions (e.g. "liking" a post) fully Client-side.

One last thing I'd like to see more discussion on is how data fetched on the server can be automatically passed to the client to use as the initial value for a cache, without needing to manually extract it on each request and pass it as a prop.

Can you be more specific? Are we talking about SSR, or about Server Components (or how they work together)? The neat thing about Server Components is that you don't really need to serialize the cache itself because it's really the render output that you're after. The cache that runs on the client only caches server responses, but the data you've fetched on the server isn't even needed by the client. Only the rendered result.

Many data fetching libraries populate some kind of external cache so that you can read from that in many parts of an application without having to pass props down. It is likely that both server and client components will want to use the same data, so those solutions will still be important in many apps.

With the idiomatic Server Components model, you "pass" things by passing props to Client Components. Including refetches. Nothing more, nothing less. This is a different model than traditional normalized caches — it's denormalized. In this model, the client doesn't need the normalized data because you prepare the render result on the server.
It's hard for me to comment in more detail unless you expand on this point with a more specific scenario. But broadly speaking, Server Components don't require transferring the server cache to the client.

The performance and transparency of this approach is much higher than standard SSR solutions.

I find it very challenging to believe that a Node server talking to the browser can be more performant and less resource-intensive than a Node server alone.

Would React become Rails-like ?

No, but it should provide better building blocks if you want to build something Rails-like on top.

Would be great if usage in service workers would be a consideration. We'd be able to have minimal code in the UI thread, and move most of the bundled code over to a worker / service worker. The "server" code, here running in a service worker, could output strings and a super light-weight UI thread could apply the deltas.

This is actually what we started with in 2014. This experiment didn't pan out for various reasons (https://github.com/facebook/react/issues/7942#issuecomment-254984862) and gave us insights for the current React architecture and its approach to concurrency. But the idea of two types of components originally comes from that research.

Does the size of React itself will be increased, if the application is just using CSR? I mean the serializer of the intermediate representation of the tree is something that will be added to React itself, no matter what environment It will running on?

On another note, how much extra code is this functionality going to add to the React package? I've never really been comfortable with React's large bundle size, and I worry this proposal will append even more bloat for features I'm never going to use. Could this functionality be replicated with a custom reconciler / renderer?

There are some things we're adding to the Client-side React, but they're useful on Client-only too. Such as just general support for Suspense data fetching. These features are currently within range of 1% to 3% as far as I know.
The (de)serializer is separate and won't get pulled in if you're not using it. So you're not paying the cost for what you don't use.

Firstly, I'd like to ask about different versions of React. Let's imagine the server is using React 30 (fake). When the client uses React 31 (fake), which introduces a different protocol schema, what would happen? I bet React would include backwards compatibility for older platforms, as they have done in the past, but this still seems like a valid concern.

The intended integration would be through frameworks (or your own infra that works the same way). A framework would always use one version of React. There are questions about what happens during deployment, but it's a more general question (and not just about upgrading React) and the solutions there are also more general.

What if server / client components were in separate Git repositories, and the maintainer forgot to update one of them? Has this use-case been covered?

I don't understand how this is different from what you get today in a server-rendered app.

Slightly off-topic, but I've never really liked this pattern. It feels like a hack on language features which were never designed to support this use-case. In most scenarios, throw is used to signal fatal errors, not promises to tack on "synchronous" code.

Thanks, we're definitely aware of what throw is used for. As noted several times throughout this thread, we will write another RFC to explain why we think this is the right approach given all the tradeoffs. I'd like to ask to not focus on this in this thread because there'll be another one.

I'm shocked to see that nobody has mentioned Deno. They support a substantial amount of the major Web API's (WASM, etc.) so I don't see why React wouldn't support this environment. As Deno is up and coming in web development, it's becoming quite a viable platform. Theoretically, if serialisation / deserialisation is decoupled from the HTTP server, support for alternative platforms should carry a low cost.

Sure, we'd be happy to accept a PR for Deno bindings. As you correctly say, as long as something can run JavaScript code and has some kind of streaming API, we can very likely make it work.

This isn't really true though, is it? For starters, you're using a special format which needs to be serialised / deserialised on the client, plus all the extra cruft of communicating with the rendering server.

The point is that you can keep adding zero-cost abstraction layers on the Server while being confident that your bundle size doesn't keep growing one bit. I don't see how this isn't true.

P.S. extraneously large dependencies aren't a good demo for this proposal. If you're only using a subset of a large dependency's functionality, perhaps consider swapping it for something else 🙂

Judging by the community response, heavy dependencies are very much a pain point. Yes, any small demo is going to feel convoluted, but having the freedom to add arbitrary dependencies without the bundle size cost is something people clearly appreciate so far.

I was referring to the use of proprietary Node.js lib modules, which would hamper compatibility with alternative runtimes.

You can make your own React I/O bindings to any modules. In fact part of the idea behind react-fetch, react-fs and others, is that constrained cloud environments could even swap them out for more "native" implementations where it makes sense.

Am I missing more detailed info on the JSON format? I can't seem to find anything on it. Was looking for a spec, but it doesn't have to be that far along. Just something that shows and explains an example would be nice. Sorry in advance if I did in fact miss some obvious public place this information exists.

It's an implementation detail that's expected to change a lot over time. There is some grammar description here.

When I need to optimize my small hobby app, I'm not sure if I'd choose server components over graphql.

You're welcome to keep using GraphQL if it works well for you.

Perhaps because of the interaction with SSR. It looks like SC will be the only way to get Suspense in SSR and thereby streaming single-pass SSR.

Yes, this is the current plan.

But that causes code duplication: if you want to make a Single Page Application that has streaming SSR (for good SEO), you have to use Server Components. But after the app loaded, you want to fetch only the data on the client so you can use a local cache. So then any components that were Server Components and fetching data now need to be Client Components that fetch their own data?

I don't follow this argument. Using SSR doesn't really affect the refetching strategy. When you want to refetch, you send a request to the Server, and it delivers the updated Server tree in the response. That's what's being rendered (and cached) on the client. Like in the demo.

This means that you need to write the same logic in Detail.server.js and the Detail.js that you replace it with.

Sorry, I don't follow this at all.

TL; DR: how to use SC only once on the server and from then on keep using CC?

No, but I don't understand why you'd want that.

What bothers me also, btw I didn't test personally, just saw in the demo, if the client child component(s) of the SC are using that data, you send the rendered SC including the data rendered, and additionally sending the raw data to be used by the client, not a good idea.

My point is, using SC is not a quick and easy solution. You just need to plan well how to organize SC and client components, not only considering the state management, but also styling/interactions, CCs shouldn't require the same data, code duplications etc.

We already use "references" in the protocol for the same objects so they never appear twice in the output stream. We could conceivably do something similar for strings if that proves to be a problem. We haven't seen that be a problem in our production testing yet. I think you're worrying about a premature optimization here. Also, we shouldn't lose sight of how much data and code we're not sending because it's not needed by the client anymore.
As for styling, it's definitely an open research area but it's not something you would need to worry about as a developer. It's something we need to figure out.

To keep the format as compact as possible increases the likelihood of this coupling. Without going into too much detail, or writing a full proposal here, I would just want to suggest one thing. That is that the format is based on decoupled component definitions, with importable / exportable schemas. I would like to imagine a client that may be built with a server component schema, to communicate and depend on that server's components, regardless of whether that particular client is actually served by that particular server.

I struggle to follow this comment. I think you're imagining the format as something much more complicated than it really is. It's essentially just a stream where every row is either a JSON object with "placeholders" or some instructions ("load a module"). This format is an implementation detail and no one is expected to care about it or interact with it directly. It's essentially a serialized React tree.

Seeing video makes this pretty clear that we cannot have any sought of animation/ client interaction with components rendering on server side. I am curious to know why it is a challenge to support that?

I'm not sure what you mean by this. The video actually does show a moment where we can animate something based on a server response. That's a novel part compared to the traditional server rendering. But yes, interactivity is achieved by Client Components. I don't know why you'd want that to be different. Maybe you can expand?

Re: https://github.com/reactjs/rfcs/pull/188#issuecomment-751797544

The restriction that Client Components aren't allowed to import Server Components is the source of complexities. I'm guessing the purpose of this restriction is to avoid the waterfall situation of rendering going back-and-forth between client and server. Is that the main reason for the restriction?

Yes. I'm not sure I would call that a "source of complexities" though because you could argue that allowing that would be a "source of complexities" (just different ones).

AFAICT this should work, or am I missing something here?