diff --git a/.prettierignore b/.prettierignore
index 4af59c9d031..ec64aebf9dc 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -25,6 +25,9 @@
/docs/source/development-testing/**
!/docs/source/development-testing/reducing-bundle-size.mdx
!/docs/source/development-testing/schema-driven-testing.mdx
+!/docs/source/ssr-and-rsc
+!/docs/source/ssr-and-rsc/**
+
!docs/shared
/docs/shared/**
diff --git a/docs/source/_redirects b/docs/source/_redirects
index 689c408a089..80a68d8fd52 100644
--- a/docs/source/_redirects
+++ b/docs/source/_redirects
@@ -1,3 +1,5 @@
+/docs/react/performance/server-side-rendering /docs/react/ssr-and-rsc/server-side-rendering-string
+
# Redirect all 3.0 beta docs to root
/v3.0-beta/* /docs/react/:splat
diff --git a/docs/source/config.json b/docs/source/config.json
index 5e85cecba5f..698a52d4122 100644
--- a/docs/source/config.json
+++ b/docs/source/config.json
@@ -53,10 +53,17 @@
"Mocking schema capabilities": "/development-testing/client-schema-mocking",
"Reducing bundle size": "/development-testing/reducing-bundle-size"
},
+ "Server-Side Rendering and React Server Components": {
+ "Introduction": "/ssr-and-rsc/introduction",
+ "Usage in React Server Components": "/ssr-and-rsc/usage-in-rsc",
+ "Usage in React Client Components with streaming SSR": "/ssr-and-rsc/usage-in-client-components",
+ "Setting up with Next.js": "/ssr-and-rsc/nextjs",
+ "Setting up a custom \"streaming SSR\" server": "/ssr-and-rsc/custom-streaming-ssr",
+ "Classic Server-side rendering with `renderToString`": "/ssr-and-rsc/server-side-rendering-string"
+ },
"Performance": {
"Improving performance": "/performance/performance",
"Optimistic mutation results": "/performance/optimistic-ui",
- "Server-side rendering": "/performance/server-side-rendering",
"Compiling queries with Babel": "/performance/babel"
},
"Integrations": {
diff --git a/docs/source/ssr-and-rsc/custom-streaming-ssr.mdx b/docs/source/ssr-and-rsc/custom-streaming-ssr.mdx
new file mode 100644
index 00000000000..df92839ece5
--- /dev/null
+++ b/docs/source/ssr-and-rsc/custom-streaming-ssr.mdx
@@ -0,0 +1,266 @@
+---
+title: Setting up Apollo Client with a custom "streaming SSR" server
+---
+
+
+
+This page covers setting up Apollo Client for usage with `renderToPipeableStream` or `renderToReadableStream` in a custom "streaming SSR" server.
+
+If you use a framework like Next.js or Redwood.js, these instructions will not apply to your situation:
+
+- If you are using Next.js, please follow the [Next.js guide](/docs/nextjs) instead.
+- Redwood is preconfigured to support Apollo Client in their latest experimental releases with RSC support, so no additional setup is required.
+
+
+
+## Why you need a specific setup for Apollo Client with streaming SSR.
+
+In a setup with streaming SSR, your server will send the HTML response in chunks as it is being generated.
+That means your browser might already be hydrating components - including your `ApolloClient` and `InMemoryCache` instances, while the server is still making GraphQL requests and rendering contents.
+Apollo Client needs to be set up with a specific transport mechanism that fulfills the following requirements:
+
+- When a query is executed on the SSR server, the same query should be simulated as "in flight" in the Browser so that components rendering in the Browser will not trigger a network request for the same query and variables.
+- When a query receives data on the SSR server, that data should be sent to the browser to hydrate the cache and resolve that simulated "in flight" query.
+- When a query receives an error on the SSR server, that error should be signaled to the browser as soon as possible so the browser can retry the query before the component renders. (Error details should not be transported from SSR to the Browser to prevent any potential "server-only" secrets from leaking to the Browser.)
+- When a hook is rendered on the server, it has to be ensured that the hydration render in the Browser sees the exact same data the server saw to prevent a hydration mismatch.
+
+As this is a complex setup, Apollo Client provides the `@apollo/client-react-streaming` package to help you set up Apollo Client in a streaming SSR environment. This functionality is not included in the main `@apollo/client` yet - we are still waiting for React to add some APIs that will make a part of this package obsolete and setup a lot simpler.
+
+## Setting up Apollo Client with a custom "streaming SSR" server - with the example of a Vite.js server
+
+This guide assumes you already have a working Vite setup with `renderToReadableStream` or `renderToPipeableStream` in place.
+Unfortunately, at the time of writing, there is no official template for Vite with streaming SSR available, so the following section is based off of [letientai299/vite-react-ssr-typescript](https://github.com/letientai299/vite-react-ssr-typescript/tree/6b0b98a2947e1b2d8bbfb610da1e53e474395fe2), which is a variation of the [official Vite React SSR template](https://github.com/bluwy/create-vite-extra/tree/master/template-ssr-react) with streaming SSR support.
+You can also find a slightly different variant with a full setup in [the Apollo Client integration tests](https://github.com/apollographql/apollo-client-nextjs/tree/main/integration-test/vite-streaming).
+
+### 1. Install the necessary package
+
+As explained above, you will need the `@apollo/client-react-streaming` package, so run the following command to install it:
+
+```bash
+npm install @apollo/client-react-streaming @apollo/client
+```
+
+### 2. Create a `WrappedApolloProvider`
+
+Create a file called `Transport.tsx` in your `src` folder with the following content:
+
+```tsx title="src/Transport.tsx"
+import { WrapApolloProvider } from "@apollo/client-react-streaming";
+import { buildManualDataTransport } from "@apollo/client-react-streaming/manual-transport";
+import * as React from "react";
+
+const InjectionContext = React.createContext<
+ (callback: () => React.ReactNode) => void
+>(() => {});
+
+export const InjectionContextProvider = InjectionContext.Provider;
+
+export const WrappedApolloProvider = WrapApolloProvider(
+ buildManualDataTransport({
+ useInsertHtml() {
+ return React.useContext(InjectionContext);
+ },
+ })
+);
+```
+
+Here, you combined a few building blocks:
+
+- `buildManualDataTransport` this creates a "manual data transport". In the future, there might be other kinds of data transport depending on your setup and React version.
+- `WrapApolloProvider` creates a version of an `ApolloProvider` component that is optimized for streaming SSR for a data transport of your choice. It has a different signature in that it doesn't accept `client` prop, but a `makeClient` prop.
+- `InjectionContext` is created so you can pass in a custom `injectIntoStream` method when rendering your app on the server.
+
+### 3. Update your `Html.tsx` file to use `InjectionContextProvider`
+
+```diff title="src/Html.tsx"
++import { InjectionContextProvider } from "./Transport";
+
+ interface HtmlProps {
+ children: ReactNode;
++ injectIntoStream: (callback: () => React.ReactNode) => void;
+ }
+
+-function Html({ children }: HtmlProps) {
++function Html({ children, injectIntoStream }: HtmlProps) {
+
+// ...
+
+
++
+ {children}
++
+
+