mirror of
https://github.com/reactjs/react.dev.git
synced 2026-02-22 03:42:14 +00:00
Docs for partial-prerendering APIs (#7869)
* Init PPR docs * Overhaul * Apply suggestions from code review --------- Co-authored-by: Sebastian Sebbie Silbermann <sebastian.silbermann@vercel.com>
This commit is contained in:
@@ -10,19 +10,27 @@ The `react-dom/server` APIs let you server-side render React components to HTML.
|
||||
|
||||
---
|
||||
|
||||
## Server APIs for Node.js Streams {/*server-apis-for-nodejs-streams*/}
|
||||
|
||||
These methods are only available in the environments with [Node.js Streams:](https://nodejs.org/api/stream.html)
|
||||
|
||||
* [`renderToPipeableStream`](/reference/react-dom/server/renderToPipeableStream) renders a React tree to a pipeable [Node.js Stream.](https://nodejs.org/api/stream.html)
|
||||
|
||||
---
|
||||
|
||||
## Server APIs for Web Streams {/*server-apis-for-web-streams*/}
|
||||
|
||||
These methods are only available in the environments with [Web Streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API), which includes browsers, Deno, and some modern edge runtimes:
|
||||
|
||||
* [`renderToReadableStream`](/reference/react-dom/server/renderToReadableStream) renders a React tree to a [Readable Web Stream.](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
|
||||
* [`resume`](/reference/react-dom/server/renderToPipeableStream) resumes [`prerender`](/reference/react-dom/static/prerender) to a [Readable Web Stream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
|
||||
|
||||
|
||||
<Note>
|
||||
|
||||
Node.js also includes these methods for compatibility, but they are not recommended due to worse performance. Use the [dedicated Node.js APIs](#server-apis-for-nodejs-streams) instead.
|
||||
|
||||
</Note>
|
||||
---
|
||||
|
||||
## Server APIs for Node.js Streams {/*server-apis-for-nodejs-streams*/}
|
||||
|
||||
These methods are only available in the environments with [Node.js Streams:](https://nodejs.org/api/stream.html)
|
||||
|
||||
* [`renderToPipeableStream`](/reference/react-dom/server/renderToPipeableStream) renders a React tree to a pipeable [Node.js Stream.](https://nodejs.org/api/stream.html)
|
||||
* [`resumeToPipeableStream`](/reference/react-dom/server/renderToPipeableStream) resumes [`prerenderToNodeStream`](/reference/react-dom/static/prerenderToNodeStream) to a pipeable [Node.js Stream.](https://nodejs.org/api/stream.html)
|
||||
|
||||
---
|
||||
|
||||
|
||||
261
src/content/reference/react-dom/server/resume.md
Normal file
261
src/content/reference/react-dom/server/resume.md
Normal file
@@ -0,0 +1,261 @@
|
||||
---
|
||||
title: resume
|
||||
canary: true
|
||||
---
|
||||
|
||||
<Canary>
|
||||
|
||||
**The `resume` API is currently only available in React’s Canary and Experimental channels.**
|
||||
|
||||
[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
|
||||
|
||||
</Canary>
|
||||
|
||||
<Intro>
|
||||
|
||||
`resume` streams a pre-rendered React tree to a [Readable Web Stream.](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
|
||||
|
||||
```js
|
||||
const stream = await resume(reactNode, postponedState, options?)
|
||||
```
|
||||
|
||||
</Intro>
|
||||
|
||||
<InlineToc />
|
||||
|
||||
<Note>
|
||||
|
||||
This API depends on [Web Streams.](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) For Node.js, use [`resumeToNodeStream`](/reference/react-dom/server/renderToPipeableStream) instead.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Reference {/*reference*/}
|
||||
|
||||
### `resume(node, postponedState, options?)` {/*resume*/}
|
||||
|
||||
Call `resume` to resume rendering a pre-rendered React tree as HTML into a [Readable Web Stream.](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
|
||||
|
||||
```js
|
||||
import { resume } from 'react-dom/server';
|
||||
import {getPostponedState} from './storage';
|
||||
|
||||
async function handler(request, writable) {
|
||||
const postponed = await getPostponedState(request);
|
||||
const resumeStream = await resume(<App />, postponed);
|
||||
return resumeStream.pipeTo(writable)
|
||||
}
|
||||
```
|
||||
|
||||
[See more examples below.](#usage)
|
||||
|
||||
#### Parameters {/*parameters*/}
|
||||
|
||||
* `reactNode`: The React node you called `prerender` with. For example, a JSX element like `<App />`. It is expected to represent the entire document, so the `App` component should render the `<html>` tag.
|
||||
* `postponedState`: The opaque `postpone` object returned from a [prerender API](/reference/react-dom/static/index), loaded from wherever you stored it (e.g. redis, a file, or S3).
|
||||
* **optional** `options`: An object with streaming options.
|
||||
* **optional** `nonce`: A [`nonce`](http://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#nonce) string to allow scripts for [`script-src` Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src).
|
||||
* **optional** `signal`: An [abort signal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that lets you [abort server rendering](#aborting-server-rendering) and render the rest on the client.
|
||||
* **optional** `onError`: A callback that fires whenever there is a server error, whether [recoverable](/reference/react-dom/server/renderToReadableStream#recovering-from-errors-outside-the-shell) or [not.](/reference/react-dom/server/renderToReadableStream#recovering-from-errors-inside-the-shell) By default, this only calls `console.error`. If you override it to [log crash reports,](/reference/react-dom/server/renderToReadableStream#logging-crashes-on-the-server) make sure that you still call `console.error`.
|
||||
|
||||
|
||||
#### Returns {/*returns*/}
|
||||
|
||||
`resume` returns a Promise:
|
||||
|
||||
- If `resume` successfully produced a [shell](/reference/react-dom/server/renderToReadableStream#specifying-what-goes-into-the-shell), that Promise will resolve to a [Readable Web Stream.](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) that can be piped to a [Writable Web Stream.](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream).
|
||||
- If an error happens in the shell, the Promise will reject with that error.
|
||||
|
||||
The returned stream has an additional property:
|
||||
|
||||
* `allReady`: A Promise that resolves when all rendering is complete. You can `await stream.allReady` before returning a response [for crawlers and static generation.](/reference/react-dom/server/renderToReadableStream#waiting-for-all-content-to-load-for-crawlers-and-static-generation) If you do that, you won't get any progressive loading. The stream will contain the final HTML.
|
||||
|
||||
#### Caveats {/*caveats*/}
|
||||
|
||||
- `resume` does not accept options for `bootstrapScripts`, `bootstrapScriptContent`, or `bootstrapModules`. Instead, you need to pass these options to the `prerender` call that generates the `postponedState`. You can also inject bootstrap content into the writable stream manually.
|
||||
- `resume` does not accept `identifierPrefix` since the prefix needs to be the same in both `prerender` and `resume`.
|
||||
- Since `nonce` cannot be provided to prerender, you should only provide `nonce` to `resume` if you're not providing scripts to prerender.
|
||||
- `resume` re-renders from the root until it finds a component that was not fully pre-rendered. Only fully prerendered Components (the Component and its children finished prerendering) are skipped entirely.
|
||||
|
||||
## Usage {/*usage*/}
|
||||
|
||||
### Resuming a prerender {/*resuming-a-prerender*/}
|
||||
|
||||
<Sandpack>
|
||||
|
||||
```js src/App.js hidden
|
||||
```
|
||||
|
||||
```json package.json hidden
|
||||
{
|
||||
"dependencies": {
|
||||
"react": "experimental",
|
||||
"react-dom": "experimental",
|
||||
"react-scripts": "latest"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```html public/index.html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="container"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```js src/index.js
|
||||
import {
|
||||
flushReadableStreamToFrame,
|
||||
getUser,
|
||||
Postponed,
|
||||
sleep,
|
||||
} from "./demo-helpers";
|
||||
import { StrictMode, Suspense, use, useEffect } from "react";
|
||||
import { prerender } from "react-dom/static";
|
||||
import { resume } from "react-dom/server";
|
||||
import { hydrateRoot } from "react-dom/client";
|
||||
|
||||
function Header() {
|
||||
return <header>Me and my descendants can be prerendered</header>;
|
||||
}
|
||||
|
||||
const { promise: cookies, resolve: resolveCookies } = Promise.withResolvers();
|
||||
|
||||
function Main() {
|
||||
const { sessionID } = use(cookies);
|
||||
const user = getUser(sessionID);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("reached interactivity!");
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<main>
|
||||
Hello, {user.name}!
|
||||
<button onClick={() => console.log("hydrated!")}>
|
||||
Clicking me requires hydration.
|
||||
</button>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
function Shell({ children }) {
|
||||
// In a real app, this is where you would put your html and body.
|
||||
// We're just using tags here we can include in an existing body for demonstration purposes
|
||||
return (
|
||||
<html>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Shell>
|
||||
<Suspense fallback="loading header">
|
||||
<Header />
|
||||
</Suspense>
|
||||
<Suspense fallback="loading main">
|
||||
<Main />
|
||||
</Suspense>
|
||||
</Shell>
|
||||
);
|
||||
}
|
||||
|
||||
async function main(frame) {
|
||||
// Layer 1
|
||||
const controller = new AbortController();
|
||||
const prerenderedApp = prerender(<App />, {
|
||||
signal: controller.signal,
|
||||
onError(error) {
|
||||
if (error instanceof Postponed) {
|
||||
} else {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
});
|
||||
// We're immediately aborting in a macrotask.
|
||||
// Any data fetching that's not available synchronously, or in a microtask, will not have finished.
|
||||
setTimeout(() => {
|
||||
controller.abort(new Postponed());
|
||||
});
|
||||
|
||||
const { prelude, postponed } = await prerenderedApp;
|
||||
await flushReadableStreamToFrame(prelude, frame);
|
||||
|
||||
// Layer 2
|
||||
// Just waiting here for demonstration purposes.
|
||||
// In a real app, the prelude and postponed state would've been serialized in Layer 1 and Layer would deserialize them.
|
||||
// The prelude content could be flushed immediated as plain HTML while
|
||||
// React is continuing to render from where the prerender left off.
|
||||
await sleep(2000);
|
||||
|
||||
// You would get the cookies from the incoming HTTP request
|
||||
resolveCookies({ sessionID: "abc" });
|
||||
|
||||
const stream = await resume(<App />, postponed);
|
||||
|
||||
await flushReadableStreamToFrame(stream, frame);
|
||||
|
||||
// Layer 3
|
||||
// Just waiting here for demonstration purposes.
|
||||
await sleep(2000);
|
||||
|
||||
hydrateRoot(frame.contentWindow.document, <App />);
|
||||
}
|
||||
|
||||
main(document.getElementById("container"));
|
||||
|
||||
```
|
||||
|
||||
```js src/demo-helpers.js
|
||||
export async function flushReadableStreamToFrame(readable, frame) {
|
||||
const document = frame.contentWindow.document;
|
||||
const decoder = new TextDecoder();
|
||||
for await (const chunk of readable) {
|
||||
const partialHTML = decoder.decode(chunk);
|
||||
document.write(partialHTML);
|
||||
}
|
||||
}
|
||||
|
||||
// This doesn't need to be an error.
|
||||
// You can use any other means to check if an error during prerender was
|
||||
// from an intentional abort or a real error.
|
||||
export class Postponed extends Error {}
|
||||
|
||||
// We're just hardcoding a session here.
|
||||
export function getUser(sessionID) {
|
||||
return {
|
||||
name: "Alice",
|
||||
};
|
||||
}
|
||||
|
||||
export function sleep(timeoutMS) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, timeoutMS);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
</Sandpack>
|
||||
|
||||
### Further reading {/*further-reading*/}
|
||||
|
||||
Resuming behaves like `renderToReadableStream`. For more examples, check out the [usage section of `renderToReadableStream`](/reference/react-dom/server/renderToReadableStream#usage).
|
||||
The [usage section of `prerender`](/reference/react-dom/static/prerender#usage) includes examples of how to use `prerender` specifically.
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
title: resumeToPipeableStream
|
||||
canary: true
|
||||
---
|
||||
|
||||
<Canary>
|
||||
|
||||
**The `resumeToPipeableStream` API is currently only available in React’s Canary and Experimental channels.**
|
||||
|
||||
[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
|
||||
|
||||
</Canary>
|
||||
|
||||
<Intro>
|
||||
|
||||
`resumeToPipeableStream` streams a pre-rendered React tree to a pipeable [Node.js Stream.](https://nodejs.org/api/stream.html)
|
||||
|
||||
```js
|
||||
const {pipe, abort} = await resumeToPipeableStream(reactNode, postponedState, options?)
|
||||
```
|
||||
|
||||
</Intro>
|
||||
|
||||
<InlineToc />
|
||||
|
||||
<Note>
|
||||
|
||||
This API is specific to Node.js. Environments with [Web Streams,](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) like Deno and modern edge runtimes, should use [`resume`](/reference/react-dom/server/renderToReadableStream) instead.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Reference {/*reference*/}
|
||||
|
||||
### `resumeToPipeableStream(node, postponed, options?)` {/*resume-to-pipeable-stream*/}
|
||||
|
||||
Call `resume` to resume rendering a pre-rendered React tree as HTML into a [Node.js Stream.](https://nodejs.org/api/stream.html#writable-streams)
|
||||
|
||||
```js
|
||||
import { resume } from 'react-dom/server';
|
||||
import {getPostponedState} from './storage';
|
||||
|
||||
async function handler(request, response) {
|
||||
const postponed = await getPostponedState(request);
|
||||
const {pipe} = resumeToPipeableStream(<App />, postponed, {
|
||||
onShellReady: () => {
|
||||
pipe(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
[See more examples below.](#usage)
|
||||
|
||||
#### Parameters {/*parameters*/}
|
||||
|
||||
* `reactNode`: The React node you called `prerender` with. For example, a JSX element like `<App />`. It is expected to represent the entire document, so the `App` component should render the `<html>` tag.
|
||||
* `postponedState`: The opaque `postpone` object returned from a [prerender API](/reference/react-dom/static/index), loaded from wherever you stored it (e.g. redis, a file, or S3).
|
||||
* **optional** `options`: An object with streaming options.
|
||||
* **optional** `nonce`: A [`nonce`](http://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#nonce) string to allow scripts for [`script-src` Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src).
|
||||
* **optional** `signal`: An [abort signal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that lets you [abort server rendering](#aborting-server-rendering) and render the rest on the client.
|
||||
* **optional** `onError`: A callback that fires whenever there is a server error, whether [recoverable](/reference/react-dom/server/renderToReadableStream#recovering-from-errors-outside-the-shell) or [not.](/reference/react-dom/server/renderToReadableStream#recovering-from-errors-inside-the-shell) By default, this only calls `console.error`. If you override it to [log crash reports,](/reference/react-dom/server/renderToReadableStream#logging-crashes-on-the-server) make sure that you still call `console.error`.
|
||||
* **optional** `onShellReady`: A callback that fires right after the [shell](#specifying-what-goes-into-the-shell) has finished. You can call `pipe` here to start streaming. React will [stream the additional content](#streaming-more-content-as-it-loads) after the shell along with the inline `<script>` tags that replace the HTML loading fallbacks with the content.
|
||||
* **optional** `onShellError`: A callback that fires if there was an error rendering the shell. It receives the error as an argument. No bytes were emitted from the stream yet, and neither `onShellReady` nor `onAllReady` will get called, so you can [output a fallback HTML shell](#recovering-from-errors-inside-the-shell) or use the prelude.
|
||||
|
||||
|
||||
#### Returns {/*returns*/}
|
||||
|
||||
`resume` returns an object with two methods:
|
||||
|
||||
* `pipe` outputs the HTML into the provided [Writable Node.js Stream.](https://nodejs.org/api/stream.html#writable-streams) Call `pipe` in `onShellReady` if you want to enable streaming, or in `onAllReady` for crawlers and static generation.
|
||||
* `abort` lets you [abort server rendering](#aborting-server-rendering) and render the rest on the client.
|
||||
|
||||
#### Caveats {/*caveats*/}
|
||||
|
||||
- `resumeToPipeableStream` does not accept options for `bootstrapScripts`, `bootstrapScriptContent`, or `bootstrapModules`. Instead, you need to pass these options to the `prerender` call that generates the `postponedState`. You can also inject bootstrap content into the writable stream manually.
|
||||
- `resumeToPipeableStream` does not accept `identifierPrefix` since the prefix needs to be the same in both `prerender` and `resumeToPipeableStream`.
|
||||
- Since `nonce` cannot be provided to prerender, you should only provide `nonce` to `resumeToPipeableStream` if you're not providing scripts to prerender.
|
||||
- `resumeToPipeableStream` re-renders from the root until it finds a component that was not fully pre-rendered. Only fully prerendered Components (the Component and its children finished prerendering) are skipped entirely.
|
||||
|
||||
## Usage {/*usage*/}
|
||||
|
||||
### Further reading {/*further-reading*/}
|
||||
|
||||
Resuming behaves like `renderToReadableStream`. For more examples, check out the [usage section of `renderToReadableStream`](/reference/react-dom/server/renderToReadableStream#usage).
|
||||
The [usage section of `prerender`](/reference/react-dom/static/prerender#usage) includes examples of how to use `prerenderToNodeStream` specifically.
|
||||
@@ -15,7 +15,9 @@ The `react-dom/static` APIs let you generate static HTML for React components. T
|
||||
These methods are only available in the environments with [Web Streams](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API), which includes browsers, Deno, and some modern edge runtimes:
|
||||
|
||||
* [`prerender`](/reference/react-dom/static/prerender) renders a React tree to static HTML with a [Readable Web Stream.](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
|
||||
* <ExperimentalBadge /> [`resumeAndPrerender`](/reference/react-dom/static/resumeAndPrerender) continues a prerendered React tree to static HTML with a [Readable Web Stream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
|
||||
|
||||
Node.js also includes these methods for compatibility, but they are not recommended due to worse performance. Use the [dedicated Node.js APIs](#static-apis-for-nodejs-streams) instead.
|
||||
|
||||
---
|
||||
|
||||
@@ -24,5 +26,5 @@ These methods are only available in the environments with [Web Streams](https://
|
||||
These methods are only available in the environments with [Node.js Streams](https://nodejs.org/api/stream.html):
|
||||
|
||||
* [`prerenderToNodeStream`](/reference/react-dom/static/prerenderToNodeStream) renders a React tree to static HTML with a [Node.js Stream.](https://nodejs.org/api/stream.html)
|
||||
|
||||
* <ExperimentalBadge /> [`resumeAndPrerenderToNodeStream`](/reference/react-dom/static/resumeAndPrerenderToNodeStream) continues a prerendered React tree to static HTML with a [Node.js Stream.](https://nodejs.org/api/stream.html)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ title: prerender
|
||||
`prerender` renders a React tree to a static HTML string using a [Web Stream](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API).
|
||||
|
||||
```js
|
||||
const {prelude} = await prerender(reactNode, options?)
|
||||
const {prelude, postponed} = await prerender(reactNode, options?)
|
||||
```
|
||||
|
||||
</Intro>
|
||||
@@ -31,7 +31,7 @@ Call `prerender` to render your app to static HTML.
|
||||
```js
|
||||
import { prerender } from 'react-dom/static';
|
||||
|
||||
async function handler(request) {
|
||||
async function handler(request, response) {
|
||||
const {prelude} = await prerender(<App />, {
|
||||
bootstrapScripts: ['/main.js']
|
||||
});
|
||||
@@ -64,19 +64,21 @@ On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to
|
||||
`prerender` returns a Promise:
|
||||
- If rendering the is successful, the Promise will resolve to an object containing:
|
||||
- `prelude`: a [Web Stream](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) of HTML. You can use this stream to send a response in chunks, or you can read the entire stream into a string.
|
||||
- `postponed` <CanaryBadge />: a JSON-serializeable, opaque object that can be passed to [`resume`](/reference/react-dom/server/resume) if `prerender` did not finish. Otherwise `null` indicating that the `prelude` contains all the content and no resume is necessary.
|
||||
- If rendering fails, the Promise will be rejected. [Use this to output a fallback shell.](/reference/react-dom/server/renderToReadableStream#recovering-from-errors-inside-the-shell)
|
||||
|
||||
#### Caveats {/*caveats*/}
|
||||
|
||||
`nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the nonce value in the prerender itself.
|
||||
|
||||
|
||||
<Note>
|
||||
|
||||
### When should I use `prerender`? {/*when-to-use-prerender*/}
|
||||
|
||||
The static `prerender` API is used for static server-side generation (SSG). Unlike `renderToString`, `prerender` waits for all data to load before resolving. This makes it suitable for generating static HTML for a full page, including data that needs to be fetched using Suspense. To stream content as it loads, use a streaming server-side render (SSR) API like [renderToReadableStream](/reference/react-dom/server/renderToReadableStream).
|
||||
|
||||
In Canary versions of React DOM, `prerender` can be aborted and later either continued with `resumeAndPrerender` or resumed with `resume` to support partial pre-rendering.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
@@ -311,7 +313,7 @@ async function renderToString() {
|
||||
|
||||
Any Suspense boundaries with incomplete children will be included in the prelude in the fallback state.
|
||||
|
||||
---
|
||||
<CanaryBadge /> This can be used for partial prerendering together with [`resume`](/reference/react-dom/server/resume) or [`resumeAndPrerender`](/reference/react-dom/static/resumeAndPrerender).
|
||||
|
||||
## Troubleshooting {/*troubleshooting*/}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ title: prerenderToNodeStream
|
||||
`prerenderToNodeStream` renders a React tree to a static HTML string using a [Node.js Stream.](https://nodejs.org/api/stream.html).
|
||||
|
||||
```js
|
||||
const {prelude} = await prerenderToNodeStream(reactNode, options?)
|
||||
const {prelude, postponed} = await prerenderToNodeStream(reactNode, options?)
|
||||
```
|
||||
|
||||
</Intro>
|
||||
@@ -65,6 +65,7 @@ On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to
|
||||
`prerenderToNodeStream` returns a Promise:
|
||||
- If rendering the is successful, the Promise will resolve to an object containing:
|
||||
- `prelude`: a [Node.js Stream.](https://nodejs.org/api/stream.html) of HTML. You can use this stream to send a response in chunks, or you can read the entire stream into a string.
|
||||
- `postponed` <CanaryBadge />: a JSON-serializeable, opaque object that can be passed to [`resumeToPipeableStream`](/reference/react-dom/server/resumeToPipeableStream) if `prerenderToNodeStream` did not finish. Otherwise `null` indicating that the `prelude` contains all the content and no resume is necessary.
|
||||
- If rendering fails, the Promise will be rejected. [Use this to output a fallback shell.](/reference/react-dom/server/renderToPipeableStream#recovering-from-errors-inside-the-shell)
|
||||
|
||||
#### Caveats {/*caveats*/}
|
||||
@@ -77,6 +78,8 @@ On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to
|
||||
|
||||
The static `prerenderToNodeStream` API is used for static server-side generation (SSG). Unlike `renderToString`, `prerenderToNodeStream` waits for all data to load before resolving. This makes it suitable for generating static HTML for a full page, including data that needs to be fetched using Suspense. To stream content as it loads, use a streaming server-side render (SSR) API like [renderToReadableStream](/reference/react-dom/server/renderToReadableStream).
|
||||
|
||||
In canary versions of React DOM, `prerenderToNodeStream` can be aborted and resumed later with `resumeToPipeableStream` to support partial pre-rendering.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
@@ -311,7 +314,7 @@ async function renderToString() {
|
||||
|
||||
Any Suspense boundaries with incomplete children will be included in the prelude in the fallback state.
|
||||
|
||||
---
|
||||
<CanaryBadge /> This can be used for partial prerendering together with [`resumeToPipeableStream`](/reference/react-dom/server/resumeToPipeableStream) or [`resumeAndPrerenderToNodeStream`](/reference/react-dom/static/resumeAndPrerenderToNodeStream).
|
||||
|
||||
## Troubleshooting {/*troubleshooting*/}
|
||||
|
||||
|
||||
96
src/content/reference/react-dom/static/resumeAndPrerender.md
Normal file
96
src/content/reference/react-dom/static/resumeAndPrerender.md
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
title: resumeAndPrerender
|
||||
version: canary
|
||||
---
|
||||
|
||||
<Canary>
|
||||
|
||||
**The `resume` API is currently only available in React’s Canary and Experimental channels.**
|
||||
|
||||
[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
|
||||
|
||||
</Canary>
|
||||
|
||||
<Intro>
|
||||
|
||||
`resumeAndPrerender` continues a prerendered React tree to a static HTML string using a [Web Stream](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API).
|
||||
|
||||
```js
|
||||
const { prelude,postpone } = await resumeAndPrerender(reactNode, postponedState, options?)
|
||||
```
|
||||
|
||||
</Intro>
|
||||
|
||||
<InlineToc />
|
||||
|
||||
<Note>
|
||||
|
||||
This API depends on [Web Streams.](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) For Node.js, use [`resumeAndPrerenderToNodeStream`](/reference/react-dom/static/resumeAndPrerenderToNodeStream) instead.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Reference {/*reference*/}
|
||||
|
||||
### `resumeAndPrerender(reactNode, postponedState, options?)` {/*resumeandprerender*/}
|
||||
|
||||
Call `resumeAndPrerender` to continue a prerendered React tree to a static HTML string.
|
||||
|
||||
```js
|
||||
import { resumeAndPrerender } from 'react-dom/static';
|
||||
import { getPostponedState } from 'storage';
|
||||
|
||||
async function handler(request, response) {
|
||||
const postponedState = getPostponedState(request);
|
||||
const { prelude } = await resumeAndPrerender(<App />, postponedState, {
|
||||
bootstrapScripts: ['/main.js']
|
||||
});
|
||||
return new Response(prelude, {
|
||||
headers: { 'content-type': 'text/html' },
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to make the server-generated HTML interactive.
|
||||
|
||||
[See more examples below.](#usage)
|
||||
|
||||
#### Parameters {/*parameters*/}
|
||||
|
||||
* `reactNode`: The React node you called `prerender` (or a previous `resumeAndPrerender`) with. For example, a JSX element like `<App />`. It is expected to represent the entire document, so the `App` component should render the `<html>` tag.
|
||||
* `postponedState`: The opaque `postpone` object returned from a [prerender API](/reference/react-dom/static/index), loaded from wherever you stored it (e.g. redis, a file, or S3).
|
||||
* **optional** `options`: An object with streaming options.
|
||||
* **optional** `signal`: An [abort signal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that lets you [abort server rendering](#aborting-server-rendering) and render the rest on the client.
|
||||
* **optional** `onError`: A callback that fires whenever there is a server error, whether [recoverable](#recovering-from-errors-outside-the-shell) or [not.](#recovering-from-errors-inside-the-shell) By default, this only calls `console.error`. If you override it to [log crash reports,](#logging-crashes-on-the-server) make sure that you still call `console.error`.
|
||||
|
||||
#### Returns {/*returns*/}
|
||||
|
||||
`prerender` returns a Promise:
|
||||
- If rendering the is successful, the Promise will resolve to an object containing:
|
||||
- `prelude`: a [Web Stream](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) of HTML. You can use this stream to send a response in chunks, or you can read the entire stream into a string.
|
||||
- `postponed`: an JSON-serializeable, opaque object that can be passed to [`resume`](/reference/react-dom/server/resume) or [`resumeAndPrerender`](/reference/react-dom/static/resumeAndPrerender) if `prerender` is aborted.
|
||||
- If rendering fails, the Promise will be rejected. [Use this to output a fallback shell.](/reference/react-dom/server/renderToReadableStream#recovering-from-errors-inside-the-shell)
|
||||
|
||||
#### Caveats {/*caveats*/}
|
||||
|
||||
`nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the nonce value in the prerender itself.
|
||||
|
||||
<Note>
|
||||
|
||||
### When should I use `resumeAndPrerender`? {/*when-to-use-prerender*/}
|
||||
|
||||
The static `resumeAndPrerender` API is used for static server-side generation (SSG). Unlike `renderToString`, `resumeAndPrerender` waits for all data to load before resolving. This makes it suitable for generating static HTML for a full page, including data that needs to be fetched using Suspense. To stream content as it loads, use a streaming server-side render (SSR) API like [renderToReadableStream](/reference/react-dom/server/renderToReadableStream).
|
||||
|
||||
`resumeAndPrerender` can be aborted and later either continued with another `resumeAndPrerender` or resumed with `resume` to support partial pre-rendering.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Usage {/*usage*/}
|
||||
|
||||
### Further reading {/*further-reading*/}
|
||||
|
||||
`resumeAndPrerender` behaves similarly to [`prerender`](/reference/react-dom/static/prerender) but can be used to continue a previously started prerendering process that was aborted.
|
||||
For more information about resuming a prerendered tree, see the [resume documentation](/reference/react-dom/server/resume#resuming-a-prerender).
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
title: resumeAndPrerenderToNodeStream
|
||||
version: canary
|
||||
---
|
||||
|
||||
<Canary>
|
||||
|
||||
**The `resumeAndPrerenderToNodeStream` API is currently only available in React’s Experimental channels.**
|
||||
|
||||
[Learn more about React’s release channels here.](/community/versioning-policy#all-release-channels)
|
||||
|
||||
</Canary>
|
||||
|
||||
<Intro>
|
||||
|
||||
`resumeAndPrerenderToNodeStream` continues a prerendered React tree to a static HTML string using a a [Node.js Stream.](https://nodejs.org/api/stream.html).
|
||||
|
||||
```js
|
||||
const {prelude, postponed} = await resumeAndPrerenderToNodeStream(reactNode, postponedState, options?)
|
||||
```
|
||||
|
||||
</Intro>
|
||||
|
||||
<InlineToc />
|
||||
|
||||
<Note>
|
||||
|
||||
This API is specific to Node.js. Environments with [Web Streams,](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) like Deno and modern edge runtimes, should use [`prerender`](/reference/react-dom/static/prerender) instead.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Reference {/*reference*/}
|
||||
|
||||
### `resumeAndPrerenderToNodeStream(reactNode, postponedState, options?)` {/*resumeandprerendertolnodestream*/}
|
||||
|
||||
Call `resumeAndPrerenderToNodeStream` to continue a prerendered React tree to a static HTML string.
|
||||
|
||||
```js
|
||||
import { resumeAndPrerenderToNodeStream } from 'react-dom/static';
|
||||
import { getPostponedState } from 'storage';
|
||||
|
||||
async function handler(request, writable) {
|
||||
const postponedState = getPostponedState(request);
|
||||
const { prelude } = await resumeAndPrerenderToNodeStream(<App />, JSON.parse(postponedState));
|
||||
prelude.pipe(writable);
|
||||
}
|
||||
```
|
||||
|
||||
On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to make the server-generated HTML interactive.
|
||||
|
||||
[See more examples below.](#usage)
|
||||
|
||||
#### Parameters {/*parameters*/}
|
||||
|
||||
* `reactNode`: The React node you called `prerender` (or a previous `resumeAndPrerenderToNodeStream`) with. For example, a JSX element like `<App />`. It is expected to represent the entire document, so the `App` component should render the `<html>` tag.
|
||||
* `postponedState`: The opaque `postpone` object returned from a [prerender API](/reference/react-dom/static/index), loaded from wherever you stored it (e.g. redis, a file, or S3).
|
||||
* **optional** `options`: An object with streaming options.
|
||||
* **optional** `signal`: An [abort signal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that lets you [abort server rendering](#aborting-server-rendering) and render the rest on the client.
|
||||
* **optional** `onError`: A callback that fires whenever there is a server error, whether [recoverable](#recovering-from-errors-outside-the-shell) or [not.](#recovering-from-errors-inside-the-shell) By default, this only calls `console.error`. If you override it to [log crash reports,](#logging-crashes-on-the-server) make sure that you still call `console.error`.
|
||||
|
||||
#### Returns {/*returns*/}
|
||||
|
||||
`resumeAndPrerenderToNodeStream` returns a Promise:
|
||||
- If rendering the is successful, the Promise will resolve to an object containing:
|
||||
- `prelude`: a [Web Stream](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) of HTML. You can use this stream to send a response in chunks, or you can read the entire stream into a string.
|
||||
- `postponed`: an JSON-serializeable, opaque object that can be passed to [`resumeToNodeStream`](/reference/react-dom/server/resume) or [`resumeAndPrerenderToNodeStream`](/reference/react-dom/static/resumeAndPrerenderToNodeStream) if `resumeAndPrerenderToNodeStream` is aborted.
|
||||
- If rendering fails, the Promise will be rejected. [Use this to output a fallback shell.](/reference/react-dom/server/renderToReadableStream#recovering-from-errors-inside-the-shell)
|
||||
|
||||
#### Caveats {/*caveats*/}
|
||||
|
||||
`nonce` is not an available option when prerendering. Nonces must be unique per request and if you use nonces to secure your application with [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) it would be inappropriate and insecure to include the nonce value in the prerender itself.
|
||||
|
||||
<Note>
|
||||
|
||||
### When should I use `resumeAndPrerenderToNodeStream`? {/*when-to-use-prerender*/}
|
||||
|
||||
The static `resumeAndPrerenderToNodeStream` API is used for static server-side generation (SSG). Unlike `renderToString`, `resumeAndPrerenderToNodeStream` waits for all data to load before resolving. This makes it suitable for generating static HTML for a full page, including data that needs to be fetched using Suspense. To stream content as it loads, use a streaming server-side render (SSR) API like [renderToReadableStream](/reference/react-dom/server/renderToReadableStream).
|
||||
|
||||
`resumeAndPrerenderToNodeStream` can be aborted and later either continued with another `resumeAndPrerenderToNodeStream` or resumed with `resume` to support partial pre-rendering.
|
||||
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## Usage {/*usage*/}
|
||||
|
||||
### Further reading {/*further-reading*/}
|
||||
|
||||
`resumeAndPrerenderToNodeStream` behaves similarly to [`prerender`](/reference/react-dom/static/prerender) but can be used to continue a previously started prerendering process that was aborted.
|
||||
For more information about resuming a prerendered tree, see the [resume documentation](/reference/react-dom/server/resume#resuming-a-prerender).
|
||||
|
||||
@@ -318,6 +318,16 @@
|
||||
{
|
||||
"title": "renderToString",
|
||||
"path": "/reference/react-dom/server/renderToString"
|
||||
},
|
||||
{
|
||||
"title": "resume",
|
||||
"path": "/reference/react-dom/server/resume",
|
||||
"version": "canary"
|
||||
},
|
||||
{
|
||||
"title": "resumeToPipeableStream",
|
||||
"path": "/reference/react-dom/server/resumeToPipeableStream",
|
||||
"version": "canary"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -332,6 +342,16 @@
|
||||
{
|
||||
"title": "prerenderToNodeStream",
|
||||
"path": "/reference/react-dom/static/prerenderToNodeStream"
|
||||
},
|
||||
{
|
||||
"title": "resumeAndPrerender",
|
||||
"path": "/reference/react-dom/static/resumeAndPrerender",
|
||||
"version": "canary"
|
||||
},
|
||||
{
|
||||
"title": "resumeAndPrerenderToNodeStream",
|
||||
"path": "/reference/react-dom/static/resumeAndPrerenderToNodeStream",
|
||||
"version": "canary"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user